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