MOM6
regrid_solvers Module Reference

Functions/Subroutines

subroutine, public solve_linear_system (A, B, X, system_size)
 
subroutine, public solve_tridiagonal_system (Al, Ad, Au, B, X, system_size)
 

Function/Subroutine Documentation

◆ solve_linear_system()

subroutine, public regrid_solvers::solve_linear_system ( real, dimension(:,:), intent(inout)  A,
real, dimension(:), intent(inout)  B,
real, dimension(:), intent(inout)  X,
integer  system_size 
)

Definition at line 30 of file regrid_solvers.F90.

References mom_error_handler::mom_error().

Referenced by regrid_edge_slopes::edge_slopes_implicit_h3(), regrid_edge_slopes::edge_slopes_implicit_h5(), regrid_edge_values::edge_values_explicit_h4(), regrid_edge_values::edge_values_implicit_h4(), and regrid_edge_values::edge_values_implicit_h6().

30 ! -----------------------------------------------------------------------------
31 ! This routine uses Gauss's algorithm to transform the system's original
32 ! matrix into an upper triangular matrix. Back substitution yields the answer.
33 ! The matrix A must be square and its size must be that of the vectors B and X.
34 ! -----------------------------------------------------------------------------
35 
36  ! Arguments
37  real, dimension(:,:), intent(inout) :: a
38  real, dimension(:), intent(inout) :: b
39  real, dimension(:), intent(inout) :: x
40  integer :: system_size
41 
42  ! Local variables
43  integer :: i, j, k
44  real, parameter :: eps = 0.0 ! Minimum pivot magnitude allowed
45  real :: factor
46  real :: pivot
47  real :: swap_a, swap_b
48  logical :: found_pivot ! boolean indicating whether
49  ! a pivot has been found
50  ! Loop on rows
51  do i = 1,system_size-1
52 
53  found_pivot = .false.
54 
55  ! Start to look for a pivot in row i. If the pivot
56  ! in row i -- which is the current row -- is not valid,
57  ! we keep looking for a valid pivot by searching the
58  ! entries of column i in rows below row i. Once a valid
59  ! pivot is found (say in row k), rows i and k are swaped.
60  k = i
61  do while ( ( .NOT. found_pivot ) .AND. ( k .LE. system_size ) )
62 
63  if ( abs( a(k,i) ) .GT. eps ) then ! a valid pivot is found
64  found_pivot = .true.
65  else ! Go to the next row to see
66  ! if there is a valid pivot there
67  k = k + 1
68  end if
69 
70  end do ! end loop to find pivot
71 
72  ! If no pivot could be found, the system is singular and we need
73  ! to end the execution
74  if ( .NOT. found_pivot ) then
75  write(0,*) ' A=',a
76  call mom_error( fatal, 'The linear system is singular !' )
77  end if
78 
79  ! If the pivot is in a row that is different than row i, that is if
80  ! k is different than i, we need to swap those two rows
81  if ( k .NE. i ) then
82  do j = 1,system_size
83  swap_a = a(i,j)
84  a(i,j) = a(k,j)
85  a(k,j) = swap_a
86  end do
87  swap_b = b(i)
88  b(i) = b(k)
89  b(k) = swap_b
90  end if
91 
92  ! Transform pivot to 1 by dividing the entire row
93  ! (right-hand side included) by the pivot
94  pivot = a(i,i)
95  do j = i,system_size
96  a(i,j) = a(i,j) / pivot
97  end do
98  b(i) = b(i) / pivot
99 
100  ! #INV: At this point, A(i,i) is a suitable pivot and it is equal to 1
101 
102  ! Put zeros in column for all rows below that containing
103  ! pivot (which is row i)
104  do k = (i+1),system_size ! k is the row index
105  factor = a(k,i)
106  do j = (i+1),system_size ! j is the column index
107  a(k,j) = a(k,j) - factor * a(i,j)
108  end do
109  b(k) = b(k) - factor * b(i)
110  end do
111 
112  end do ! end loop on i
113 
114 
115  ! Solve system by back substituting
116  x(system_size) = b(system_size) / a(system_size,system_size)
117  do i = system_size-1,1,-1 ! loop on rows, starting from second to last row
118  x(i) = b(i)
119  do j = (i+1),system_size
120  x(i) = x(i) - a(i,j) * x(j)
121  end do
122  x(i) = x(i) / a(i,i)
123  end do
124 
Here is the call graph for this function:
Here is the caller graph for this function:

◆ solve_tridiagonal_system()

subroutine, public regrid_solvers::solve_tridiagonal_system ( real, dimension(:), intent(inout)  Al,
real, dimension(:), intent(inout)  Ad,
real, dimension(:), intent(inout)  Au,
real, dimension(:), intent(inout)  B,
real, dimension(:), intent(inout)  X,
integer, intent(in)  system_size 
)

Definition at line 132 of file regrid_solvers.F90.

Referenced by regrid_edge_slopes::edge_slopes_implicit_h3(), regrid_edge_slopes::edge_slopes_implicit_h5(), regrid_edge_values::edge_values_implicit_h4(), and regrid_edge_values::edge_values_implicit_h6().

132 ! -----------------------------------------------------------------------------
133 ! This routine uses Thomas's algorithm to solve the tridiagonal system AX = B.
134 ! (A is made up of lower, middle and upper diagonals)
135 ! -----------------------------------------------------------------------------
136  ! Arguments
137  real, dimension(:), intent(inout) :: al, ad, au ! lo., mid. and up. diagonals
138  real, dimension(:), intent(inout) :: b ! system right-hand side
139  real, dimension(:), intent(inout) :: x ! solution vector
140  integer, intent(in) :: system_size
141 
142  ! Local variables
143  integer :: k ! Loop index
144  integer :: n ! system size
145 
146  n = system_size
147 
148  ! Factorization
149  do k = 1,n-1
150  al(k+1) = al(k+1) / ad(k)
151  ad(k+1) = ad(k+1) - al(k+1) * au(k)
152  end do
153 
154  ! Forward sweep
155  do k = 2,n
156  b(k) = b(k) - al(k) * b(k-1)
157  end do
158 
159  ! Backward sweep
160  x(n) = b(n) / ad(n)
161  do k = n-1,1,-1
162  x(k) = ( b(k) - au(k)*x(k+1) ) / ad(k)
163  end do
164 
Here is the caller graph for this function: