68 INTEGER,
PARAMETER :: dp = selected_real_kind(12,100)
71 INTEGER :: iterOut, jH,
72 & retlbl=0, j, northo, comprsd
73 REAL(dp) :: dnormres, beta, bn, sA, sb, sPA, sPb,
74 & dloo, dnormx, truenormres, bea, be
77 SUBROUTINE drive_dgmres(n,nloc,m,lwork,work,
78 & irc,icntl,cntl,info,rinfo)
79 USE gmres_dim,
ONLY: dp, icheck
212 INTEGER,
INTENT(IN) :: n, nloc, lwork
213 REAL(dp),
INTENT(IN) :: cntl(5)
214 REAL(dp) sA, sb, sPA, sPb
217 integer,
INTENT(OUT) :: info(3)
218 REAL(dp),
INTENT(OUT) :: rinfo(2)
221 integer,
INTENT(INOUT) :: icntl(9), irc(5), m
222 REAL(dp),
INTENT(INOUT) :: work(lwork)
225 integer xptr, bptr, wptr, r0ptr, Vptr, Hptr, dotptr
226 integer yCurrent,rotSin, rotCos, xCurrent
227 integer sizeWrk, newRestart
228 integer iwarn, ierr, ihist, compRsd
231 REAL(dp),
PARAMETER :: DZRO=0
244 if (ierr.lt.0) ierr = 6
246 if (comprsd.eq.1)
then
247 sizewrk = m*m + m*(nloc+5) + 5*nloc+ 1
249 sizewrk = m*m + m*(nloc+5) + 6*nloc+ 1
252 if (icheck.eq.0)
then
254 if ((n.lt.1).or.(nloc.lt.1))
then
256 write(ierr,*)
' ERROR GMRES : '
257 write(ierr,*)
' N < 1 '
265 write(ierr,*)
' ERROR GMRES :'
266 write(ierr,*)
' M < 1 '
272 if ((icntl(4).ne.0).and.(icntl(4).ne.1).and.
273 & (icntl(4).ne.2).and.(icntl(4).ne.3))
then
275 write(ierr,*)
' ERROR GMRES : '
276 write(ierr,*)
' Undefined preconditioner '
283 if ((icntl(5).lt.0).or.(icntl(5).gt.3))
then
287 write(iwarn,*)
' WARNING GMRES : '
288 write(iwarn,*)
' Undefined orthogonalisation '
289 write(iwarn,*)
' Default MGS '
294 if ((icntl(5).eq.2).or.(icntl(5).eq.3))
then
296 sizewrk = sizewrk + m
298 sizewrk = sizewrk + 1
303 write(iwarn,*)
' WARNING GMRES : '
304 write(iwarn,*)
' For M = ',m,
' optimal value '
305 write(iwarn,*)
' for LWORK = ', sizewrk
309 if ((icntl(6).ne.0).and.(icntl(6).ne.1))
then
313 write(iwarn,*)
' WARNING GMRES : '
314 write(iwarn,*)
' Undefined intial guess '
315 write(iwarn,*)
' Default x0 = 0 '
319 if (icntl(7).le.0)
then
323 write(iwarn,*)
' WARNING GMRES :'
324 write(iwarn,*)
' Negative max number of iterations'
325 write(iwarn,*)
' Default N '
329 if ((icntl(8).ne.0).and.(icntl(8).ne.1))
then
332 write(iwarn,*)
' WARNING GMRES :'
333 write(iwarn,*)
' Undefined strategy for the residual'
334 write(iwarn,*)
' at restart'
335 write(iwarn,*)
' Default 1 '
342 if ((m .gt. n).or.(lwork.lt.sizewrk))
then
347 write(iwarn,*)
' WARNING GMRES : '
348 write(iwarn,*)
' Parameter M bigger than N'
349 write(iwarn,*)
' New value for M ',m
352 if (comprsd.eq.1)
then
353 sizewrk = m*m + m*(nloc+5) + 5*nloc+1
355 sizewrk = m*m + m*(nloc+5) + 6*nloc+1
357 if ((icntl(5).eq.2).or.(icntl(5).eq.3))
then
359 sizewrk = sizewrk + m
361 sizewrk = sizewrk + 1
364 if ((lwork.lt.sizewrk).and.(n.eq.nloc))
then
371 if ((icntl(5).eq.2).or.(icntl(5).eq.3))
then
376 if (icntl(8).eq.0)
then
380 newrestart = int((-rx+sqrt(rx*rx-4*rc))/2._dp)
382 if (newrestart.gt.0)
then
386 write(iwarn,*)
' WARNING GMRES : '
387 write(iwarn,*)
' Workspace too small for M'
388 write(iwarn,*)
' New value for M ',m
393 write(ierr,*)
' ERROR GMRES : '
394 write(ierr,*)
' Not enough space for the problem'
395 write(ierr,*)
' the space does not permit any m'
402 if ((lwork.lt.sizewrk).and.(n.ne.nloc))
then
404 write(ierr,*)
' ERROR GMRES : '
405 write(ierr,*)
' Not enough space for the problem'
419 write(ihist,
'(10x,A39)')
'CONVERGENCE HISTORY FOR GMRES'
421 write(ihist,
'(A30,I2)')
'Errors are displayed in unit: ',ierr
423 write(ihist,
'(A27)')
'Warnings are not displayed:'
425 write(ihist,
'(A32,I2)')
'Warnings are displayed in unit: ',
428 write(ihist,
'(A13,I7)')
'Matrix size: ',n
429 write(ihist,
'(A19,I7)')
'Local matrix size: ',nloc
430 write(ihist,
'(A9,I7)')
'Restart: ',m
431 if (icntl(4).eq.0)
then
432 write(ihist,
'(A18)')
'No preconditioning'
433 elseif (icntl(4).eq.1)
then
434 write(ihist,
'(A20)')
'Left preconditioning'
435 elseif (icntl(4).eq.2)
then
436 write(ihist,
'(A21)')
'Right preconditioning'
437 elseif (icntl(4).eq.3)
then
438 write(ihist,
'(A30)')
'Left and right preconditioning'
440 if (icntl(5).eq.0)
then
441 write(ihist,
'(A21)')
'Modified Gram-Schmidt'
442 elseif (icntl(5).eq.1)
then
443 write(ihist,
'(A31)')
'Iterative modified Gram-Schmidt'
444 elseif (icntl(5).eq.2)
then
445 write(ihist,
'(A22)')
'Classical Gram-Schmidt'
447 write(ihist,
'(A32)')
'Iterative classical Gram-Schmidt'
449 if (icntl(6).eq.0)
then
450 write(ihist,
'(A29)')
'Default initial guess x_0 = 0'
452 write(ihist,
'(A27)')
'User supplied initial guess'
454 if (icntl(8).eq.1)
then
455 write(ihist,
'(A33)')
'True residual computed at restart'
457 write(ihist,
'(A30)')
'Recurrence residual at restart'
459 write(ihist,
'(A30,I5)')
'Maximum number of iterations: ',
461 write(ihist,
'(A27,E8.2)')
'Tolerance for convergence: ',
465 &
'Backward error on the unpreconditioned system Ax = b:'
468 if ((sa.eq.dzro).and.(sb.eq.dzro))
then
470 &
' the residual is normalised by ||b||'
473 1
format(
' the residual is normalised by ',e8.2,
474 &
' !*||x|| + ',e8.2)
479 2
format(
'Backward error on the preconditioned system',
480 &
' (P1)A(P2)y = (P1)b:')
481 if ((spa.eq.dzro).and.(spb.eq.dzro))
then
483 3
format(
' the preconditioned residual is normalised ',
486 write(ihist,4) spa, spb
487 4
format(
' the preconditioned residual is normalised by ', e8.2,
488 &
' !*||(P2)y|| + ',e8.2)
491 write(ihist,5) info(3)
492 5
format(
'Optimal size for the local workspace:',i7)
495 6
format(
'Convergence history: b.e. on the preconditioned system')
497 7
format(
' Iteration Arnoldi b.e. True b.e.')
507 if (comprsd.eq.1)
then
510 hptr = vptr + (m+1)*nloc
512 dotptr = hptr + (m+1)*(m+1)
513 if ((icntl(5).eq.2).or.(icntl(5).eq.3))
then
514 ycurrent = dotptr + m
516 ycurrent = dotptr + 1
518 xcurrent = ycurrent + m
519 rotsin = xcurrent + nloc
522 call dgmres(nloc,m,work(bptr),work(xptr),
523 & work(hptr),work(wptr),work(r0ptr),work(vptr),
524 & work(dotptr),work(ycurrent),work(xcurrent),
525 & work(rotsin),work(rotcos),irc,icntl,cntl,info,rinfo)
527 if (irc(1).eq.0)
then
534 subroutine dgmres(n,m,b,x,H,w,r0,V,dot,yCurrent,xCurrent,rotSin,
535 & rotCos,irc,icntl,cntl,info,rinfo)
702 integer,
INTENT(IN) :: n, m, icntl(9)
703 REAL(dp),
INTENT(IN) :: b(n), cntl(5)
707 integer,
INTENT(OUT) :: info(3)
708 REAL(dp),
INTENT(OUT) :: rinfo(2)
712 integer,
INTENT(INOUT) :: irc(5)
713 REAL(dp),
INTENT(INOUT) :: x(n), H(m+1,m+1), w(n), r0(n)
714 REAL(dp) :: V(n,m), dot(*), yCurrent(m)
715 REAL(dp) :: xCurrent(n), rotSin(m), rotCos(m)
719 INTEGER iterMax, initGuess, iOrthog
720 integer xptr, bptr, wptr, r0ptr, Vptr, Hptr, yptr, xcuptr
722 integer typePrec, iwarn, ihist
723 REAL(dp) temp, dnormw
725 REAL(dp) auxHjj, auxHjp1j
727 integer,
parameter :: noPrec = 0, leftprec = 1, rightprec = 2,
728 & dbleprec = 3, peek = 5
730 REAL(dp),
PARAMETER :: ZERO=0, one=1
732 REAL(dp),
PARAMETER :: DZRO=0, done=1
750 integer,
parameter :: matvec=1, precondleft=2, precondright=3,
768 if (icntl(8).eq.1)
then
771 hptr = vptr + (m+1)*n
773 dotptr = hptr + (m+1)*(m+1)
774 if ((icntl(5).eq.2).or.(icntl(5).eq.3))
then
788 if (retlbl.eq.0)
then
793 if (itmod .eq. 0) itmod = huge(itmod)-1
795 if (retlbl.ne.0)
then
796 if (retlbl.eq.5)
then
798 else if (retlbl.eq.6)
then
800 else if (retlbl.eq.8)
then
802 else if (retlbl.eq.11)
then
804 else if (retlbl.eq.16)
then
806 else if (retlbl.eq.18)
then
808 else if (retlbl.eq.21)
then
810 else if (retlbl.eq.26)
then
812 else if (retlbl.eq.31)
then
814 else if (retlbl.eq.32)
then
816 else if (retlbl.eq.33)
then
818 else if (retlbl.eq.34)
then
820 else if (retlbl.eq.36)
then
822 else if (retlbl.eq.37)
then
824 else if (retlbl.eq.38)
then
826 else if (retlbl.eq.41)
then
828 else if (retlbl.eq.43)
then
830 else if (retlbl.eq.46)
then
832 else if (retlbl.eq.48)
then
834 else if (retlbl.eq.51)
then
836 else if (retlbl.eq.52)
then
838 else if (retlbl.eq.61)
then
840 else if (retlbl.eq.66)
then
842 else if (retlbl.eq.68)
then
845 else if (retlbl.eq.69)
then
857 if (initguess.eq.0)
then
881 write(iwarn,*)
' WARNING GMRES : '
882 write(iwarn,*)
' Null right hand side'
883 write(iwarn,*)
' solution set to zero'
889 write(ihist,
'(I5,11x,E8.2,$)') jh,bea
890 write(ihist,
'(7x,E8.2)') be
905 if ((sa.eq.dzro).and.(sb.eq.dzro))
then
913 if ((spa.eq.dzro).and.(spb.eq.dzro))
then
914 if ((typeprec.eq.noprec).or.(typeprec.eq.rightprec))
then
925 if ((spa.eq.dzro).and.(spb.eq.dzro))
then
926 if ((typeprec.eq.dbleprec).or.(typeprec.eq.leftprec))
then
940 if ((spa.eq.dzro).and.(spb.eq.dzro))
then
941 if ((typeprec.eq.dbleprec).or.(typeprec.eq.leftprec))
then
953 if (initguess.ne.0)
then
961 if (initguess.ne.0)
then
966 call dcopy(n,b,1,r0,1)
972 if ((typeprec.eq.noprec).or.(typeprec.eq.rightprec))
then
973 call dcopy(n,r0,1,w,1)
995 beta = sqrt((dot(1)))
997 if (beta .eq. dzro)
then
1008 write(ihist,
'(I5,11x,E8.2,$)') jh,bea
1009 write(ihist,
'(7x,E8.2)') be
1010 if (iwarn.ne.0)
then
1012 write(iwarn,*)
' WARNING GMRES : '
1013 write(iwarn,*)
' Intial residual is zero'
1014 write(iwarn,*)
' initial guess is solution'
1024 call daxpy(n,aux,w,1,v(1,1),1)
1051 if ((typeprec.eq.rightprec).or.(typeprec.eq.dbleprec))
then
1055 irc(1) = precondright
1056 irc(2) = vptr + (jh-1)*n
1061 call dcopy(n,v(1,jh),1,w,1)
1076 if ((typeprec.eq.noprec).or.(typeprec.eq.rightprec))
then
1077 call dcopy(n,r0,1,w,1)
1079 irc(1) = precondleft
1099 if ((iorthog.eq.0).or.(iorthog.eq.1))
then
1108 if ((iorthog.eq.0).or.(iorthog.eq.1))
then
1113 irc(2) = vptr + (j-1)*n
1121 if ((iorthog.eq.0).or.(iorthog.eq.1))
then
1123 h(j,jh) = h(j,jh) + dvi
1124 dloo = dloo + dvi**2
1126 call daxpy(n,aux,v(1,j),1,w,1)
1128 if (j.le.jh)
goto 23
1145 if ((iorthog.eq.2).or.(iorthog.eq.3))
then
1147 call daxpy(jh,one,dot,1,h(1,jh),1)
1148 call dgemv(
'N',n,jh,-one,v(1,1),n,dot,1,one,w,1)
1149 dloo = dnrm2(jh,dot,1)**2
1162 dnormw = sqrt((dot(1)))
1164 if ((iorthog.eq.1).or.(iorthog.eq.3))
then
1168 if (((2*dnormw).le.dloo).and.(northo.lt.3))
then
1174 if ((jh.lt.m).or.(icntl(8).eq.0))
then
1179 call daxpy(n,aux,w,1,v(1,jh+1),1)
1183 call drot(1, h(j,jh), 1, h(j+1,jh), 1,(rotcos(j)),
1187 auxhjp1j= h(jh+1,jh)
1188 call drotg(auxhjj, auxhjp1j,temp,rotsin(jh))
1191 call drot(1, h(jh,m+1), 1, h(jh+1,m+1), 1, (rotcos(jh)),
1198 call drot(1, h(jh,jh), 1, h(jh+1,jh), 1, (rotcos(jh)),
1204 dnormres = abs(h(jh+1,m+1))
1206 if ((spa.ne.dzro).or.(mod(iterout*m+jh,itmod).eq.0))
then
1210 call dcopy(jh,h(1,m+1),1,ycurrent,1)
1211 call dtrsv(
'U',
'N',
'N',jh,h,m+1,ycurrent,1)
1215 call dgemv(
'N',n,jh,one,v,n,
1216 & ycurrent,1,zero,xcurrent,1)
1218 if ((typeprec.eq.rightprec).or.(typeprec.eq.dbleprec))
then
1222 irc(1) = precondright
1228 call dcopy(n,xcurrent,1,r0,1)
1234 if (spa.ne.dzro)
then
1236 call dcopy(n,x,1,xcurrent,1)
1237 call daxpy(n,one,r0,1,xcurrent,1)
1252 if (spa.ne.dzro)
then
1253 dnormx = sqrt((dot(1)))
1256 bea = dnormres/(spa*dnormx+spb)
1258 if (mod(iterout*m+jh,itmod).eq.0)
then
1259 call dcopy(n,x,1,xcurrent,1)
1260 call daxpy(n,one,r0,1,xcurrent,1)
1263 info(1) = iterout*m+jh
1272 if ((bea.le.cntl(1)).or.(iterout*m+jh.ge.itermax))
then
1279 if (spa.eq.dzro)
then
1283 call dcopy(jh,h(1,m+1),1,ycurrent,1)
1284 call dtrsv(
'U',
'N',
'N',jh,h,m+1,ycurrent,1)
1288 call dgemv(
'N',n,jh,one,v,n,
1289 & ycurrent,1,zero,xcurrent,1)
1291 if ((typeprec.eq.rightprec).or.(typeprec.eq.dbleprec))
then
1295 irc(1) = precondright
1301 call dcopy(n,xcurrent,1,r0,1)
1306 if ((bea.le.cntl(1)).or.(iterout*m+jh.ge.itermax))
then
1307 if (spa.eq.dzro)
then
1309 call dcopy(n,x,1,xcurrent,1)
1310 call daxpy(n,one,r0,1,xcurrent,1)
1313 call dcopy(n,xcurrent,1,r0,1)
1325 if ((bea.le.cntl(1)).or.(iterout*m+jh.ge.itermax))
then
1343 if ((bea.le.cntl(1)).or.(iterout*m+jh.ge.itermax))
then
1344 truenormres = sqrt((dot(1)))
1346 if ((typeprec.eq.leftprec).or.(typeprec.eq.dbleprec))
then
1350 irc(1) = precondleft
1356 call dcopy(n,w,1,r0,1)
1360 if ((bea.le.cntl(1)).or.(iterout*m+jh.ge.itermax))
then
1373 if ((bea.le.cntl(1)).or.(iterout*m+jh.ge.itermax))
then
1374 dnormres = sqrt((dot(1)))
1376 be = dnormres/(spa*dnormx+spb)
1378 if (ihist.ne.0)
then
1379 write(ihist,1000)iterout*m+jh,bea,be
1380 1000
format(i5,11x,e8.2,7x,e8.2)
1387 if ((bea.le.cntl(1)).or.(iterout*m+jh.ge.itermax))
then
1388 if ((be.le.cntl(1)).or.(iterout*m+jh.ge.itermax))
then
1391 call dcopy(n,xcurrent,1,x,1)
1393 if (sa.ne.dzro)
then
1408 if ((bea.le.cntl(1)).or.(iterout*m+jh.ge.itermax))
then
1409 if ((be.le.cntl(1)).or.(iterout*m+jh.ge.itermax))
then
1410 if (sa.ne.dzro)
then
1411 dnormx = sqrt((dot(1)))
1418 rinfo(2) = truenormres/(sa*dnormx+sb)
1419 if (be.le.cntl(1))
then
1421 if (ihist.ne.0)
then
1423 write(ihist,
'(A20)')
'Convergence achieved'
1425 else if (be.gt.cntl(1))
then
1426 if (iwarn.ne.0)
then
1428 write(iwarn,*)
' WARNING GMRES : '
1429 write(iwarn,*)
' No convergence after '
1430 write(iwarn,*) iterout*m+jh,
' iterations '
1433 if (ihist.ne.0)
then
1435 write(ihist,*)
' WARNING GMRES :'
1436 write(ihist,*)
' No convergence after '
1437 write(ihist,*) iterout*m+jh,
' iterations '
1442 if (ihist.ne.0)
then
1443 write(ihist,1010) rinfo(1)
1444 write(ihist,1011) rinfo(2)
1445 1010
format(
'B.E. on the preconditioned system: ',e8.2)
1446 1011
format(
'B.E. on the unpreconditioned system: ',e8.2)
1448 info(2) = iterout*m+jh
1449 if (ihist.ne.0)
then
1450 write(ihist,
'(A10,I2)')
'info(1) = ',info(1)
1451 write(ihist,
'(A32,I5)')
1452 &
'Number of iterations (info(2)): ',info(2)
1460 if (ihist.ne.0)
then
1461 write(ihist,1001)iterout*m+jh,bea
1462 1001
format(i5,11x,e8.2,7x,
'--')
1472 iterout = iterout + 1
1477 if ((spa.eq.dzro).and.(bea.gt.cntl(1)))
then
1482 call dcopy(jh,h(1,m+1),1,ycurrent,1)
1483 call dtrsv(
'U',
'N',
'N',jh,h,m+1,ycurrent,1)
1487 call dgemv(
'N',n,jh,one,v,n,
1488 & ycurrent,1,zero,xcurrent,1)
1490 if ((typeprec.eq.rightprec).or.(typeprec.eq.dbleprec))
then
1494 irc(1) = precondright
1500 call dcopy(n,xcurrent,1,r0,1)
1504 if ((spa.eq.dzro).and.(bea.gt.cntl(1)))
then
1506 call dcopy(n,x,1,xcurrent,1)
1507 call daxpy(n,one,r0,1,xcurrent,1)
1510 call dcopy(n,xcurrent,1,x,1)
1512 if (comprsd.eq.1)
then
1516 call dcopy(n,x,1,w,1)
1524 if (comprsd.eq.1)
then
1526 r0(j) = b(j) - r0(j)
1531 if ((typeprec.eq.leftprec).or.(typeprec.eq.dbleprec))
then
1535 irc(1) = precondleft
1541 call dcopy(n,r0,1,w,1)
1548 if (comprsd.eq.1)
then
1558 if (comprsd.eq.1)
then
1559 beta = sqrt((dot(1)))
1563 beta = abs(h(m+1,m+1))
1567 call drot(1, h(j,m+1), 1, h(j+1,m+1), 1,
1568 & (rotcos(j)), -rotsin(j))
1573 call dgemv(
'N',n,m+1,one,v,n,h(1,m+1),1,zero,w,1)
1580 call daxpy(n,aux,w,1,v(1,1),1)
1587 subroutine init_dgmres(icntl,cntl)
1637 integer,
INTENT(OUT) :: icntl(9)
1638 REAL(dp),
INTENT(OUT) :: cntl(5)
1648 icntl(9) = huge(icntl(9))-1