8 implicit none ;
private
10 public :: solve_linear_system, linear_solver, solve_tridiagonal_system, solve_diag_dominant_tridiag
19 subroutine solve_linear_system( A, R, X, N, answers_2018 )
20 integer,
intent(in) :: n
21 real,
dimension(N,N),
intent(inout) :: a
22 real,
dimension(N),
intent(inout) :: r
23 real,
dimension(N),
intent(inout) :: x
24 logical,
optional,
intent(in) :: answers_2018
26 real,
parameter :: eps = 0.0
28 real :: pivot, i_pivot
29 real :: swap_a, swap_b
30 logical :: found_pivot
31 logical :: old_answers
34 old_answers = .true. ;
if (
present(answers_2018)) old_answers = answers_2018
45 do while ( ( .NOT. found_pivot ) .AND. ( k <= n ) )
46 if ( abs( a(k,i) ) > eps )
then
54 if ( .NOT. found_pivot )
then
56 call mom_error( fatal,
'The linear system is singular !' )
63 swap_a = a(i,j) ; a(i,j) = a(k,j) ; a(k,j) = swap_a
65 swap_b = r(i) ; r(i) = r(k) ; r(k) = swap_b
71 do j = i,n ; a(i,j) = a(i,j) / pivot ;
enddo
74 i_pivot = 1.0 / a(i,i)
76 do j = i+1,n ; a(i,j) = a(i,j) * i_pivot ;
enddo
87 a(k,j) = a(k,j) - factor * a(i,j)
89 r(k) = r(k) - factor * r(i)
99 x(i) = x(i) - a(i,j) * x(j)
101 if (old_answers) x(i) = x(i) / a(i,i)
104 end subroutine solve_linear_system
111 subroutine linear_solver( N, A, R, X )
112 integer,
intent(in) :: n
113 real,
dimension(N,N),
intent(inout) :: a
114 real,
dimension(N),
intent(inout) :: r
115 real,
dimension(N),
intent(inout) :: x
118 real,
parameter :: eps = 0.0
122 logical :: found_pivot
129 do k=i,n ;
if ( abs( a(i,k) ) > eps )
exit ;
enddo
132 call mom_error( fatal,
'The linear system is singular !' )
138 do j=i,n ; swap = a(j,i) ; a(j,i) = a(j,k) ; a(j,k) = swap ;
enddo
139 swap = r(i) ; r(i) = r(k) ; r(k) = swap
143 i_pivot = 1.0 / a(i,i)
145 do j=i+1,n ; a(j,i) = a(j,i) * i_pivot ;
enddo
146 r(i) = r(i) * i_pivot
152 do j=i+1,n ; a(j,k) = a(j,k) - factor * a(j,i) ;
enddo
153 r(k) = r(k) - factor * r(i)
162 do j=i+1,n ; x(i) = x(i) - a(j,i) * x(j) ;
enddo
165 end subroutine linear_solver
172 subroutine solve_tridiagonal_system( Al, Ad, Au, R, X, N, answers_2018 )
173 integer,
intent(in) :: n
174 real,
dimension(N),
intent(in) :: ad
175 real,
dimension(N),
intent(in) :: al
176 real,
dimension(N),
intent(in) :: au
177 real,
dimension(N),
intent(in) :: r
178 real,
dimension(N),
intent(out) :: x
179 logical,
optional,
intent(in) :: answers_2018
181 real,
dimension(N) :: pivot, al_piv
182 real,
dimension(N) :: c1
185 logical :: old_answers
187 old_answers = .true. ;
if (
present(answers_2018)) old_answers = answers_2018
189 if (old_answers)
then
195 al_piv(k) = al(k) / pivot(k-1)
196 pivot(k) = ad(k) - al_piv(k) * au(k-1)
197 x(k) = r(k) - al_piv(k) * x(k-1)
201 x(n) = r(n) / pivot(n)
203 x(k) = ( x(k) - au(k)*x(k+1) ) / pivot(k)
210 i_pivot = 1.0 / ad(1)
211 x(1) = r(1) * i_pivot
213 c1(k-1) = au(k-1) * i_pivot
214 i_pivot = 1.0 / (ad(k) - al(k) * c1(k-1))
215 x(k) = (r(k) - al(k) * x(k-1)) * i_pivot
219 x(k) = x(k) - c1(k) * x(k+1)
224 end subroutine solve_tridiagonal_system
234 subroutine solve_diag_dominant_tridiag( Al, Ac, Au, R, X, N )
235 integer,
intent(in) :: n
236 real,
dimension(N),
intent(in) :: ac
237 real,
dimension(N),
intent(in) :: al
238 real,
dimension(N),
intent(in) :: au
239 real,
dimension(N),
intent(in) :: r
240 real,
dimension(N),
intent(out) :: x
242 real,
dimension(N) :: c1
250 i_pivot = 1.0 / (ac(1) + au(1))
252 c1(1) = au(1) * i_pivot
253 x(1) = r(1) * i_pivot
255 denom_t1 = ac(k) + d1 * al(k)
256 i_pivot = 1.0 / (denom_t1 + au(k))
257 d1 = denom_t1 * i_pivot
258 c1(k) = au(k) * i_pivot
259 x(k) = (r(k) - al(k) * x(k-1)) * i_pivot
261 i_pivot = 1.0 / (ac(n) + d1 * al(n))
262 x(n) = (r(n) - al(n) * x(n-1)) * i_pivot
265 x(k) = x(k) - c1(k) * x(k+1)
268 end subroutine solve_diag_dominant_tridiag