FE-Project
Loading...
Searching...
No Matches
scale_linalgebra.F90
Go to the documentation of this file.
1
10#include "scaleFElib.h"
12 !-----------------------------------------------------------------------------
13 !
14 !++ used modules
15 !
16 use scale_precision
17 use scale_io
18 use scale_prc
19 use scale_sparsemat, only: sparsemat
20
21 !-----------------------------------------------------------------------------
22 implicit none
23 private
24
25 !-----------------------------------------------------------------------------
26 !
27 !++ Public procedure
28 !
29
30 public :: linalgebra_lu
31 public :: linalgebra_inv
33 module procedure linalgebra_solvelineq_b1d
34 module procedure linalgebra_solvelineq_b2d
35 end interface
36 public :: linalgebra_solvelineq
38
39
40 !-----------------------------------------------------------------------------
41 !
42 !++ Public parameters & variables
43 !
44
45 !-----------------------------------------------------------------------------
46 !
47 !++ Private procedure
48 !
49
50 !-----------------------------------------------------------------------------
51 !
52 !++ Private parameters & variables
53 !
54
55 !-----------------------------------------------------------------------------
56
57 ! Private procedure
58 !
59
60 ! Private variable
61 !
62
63contains
64
65!OCL SERIAL
66 function linalgebra_inv(A) result(Ainv)
67
68 real(rp), intent(in) :: a(:,:)
69 real(rp) :: ainv(size(a,1),size(a,2))
70
71 real(rp) :: work(size(a,1))
72 integer :: ipiv(size(a,1))
73 integer :: n, info
74
75 !---------------------------------------------------------------------------
76
77 ainv(:,:) = a
78 n = size(a,1)
79
80 call dgetrf(n, n, ainv, n, ipiv, info)
81 if (info /=0 ) then
82 log_error("linalgebra_inv",*) "Matrix is singular"
83 call prc_abort
84 end if
85
86 call dgetri(n, ainv, n, ipiv, work, n, info)
87 if (info /=0 ) then
88 log_error("linalgebra_inv",*) "Matrix inversion is failed"
89 call prc_abort
90 end if
91
92 return
93 end function linalgebra_inv
94
95!OCL SERIAL
96 subroutine linalgebra_solvelineq_b1d(A, b, x)
97
98 real(RP), intent(in) :: A(:,:)
99 real(RP), intent(in) :: b(:)
100 real(RP), intent(out) :: x(size(b))
101
102 real(RP) :: A_lu(size(A,1),size(A,2))
103 integer :: ipiv(size(A,1))
104 integer :: n, info
105
106 !---------------------------------------------------------------------------
107
108 a_lu = a
109 n = size(a,1)
110
111 call dgetrf(n, n, a_lu, n, ipiv, info)
112 if (info /=0 ) then
113 log_error("linalgebra_SolveLinEq",*) "Matrix is singular"
114 call prc_abort
115 end if
116
117 x(:) = b
118 call dgetrs('N', n, 1, a_lu, n, ipiv, x, n, info)
119 if (info /=0 ) then
120 log_error("linalgebra_SolveLinEq",*) "Matrix inversion is failed"
121 call prc_abort
122 end if
123
124 return
125 end subroutine linalgebra_solvelineq_b1d
126
127!OCL SERIAL
128 subroutine linalgebra_solvelineq_b2d(A, b, x)
129
130 real(RP), intent(in) :: A(:,:)
131 real(RP), intent(in) :: b(:,:)
132 real(RP), intent(out) :: x(size(b,1),size(b,2))
133
134 real(RP) :: A_lu(size(A,1),size(A,2))
135 integer :: ipiv(size(A,1))
136 integer :: n, info
137
138 !---------------------------------------------------------------------------
139
140 a_lu = a
141 n = size(a,1)
142
143 call dgetrf(n, n, a_lu, n, ipiv, info)
144 if (info /=0 ) then
145 log_error("linalgebra_SolveLinEq",*) "Matrix is singular"
146 call prc_abort
147 end if
148
149 x(:,:) = b
150 call dgetrs('N', n, size(b,2), a_lu, n, ipiv, x, n, info)
151 if (info /=0 ) then
152 log_error("linalgebra_SolveLinEq",*) "Matrix inversion is failed"
153 call prc_abort
154 end if
155
156 return
157 end subroutine linalgebra_solvelineq_b2d
158
159!OCL SERIAL
160 subroutine linalgebra_lu(A_lu, ipiv)
161
162 real(rp), intent(inout) :: a_lu(:,:)
163 integer, intent(out) :: ipiv(size(a_lu,1))
164
165 integer :: n
166 integer :: info
167
168 !---------------------------------------------------------------------------
169 n = size(a_lu,1)
170
171 call dgetrf(n, n, a_lu, n, ipiv, info)
172 if (info /=0 ) then
173 log_error("linalgebra_LU",*) "Matrix is singular"
174 call prc_abort
175 end if
176
177 return
178 end subroutine linalgebra_lu
179
180 subroutine linalgebra_solvelineq_gmres(A, b, x, m, restart_num, CONV_CRIT)
181
183 implicit none
184
185 type(sparsemat), intent(in) :: a
186 real(rp), intent(in) :: b(:)
187 real(rp), intent(inout) :: x(:)
188 integer, intent(in) :: m
189 integer, intent(in) ::restart_num
190 real(rp), intent(in) :: conv_crit
191
192 real(rp) :: x0(size(x))
193 real(rp) :: w(size(x))
194 real(rp) :: v(size(x),m+1)
195 real(rp) :: z(size(x),m+1)
196 real(rp) :: av(size(x))
197 real(rp) :: g(size(x)+1)
198 real(rp) :: r0_l2, r0_l2_new
199 real(rp) :: h(m+1,m)
200 real(rp) :: r(m,m)
201 real(rp) :: c(m), s(m)
202 real(rp) :: y(m)
203 real(rp) :: tmp, tmp1, tmp2
204 integer :: i, j
205 integer :: restart_i
206
207 type(sparsemat) :: m_pc
208
209 !---------------------------------------------------------------------------
210
211 call precondstep_ilu0_constructmat(a, m_pc)
212 x0(:) = x
213
214 do restart_i=1, restart_num
215
216 if (restart_i == 1) then
217 call sparsemat_matmul(a, x, av)
218 v(:,1) = b - av
219 r0_l2 = sqrt(sum(v(:,1)**2))
220 end if
221 v(:,1) = v(:,1)/r0_l2
222 g(1) = r0_l2
223
224 do j=1, m
225
226 call precondstep_ilu0_solve(m_pc, v(:,j), z(:,j))
227
228 call sparsemat_matmul(a, z(:,j), w)
229
230 do i=1, j
231 h(i,j) = sum(w*v(:,i))
232 w(:) = w - h(i,j)*v(:,i)
233 end do
234 h(j+1,j) = sqrt(sum(w**2))
235 v(:,j+1) = w(:)/h(j+1,j)
236
237 r(1,j) = h(1,j)
238 do i=1, j-1
239 tmp1 = c(i)*r(i,j) + s(i)*h(i+1,j)
240 tmp2 = -s(i)*r(i,j) + c(i)*h(i+1,j)
241 r(i,j) = tmp1
242 r(i+1,j) = tmp2
243 end do
244
245 tmp = sqrt(r(j,j)**2 + h(j+1,j)**2)
246 c(j) = r(j,j)/tmp
247 s(j) = h(j+1,j)/tmp
248
249 g(j+1) = -s(j)*g(j)
250 g(j) = c(j)*g(j)
251 r(j,j) = c(j)*r(j,j) + s(j)*h(j+1,j)
252 end do
253
254 y(m) = g(m)/r(m,m)
255 do i=m-1,1,-1
256 y(i) = (g(i) - sum(r(i,i+1:m)*y(i+1:m)))/r(i,i)
257 end do
258
259 x(:) = x + matmul(z(:,1:m),y)
260
261 !write(*,*) "x:", x
262 !write(*,*) "x0:", x0
263
264 call sparsemat_matmul(a, x, av)
265 v(:,1) = b - av
266 r0_l2_new = sqrt(sum(v(:,1)**2))
267
268 !write(*,*) "r:", r0_l2, "->", r0_l2_new
269 if (r0_l2_new < conv_crit) exit
270 r0_l2 = r0_l2_new
271 end do
272
273 return
274 end subroutine linalgebra_solvelineq_gmres
275
276 subroutine precondstep_ptjacobi(A, b, x)
277 implicit none
278 type(sparsemat), intent(in) :: a
279 real(rp), intent(in) :: b(:)
280 real(rp), intent(out) :: x(size(b))
281
282 integer :: n
283 !---------------------------------------------------------------------------
284
285 do n=1, size(x)
286 x(n) = b(n) / a%GetVal(n, n)
287 end do
288
289 return
290 end subroutine precondstep_ptjacobi
291
292 subroutine precondstep_ilu0_constructmat(A, M)
293 use scale_const, only: &
294 eps => const_eps
295 implicit none
296
297 type(sparsemat), intent(in) :: a
298 type(sparsemat), intent(inout) :: m
299
300 integer :: i, j, k, n
301 real(rp) :: mij, m_ik, m_kk
302 !---------------------------------------------------------------------------
303
304 n = a%rowPtrSize-1
305
306 m = a
307 do i=2, n
308 do k=1, i-1
309 m_ik = m%GetVal(i,k)
310 m_kk = m%GetVal(k,k)
311 if ( abs(m_ik) < eps .and. abs(m_kk) < eps ) then
312 m_ik = m_ik / m_kk
313 call m%ReplaceVal( i, k, m_ik )
314
315 do j=k+1, n
316 mij = m%GetVal(i,j)
317 if ( abs(mij) < eps ) then
318 call m%ReplaceVal( i, j, mij - m%GetVal(i,k) * m%GetVal(k,j) )
319 end if
320 end do
321 end if
322 end do
323 end do
324
325 return
326 end subroutine precondstep_ilu0_constructmat
327
328 subroutine precondstep_ilu0_solve(M, b, x)
329 use scale_sparsemat, only: &
331 implicit none
332
333 type(sparsemat), intent(in) :: m
334 real(rp), intent(in) :: b(:)
335 real(rp), intent(out) :: x(size(b))
336
337 integer :: i
338 integer :: j
339 integer :: n
340
341 integer :: j1, j2
342 !---------------------------------------------------------------------------
343
344 if ( m%GetStorageFormatId() /= sparsemat_storage_typeid_csr ) then
345 log_error("linalgebra_PreCondStep_ILU0_solve",*) "The strorge type of specified sparse matrix is not supported. Check!"
346 call prc_abort
347 end if
348
349 n = size(x)
350
351 x(1) = b(1)
352 do i=2, n
353 j1 = m%rowPtr(i)
354 j2 = m%rowPtr(i+1)-1
355 x(i) = b(i)
356 do j=j1, j2
357 if (m%colIdx(j) <= i-1) &
358 x(i) = x(i) - m%val(j)*x(m%colIdx(j))
359 end do
360 end do
361
362 x(n) = x(n) / m%GetVal(n,n)
363 do i=n-1, 1, -1
364 j1 = m%rowPtr(i)
365 j2 = m%rowPtr(i+1)-1
366 do j=j1, j2
367 if (m%colIdx(j) >= i+1) &
368 x(i) = x(i) - m%val(j)*x(m%colIdx(j))
369 end do
370 x(i) = x(i)/m%GetVal(i,i)
371 end do
372
373 return
374 end subroutine precondstep_ilu0_solve
375
376end module scale_linalgebra
module common / Linear algebra
real(rp) function, dimension(size(a, 1), size(a, 2)), public linalgebra_inv(a)
subroutine, public linalgebra_solvelineq_gmres(a, b, x, m, restart_num, conv_crit)
subroutine, public linalgebra_lu(a_lu, ipiv)
module common / sparsemat
integer, parameter, public sparsemat_storage_typeid_csr