xref: /phasta/phSolver/compressible/solgmr.f (revision 13c4f35a7b4a194dfdf35c2fe14e1d6cc20c4641)
159599516SKenneth E. Jansen        subroutine SolGMRe (y,         ac,        yold,      acold,
259599516SKenneth E. Jansen     &			   x,         iBC,       BC,        EGmass,
359599516SKenneth E. Jansen     &                     res,       BDiag,     HBrg,      eBrg,
459599516SKenneth E. Jansen     &                     yBrg,      Rcos,      Rsin,      iper,
559599516SKenneth E. Jansen     &                     ilwork,    shp,       shgl,      shpb,
659599516SKenneth E. Jansen     &                     shglb,     Dy, rerr)
759599516SKenneth E. Jansenc
859599516SKenneth E. Jansenc----------------------------------------------------------------------
959599516SKenneth E. Jansenc
1059599516SKenneth E. Jansenc  This is the preconditioned GMRES driver routine.
1159599516SKenneth E. Jansenc
1259599516SKenneth E. Jansenc input:
1359599516SKenneth E. Jansenc  y      (nshg,ndof)           : Y-variables at n+alpha_v
1459599516SKenneth E. Jansenc  ac     (nshg,ndof)           : Primvar. accel. variable n+alpha_m
1559599516SKenneth E. Jansenc  yold   (nshg,ndof)           : Y-variables at beginning of step
1659599516SKenneth E. Jansenc  acold  (nshg,ndof)           : Primvar. accel. variable at begng step
1759599516SKenneth E. Jansenc  x      (numnp,nsd)            : node coordinates
1859599516SKenneth E. Jansenc  iBC    (nshg)                : BC codes
1959599516SKenneth E. Jansenc  BC     (nshg,ndofBC)         : BC constraint parameters
2059599516SKenneth E. Jansenc  HBrg   (Kspace+1,Kspace)      : Hessenberg matrix (LHS matrix)
2159599516SKenneth E. Jansenc  eBrg   (Kspace+1)             : RHS      of Hessenberg minim. problem
2259599516SKenneth E. Jansenc  yBrg   (Kspace)               : solution of Hessenberg minim. problem
2359599516SKenneth E. Jansenc  Rcos   (Kspace)               : Rotational cosine of QR algorithm
2459599516SKenneth E. Jansenc  Rsin   (Kspace)               : Rotational sine   of QR algorithm
2559599516SKenneth E. Jansenc  shp(b) (nen,maxsh,melCat)     : element shape functions (boundary)
2659599516SKenneth E. Jansenc  shgl(b)(nsd,nen,maxsh,melCat) : local gradients of shape functions
2759599516SKenneth E. Jansenc
2859599516SKenneth E. Jansenc output:
2959599516SKenneth E. Jansenc  res    (nshg,nflow)           : preconditioned residual
3059599516SKenneth E. Jansenc  BDiag  (nshg,nflow,nflow)      : block-diagonal preconditioner
3159599516SKenneth E. Jansenc
3259599516SKenneth E. Jansenc
3359599516SKenneth E. Jansenc Zdenek Johan,  Winter 1991.  (Fortran 90)
3459599516SKenneth E. Jansenc----------------------------------------------------------------------
3559599516SKenneth E. Jansenc
3659599516SKenneth E. Jansen        use pointer_data
3759599516SKenneth E. Jansen
3859599516SKenneth E. Jansen        include "common.h"
3959599516SKenneth E. Jansen        include "mpif.h"
4059599516SKenneth E. Jansen        include "auxmpi.h"
4159599516SKenneth E. Jansenc
4259599516SKenneth E. Jansen        dimension y(nshg,ndof),             ac(nshg,ndof),
4359599516SKenneth E. Jansen     &            yold(nshg,ndof),          acold(nshg,ndof),
4459599516SKenneth E. Jansen     &            x(numnp,nsd),
4559599516SKenneth E. Jansen     &            iBC(nshg),                BC(nshg,ndofBC),
4659599516SKenneth E. Jansen     &            res(nshg,nflow),
4759599516SKenneth E. Jansen     &            BDiag(nshg,nflow,nflow),
4859599516SKenneth E. Jansen     &            HBrg(Kspace+1,*),         eBrg(*),
4959599516SKenneth E. Jansen     &            yBrg(*),                  Rcos(*),
5059599516SKenneth E. Jansen     &            Rsin(*),                  ilwork(nlwork),
5159599516SKenneth E. Jansen     &            iper(nshg),               EGmass(numel,nedof,nedof)!,
5259599516SKenneth E. Jansenctoomuchmem     &            Binv(numel,nedof,nedof)
5359599516SKenneth E. Jansenc
5459599516SKenneth E. Jansen        dimension Dy(nshg,nflow),            rmes(nshg,nflow),
5559599516SKenneth E. Jansen     &            temp(nshg,nflow),
5659599516SKenneth E. Jansen     &            uBrg(nshg,nflow,Kspace+1)
5759599516SKenneth E. Jansenc
5859599516SKenneth E. Jansen        dimension shp(MAXTOP,maxsh,MAXQPT),
5959599516SKenneth E. Jansen     &            shgl(MAXTOP,nsd,maxsh,MAXQPT),
6059599516SKenneth E. Jansen     &            shpb(MAXTOP,maxsh,MAXQPT),
6159599516SKenneth E. Jansen     &            shglb(MAXTOP,nsd,maxsh,MAXQPT)
6259599516SKenneth E. Jansen      real*8    rerr(nshg,10)
6359599516SKenneth E. Jansenc
6459599516SKenneth E. Jansenc.... *******************>> Element Data Formation <<******************
6559599516SKenneth E. Jansenc
6659599516SKenneth E. Jansenc
6759599516SKenneth E. Jansenc.... set the parameters for flux and surface tension calculations
6859599516SKenneth E. Jansenc
6959599516SKenneth E. Jansenc
7059599516SKenneth E. Jansen        idflx = 0
7159599516SKenneth E. Jansen        if(idiff >= 1)  idflx= idflx + (nflow-1) * nsd
7259599516SKenneth E. Jansen        if (isurf == 1) idflx=idflx + nsd
7359599516SKenneth E. Jansenc
7459599516SKenneth E. Jansenc.... form the LHS matrices, the residual vector, and the block
7559599516SKenneth E. Jansenc     diagonal preconditioner
7659599516SKenneth E. Jansenc
7759599516SKenneth E. Jansen        call ElmGMRe(y,             ac,            x,
7859599516SKenneth E. Jansen     &               shp,           shgl,          iBC,
7959599516SKenneth E. Jansen     &               BC,            shpb,
8059599516SKenneth E. Jansen     &               shglb,         res,
8159599516SKenneth E. Jansen     &               rmes,          BDiag,         iper,
8259599516SKenneth E. Jansen     &               ilwork,        EGmass,        rerr )
8359599516SKenneth E. Jansenc
8459599516SKenneth E. Jansenc.... **********************>>    EBE - GMRES    <<********************
8559599516SKenneth E. Jansenc
8659599516SKenneth E. Jansen        call timer ('Solver  ')
8759599516SKenneth E. Jansenc
8859599516SKenneth E. Jansenc.... ------------------------> Initialization <-----------------------
8959599516SKenneth E. Jansenc
9059599516SKenneth E. Jansenc
9159599516SKenneth E. Jansenc.... LU decompose the block diagonals
9259599516SKenneth E. Jansenc
9359599516SKenneth E. Jansen        if (iprec .ne. 0)
9459599516SKenneth E. Jansen     &  call i3LU (BDiag, res,  'LU_Fact ')
9559599516SKenneth E. Jansen
9659599516SKenneth E. Jansenc
9759599516SKenneth E. Jansenc.... block diagonal precondition residual
9859599516SKenneth E. Jansenc
9959599516SKenneth E. Jansen        call i3LU (BDiag, res,  'forward ')
10059599516SKenneth E. Jansenc
10159599516SKenneth E. Jansenc.... initialize Dy
10259599516SKenneth E. Jansenc
10359599516SKenneth E. Jansen        Dy = zero
10459599516SKenneth E. Jansenc
10559599516SKenneth E. Jansenc.... Pre-precondition the LHS mass matrix and set up the element
10659599516SKenneth E. Jansenc     by element preconditioners
10759599516SKenneth E. Jansenc
10859599516SKenneth E. Jansenctoomuchmemory note that Binv is demoted from huge array to just one
10959599516SKenneth E. Jansenc        real*8 in i3pre because it takes too much memory
11059599516SKenneth E. Jansen
11159599516SKenneth E. Jansen        call i3pre (BDiag,    Binv,   EGmass,  ilwork)
11259599516SKenneth E. Jansenc
11359599516SKenneth E. Jansenc.... left EBE precondition the residual
11459599516SKenneth E. Jansenc
11559599516SKenneth E. Jansenctoomuchmem        call i3Pcond (Binv,  res,  ilwork,   'L_Pcond ')
11659599516SKenneth E. Jansenc
11759599516SKenneth E. Jansenc.... copy res in uBrg(1)
11859599516SKenneth E. Jansenc
11959599516SKenneth E. Jansen        uBrg(:,:,1) = res
12059599516SKenneth E. Jansenc
12159599516SKenneth E. Jansenc.... calculate norm of residual
12259599516SKenneth E. Jansenc
12359599516SKenneth E. Jansen        temp  = res**2
12459599516SKenneth E. Jansen
12559599516SKenneth E. Jansen        call sumgat (temp, nflow, summed, ilwork)
12659599516SKenneth E. Jansen        unorm = sqrt(summed)
12759599516SKenneth E. Jansenc
12859599516SKenneth E. Jansenc.... check if GMRES iterations are required
12959599516SKenneth E. Jansenc
13059599516SKenneth E. Jansen        iKs    = 0
13159599516SKenneth E. Jansen        lGMRES = 0
13259599516SKenneth E. Jansenc
13359599516SKenneth E. Jansenc.... if we are down to machine precision, don't bother solving
13459599516SKenneth E. Jansenc
13559599516SKenneth E. Jansen        if (unorm .lt. 100.*epsM**2) goto 3000
13659599516SKenneth E. Jansenc
13759599516SKenneth E. Jansenc.... set up tolerance of the Hessenberg's problem
13859599516SKenneth E. Jansenc
13959599516SKenneth E. Jansen        epsnrm = etol * unorm
14059599516SKenneth E. Jansenc
14159599516SKenneth E. Jansenc.... ------------------------>  GMRES Loop  <-------------------------
14259599516SKenneth E. Jansenc
14359599516SKenneth E. Jansenc.... loop through GMRES cycles
14459599516SKenneth E. Jansenc
14559599516SKenneth E. Jansen        do 2000 mGMRES = 1, nGMRES
14659599516SKenneth E. Jansen        lGMRES = mGMRES - 1
14759599516SKenneth E. Jansenc
14859599516SKenneth E. Jansen        if (lGMRES .gt. 0) then
14959599516SKenneth E. Jansenc
15059599516SKenneth E. Jansenc.... if GMRES restarts are necessary, calculate  R - A x
15159599516SKenneth E. Jansenc
15259599516SKenneth E. Jansenc
15359599516SKenneth E. Jansenc.... right precondition Dy
15459599516SKenneth E. Jansenc
15559599516SKenneth E. Jansen           temp = Dy
15659599516SKenneth E. Jansen
15759599516SKenneth E. Jansenctoomuchmem           call i3Pcond (Binv,  temp,  ilwork,  'R_Pcond ')
15859599516SKenneth E. Jansenc
15959599516SKenneth E. Jansenc.... perform the A x product
16059599516SKenneth E. Jansenc
16159599516SKenneth E. Jansen           call Au1GMR (EGmass,  temp,  ilwork, iBC,iper)
16259599516SKenneth E. Jansenc
16359599516SKenneth E. Jansenc.... periodic nodes have to assemble results to their partners
16459599516SKenneth E. Jansenc
16559599516SKenneth E. Jansen           call bc3per (iBC,  temp,  iper, ilwork, nflow)
16659599516SKenneth E. Jansenc
16759599516SKenneth E. Jansenc.... left preconditioning
16859599516SKenneth E. Jansenc
16959599516SKenneth E. Jansenctoomuchmem           call i3Pcond (Binv,  temp,  ilwork,  'L_Pcond ')
17059599516SKenneth E. Jansenc
17159599516SKenneth E. Jansenc.... subtract A x from residual and calculate the norm
17259599516SKenneth E. Jansenc
17359599516SKenneth E. Jansen           temp = res - temp
17459599516SKenneth E. Jansen           uBrg(:,:,1) = temp
17559599516SKenneth E. Jansenc
17659599516SKenneth E. Jansenc.... calculate the norm
17759599516SKenneth E. Jansenc
17859599516SKenneth E. Jansen           temp  = temp**2
17959599516SKenneth E. Jansen           call sumgat (temp, nflow, summed, ilwork)
18059599516SKenneth E. Jansen           unorm = sqrt(summed)
18159599516SKenneth E. Jansenc
18259599516SKenneth E. Jansenc.... flop count
18359599516SKenneth E. Jansenc
184f4d0b58bSKenneth E. Jansen      !      flops = flops + nflow*nshg+nshg
18559599516SKenneth E. Jansenc
18659599516SKenneth E. Jansen        endif
18759599516SKenneth E. Jansenc
18859599516SKenneth E. Jansenc.... set up RHS of the Hessenberg's problem
18959599516SKenneth E. Jansenc
19059599516SKenneth E. Jansen        call clear (eBrg, Kspace+1)
19159599516SKenneth E. Jansen        eBrg(1) = unorm
19259599516SKenneth E. Jansenc
19359599516SKenneth E. Jansenc.... normalize the first Krylov vector
19459599516SKenneth E. Jansenc
19559599516SKenneth E. Jansen        uBrg(:,:,1) = uBrg(:,:,1) / unorm
19659599516SKenneth E. Jansenc
19759599516SKenneth E. Jansenc.... loop through GMRES iterations
19859599516SKenneth E. Jansenc
19959599516SKenneth E. Jansen        do 1000 iK = 1, Kspace
20059599516SKenneth E. Jansen           iKs = iK
20159599516SKenneth E. Jansen
20259599516SKenneth E. Jansen           uBrg(:,:,iKs+1) = uBrg(:,:,iKs)
20359599516SKenneth E. Jansenc
20459599516SKenneth E. Jansenc.... right EBE precondition the LHS ( u_{i+1} <-- inverse(U) u_i )
20559599516SKenneth E. Jansenc
20659599516SKenneth E. Jansenctoomuchmem           call i3Pcond (Binv,  uBrg(:,:,iKs+1), ilwork,  'R_Pcond ')
20759599516SKenneth E. Jansenc
20859599516SKenneth E. Jansenc.... Au product  ( u_{i+1} <-- EGmass u_{i+1} )
20959599516SKenneth E. Jansenc
21059599516SKenneth E. Jansen           call Au1GMR ( EGmass, uBrg(:,:,iKs+1),  ilwork, iBC,iper)
21159599516SKenneth E. Jansenc
21259599516SKenneth E. Jansenc.... periodic nodes have to assemble results to their partners
21359599516SKenneth E. Jansenc
21459599516SKenneth E. Jansen           call bc3per (iBC,  uBrg(:,:,iKs+1),  iper, ilwork, nflow)
21559599516SKenneth E. Jansen
21659599516SKenneth E. Jansenc
21759599516SKenneth E. Jansenc.... left EBE precondition the LHS ( u_{i+1} <-- inverse(L) u_{i+1} )
21859599516SKenneth E. Jansenc
21959599516SKenneth E. Jansenctoomuchmem           call i3Pcond (Binv,  uBrg(:,:,iKs+1), ilwork, 'L_Pcond ')
22059599516SKenneth E. Jansenc
22159599516SKenneth E. Jansenc.... orthogonalize and get the norm
22259599516SKenneth E. Jansenc
22359599516SKenneth E. Jansen          do jK = 1, iKs+1
22459599516SKenneth E. Jansenc
22559599516SKenneth E. Jansen            if (jK .eq. 1) then
22659599516SKenneth E. Jansenc
22759599516SKenneth E. Jansen              temp = uBrg(:,:,iKs+1) * uBrg(:,:,1)  ! {u_{i+1}*u_1} vector
22859599516SKenneth E. Jansen              call sumgat (temp, nflow, beta, ilwork) ! sum vector=(u_{i+1},u_1)
22959599516SKenneth E. Jansenc
23059599516SKenneth E. Jansen            else
23159599516SKenneth E. Jansenc
23259599516SKenneth E. Jansenc project off jK-1 vector
23359599516SKenneth E. Jansenc
23459599516SKenneth E. Jansen              uBrg(:,:,iKs+1) = uBrg(:,:,iKs+1) - beta * uBrg(:,:,jK-1)
23559599516SKenneth E. Jansenc
23659599516SKenneth E. Jansen              temp = uBrg(:,:,iKs+1) * uBrg(:,:,jK) !{u_{i+1}*u_j} vector
23759599516SKenneth E. Jansen              call sumgat (temp, nflow, beta, ilwork) ! sum vector=(u_{i+1},u_j)
23859599516SKenneth E. Jansenc
23959599516SKenneth E. Jansen            endif
24059599516SKenneth E. Jansenc
24159599516SKenneth E. Jansen            HBrg(jK,iKs) = beta   ! put this in the Hessenberg Matrix
24259599516SKenneth E. Jansenc
24359599516SKenneth E. Jansen        enddo
24459599516SKenneth E. Jansenc
245f4d0b58bSKenneth E. Jansen   !      flops = flops + (3*iKs+1)*nflow*numnp+(iKs+1)*numnp
24659599516SKenneth E. Jansenc
24759599516SKenneth E. Jansenc  the last inner product was with what was left of the vector (after
24859599516SKenneth E. Jansenc  projecting off all of the previous vectors
24959599516SKenneth E. Jansenc
25059599516SKenneth E. Jansen        unorm           = sqrt(beta)
25159599516SKenneth E. Jansen        HBrg(iKs+1,iKs) = unorm   ! this fills the 1 sub diagonal band
25259599516SKenneth E. Jansenc
25359599516SKenneth E. Jansenc.... normalize the Krylov vector
25459599516SKenneth E. Jansenc
25559599516SKenneth E. Jansen        uBrg(:,:,iKs+1) = uBrg(:,:,iKs+1) / unorm  ! normalize the next Krylov
25659599516SKenneth E. Jansenc vector
25759599516SKenneth E. Jansenc
25859599516SKenneth E. Jansenc.... construct and reduce the Hessenberg Matrix
25959599516SKenneth E. Jansenc  since there is only one subdiagonal we can use a Givens rotation to
26059599516SKenneth E. Jansenc  rotate off each subdiagonal AS IT IS FORMED.   We do this because it
26159599516SKenneth E. Jansenc  allows us to check progress of solution and quit when satisfied.  Note
26259599516SKenneth E. Jansenc  that all future K vects will put a subdiagonal in the next column so
26359599516SKenneth E. Jansenc  there is no penalty to work ahead as  the rotation for the next vector
26459599516SKenneth E. Jansenc  will be unaffected by this rotation.
26559599516SKenneth E. Jansen
26659599516SKenneth E. Jansenc
26759599516SKenneth E. Jansenc     H Y = E ========>   R_i H Y = R_i E
26859599516SKenneth E. Jansenc
26959599516SKenneth E. Jansen           do jK = 1, iKs-1
27059599516SKenneth E. Jansen              tmp            =  Rcos(jK) * HBrg(jK,  iKs) +
27159599516SKenneth E. Jansen     &                          Rsin(jK) * HBrg(jK+1,iKs)
27259599516SKenneth E. Jansen              HBrg(jK+1,iKs) = -Rsin(jK) * HBrg(jK,  iKs) +
27359599516SKenneth E. Jansen     &                          Rcos(jK) * HBrg(jK+1,iKs)
27459599516SKenneth E. Jansen              HBrg(jK,  iKs) =  tmp
27559599516SKenneth E. Jansen           enddo
27659599516SKenneth E. Jansenc
27759599516SKenneth E. Jansen           tmp             = sqrt(HBrg(iKs,iKs)**2 + HBrg(iKs+1,iKs)**2)
27859599516SKenneth E. Jansen           Rcos(iKs)       = HBrg(iKs,  iKs) / tmp
27959599516SKenneth E. Jansen           Rsin(iKs)       = HBrg(iKs+1,iKs) / tmp
28059599516SKenneth E. Jansen           HBrg(iKs,  iKs) = tmp
28159599516SKenneth E. Jansen           HBrg(iKs+1,iKs) = zero
28259599516SKenneth E. Jansenc
28359599516SKenneth E. Jansenc.... rotate eBrg    R_i E
28459599516SKenneth E. Jansenc
28559599516SKenneth E. Jansen           tmp         = Rcos(iKs) * eBrg(iKs) + Rsin(iKs) * eBrg(iKs+1)
28659599516SKenneth E. Jansen           eBrg(iKs+1) =-Rsin(iKs) * eBrg(iKs) + Rcos(iKs) * eBrg(iKs+1)
28759599516SKenneth E. Jansen           eBrg(iKs)   = tmp
28859599516SKenneth E. Jansenc
28959599516SKenneth E. Jansenc.... check for convergence
29059599516SKenneth E. Jansenc
29159599516SKenneth E. Jansen           ntotGM = ntotGM + 1
29259599516SKenneth E. Jansen           echeck=abs(eBrg(iKs+1))
29359599516SKenneth E. Jansen           if (echeck .le. epsnrm) exit
29459599516SKenneth E. Jansenc
29559599516SKenneth E. Jansenc.... end of GMRES iteration loop
29659599516SKenneth E. Jansenc
29759599516SKenneth E. Jansen 1000   continue
29859599516SKenneth E. Jansenc
29959599516SKenneth E. Jansenc.... ------------------------->   Solution   <------------------------
30059599516SKenneth E. Jansenc
30159599516SKenneth E. Jansenc.... if converged or end of Krylov space
30259599516SKenneth E. Jansenc
30359599516SKenneth E. Jansenc.... solve for yBrg
30459599516SKenneth E. Jansenc
30559599516SKenneth E. Jansen        do jK = iKs, 1, -1
30659599516SKenneth E. Jansen           yBrg(jK) = eBrg(jK) / HBrg(jK,jK)
30759599516SKenneth E. Jansen           do lK = 1, jK-1
30859599516SKenneth E. Jansen              eBrg(lK) = eBrg(lK) - yBrg(jK) * HBrg(lK,jK)
30959599516SKenneth E. Jansen           enddo
31059599516SKenneth E. Jansen        enddo
31159599516SKenneth E. Jansenc
31259599516SKenneth E. Jansenc.... update Dy
31359599516SKenneth E. Jansenc
31459599516SKenneth E. Jansen        do jK = 1, iKs
31559599516SKenneth E. Jansen           Dy = Dy + yBrg(jK) * uBrg(:,:,jK)
31659599516SKenneth E. Jansen        enddo
31759599516SKenneth E. Jansenc
31859599516SKenneth E. Jansenc.... flop count
31959599516SKenneth E. Jansenc
320f4d0b58bSKenneth E. Jansen   !      flops = flops + (3*iKs+1)*nflow*nshg
32159599516SKenneth E. Jansenc
32259599516SKenneth E. Jansenc.... check for convergence
32359599516SKenneth E. Jansenc
32459599516SKenneth E. Jansen
32559599516SKenneth E. Jansen        echeck=abs(eBrg(iKs+1))
32659599516SKenneth E. Jansen        if (echeck .le. epsnrm) exit
32759599516SKenneth E. Jansen        if(myrank.eq.master) write(*,*)'solver tolerance %satisfaction',
32859599516SKenneth E. Jansen     &  (one-echeck/unorm)/(one-etol)*100
32959599516SKenneth E. Jansenc
33059599516SKenneth E. Jansenc.... end of mGMRES loop
33159599516SKenneth E. Jansenc
33259599516SKenneth E. Jansen 2000 continue
33359599516SKenneth E. Jansenc
33459599516SKenneth E. Jansenc.... ------------------------>   Converged   <------------------------
33559599516SKenneth E. Jansenc
33659599516SKenneth E. Jansenc.... if converged
33759599516SKenneth E. Jansenc
33859599516SKenneth E. Jansen 3000 continue
33959599516SKenneth E. Jansenc
34059599516SKenneth E. Jansenc.... back EBE precondition the results
34159599516SKenneth E. Jansenc
34259599516SKenneth E. Jansenctoomuchmem      call i3Pcond (Binv,  Dy, ilwork, 'R_Pcond ')
34359599516SKenneth E. Jansenc
34459599516SKenneth E. Jansenc.... back block-diagonal precondition the results
34559599516SKenneth E. Jansenc
34659599516SKenneth E. Jansen      call i3LU (BDiag, Dy, 'backward')
34759599516SKenneth E. Jansenc
34859599516SKenneth E. Jansenc
34959599516SKenneth E. Jansenc.... output the statistics
35059599516SKenneth E. Jansenc
35159599516SKenneth E. Jansen              call rstat (res, ilwork)
35259599516SKenneth E. Jansenc
35359599516SKenneth E. Jansenc.... stop the timer
35459599516SKenneth E. Jansenc
35559599516SKenneth E. Jansen 3002 continue                  ! no solve just res.
35659599516SKenneth E. Jansen      call timer ('Back    ')
35759599516SKenneth E. Jansenc
35859599516SKenneth E. Jansenc.... end
35959599516SKenneth E. Jansenc
36059599516SKenneth E. Jansen      return
36159599516SKenneth E. Jansen      end
36259599516SKenneth E. Jansen
36359599516SKenneth E. Jansen
36459599516SKenneth E. Jansen
36559599516SKenneth E. Jansen
36659599516SKenneth E. Jansen
36759599516SKenneth E. Jansen      subroutine SolGMRs(y,         ac,        yold,      acold,
36859599516SKenneth E. Jansen     &			 x,         iBC,       BC,
36959599516SKenneth E. Jansen     &                   col,       row,       lhsk,
37059599516SKenneth E. Jansen     &                   res,       BDiag,     HBrg,      eBrg,
37159599516SKenneth E. Jansen     &                   yBrg,      Rcos,      Rsin,      iper,
37259599516SKenneth E. Jansen     &                   ilwork,    shp,       shgl,      shpb,
37359599516SKenneth E. Jansen     &                   shglb,     Dy,        rerr)
37459599516SKenneth E. Jansenc
37559599516SKenneth E. Jansenc----------------------------------------------------------------------
37659599516SKenneth E. Jansenc
37759599516SKenneth E. Jansenc  This is the preconditioned GMRES driver routine.
37859599516SKenneth E. Jansenc
37959599516SKenneth E. Jansenc input:
38059599516SKenneth E. Jansenc  y      (nshg,ndof)           : Y-variables at n+alpha_v
38159599516SKenneth E. Jansenc  ac     (nshg,ndof)           : Primvar. accel. variable n+alpha_m
38259599516SKenneth E. Jansenc  yold   (nshg,ndof)           : Y-variables at beginning of step
38359599516SKenneth E. Jansenc  acold  (nshg,ndof)           : Primvar. accel. variable at begng step
38459599516SKenneth E. Jansenc  x      (numnp,nsd)            : node coordinates
38559599516SKenneth E. Jansenc  iBC    (nshg)                : BC codes
38659599516SKenneth E. Jansenc  BC     (nshg,ndofBC)         : BC constraint parameters
38759599516SKenneth E. Jansenc  HBrg   (Kspace+1,Kspace)      : Hessenberg matrix (LHS matrix)
38859599516SKenneth E. Jansenc  eBrg   (Kspace+1)             : RHS      of Hessenberg minim. problem
38959599516SKenneth E. Jansenc  yBrg   (Kspace)               : solution of Hessenberg minim. problem
39059599516SKenneth E. Jansenc  Rcos   (Kspace)               : Rotational cosine of QR algorithm
39159599516SKenneth E. Jansenc  Rsin   (Kspace)               : Rotational sine   of QR algorithm
39259599516SKenneth E. Jansenc  shp(b) (nen,maxsh,melCat)     : element shape functions (boundary)
39359599516SKenneth E. Jansenc  shgl(b)(nsd,nen,maxsh,melCat) : local gradients of shape functions
39459599516SKenneth E. Jansenc
39559599516SKenneth E. Jansenc output:
39659599516SKenneth E. Jansenc  res    (nshg,nflow)           : preconditioned residual
39759599516SKenneth E. Jansenc  BDiag  (nshg,nflow,nflow)      : block-diagonal preconditioner
39859599516SKenneth E. Jansenc
39959599516SKenneth E. Jansenc
40059599516SKenneth E. Jansenc Zdenek Johan,  Winter 1991.  (Fortran 90)
40159599516SKenneth E. Jansenc----------------------------------------------------------------------
40259599516SKenneth E. Jansenc
40359599516SKenneth E. Jansen      use pointer_data
40459599516SKenneth E. Jansen
40559599516SKenneth E. Jansen      include "common.h"
40659599516SKenneth E. Jansen      include "mpif.h"
40759599516SKenneth E. Jansen      include "auxmpi.h"
40859599516SKenneth E. Jansenc
40959599516SKenneth E. Jansen      integer col(nshg+1), row(nnz*nshg)
41059599516SKenneth E. Jansen      real*8 lhsK(nflow*nflow,nnz_tot)
41159599516SKenneth E. Jansen
41259599516SKenneth E. Jansen
41359599516SKenneth E. Jansen      dimension y(nshg,ndof),             ac(nshg,ndof),
41459599516SKenneth E. Jansen     &          yold(nshg,ndof),          acold(nshg,ndof),
41559599516SKenneth E. Jansen     &          x(numnp,nsd),
41659599516SKenneth E. Jansen     &          iBC(nshg),                BC(nshg,ndofBC),
41759599516SKenneth E. Jansen     &          res(nshg,nflow),
41859599516SKenneth E. Jansen     &          BDiag(nshg,nflow,nflow),
41959599516SKenneth E. Jansen     &          HBrg(Kspace+1,Kspace),    eBrg(Kspace+1),
42059599516SKenneth E. Jansen     &          yBrg(Kspace),             Rcos(Kspace),
42159599516SKenneth E. Jansen     &          Rsin(Kspace),             ilwork(nlwork),
42259599516SKenneth E. Jansen     &          iper(nshg)
42359599516SKenneth E. Jansenc
42459599516SKenneth E. Jansen      dimension Dy(nshg,nflow),            rmes(nshg,nflow),
42559599516SKenneth E. Jansen     &          temp(nshg,nflow),
42659599516SKenneth E. Jansen     &          uBrg(nshg,nflow,Kspace+1)
42759599516SKenneth E. Jansenc
42859599516SKenneth E. Jansen      dimension shp(MAXTOP,maxsh,MAXQPT),
42959599516SKenneth E. Jansen     &          shgl(MAXTOP,nsd,maxsh,MAXQPT),
43059599516SKenneth E. Jansen     &          shpb(MAXTOP,maxsh,MAXQPT),
43159599516SKenneth E. Jansen     &          shglb(MAXTOP,nsd,maxsh,MAXQPT)
43259599516SKenneth E. Jansen      real*8    rerr(nshg,10)
43359599516SKenneth E. Jansenc
43459599516SKenneth E. Jansenc
43559599516SKenneth E. Jansenc.... *******************>> Element Data Formation <<******************
43659599516SKenneth E. Jansenc
43759599516SKenneth E. Jansenc
43859599516SKenneth E. Jansenc.... set the parameters for flux and surface tension calculations
43959599516SKenneth E. Jansenc
44059599516SKenneth E. Jansenc
44159599516SKenneth E. Jansen      idflx = 0
44259599516SKenneth E. Jansen      if(idiff >= 1)  idflx= idflx + (nflow-1) * nsd
44359599516SKenneth E. Jansen      if (isurf == 1) idflx=idflx + nsd
44459599516SKenneth E. Jansenc
44559599516SKenneth E. Jansenc.... form the LHS matrices, the residual vector, and the block
44659599516SKenneth E. Jansenc     diagonal preconditioner
44759599516SKenneth E. Jansenc
44859599516SKenneth E. Jansen      call ElmGMRs(y,             ac,            x,
44959599516SKenneth E. Jansen     &             shp,           shgl,          iBC,
45059599516SKenneth E. Jansen     &             BC,            shpb,
45159599516SKenneth E. Jansen     &             shglb,         res,
45259599516SKenneth E. Jansen     &             rmes,          BDiag,         iper,
45359599516SKenneth E. Jansen     &             ilwork,        lhsK,          col,
45459599516SKenneth E. Jansen     &             row,           rerr )
455*13c4f35aSKenneth E. Jansen!      call rstat (res, ilwork)
456*13c4f35aSKenneth E. Jansen!      if(ntotGM.eq.0) resfrt=zero  !don't let this mess up scaled dB
457*13c4f35aSKenneth E. Jansen!      if(myrank.eq.master) then
458*13c4f35aSKenneth E. Jansen!            write(*,*)'residual prior to sbd-preconditioning'
459*13c4f35aSKenneth E. Jansen!      endif
460*13c4f35aSKenneth E. Jansenc
46159599516SKenneth E. Jansen
46259599516SKenneth E. Jansen	call tnanq(res,5, 'res_egmr')
46359599516SKenneth E. Jansen	call tnanq(BDiag,25, 'bdg_egmr')
46459599516SKenneth E. Jansenc
46559599516SKenneth E. Jansenc.... **********************>>    EBE - GMRES    <<********************
46659599516SKenneth E. Jansenc
46759599516SKenneth E. Jansen      call timer ('Solver  ')
46859599516SKenneth E. Jansenc
46959599516SKenneth E. Jansenc.... ------------------------> Initialization <-----------------------
47059599516SKenneth E. Jansenc
47159599516SKenneth E. Jansenc
47259599516SKenneth E. Jansenc.... LU decompose the block diagonals
47359599516SKenneth E. Jansenc
47459599516SKenneth E. Jansen      if (iprec .ne. 0) then
47559599516SKenneth E. Jansen         call i3LU (BDiag, res,  'LU_Fact ')
47659599516SKenneth E. Jansen         if (numpe > 1) then
47759599516SKenneth E. Jansen            call commu (BDiag  , ilwork, nflow*nflow  , 'out')
47859599516SKenneth E. Jansen         endif
47959599516SKenneth E. Jansen      endif
48059599516SKenneth E. Jansenc
48159599516SKenneth E. Jansenc.... block diagonal precondition residual
48259599516SKenneth E. Jansenc
48359599516SKenneth E. Jansen      call i3LU (BDiag, res,  'forward ')
48459599516SKenneth E. Jansenc
48559599516SKenneth E. Jansenc Check the residual for divering trend
48659599516SKenneth E. Jansenc
48759599516SKenneth E. Jansen	call rstatCheck(res,ilwork,y,ac)
48859599516SKenneth E. Jansenc
48959599516SKenneth E. Jansenc.... initialize Dy
49059599516SKenneth E. Jansenc
49159599516SKenneth E. Jansen      Dy = zero
49259599516SKenneth E. Jansenc
49359599516SKenneth E. Jansenc.... Pre-precondition the LHS mass matrix and set up the sparse
49459599516SKenneth E. Jansenc     preconditioners
49559599516SKenneth E. Jansenc
49659599516SKenneth E. Jansen
49759599516SKenneth E. Jansen      if(lhs.eq.1) call Spsi3pre (BDiag,    lhsK,  col, row)
49859599516SKenneth E. Jansenc
49959599516SKenneth E. Jansenc.... copy res in uBrg(1)
50059599516SKenneth E. Jansenc
50159599516SKenneth E. Jansen      uBrg(:,:,1) = res
50259599516SKenneth E. Jansenc
50359599516SKenneth E. Jansenc.... calculate norm of residual
50459599516SKenneth E. Jansenc
50559599516SKenneth E. Jansen      temp  = res**2
50659599516SKenneth E. Jansen
50759599516SKenneth E. Jansen      call sumgat (temp, nflow, summed, ilwork)
50859599516SKenneth E. Jansen      unorm = sqrt(summed)
50959599516SKenneth E. Jansenc
51059599516SKenneth E. Jansenc.... check if GMRES iterations are required
51159599516SKenneth E. Jansenc
51259599516SKenneth E. Jansen      iKs    = 0
513513954efSKenneth E. Jansen      lGMRESs = 0
51459599516SKenneth E. Jansenc
51559599516SKenneth E. Jansenc.... if we are down to machine precision, don't bother solving
51659599516SKenneth E. Jansenc
51759599516SKenneth E. Jansen      if (unorm .lt. 100.*epsM**2) goto 3000
51859599516SKenneth E. Jansenc
51959599516SKenneth E. Jansenc.... set up tolerance of the Hessenberg's problem
52059599516SKenneth E. Jansenc
52159599516SKenneth E. Jansen      epsnrm = etol * unorm
52259599516SKenneth E. Jansenc
52359599516SKenneth E. Jansenc.... ------------------------>  GMRES Loop  <-------------------------
52459599516SKenneth E. Jansenc
52559599516SKenneth E. Jansenc.... loop through GMRES cycles
52659599516SKenneth E. Jansenc
52759599516SKenneth E. Jansen      do 2000 mGMRES = 1, nGMRES
528513954efSKenneth E. Jansen         lGMRESs = mGMRES - 1
52959599516SKenneth E. Jansenc
53059599516SKenneth E. Jansen         if (lGMRES .gt. 0) then
53159599516SKenneth E. Jansenc
53259599516SKenneth E. Jansenc.... if GMRES restarts are necessary, calculate  R - A x
53359599516SKenneth E. Jansenc
53459599516SKenneth E. Jansenc
53559599516SKenneth E. Jansenc.... right precondition Dy
53659599516SKenneth E. Jansenc
53759599516SKenneth E. Jansen            temp = Dy
53859599516SKenneth E. Jansen
53959599516SKenneth E. Jansenc
54059599516SKenneth E. Jansenc.... perform the A x product
54159599516SKenneth E. Jansenc
54259599516SKenneth E. Jansen            call SparseAp (iper,ilwork,iBC, col, row, lhsK,  temp)
543513954efSKenneth E. Jansenc           call tnanq(temp,5, 'q_spAPrs')
54459599516SKenneth E. Jansen
54559599516SKenneth E. Jansenc
54659599516SKenneth E. Jansenc.... periodic nodes have to assemble results to their partners
54759599516SKenneth E. Jansenc
54859599516SKenneth E. Jansen            call bc3per (iBC,  temp,  iper, ilwork, nflow)
549513954efSKenneth E. Jansenc           call tnanq(temp,5, 'q_BCprs')
55059599516SKenneth E. Jansenc
55159599516SKenneth E. Jansenc.... subtract A x from residual and calculate the norm
55259599516SKenneth E. Jansenc
55359599516SKenneth E. Jansen            temp = res - temp
55459599516SKenneth E. Jansen            uBrg(:,:,1) = temp
55559599516SKenneth E. Jansenc
55659599516SKenneth E. Jansenc.... calculate the norm
55759599516SKenneth E. Jansenc
55859599516SKenneth E. Jansen            temp  = temp**2
55959599516SKenneth E. Jansen            call sumgat (temp, nflow, summed, ilwork)
56059599516SKenneth E. Jansen            unorm = sqrt(summed)
56159599516SKenneth E. Jansenc
56259599516SKenneth E. Jansenc.... flop count
56359599516SKenneth E. Jansenc
564f4d0b58bSKenneth E. Jansen       !      flops = flops + nflow*nshg+nshg
56559599516SKenneth E. Jansenc
56659599516SKenneth E. Jansen         endif
56759599516SKenneth E. Jansenc
56859599516SKenneth E. Jansenc.... set up RHS of the Hessenberg's problem
56959599516SKenneth E. Jansenc
57059599516SKenneth E. Jansen         call clear (eBrg, Kspace+1)
57159599516SKenneth E. Jansen         eBrg(1) = unorm
57259599516SKenneth E. Jansenc
57359599516SKenneth E. Jansenc.... normalize the first Krylov vector
57459599516SKenneth E. Jansenc
57559599516SKenneth E. Jansen         uBrg(:,:,1) = uBrg(:,:,1) / unorm
57659599516SKenneth E. Jansenc
57759599516SKenneth E. Jansenc.... loop through GMRES iterations
57859599516SKenneth E. Jansenc
57959599516SKenneth E. Jansen         do 1000 iK = 1, Kspace
58059599516SKenneth E. Jansen            iKs = iK
58159599516SKenneth E. Jansen
58259599516SKenneth E. Jansen            uBrg(:,:,iKs+1) = uBrg(:,:,iKs)
58359599516SKenneth E. Jansenc
58459599516SKenneth E. Jansenc.... Au product  ( u_{i+1} <-- EGmass u_{i+1} )
58559599516SKenneth E. Jansenc
58659599516SKenneth E. Jansen            call SparseAp (iper, ilwork, iBC,
58759599516SKenneth E. Jansen     &                     col,  row,    lhsK,
58859599516SKenneth E. Jansen     &                     uBrg(:,:,iKs+1) )
589513954efSKenneth E. Jansenc           call tnanq(uBrg(:,:,iKS+1),5, 'q_spAP')
59059599516SKenneth E. Jansen
59159599516SKenneth E. Jansenc
59259599516SKenneth E. Jansenc.... periodic nodes have to assemble results to their partners
59359599516SKenneth E. Jansenc
59459599516SKenneth E. Jansen            call bc3per (iBC,  uBrg(:,:,iKs+1),  iper, ilwork, nflow)
595513954efSKenneth E. Jansenc           call tnanq(uBrg(:,:,iKS+1),5, 'q_bc')
59659599516SKenneth E. Jansen
59759599516SKenneth E. Jansenc
59859599516SKenneth E. Jansenc.... orthogonalize and get the norm
59959599516SKenneth E. Jansenc
60059599516SKenneth E. Jansen            do jK = 1, iKs+1
60159599516SKenneth E. Jansenc
60259599516SKenneth E. Jansen               if (jK .eq. 1) then
60359599516SKenneth E. Jansenc
60459599516SKenneth E. Jansen                  temp = uBrg(:,:,iKs+1) * uBrg(:,:,1) ! {u_{i+1}*u_1} vector
60559599516SKenneth E. Jansen                  call sumgat (temp, nflow, beta, ilwork) ! sum vector=(u_{i+1},u_1)
60659599516SKenneth E. Jansenc
60759599516SKenneth E. Jansen               else
60859599516SKenneth E. Jansenc
60959599516SKenneth E. Jansenc project off jK-1 vector
61059599516SKenneth E. Jansenc
61159599516SKenneth E. Jansen                  uBrg(:,:,iKs+1)=uBrg(:,:,iKs+1)-beta * uBrg(:,:,jK-1)
61259599516SKenneth E. Jansenc
61359599516SKenneth E. Jansen                  temp = uBrg(:,:,iKs+1) * uBrg(:,:,jK) !{u_{i+1}*u_j} vector
61459599516SKenneth E. Jansen                  call sumgat (temp, nflow, beta, ilwork) ! sum vector=(u_{i+1},u_j)
61559599516SKenneth E. Jansenc
61659599516SKenneth E. Jansen               endif
61759599516SKenneth E. Jansenc
61859599516SKenneth E. Jansen               HBrg(jK,iKs) = beta ! put this in the Hessenberg Matrix
61959599516SKenneth E. Jansenc
62059599516SKenneth E. Jansen            enddo
62159599516SKenneth E. Jansenc
622f4d0b58bSKenneth E. Jansen       !      flops = flops + (3*iKs+1)*nflow*numnp+(iKs+1)*numnp
62359599516SKenneth E. Jansenc
62459599516SKenneth E. Jansenc  the last inner product was with what was left of the vector (after
62559599516SKenneth E. Jansenc  projecting off all of the previous vectors
62659599516SKenneth E. Jansenc
627513954efSKenneth E. Jansen        if(beta.le.0) write(*,*) 'beta in solgmr non-positive'
62859599516SKenneth E. Jansen            unorm           = sqrt(beta)
62959599516SKenneth E. Jansen            HBrg(iKs+1,iKs) = unorm ! this fills the 1 sub diagonal band
63059599516SKenneth E. Jansenc
63159599516SKenneth E. Jansenc.... normalize the Krylov vector
63259599516SKenneth E. Jansenc
63359599516SKenneth E. Jansen            uBrg(:,:,iKs+1) = uBrg(:,:,iKs+1) / unorm ! normalize the next Krylov
63459599516SKenneth E. Jansenc vector
63559599516SKenneth E. Jansenc
63659599516SKenneth E. Jansenc.... construct and reduce the Hessenberg Matrix
63759599516SKenneth E. Jansenc  since there is only one subdiagonal we can use a Givens rotation to
63859599516SKenneth E. Jansenc  rotate off each subdiagonal AS IT IS FORMED.   We do this because it
63959599516SKenneth E. Jansenc  allows us to check progress of solution and quit when satisfied.  Note
64059599516SKenneth E. Jansenc  that all future K vects will put a subdiagonal in the next column so
64159599516SKenneth E. Jansenc  there is no penalty to work ahead as  the rotation for the next vector
64259599516SKenneth E. Jansenc  will be unaffected by this rotation.
64359599516SKenneth E. Jansen
64459599516SKenneth E. Jansenc
64559599516SKenneth E. Jansenc     H Y = E ========>   R_i H Y = R_i E
64659599516SKenneth E. Jansenc
64759599516SKenneth E. Jansen            do jK = 1, iKs-1
64859599516SKenneth E. Jansen               tmp            =  Rcos(jK) * HBrg(jK,  iKs) +
64959599516SKenneth E. Jansen     &                           Rsin(jK) * HBrg(jK+1,iKs)
65059599516SKenneth E. Jansen               HBrg(jK+1,iKs) = -Rsin(jK) * HBrg(jK,  iKs) +
65159599516SKenneth E. Jansen     &                           Rcos(jK) * HBrg(jK+1,iKs)
65259599516SKenneth E. Jansen               HBrg(jK,  iKs) =  tmp
65359599516SKenneth E. Jansen            enddo
65459599516SKenneth E. Jansenc
65559599516SKenneth E. Jansen            tmp            = sqrt(HBrg(iKs,iKs)**2 + HBrg(iKs+1,iKs)**2)
65659599516SKenneth E. Jansen            Rcos(iKs)      = HBrg(iKs,  iKs) / tmp
65759599516SKenneth E. Jansen            Rsin(iKs)      = HBrg(iKs+1,iKs) / tmp
65859599516SKenneth E. Jansen            HBrg(iKs,  iKs)= tmp
65959599516SKenneth E. Jansen            HBrg(iKs+1,iKs)= zero
66059599516SKenneth E. Jansenc
66159599516SKenneth E. Jansenc.... rotate eBrg    R_i E
66259599516SKenneth E. Jansenc
66359599516SKenneth E. Jansen            tmp        = Rcos(iKs) * eBrg(iKs) + Rsin(iKs) * eBrg(iKs+1)
66459599516SKenneth E. Jansen            eBrg(iKs+1)=-Rsin(iKs) * eBrg(iKs) + Rcos(iKs) * eBrg(iKs+1)
66559599516SKenneth E. Jansen            eBrg(iKs)  = tmp
66659599516SKenneth E. Jansenc
66759599516SKenneth E. Jansenc.... check for convergence
66859599516SKenneth E. Jansenc
66959599516SKenneth E. Jansen            ntotGM = ntotGM + 1
67059599516SKenneth E. Jansen            echeck=abs(eBrg(iKs+1))
67159599516SKenneth E. Jansen            if (echeck .le. epsnrm.and. iKs .ge. minIters) exit
67259599516SKenneth E. Jansenc
67359599516SKenneth E. Jansenc.... end of GMRES iteration loop
67459599516SKenneth E. Jansenc
67559599516SKenneth E. Jansen 1000    continue
67659599516SKenneth E. Jansenc
67759599516SKenneth E. Jansenc.... ------------------------->   Solution   <------------------------
67859599516SKenneth E. Jansenc
67959599516SKenneth E. Jansenc.... if converged or end of Krylov space
68059599516SKenneth E. Jansenc
68159599516SKenneth E. Jansenc.... solve for yBrg
68259599516SKenneth E. Jansenc
68359599516SKenneth E. Jansen         do jK = iKs, 1, -1
68459599516SKenneth E. Jansen            yBrg(jK) = eBrg(jK) / HBrg(jK,jK)
68559599516SKenneth E. Jansen            do lK = 1, jK-1
68659599516SKenneth E. Jansen               eBrg(lK) = eBrg(lK) - yBrg(jK) * HBrg(lK,jK)
68759599516SKenneth E. Jansen            enddo
68859599516SKenneth E. Jansen         enddo
68959599516SKenneth E. Jansenc
69059599516SKenneth E. Jansenc.... update Dy
69159599516SKenneth E. Jansenc
69259599516SKenneth E. Jansen         do jK = 1, iKs
69359599516SKenneth E. Jansen            Dy = Dy + yBrg(jK) * uBrg(:,:,jK)
69459599516SKenneth E. Jansen         enddo
69559599516SKenneth E. Jansenc
69659599516SKenneth E. Jansenc.... flop count
69759599516SKenneth E. Jansenc
698f4d0b58bSKenneth E. Jansen    !      flops = flops + (3*iKs+1)*nflow*nshg
69959599516SKenneth E. Jansenc
70059599516SKenneth E. Jansenc.... check for convergence
70159599516SKenneth E. Jansenc
70259599516SKenneth E. Jansen        echeck=abs(eBrg(iKs+1))
70359599516SKenneth E. Jansen        if (echeck .le. epsnrm) exit
704513954efSKenneth E. Jansen!        if(myrank.eq.master) write(*,*)'solver tolerance %satisfaction',
705513954efSKenneth E. Jansen!     &  (one-echeck*etol/epsnrm)/(one-etol)*100
70659599516SKenneth E. Jansen
70759599516SKenneth E. Jansenc
70859599516SKenneth E. Jansenc.... end of mGMRES loop
70959599516SKenneth E. Jansenc
71059599516SKenneth E. Jansen 2000 continue
71159599516SKenneth E. Jansenc
71259599516SKenneth E. Jansenc.... ------------------------>   Converged   <------------------------
71359599516SKenneth E. Jansenc
71459599516SKenneth E. Jansenc.... if converged
71559599516SKenneth E. Jansenc
71659599516SKenneth E. Jansen 3000 continue
71759599516SKenneth E. Jansen
71859599516SKenneth E. Jansenc
71959599516SKenneth E. Jansenc
72059599516SKenneth E. Jansenc.... back block-diagonal precondition the results
72159599516SKenneth E. Jansenc
72259599516SKenneth E. Jansen      call i3LU (BDiag, Dy, 'backward')
72359599516SKenneth E. Jansenc
72459599516SKenneth E. Jansenc
72559599516SKenneth E. Jansenc.... output the statistics
72659599516SKenneth E. Jansenc
72759599516SKenneth E. Jansen      call rstat (res, ilwork)
728513954efSKenneth E. Jansen
729513954efSKenneth E. Jansen      if(myrank.eq.master) then
730513954efSKenneth E. Jansen        if (echeck .le. epsnrm) then
731513954efSKenneth E. Jansen            write(*,*)
732513954efSKenneth E. Jansen        else
733513954efSKenneth E. Jansen            write(*,*)'solver tolerance %satisfaction',
734513954efSKenneth E. Jansen     &  (one-echeck*etol/epsnrm)/(one-etol)*100
735513954efSKenneth E. Jansen        endif
736513954efSKenneth E. Jansen      endif
73759599516SKenneth E. Jansenc
73859599516SKenneth E. Jansenc.... stop the timer
73959599516SKenneth E. Jansenc
74059599516SKenneth E. Jansen 3002 continue                  ! no solve just res.
74159599516SKenneth E. Jansen      call timer ('Back    ')
74259599516SKenneth E. Jansenc
74359599516SKenneth E. Jansenc.... end
74459599516SKenneth E. Jansenc
74559599516SKenneth E. Jansen      return
74659599516SKenneth E. Jansen      end
74759599516SKenneth E. Jansen
74859599516SKenneth E. Jansen        subroutine SolGMRSclr(y,       ac,      yold,
74959599516SKenneth E. Jansen     &                        acold,   EGmasst,
75059599516SKenneth E. Jansen     &                        x,       elDw,
75159599516SKenneth E. Jansen     &                        iBC,      BC,
75259599516SKenneth E. Jansen     &                        rest,     HBrg,     eBrg,
75359599516SKenneth E. Jansen     &                        yBrg,     Rcos,     Rsin,    iper,
75459599516SKenneth E. Jansen     &                        ilwork,
75559599516SKenneth E. Jansen     &                        shp,      shgl,
75659599516SKenneth E. Jansen     &                        shpb,     shglb,  Dyt)
75759599516SKenneth E. Jansenc
75859599516SKenneth E. Jansenc----------------------------------------------------------------------
75959599516SKenneth E. Jansenc
76059599516SKenneth E. Jansenc  This is the preconditioned GMRES driver routine.
76159599516SKenneth E. Jansenc
76259599516SKenneth E. Jansenc input:
76359599516SKenneth E. Jansenc  y      (nshg,ndof)           : Y-variables at n+alpha_f
76459599516SKenneth E. Jansenc  ac     (nshg,ndof)           : Primvar. accel. variable n+alpha_m
76559599516SKenneth E. Jansenc  yold   (nshg,ndof)           : Y-variables at beginning of step
76659599516SKenneth E. Jansenc  acold  (nshg,ndof)           : Primvar. accel. variable at begng step
76759599516SKenneth E. Jansenc  x      (numnp,nsd)            : node coordinates
76859599516SKenneth E. Jansenc  iBC    (nshg)                : BC codes
76959599516SKenneth E. Jansenc  BC     (nshg,ndofBC)         : BC constraint parameters
77059599516SKenneth E. Jansenc  iper   (nshg)                : periodic nodal information
77159599516SKenneth E. Jansenc
77259599516SKenneth E. Jansenc output:
77359599516SKenneth E. Jansenc  y      (nshg,ndof)           : Y-variables at n+alpha_f
77459599516SKenneth E. Jansenc  ac     (nshg,ndof)           : Primvar. accel. variable n+alpha_m
77559599516SKenneth E. Jansenc  HBrg   (Kspace+1,Kspace)      : Hessenberg matrix (LHS matrix)
77659599516SKenneth E. Jansenc  eBrg   (Kspace+1)             : RHS      of Hessenberg minim. problem
77759599516SKenneth E. Jansenc  yBrg   (Kspace)               : solution of Hessenberg minim. problem
77859599516SKenneth E. Jansenc  Rcos   (Kspace)               : Rotational cosine of QR algorithm
77959599516SKenneth E. Jansenc  Rsin   (Kspace)               : Rotational sine   of QR algorithm
78059599516SKenneth E. Jansenc output:
78159599516SKenneth E. Jansenc  rest   (numnp)           : preconditioned residual
78259599516SKenneth E. Jansenc
78359599516SKenneth E. Jansenc
78459599516SKenneth E. Jansenc Zdenek Johan,  Winter 1991.  (Fortran 90)
78559599516SKenneth E. Jansenc----------------------------------------------------------------------
78659599516SKenneth E. Jansenc
78759599516SKenneth E. Jansen        use pointer_data
78859599516SKenneth E. Jansen
78959599516SKenneth E. Jansen        include "common.h"
79059599516SKenneth E. Jansen        include "mpif.h"
79159599516SKenneth E. Jansen        include "auxmpi.h"
79259599516SKenneth E. Jansenc
79359599516SKenneth E. Jansen        dimension y(nshg,ndof),      ac(nshg,ndof),
79459599516SKenneth E. Jansen     &            yold(nshg,ndof),   acold(nshg,ndof),
79559599516SKenneth E. Jansen     &            x(numnp,nsd),
79659599516SKenneth E. Jansen     &            iBC(nshg),         BC(nshg,ndofBC),
79759599516SKenneth E. Jansen     &            rest(nshg),
79859599516SKenneth E. Jansen     &            Diag(nshg),
79959599516SKenneth E. Jansen     &            HBrg(Kspace+1,*),  eBrg(*),
80059599516SKenneth E. Jansen     &            yBrg(*),           Rcos(*),
80159599516SKenneth E. Jansen     &            Rsin(*),           ilwork(nlwork),
80259599516SKenneth E. Jansen     &            iper(nshg),        EGmasst(numel,nshape,nshape)
80359599516SKenneth E. Jansenc
80459599516SKenneth E. Jansen        dimension Dyt(nshg),         rmest(nshg),
80559599516SKenneth E. Jansen     &            tempt(nshg),       Dinv(nshg),
80659599516SKenneth E. Jansen     &            uBrgt(nshg,Kspace+1)
80759599516SKenneth E. Jansenc
80859599516SKenneth E. Jansen        dimension shp(MAXTOP,maxsh,MAXQPT),
80959599516SKenneth E. Jansen     &            shgl(MAXTOP,nsd,maxsh,MAXQPT),
81059599516SKenneth E. Jansen     &            shpb(MAXTOP,maxsh,MAXQPT),
81159599516SKenneth E. Jansen     &            shglb(MAXTOP,nsd,maxsh,MAXQPT)
81259599516SKenneth E. Jansen        real*8    elDw(numel)
81359599516SKenneth E. Jansenc
81459599516SKenneth E. Jansenc.... *******************>> Element Data Formation <<******************
81559599516SKenneth E. Jansenc
81659599516SKenneth E. Jansenc
81759599516SKenneth E. Jansenc.... form the LHS matrices, the residual vector, and the block
81859599516SKenneth E. Jansenc     diagonal preconditioner
81959599516SKenneth E. Jansenc
82059599516SKenneth E. Jansen        call ElmGMRSclr(y,             ac,
82159599516SKenneth E. Jansen     &                  x,             elDw,      shp,        shgl,
82259599516SKenneth E. Jansen     &                  iBC,           BC,
82359599516SKenneth E. Jansen     &                  shpb,          shglb,
82459599516SKenneth E. Jansen     &                  rest,
82559599516SKenneth E. Jansen     &                  rmest,         Diag,       iper,
82659599516SKenneth E. Jansen     &                  ilwork,        EGmasst)
82759599516SKenneth E. Jansenc
82859599516SKenneth E. Jansenc.... **********************>>    EBE - GMRES    <<********************
82959599516SKenneth E. Jansenc
83059599516SKenneth E. Jansen        call timer ('Solver  ')
83159599516SKenneth E. Jansenc
83259599516SKenneth E. Jansenc.... ------------------------> Initialization <-----------------------
83359599516SKenneth E. Jansenc
83459599516SKenneth E. Jansenc
83559599516SKenneth E. Jansen      id = isclr+5
83659599516SKenneth E. Jansenc.... initialize Dy
83759599516SKenneth E. Jansenc
83859599516SKenneth E. Jansen        Dyt = zero
83959599516SKenneth E. Jansenc
84059599516SKenneth E. Jansenc.... Right preconditioner
84159599516SKenneth E. Jansenc
84259599516SKenneth E. Jansen        call i3preSclr(Diag, Dinv, EGmassT, ilwork)
84359599516SKenneth E. Jansenc
84459599516SKenneth E. Jansenc Check the residual for divering trend
84559599516SKenneth E. Jansenc
846513954efSKenneth E. Jansen
84759599516SKenneth E. Jansen        call rstatCheckSclr(rest,ilwork,y,ac)
84859599516SKenneth E. Jansen
84959599516SKenneth E. Jansenc
85059599516SKenneth E. Jansenc.... copy rest in uBrgt(1)
85159599516SKenneth E. Jansenc
85259599516SKenneth E. Jansen        uBrgt(:,1) = rest
85359599516SKenneth E. Jansenc
85459599516SKenneth E. Jansenc.... calculate norm of residual
85559599516SKenneth E. Jansenc
85659599516SKenneth E. Jansen        tempt  = rest**2
85759599516SKenneth E. Jansen
85859599516SKenneth E. Jansen        call sumgat (tempt, 1, summed, ilwork)
85959599516SKenneth E. Jansen        unorm = sqrt(summed)
86059599516SKenneth E. Jansenc
86159599516SKenneth E. Jansenc.... check if GMRES iterations are required
86259599516SKenneth E. Jansenc
863513954efSKenneth E. Jansen        iKss    = 0
86459599516SKenneth E. Jansen        lGMRESt = 0
86559599516SKenneth E. Jansenc
86659599516SKenneth E. Jansenc.... if we are down to machine precision, don't bother solving
86759599516SKenneth E. Jansenc
86859599516SKenneth E. Jansen        if (unorm .lt. 100.*epsM**2) goto 3000
86959599516SKenneth E. Jansenc
87059599516SKenneth E. Jansenc.... set up tolerance of the Hessenberg's problem
87159599516SKenneth E. Jansenc
87259599516SKenneth E. Jansen        epsnrm = etol * unorm
87359599516SKenneth E. Jansenc
87459599516SKenneth E. Jansenc.... ------------------------>  GMRES Loop  <-------------------------
87559599516SKenneth E. Jansenc
87659599516SKenneth E. Jansenc.... loop through GMRES cycles
87759599516SKenneth E. Jansenc
87859599516SKenneth E. Jansen        do 2000 mGMRES = 1, nGMRES
87959599516SKenneth E. Jansen        lGMRESt = mGMRES - 1
88059599516SKenneth E. Jansenc
88159599516SKenneth E. Jansen        if (lGMRESt .gt. 0) then
88259599516SKenneth E. Jansenc
88359599516SKenneth E. Jansenc.... if GMRES restarts are necessary, calculate  R - A x
88459599516SKenneth E. Jansenc
88559599516SKenneth E. Jansenc
88659599516SKenneth E. Jansen
88759599516SKenneth E. Jansenc.... perform the A x product
88859599516SKenneth E. Jansenc
88959599516SKenneth E. Jansen           call Au1GMRSclr (EGmasst,  tempt,  ilwork, iper)
89059599516SKenneth E. Jansenc
89159599516SKenneth E. Jansenc.... periodic nodes have to assemble results to their partners
89259599516SKenneth E. Jansenc
89359599516SKenneth E. Jansenc          call bc3perSclr (iBC,  tempt,  iper)
89459599516SKenneth E. Jansenc
89559599516SKenneth E. Jansenc.... subtract A x from residual and calculate the norm
89659599516SKenneth E. Jansenc
89759599516SKenneth E. Jansen           tempt = rest - tempt
89859599516SKenneth E. Jansen           uBrgt(:,1) = tempt
89959599516SKenneth E. Jansenc
90059599516SKenneth E. Jansenc.... calculate the norm
90159599516SKenneth E. Jansenc
90259599516SKenneth E. Jansen           tempt  = tempt**2
90359599516SKenneth E. Jansen           call sumgat (tempt, 1, summed, ilwork)
90459599516SKenneth E. Jansen           unorm = sqrt(summed)
90559599516SKenneth E. Jansenc
90659599516SKenneth E. Jansenc.... flop count
90759599516SKenneth E. Jansenc
908f4d0b58bSKenneth E. Jansen      !      flops = flops + ndof*numnp+numnp
90959599516SKenneth E. Jansenc
91059599516SKenneth E. Jansen        endif
91159599516SKenneth E. Jansenc
91259599516SKenneth E. Jansenc.... set up RHS of the Hessenberg's problem
91359599516SKenneth E. Jansenc
91459599516SKenneth E. Jansen        call clear (eBrg, Kspace+1)
91559599516SKenneth E. Jansen        call clear (HBrg, Kspace+1)
91659599516SKenneth E. Jansen        eBrg(1) = unorm
91759599516SKenneth E. Jansenc
91859599516SKenneth E. Jansenc.... normalize the first Krylov vector
91959599516SKenneth E. Jansenc
92059599516SKenneth E. Jansen        uBrgt(:,1) = uBrgt(:,1) / unorm
92159599516SKenneth E. Jansenc
92259599516SKenneth E. Jansenc.... loop through GMRES iterations
92359599516SKenneth E. Jansenc
92459599516SKenneth E. Jansen        do 1000 iK = 1, Kspace
925513954efSKenneth E. Jansen           iKss = iK
92659599516SKenneth E. Jansen
927513954efSKenneth E. Jansen           uBrgt(:,iKss+1) = uBrgt(:,iKss)
92859599516SKenneth E. Jansen
92959599516SKenneth E. Jansenc.... Au product  ( u_{i+1} <-- EGmass u_{i+1} )
93059599516SKenneth E. Jansenc
931513954efSKenneth E. Jansen           call Au1GMRSclr ( EGmasst, uBrgt(:,iKss+1),  ilwork, iper )
93259599516SKenneth E. Jansen
93359599516SKenneth E. Jansenc
93459599516SKenneth E. Jansenc.... periodic nodes have to assemble results to their partners
93559599516SKenneth E. Jansenc
936513954efSKenneth E. Jansen           call bc3perSclr (iBC,  uBrgt(:,iKss+1),  iper)
93759599516SKenneth E. Jansenc
93859599516SKenneth E. Jansenc.... orthogonalize and get the norm
93959599516SKenneth E. Jansenc
940513954efSKenneth E. Jansen          do jK = 1, iKss+1
94159599516SKenneth E. Jansenc
94259599516SKenneth E. Jansen            if (jK .eq. 1) then
94359599516SKenneth E. Jansenc
944513954efSKenneth E. Jansen              tempt = uBrgt(:,iKss+1) * uBrgt(:,1)  ! {u_{i+1}*u_1} vector
94559599516SKenneth E. Jansen              call sumgat (tempt, 1, beta, ilwork) ! sum vector=(u_{i+1},u_1)
94659599516SKenneth E. Jansenc
94759599516SKenneth E. Jansen            else
94859599516SKenneth E. Jansenc
94959599516SKenneth E. Jansenc project off jK-1 vector
95059599516SKenneth E. Jansenc
951513954efSKenneth E. Jansen          uBrgt(:,iKss+1) = uBrgt(:,iKss+1) - beta * uBrgt(:,jK-1)
95259599516SKenneth E. Jansenc
953513954efSKenneth E. Jansen              tempt = uBrgt(:,iKss+1) * uBrgt(:,jK) !{u_{i+1}*u_j} vector
95459599516SKenneth E. Jansen              call sumgat (tempt, 1, beta, ilwork) ! sum vector=(u_{i+1},u_j)
95559599516SKenneth E. Jansenc
95659599516SKenneth E. Jansen            endif
95759599516SKenneth E. Jansenc
958513954efSKenneth E. Jansen            HBrg(jK,iKss) = beta   ! put this in the Hessenberg Matrix
95959599516SKenneth E. Jansenc
96059599516SKenneth E. Jansen        enddo
96159599516SKenneth E. Jansenc
962f4d0b58bSKenneth E. Jansen   !      flops = flops + (3*iKss+1)*ndof*numnp+(iKss+1)*numnp
96359599516SKenneth E. Jansenc
96459599516SKenneth E. Jansenc  the last inner product was with what was left of the vector (after
96559599516SKenneth E. Jansenc  projecting off all of the previous vectors
96659599516SKenneth E. Jansenc
96759599516SKenneth E. Jansen        unorm           = sqrt(beta)
968513954efSKenneth E. Jansen        HBrg(iKss+1,iKss) = unorm   ! this fills the 1 sub diagonal band
96959599516SKenneth E. Jansenc
97059599516SKenneth E. Jansenc.... normalize the Krylov vector
97159599516SKenneth E. Jansenc
972513954efSKenneth E. Jansen        uBrgt(:,iKss+1) = uBrgt(:,iKss+1) / unorm  ! normalize the next Krylov
97359599516SKenneth E. Jansenc vector
97459599516SKenneth E. Jansenc
97559599516SKenneth E. Jansenc.... construct and reduce the Hessenberg Matrix
97659599516SKenneth E. Jansenc  since there is only one subdiagonal we can use a Givens rotation to
97759599516SKenneth E. Jansenc  rotate off each subdiagonal AS IT IS FORMED.   We do this because it
97859599516SKenneth E. Jansenc  allows us to check progress of solution and quit when satisfied.  Note
97959599516SKenneth E. Jansenc  that all future K vects will put a subdiagonal in the next column so
98059599516SKenneth E. Jansenc  there is no penalty to work ahead as  the rotation for the next vector
98159599516SKenneth E. Jansenc  will be unaffected by this rotation.
98259599516SKenneth E. Jansen
98359599516SKenneth E. Jansenc
98459599516SKenneth E. Jansenc     H Y = E ========>   R_i H Y = R_i E
98559599516SKenneth E. Jansenc
986513954efSKenneth E. Jansen           do jK = 1, iKss-1
987513954efSKenneth E. Jansen              tmp            =  Rcos(jK) * HBrg(jK,  iKss) +
988513954efSKenneth E. Jansen     &                          Rsin(jK) * HBrg(jK+1,iKss)
989513954efSKenneth E. Jansen              HBrg(jK+1,iKss) = -Rsin(jK) * HBrg(jK,  iKss) +
990513954efSKenneth E. Jansen     &                          Rcos(jK) * HBrg(jK+1,iKss)
991513954efSKenneth E. Jansen              HBrg(jK,  iKss) =  tmp
99259599516SKenneth E. Jansen           enddo
99359599516SKenneth E. Jansenc
994513954efSKenneth E. Jansen           tmp        = sqrt(HBrg(iKss,iKss)**2 + HBrg(iKss+1,iKss)**2)
995513954efSKenneth E. Jansen           Rcos(iKss) = HBrg(iKss,  iKss) / tmp
996513954efSKenneth E. Jansen           Rsin(iKss) = HBrg(iKss+1,iKss) / tmp
997513954efSKenneth E. Jansen           HBrg(iKss,  iKss) = tmp
998513954efSKenneth E. Jansen           HBrg(iKss+1,iKss) = zero
99959599516SKenneth E. Jansenc
100059599516SKenneth E. Jansenc.... rotate eBrg    R_i E
100159599516SKenneth E. Jansenc
1002513954efSKenneth E. Jansen           tmp         = Rcos(iKss)*eBrg(iKss) + Rsin(iKss)*eBrg(iKss+1)
1003513954efSKenneth E. Jansen           eBrg(iKss+1)=-Rsin(iKss)*eBrg(iKss) + Rcos(iKss)*eBrg(iKss+1)
1004513954efSKenneth E. Jansen           eBrg(iKss)  = tmp
100559599516SKenneth E. Jansenc
100659599516SKenneth E. Jansenc.... check for convergence
100759599516SKenneth E. Jansenc
1008513954efSKenneth E. Jansen           ercheck=eBrg(iKss+1)
1009513954efSKenneth E. Jansen           ntotGMs = ntotGMs + 1
1010513954efSKenneth E. Jansen           if (abs(eBrg(iKss+1)) .le. epsnrm) exit
101159599516SKenneth E. Jansenc
101259599516SKenneth E. Jansenc.... end of GMRES iteration loop
101359599516SKenneth E. Jansenc
101459599516SKenneth E. Jansen 1000   continue
101559599516SKenneth E. Jansenc
101659599516SKenneth E. Jansenc.... ------------------------->   Solution   <------------------------
101759599516SKenneth E. Jansenc
101859599516SKenneth E. Jansenc.... if converged or end of Krylov space
101959599516SKenneth E. Jansenc
102059599516SKenneth E. Jansenc.... solve for yBrg
102159599516SKenneth E. Jansenc
1022513954efSKenneth E. Jansen        do jK = iKss, 1, -1
102359599516SKenneth E. Jansen           yBrg(jK) = eBrg(jK) / HBrg(jK,jK)
102459599516SKenneth E. Jansen           do lK = 1, jK-1
102559599516SKenneth E. Jansen              eBrg(lK) = eBrg(lK) - yBrg(jK) * HBrg(lK,jK)
102659599516SKenneth E. Jansen           enddo
102759599516SKenneth E. Jansen        enddo
102859599516SKenneth E. Jansenc
102959599516SKenneth E. Jansenc.... update Dy
103059599516SKenneth E. Jansenc
1031513954efSKenneth E. Jansen        do jK = 1, iKss
103259599516SKenneth E. Jansen           Dyt = Dyt + yBrg(jK) * uBrgt(:,jK)
103359599516SKenneth E. Jansen        enddo
103459599516SKenneth E. Jansenc
103559599516SKenneth E. Jansenc.... flop count
103659599516SKenneth E. Jansenc
1037f4d0b58bSKenneth E. Jansen   !      flops = flops + (3*iKss+1)*ndof*numnp
103859599516SKenneth E. Jansenc
103959599516SKenneth E. Jansenc.... check for convergence
104059599516SKenneth E. Jansenc
1041513954efSKenneth E. Jansen        if (abs(eBrg(iKss+1)) .le. epsnrm) exit
104259599516SKenneth E. Jansenc
104359599516SKenneth E. Jansenc.... end of mGMRES loop
104459599516SKenneth E. Jansenc
104559599516SKenneth E. Jansen 2000 continue
104659599516SKenneth E. Jansenc
104759599516SKenneth E. Jansenc.... ------------------------>   Converged   <------------------------
104859599516SKenneth E. Jansenc
104959599516SKenneth E. Jansenc.... if converged
105059599516SKenneth E. Jansenc
105159599516SKenneth E. Jansen 3000 continue
105259599516SKenneth E. Jansenc
105359599516SKenneth E. Jansenc.... back precondition the result
105459599516SKenneth E. Jansenc
105559599516SKenneth E. Jansen      Dyt(:) = Dyt(:) * Dinv(:)
105659599516SKenneth E. Jansenc
105759599516SKenneth E. Jansenc.... output the statistics
105859599516SKenneth E. Jansenc
1059513954efSKenneth E. Jansen      call rstatSclr(rest, ilwork)
106059599516SKenneth E. Jansenc.... stop the timer
106159599516SKenneth E. Jansenc
106259599516SKenneth E. Jansen 3002 continue                  ! no solve just res.
106359599516SKenneth E. Jansen      call timer ('Back    ')
106459599516SKenneth E. Jansenc
106559599516SKenneth E. Jansenc.... end
106659599516SKenneth E. Jansenc
106759599516SKenneth E. Jansen      return
106859599516SKenneth E. Jansen      end
106959599516SKenneth E. Jansen
107059599516SKenneth E. Jansen
1071