File: RELATIVE:/../../../mfix.git/model/leq_cg.f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 SUBROUTINE LEQ_CG(VNAME, VNO, VAR, A_M, B_m, cmethod, &
18 TOL, PC, ITMAX, IER)
19
20
21
22
23 USE param
24 USE param1
25 USE matrix
26 USE geometry
27 USE compar
28 USE indices
29 USE leqsol
30 USE funits
31 IMPLICIT NONE
32
33
34
35
36 CHARACTER(LEN=*), INTENT(IN) :: Vname
37
38 INTEGER, INTENT(IN) :: VNO
39
40
41
42
43 DOUBLE PRECISION, DIMENSION(ijkstart3:ijkend3), INTENT(INOUT) :: Var
44
45 DOUBLE PRECISION, DIMENSION(ijkstart3:ijkend3,-3:3), INTENT(INOUT) :: A_m
46
47 DOUBLE PRECISION, DIMENSION(ijkstart3:ijkend3), INTENT(INOUT) :: B_m
48
49
50
51 CHARACTER(LEN=*), INTENT(IN) :: CMETHOD
52
53 DOUBLE PRECISION, INTENT(IN) :: TOL
54
55
56 CHARACTER(LEN=4), INTENT(IN) :: PC
57
58 INTEGER, INTENT(IN) :: ITMAX
59
60 INTEGER, INTENT(INOUT) :: IER
61
62
63 if(PC.eq.'LINE') then
64 call LEQ_CG0( Vname, Vno, Var, A_m, B_m, &
65 cmethod, TOL, ITMAX, LEQ_MATVEC, LEQ_MSOLVE, IER )
66 elseif(PC.eq.'DIAG') then
67 call LEQ_CG0( Vname, Vno, Var, A_m, B_m, &
68 cmethod, TOL, ITMAX, LEQ_MATVEC, LEQ_MSOLVE1, IER )
69 elseif(PC.eq.'NONE') then
70 call LEQ_CG0( Vname, Vno, Var, A_m, B_m, &
71 cmethod, TOL, ITMAX, LEQ_MATVEC, LEQ_MSOLVE0, IER )
72 else
73 IF(DMP_LOG)WRITE (UNIT_LOG,*) &
74 'preconditioner option not found - check mfix.dat and readme'
75 call mfix_exit(myPE)
76 endif
77
78 return
79 END SUBROUTINE LEQ_CG
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 SUBROUTINE LEQ_CG0(VNAME, VNO, VAR, A_M, B_m, cmethod, &
98 TOL, ITMAX, MATVEC, MSOLVE, IER )
99
100
101
102
103 USE param
104 USE param1
105 USE parallel
106 USE matrix
107 USE geometry
108 USE compar
109 USE mpi_utility
110 USE sendrecv
111 USE indices
112 USE leqsol
113 USE functions
114 IMPLICIT NONE
115
116
117
118
119 CHARACTER(LEN=*), INTENT(IN) :: Vname
120
121 INTEGER, INTENT(IN) :: VNO
122
123
124
125
126 DOUBLE PRECISION, INTENT(INOUT) :: Var(ijkstart3:ijkend3)
127
128 DOUBLE PRECISION, INTENT(INOUT) :: A_m(ijkstart3:ijkend3,-3:3)
129
130 DOUBLE PRECISION, INTENT(INOUT) :: B_m(ijkstart3:ijkend3)
131
132
133 CHARACTER(LEN=*), INTENT(IN) :: CMETHOD
134
135 DOUBLE PRECISION, INTENT(IN) :: TOL
136
137 INTEGER, INTENT(IN) :: ITMAX
138
139 INTEGER, INTENT(INOUT) :: IER
140
141
142
143
144
145
146
147
148
149 INTEGER, PARAMETER :: idebugl = 0
150 DOUBLE PRECISION, PARAMETER :: ratiotol = 0.2
151 logical, parameter :: do_unit_scaling = .true.
152
153
154
155 DOUBLE PRECISION, DIMENSION(ijkstart3:ijkend3) :: &
156 R, P, Zvec, Q
157 DOUBLE PRECISION, DIMENSION(0:ITMAX+1) :: &
158 alpha, beta, rho
159 DOUBLE PRECISION :: RxZ, PxQ, oam
160 DOUBLE PRECISION :: Rnorm, Rnorm0, TOLMIN
161 LOGICAL :: isconverged
162 INTEGER :: i, j, k, ijk
163 INTEGER :: iter
164
165
166 = numPEs.eq.1.and.is_serial
167
168
169 = ZERO
170 rnorm0 = ZERO
171
172
173 (:) = zero
174 beta(:) = zero
175 rho(:) = zero
176
177
178
179
180 if (use_doloop) then
181
182 do ijk=ijkstart3,ijkend3
183 R(ijk) = zero
184 Zvec(ijk) = zero
185 P(ijk) = zero
186 Q(ijk) = zero
187 enddo
188 else
189 R(:) = zero
190 Zvec(:) = zero
191 P(:) = zero
192 Q(:) = zero
193 endif
194
195 TOLMIN = EPSILON( one )
196
197
198
199 if (do_unit_scaling) then
200
201 do k = kstart2,kend2
202 do i = istart2,iend2
203 do j = jstart2,jend2
204 IJK = funijk(i,j,k)
205
206
207
208 = one/A_M(ijk,0)
209 A_M(IJK,:) = A_M(IJK,:)*OAM
210 B_M(IJK) = B_M(IJK)*OAM
211 enddo
212 enddo
213 enddo
214 endif
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231 if (idebugl >= 1) then
232 if(myPE.eq.0) print*,'leq_cg, initial: ', Vname,' resid ', Rnorm0
233 endif
234
235
236
237
238 call MATVEC(Vname, Var, A_M, R)
239
240 if (use_doloop) then
241
242 do ijk=ijkstart3,ijkend3
243 R(ijk) = B_m(ijk) - R(ijk)
244 enddo
245 else
246 R(:) = B_m(:) - R(:)
247 endif
248
249 if(is_serial) then
250 Rnorm0 = zero
251 if (use_doloop) then
252
253 do ijk=ijkstart3,ijkend3
254 Rnorm0 = Rnorm0 + R(ijk)*R(ijk)
255 enddo
256 else
257 Rnorm0 = dot_product(R,R)
258 endif
259 Rnorm0 = sqrt( Rnorm0 )
260 else
261 Rnorm0 = sqrt( dot_product_par( R, R ) )
262 endif
263
264 if (idebugl >= 1) then
265 if(myPE.eq.0) print*,'leq_cg, initial: ', Vname,' resid ', Rnorm0
266 endif
267
268
269
270
271
272 = 1
273 do i=1,itmax
274
275
276 call MSOLVE( Vname, R, A_m, Zvec, CMETHOD)
277
278
279
280 if(is_serial) then
281 if (use_doloop) then
282 RxZ = zero
283
284 do ijk=ijkstart3,ijkend3
285 RxZ = RxZ + R(ijk) * Zvec(ijk)
286 enddo
287 rho(i-1) = RxZ
288 else
289 rho(i-1) = dot_product( R, Zvec )
290 endif
291 else
292 rho(i-1) = dot_product_par( R, Zvec )
293 endif
294
295
296 if (rho(i-1) .eq. zero) then
297 if(i /= 1)then
298
299
300 = -2
301 else
302
303
304 = 0
305 endif
306 call send_recv(var,2)
307 return
308 endif
309
310 if (i .eq. 1) then
311
312
313 if (use_doloop) then
314
315 do ijk=ijkstart3,ijkend3
316 P(ijk) = Zvec(ijk)
317 enddo
318 else
319 P(:) = Zvec(:)
320 endif
321 else
322
323
324
325 (i-1) = ( rho(i-1)/rho(i-2) )
326 if (use_doloop) then
327
328 do ijk=ijkstart3,ijkend3
329 P(ijk) = Zvec(ijk) + beta(i-1)* P(ijk)
330 enddo
331 else
332 P(:) = Zvec(:) + beta(i-1)*P(:)
333 endif
334 endif
335
336
337
338 call MATVEC(Vname, P, A_m, Q)
339
340 if(is_serial) then
341 if (use_doloop) then
342 PxQ = zero
343
344 do ijk=ijkstart3,ijkend3
345 PxQ = PxQ + P(ijk) * Q(ijk)
346 enddo
347 else
348 PxQ = dot_product( P, Q )
349 endif
350 else
351 PxQ = dot_product_par( P, Q )
352 endif
353
354
355
356 (i) = rho(i-1)/PxQ
357
358
359
360
361 if (use_doloop) then
362
363 do ijk=ijkstart3,ijkend3
364 R(ijk) = R(ijk) - alpha(i) * Q(ijk)
365 Var(ijk) = Var(ijk) + alpha(i) * P(ijk)
366 enddo
367 else
368 R(:) = R(:) - alpha(i) * Q(:)
369 Var(:) = Var(:) + alpha(i) * P(:)
370 endif
371
372
373
374 if(is_serial) then
375 if (use_doloop) then
376 Rnorm = zero
377
378 do ijk=ijkstart3,ijkend3
379 Rnorm = Rnorm + R(ijk) * R(ijk)
380 enddo
381 else
382 Rnorm = dot_product( R, R )
383 endif
384 Rnorm = sqrt( Rnorm )
385 else
386 Rnorm = sqrt( dot_product_par( R, R ) )
387 endif
388
389 if (idebugl.ge.1) then
390 print*,'leq_cs, initial: ', Vname,' Vnorm ', Rnorm
391 if (myPE.eq.PE_IO) then
392 print*,'iter, Rnorm ', iter, Rnorm
393 print*,'PxQ, rho(i-1) ', PxQ, rho(i-1)
394 print*,'alpha(i), beta(i-1) ', alpha(i), beta(i-1)
395 endif
396 endif
397
398 isconverged = (Rnorm <= TOL*Rnorm0)
399
400 if (isconverged) then
401 iter_tot(vno) = iter_tot(vno) + iter + 1
402 EXIT
403 endif
404
405
406 = iter + 1
407
408 enddo
409
410
411
412
413 if (idebugl >= 1) then
414 call MATVEC( Vname, Var, A_m, R )
415 if (use_doloop) then
416
417 do ijk=ijkstart3,ijkend3
418 R(ijk) = R(ijk) - B_m(ijk)
419 enddo
420 else
421 R(:) = R(:) - B_m(:)
422 endif
423
424 if(is_serial) then
425 if (use_doloop) then
426 Rnorm = zero
427
428 do ijk=ijkstart3,ijkend3
429 Rnorm = Rnorm + R(ijk) * R(ijk)
430 enddo
431 else
432 Rnorm = dot_product( R,R)
433 endif
434 Rnorm = sqrt( Rnorm )
435 else
436 Rnorm = sqrt( dot_product_par( R,R) )
437 endif
438
439 if(myPE.eq.0) print*,'leq_cg: final Rnorm ', Rnorm
440
441 if(myPE.eq.0) print*,'leq_cg ratio : ', Vname,' ',iter, &
442 ' L-2', Rnorm/Rnorm0
443 endif
444
445 IER = 0
446 if (.not.isconverged) then
447 IER = -1
448 iter_tot(vno) = iter_tot(vno) + iter
449 if (real(Rnorm) >= ratiotol*real(Rnorm0)) then
450 IER = -2
451 endif
452 endif
453
454 call send_recv(var,2)
455
456 return
457 end subroutine LEQ_CG0
458