LCOV - code coverage report
Current view: top level - ionosphere/waccmx - edyn_mud.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 236 485 48.7 %
Date: 2025-03-14 01:26:08 Functions: 7 9 77.8 %

          Line data    Source code
       1             : module edyn_mud
       2             :   use shr_kind_mod,only: r8 => shr_kind_r8
       3             :   use cam_abortutils,only: endrun
       4             :   use edyn_mudcom, only: cor2, res2, factri, factrp, prolon2, trsfc2, swk2
       5             : 
       6             :   implicit none
       7             : 
       8             :   private
       9             : 
      10             :   public :: mud2cr1
      11             :   public :: dismd2cr
      12             :   public :: adjmd2cr
      13             :   public :: kcymd2cr
      14             :   public :: relmd2cr
      15             :   public :: resmd2cr
      16             : 
      17             :   contains
      18             : !-----------------------------------------------------------------------
      19             : !
      20             : !     file mud2cr.f  (version 4.0 modified for Cicley 2/99)
      21             : !                                                             .
      22             : !  .                      MUDPACK version 4.0                    .
      23             : !  .                                                             .
      24             : ! ... author and specialist
      25             : !
      26             : !          John C. Adams (National Center for Atmospheric Research) (retired)
      27             : !
      28             : ! ... For MUDPACK information, visit the website:
      29             : !     (https://www2.cisl.ucar.edu/resources/legacy/mudpack)
      30             : !
      31             : ! ... purpose
      32             : !
      33             : !     mud2cr attempts to produce a second order finite difference
      34             : !     approximation to the two dimensional nonseparable elliptic
      35             : !     partial differential equation with cross derivative
      36             : !
      37             : !       cxx(x,y)*pxx + cxy(x,y)*pxy + cyy(x,y)*pyy +
      38             : !
      39             : !       cx(x,y)*px + cy(x,y)*py + ce(x,y)*pe(x,y) = r(x,y)
      40             : !
      41             : ! ... documentation
      42             : !
      43             : !     see the documentation on above website for a complete discussion
      44             : !     of how to use subroutine mud2cr.
      45             : !
      46             : ! ... required MUDPACK files
      47             : !
      48             : !     mudcom.f
      49             : !
      50             : !
      51             : !
      52       33516 :       subroutine mud2cr(iparm,fparm,work,rhs,phi,mgopt, &
      53             :                         ierror,isolve)
      54             : 
      55             :       integer,intent(in) :: isolve
      56             :       integer iparm,mgopt,ierror
      57             :       integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess, &
      58             :                    maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur, &
      59             :                    kcycle,iprer,ipost,intpol,kps
      60             :       real(r8) :: fparm,xa,xb,yc,yd,tolmax,relmax
      61             :       integer kpbgn,kcbgn,ktxbgn,ktybgn,nxk,nyk,isx,jsy
      62             :       integer int,iw,k,kb,nx,ny,ic,itx,ity
      63             :       dimension iparm(17),fparm(6),mgopt(4)
      64             :       real(r8) :: work(*),phi(*),rhs(*)
      65             :       common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy, &
      66             :                      iguess, maxcy,method,nwork,lwork,itero,ngrid, &
      67             :                      klevel,kcur,kcycle,iprer,ipost,intpol,kps
      68             :       common/fmud2cr/xa,xb,yc,yd,tolmax,relmax
      69             :       common/mud2crc/kpbgn(50),kcbgn(50),ktxbgn(50),ktybgn(50), &
      70             :         nxk(50),nyk(50),isx,jsy
      71             :       data int / 0 /
      72             :       save int
      73             : !
      74             :       ierror = 1
      75             :       intl = iparm(1)    ! set and check intl on all calls
      76             :       if (intl*(intl-1).ne.0) return
      77             :       if (int.eq.0) then
      78             :         int = 1
      79             :         if (intl.ne.0) return  ! very first call is not intl=0
      80             :       end if
      81             :       ierror = 0
      82             : !
      83             : !     set  arguments internally
      84             : !     these will not be rechecked if intl=1!
      85             : !
      86             :       nxa = iparm(2)
      87             :       nxb = iparm(3)
      88             :       nyc = iparm(4)
      89             :       nyd = iparm(5)
      90             :       ixp = iparm(6)
      91             :       jyq = iparm(7)
      92             :       iex = iparm(8)
      93             :       jey = iparm(9)
      94             :       ngrid = max0(iex,jey)
      95             :       nfx = iparm(10)
      96             :       nfy = iparm(11)
      97             :       iguess = iparm(12)
      98             :       maxcy = iparm(13)
      99             :       method = iparm(14)
     100             :       nwork = iparm(15)
     101             :       kcycle = mgopt(1)
     102             :       if (kcycle .eq. 0) then
     103             : !       set defaults
     104             :         kcycle = 2
     105             :         iprer = 2
     106             :         ipost = 1
     107             :         intpol = 3
     108             :       else
     109             :         iprer = mgopt(2)
     110             :         ipost = mgopt(3)
     111             :         intpol = mgopt(4)
     112             :       end if
     113             :       xa = fparm(1)
     114             :       xb = fparm(2)
     115             :       yc = fparm(3)
     116             :       yd = fparm(4)
     117             :       tolmax = fparm(5)
     118             :       if (intl .eq. 0) then  ! intialization call
     119             : !
     120             : !     check input arguments
     121             : !
     122             :         ierror = 2   ! check boundary condition flags
     123             :         if (max0(nxa,nxb,nyc,nyd).gt.2) return
     124             :         if (min0(nxa,nxb,nyc,nyd).lt.0) return
     125             :         if (nxa.eq.0.and.nxb.ne.0) return
     126             :         if (nxa.ne.0.and.nxb.eq.0) return
     127             :         if (nyc.eq.0.and.nyd.ne.0) return
     128             :         if (nyc.ne.0.and.nyd.eq.0) return
     129             :         ierror = 3   ! check grid sizes
     130             :         if (ixp.lt.2) return
     131             :         if (jyq.lt.2) return
     132             :         ierror = 4
     133             :         ngrid = max0(iex,jey)
     134             :         if (iex.lt.1) return
     135             :         if (jey.lt.1) return
     136             :         if (ngrid.gt.50) return
     137             :         ierror = 5
     138             :         if (nfx.ne.ixp*2**(iex-1)+1) return
     139             :         if (nfy.ne.jyq*2**(jey-1)+1) return
     140             :         ierror = 6
     141             :         if (iguess*(iguess-1).ne.0) return
     142             :         ierror = 7
     143             :         if (maxcy.lt.1) return
     144             :         ierror = 8
     145             :         if (method.lt.0 .or. method.gt.3) return
     146             :         ierror = 9
     147             : !       compute and test minimum work space
     148             :         isx = 0
     149             :         if (method.eq.1 .or. method.eq.3) then
     150             :           if (nxa.ne.0) isx = 3
     151             :           if (nxa.eq.0) isx = 5
     152             :         end if
     153             :         jsy = 0
     154             :         if (method.eq.2 .or. method.eq.3) then
     155             :           if (nyc.ne.0) jsy = 3
     156             :           if (nyc.eq.0) jsy = 5
     157             :         end if
     158             :         kps = 1
     159             :         do k=1,ngrid
     160             : !       set subgrid sizes
     161             :           nxk(k) = ixp*2**(max0(k+iex-ngrid,1)-1)+1
     162             :           nyk(k) = jyq*2**(max0(k+jey-ngrid,1)-1)+1
     163             :           nx = nxk(k)
     164             :           ny = nyk(k)
     165             :           kps = kps+(nx+2)*(ny+2)+nx*ny*(10+isx+jsy)
     166             :         end do
     167             :         iparm(16) = kps+(nfx+2)*(nfy+2)   ! exact minimum work space
     168             :         lwork = iparm(16)
     169             :         if (lwork .gt. nwork) return
     170             :         ierror = 10   ! check solution region
     171             :         if (xb.le.xa .or. yd.le.yc) return
     172             :         ierror = 11
     173             :         if (tolmax .lt. 0.0_r8) return
     174             :         ierror = 12   ! multigrid parameters
     175             :         if (kcycle.lt.0) return
     176             :         if (min0(iprer,ipost).lt.1) return
     177             :         if ((intpol-1)*(intpol-3).ne.0) return
     178             :         if (max0(kcycle,iprer,ipost).gt.2) then
     179             :           ierror = -5   ! inefficient multigrid cycling
     180             :         end if
     181             :         if (ierror .gt. 0) ierror = 0   ! no fatal errors
     182             : !
     183             : !     set work space pointers and discretize pde at each grid level
     184             : !
     185             :         iw = 1
     186             :         do kb=1,ngrid
     187             :           k = ngrid-kb+1
     188             :           nx = nxk(k)
     189             :           ny = nyk(k)
     190             :           kpbgn(k) = iw
     191             :           kcbgn(k) = kpbgn(k)+(nx+2)*(ny+2)
     192             :           ktxbgn(k) = kcbgn(k)+10*nx*ny
     193             :           ktybgn(k) = ktxbgn(k)+isx*nx*ny
     194             :           iw = ktybgn(k)+jsy*nx*ny
     195             :           ic = kcbgn(k)
     196             :           itx = ktxbgn(k)
     197             :           ity = ktybgn(k)
     198             :           klevel = k
     199             :           call dismd2cr(nx,ny,work(ic),work(itx),work(ity), &
     200             :                         work,ierror,isolve)
     201             :           end do
     202             :         return
     203             :       end if   ! end of intl=0 initialization call block
     204             :       nx = nfx
     205             :       ny = nfy
     206             :       call mud2cr1(nx,ny,rhs,phi,work)
     207             :       iparm(17) = itero
     208             :       if (tolmax.gt.0.0_r8) then   ! check for convergence
     209             :         fparm(6) = relmax
     210             :         if (relmax.gt.tolmax) ierror = -1   ! flag convergenc failure
     211             :       end if
     212             :       return
     213             :       end subroutine mud2cr
     214             : !-----------------------------------------------------------------------
     215           0 :       subroutine mud2cr1(nx,ny,rhsf,phif,wk)
     216             : 
     217             :       integer nx,ny
     218             :       real(r8) :: phif(nx,ny),rhsf(nx,ny),wk(*)
     219             :       integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess,&
     220             :                    maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur,&
     221             :                    kcycle,iprer,ipost,intpol,kps
     222             :       real(r8) :: xa,xb,yc,yd,tolmax,relmax,phmax
     223             :       integer kpbgn,kcbgn,ktxbgn,ktybgn,nxk,nyk,isx,jsy
     224             :       integer k,kb,ip,ic,ir,ipc,irc,icc
     225             :       integer ncx,ncy,jj,ij,i,j,iter
     226             :       common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,&
     227             :                      iguess, maxcy,method,nwork,lwork,itero,ngrid,&
     228             :                      klevel,kcur,kcycle,iprer,ipost,intpol,kps
     229             :       common/fmud2cr/xa,xb,yc,yd,tolmax,relmax
     230             :       common/mud2crc/kpbgn(50),kcbgn(50),ktxbgn(50),ktybgn(50),&
     231             :       nxk(50),nyk(50),isx,jsy
     232           0 :       nx = nxk(ngrid)
     233           0 :       ny = nyk(ngrid)
     234           0 :       ip = kpbgn(ngrid)
     235           0 :       ic = kcbgn(ngrid)
     236           0 :       ir = ic+9*nx*ny
     237             : !
     238             : !     set phif,rhsf in wk and adjust right hand side
     239             : !
     240           0 :       call swk2(nx,ny,phif,rhsf,wk(ip),wk(ir))
     241           0 :       if (iguess.eq.0) then
     242             : !
     243             : !     no initial guess at finest grid level!
     244             : !
     245           0 :         do kb=2,ngrid
     246           0 :           k = ngrid-kb+1
     247           0 :           nx = nxk(k+1)
     248           0 :           ny = nyk(k+1)
     249           0 :           ip = kpbgn(k+1)
     250           0 :           ir = kcbgn(k+1)+9*nx*ny
     251           0 :           ncx = nxk(k)
     252           0 :           ncy = nyk(k)
     253           0 :           ipc = kpbgn(k)
     254           0 :           icc = kcbgn(k)
     255           0 :           irc = icc+9*ncx*ncy
     256             : !
     257             : !     transfer down to all grid levels
     258             : !
     259           0 :           call trsfc2(nx,ny,wk(ip),wk(ir),ncx,ncy,&
     260           0 :                       wk(ipc),wk(irc))
     261             :         end do
     262             : !
     263             : !     adjust right hand side at all grid levels in case
     264             : !     rhs or specified b.c. in phi or gbdy changed
     265             : !
     266           0 :         do k=1,ngrid
     267           0 :           nx = nxk(k)
     268           0 :           ny = nyk(k)
     269           0 :           ip = kpbgn(k)
     270           0 :           ic = kcbgn(k)
     271           0 :           call adjmd2cr(nx,ny,wk(ip),wk(ic))
     272             :         end do
     273             : !
     274             : !     execute one full multigrid cycle
     275             : !
     276           0 :         do k=1,ngrid-1
     277           0 :           kcur = k
     278           0 :           call kcymd2cr(wk)
     279           0 :           nx = nxk(k+1)
     280           0 :           ny = nyk(k+1)
     281           0 :           ip = kpbgn(k+1)
     282           0 :           ipc = kpbgn(k)
     283           0 :           ncx = nxk(k)
     284           0 :           ncy = nyk(k)
     285             : !
     286             : !     lift or prolong approximation from k to k+1
     287             : !
     288           0 :           call prolon2(ncx,ncy,wk(ipc),nx,ny,wk(ip),nxa,nxb,&
     289           0 :                        nyc,nyd,intpol)
     290             :         end do
     291             :       else
     292             : !
     293             : !     adjust rhs at finest grid level only
     294             : !
     295           0 :         nx = nxk(ngrid)
     296           0 :         ny = nyk(ngrid)
     297           0 :         ip = kpbgn(ngrid)
     298           0 :         ic = kcbgn(ngrid)
     299           0 :         call adjmd2cr(nx,ny,wk(ip),wk(ic))
     300             :       end if
     301             : !
     302             : !     execute maxcy more multigrid k cycles from finest level
     303             : !
     304           0 :       kcur = ngrid
     305           0 :       do iter=1,maxcy
     306           0 :         itero = iter
     307           0 :         call kcymd2cr(wk)
     308           0 :         if (tolmax.gt.0.0_r8) then
     309             : !
     310             : !      error control
     311             : !
     312           0 :           relmax = 0.0_r8
     313           0 :           phmax = 0.0_r8
     314           0 :           do j=1,nfy
     315           0 :             jj = j*(nfx+2)
     316           0 :             do i=1,nfx
     317           0 :               ij = jj+i+1
     318             : !             phmax = amax1(phmax,abs(wk(ij)))
     319             : !             relmax = amax1(relmax,abs(wk(ij)-phif(i,j)))
     320           0 :               phmax = max(phmax,abs(wk(ij)))
     321           0 :               relmax = max(relmax,abs(wk(ij)-phif(i,j)))
     322           0 :               phif(i,j) = wk(ij)
     323             :             end do
     324             :           end do
     325             : !
     326             : !     set maximum relative difference and check for convergence
     327             : !
     328           0 :           if (phmax.gt.0.0_r8) relmax = relmax/phmax
     329           0 :           if (relmax.le.tolmax) return
     330             :         end if
     331             :       end do
     332             : !
     333             : !     set final interate after maxcy cycles in phif
     334             : !
     335           0 :       do j=1,nfy
     336           0 :         jj = j*(nfx+2)
     337           0 :         do i=1,nfx
     338           0 :           ij = jj+i+1
     339           0 :           phif(i,j) = wk(ij)
     340             :         end do
     341             :       end do
     342             :       return
     343             :       end subroutine mud2cr1
     344             : !-----------------------------------------------------------------------
     345         133 :       subroutine kcymd2cr(wk)
     346             : !
     347             : !     execute multigrid k cycle from kcur grid level
     348             : !     kcycle=1 for v cycles, kcycle=2 for w cycles
     349             : !
     350             :       real(r8) :: wk(*)
     351             :       integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess,&
     352             :                    maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur,&
     353             :                    kcycle,iprer,ipost,intpol,kps
     354             :       integer nx,ny,ip,ic,ipc,irc,itx,ity,ncx,ncy,l,nrel
     355             :       real(r8) :: xa,xb,yc,yd,tolmax,relmax
     356             :       integer kpbgn,kcbgn,ktxbgn,ktybgn,nxk,nyk,isx,jsy
     357             :       common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,&
     358             :                      iguess, maxcy,method,nwork,lwork,itero,ngrid,&
     359             :                      klevel,kcur,kcycle,iprer,ipost,intpol,kps
     360             :       common/fmud2cr/xa,xb,yc,yd,tolmax,relmax
     361             :       common/mud2crc/kpbgn(50),kcbgn(50),ktxbgn(50),ktybgn(50),&
     362             :         nxk(50),nyk(50),isx,jsy
     363             :       integer kount(50)
     364          76 :       klevel = kcur
     365          76 :       nx = nxk(klevel)
     366          76 :       ny = nyk(klevel)
     367          76 :       ip = kpbgn(klevel)
     368          76 :       ic = kcbgn(klevel)
     369          76 :       itx = ktxbgn(klevel)
     370          76 :       ity = ktybgn(klevel)
     371             : !
     372             : !     prerelax at current finest grid level
     373             : !
     374         304 :       do l=1,iprer
     375         532 :         call relmd2cr(nx,ny,wk(ip),wk(ic),wk(itx),wk(ity),wk(kps))
     376             :       end do
     377          76 :       if (kcur .eq. 1) go to 5
     378             : !
     379             : !     restrict residual to kcur-1 level
     380             : !
     381          57 :       ipc = kpbgn(klevel-1)
     382          57 :       ncx = nxk(klevel-1)
     383          57 :       ncy = nyk(klevel-1)
     384          57 :       irc = kcbgn(klevel-1)+9*ncx*ncy
     385         114 :       call resmd2cr(nx,ny,wk(ip),ncx,ncy,wk(ipc),wk(irc),wk(ic),wk(kps))
     386             : !
     387             : !    set counter for grid levels to zero
     388             : !
     389         228 :       do l = 1,kcur
     390         228 :         kount(l) = 0
     391             :       end do
     392             : !
     393             : !    set new grid level and continue k-cycling
     394             : !
     395          57 :       klevel = kcur-1
     396          57 :       nrel = iprer
     397             : !
     398             : !   kcycle control point
     399             : !
     400             :    10 continue
     401             : !
     402             : !      post relax when kcur revisited
     403             : !
     404         418 :       if (klevel .eq. kcur) go to 5
     405             : !
     406             : !   count hit at current level
     407             : !
     408         361 :       kount(klevel) = kount(klevel)+1
     409             : !
     410             : !   relax at current level
     411             : !
     412         361 :       nx = nxk(klevel)
     413         361 :       ny = nyk(klevel)
     414         361 :       ip = kpbgn(klevel)
     415         361 :       ic = kcbgn(klevel)
     416         361 :       itx = ktxbgn(klevel)
     417         361 :       ity = ktybgn(klevel)
     418        1292 :       do l=1,nrel
     419        2223 :         call relmd2cr(nx,ny,wk(ip),wk(ic),wk(itx),wk(ity),wk(kps))
     420             :       end do
     421         361 :       if (kount(klevel) .eq. kcycle+1) then
     422             : !
     423             : !     kcycle complete at klevel
     424             : !
     425          95 :         ipc = ip
     426          95 :         ip = kpbgn(klevel+1)
     427          95 :         ncx = nxk(klevel)
     428          95 :         ncy = nyk(klevel)
     429          95 :         nx = nxk(klevel+1)
     430          95 :         ny = nyk(klevel+1)
     431             : !
     432             : !    inject correction to finer grid
     433             : !
     434           0 :         call cor2(nx,ny,wk(ip),ncx,ncy,wk(ipc),nxa,nxb,nyc,nyd,&
     435         190 :                   intpol,wk(kps))
     436             : !
     437             : !    reset counter to zero
     438             : !
     439          95 :         kount(klevel) = 0
     440             : !
     441             : !     ascend to next higher level and set to postrelax there
     442             : !
     443          95 :         klevel = klevel+1
     444          95 :         nrel = ipost
     445          95 :         go to 10
     446             :       else
     447         266 :         if (klevel .gt. 1) then
     448             : !
     449             : !    kcycle not complete so descend unless at coarsest grid
     450             : !
     451         152 :           ipc = kpbgn(klevel-1)
     452         152 :           ncx = nxk(klevel-1)
     453         152 :           ncy = nyk(klevel-1)
     454         152 :           irc = kcbgn(klevel-1)+9*ncx*ncy
     455           0 :           call resmd2cr(nx,ny,wk(ip),ncx,ncy,wk(ipc),wk(irc),wk(ic),&
     456         304 :                       wk(kps))
     457             : !
     458             : !     prerelax at next coarser level
     459             : !
     460         152 :           klevel = klevel-1
     461         152 :           nrel = iprer
     462         152 :           go to 10
     463             :         else
     464             : !
     465             : !    postrelax at coarsest level
     466             : !
     467         342 :           do l=1,ipost
     468         570 :             call relmd2cr(nx,ny,wk(ip),wk(ic),wk(itx),wk(ity),wk(kps))
     469             :           end do
     470         114 :           ipc = ip
     471         114 :           ip = kpbgn(2)
     472         114 :           ncx = nxk(1)
     473         114 :           ncy = nyk(1)
     474         114 :           nx = nxk(2)
     475         114 :           ny = nyk(2)
     476             : !
     477             : !    inject correction to level 2
     478             : !
     479           0 :         call cor2(nx,ny,wk(ip),ncx,ncy,wk(ipc),nxa,nxb,nyc,nyd,&
     480         228 :                   intpol,wk(kps))
     481             : !
     482             : !     set to postrelax at level 2
     483             : !
     484         114 :           nrel = ipost
     485         114 :           klevel = 2
     486         190 :           go to 10
     487             :         end if
     488             :       end if
     489             :     5 continue
     490             : !
     491             : !     post relax at current finest grid level
     492             : !
     493          76 :       nx = nxk(kcur)
     494          76 :       ny = nyk(kcur)
     495          76 :       ip = kpbgn(kcur)
     496          76 :       ic = kcbgn(kcur)
     497          76 :       itx = ktxbgn(kcur)
     498          76 :       ity = ktybgn(kcur)
     499         228 :       do l=1,ipost
     500         380 :         call relmd2cr(nx,ny,wk(ip),wk(ic),wk(itx),wk(ity),wk(kps))
     501             :       end do
     502          76 :       return
     503           0 :       end subroutine kcymd2cr
     504             : !-----------------------------------------------------------------------
     505          95 :       subroutine dismd2cr(nx,ny,cf,tx,ty,wk,ier,isolve)
     506        3572 :       use edyn_solver_coefs,only:    nc,cee,ceee
     507             :       use edyn_maggrid, only: res_nlev
     508             : !
     509             : !     discretize elliptic pde for mud2cr, set nonfatal errors
     510             : !
     511             :       integer,intent(in) :: isolve
     512             :       integer nx,ny,i,j,l,im1,jm1,ier,nnx,nny
     513             :       real(r8) :: cf(nx,ny,10),tx(nx,ny,*),ty(ny,nx,*)
     514             :       real(r8) :: wk(*)
     515             :       integer        intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,&
     516             :                      iguess, maxcy,method,nwork,lwork,itero,ngrid,&
     517             :                      klevel,kcur,kcycle,iprer,ipost,intpol,kps
     518             :       common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,&
     519             :                      iguess, maxcy,method,nwork,lwork,itero,ngrid,&
     520             :                      klevel,kcur,kcycle,iprer,ipost,intpol,kps
     521             : 
     522             :       real(r8) ::           xa,xb,yc,yd,tolmax,relmax
     523             :       common/fmud2cr/xa,xb,yc,yd,tolmax,relmax
     524             : !
     525             : !     CHECK FOR CONSISTENCYT WRT KLEVEL
     526             : !
     527          95 :       NNX = ixp*2**(KLEVEL-1)+1
     528          95 :       NNY = jyq*2**(KLEVEL-1)+1
     529          95 :       IF(NNX.NE.NX.OR.NNY.NE.NY)THEN
     530           0 :         call endrun('dismd2cr in mud')
     531             :       ENDIF
     532          95 :       if (isolve >= 0) then
     533          95 :         call ceee(cee(nc(res_nlev+1-klevel)),nx,ny,cf)
     534             :       endif
     535             : !
     536             : !     set coefficient for specified boundaries
     537             : !
     538          95 :       if (nxa.eq.1) then
     539           0 :         i = 1
     540           0 :         do j=1,ny
     541           0 :           do l=1,9
     542           0 :             cf(i,j,l) = 0.0_r8
     543             :           end do
     544           0 :           cf(i,j,9) = 1.0_r8
     545             :         end do
     546             :       end if
     547          95 :       if (nxb.eq.1) then
     548           0 :         i = nx
     549           0 :         do j=1,ny
     550           0 :           do l=1,9
     551           0 :             cf(i,j,l) = 0.0_r8
     552             :           end do
     553           0 :           cf(i,j,9) = 1.0_r8
     554             :         end do
     555             :       end if
     556          95 :       if (nyc.eq.1) then
     557           0 :         j = 1
     558           0 :         do i=1,nx
     559           0 :           do l=1,9
     560           0 :             cf(i,j,l) = 0.0_r8
     561             :           end do
     562           0 :           cf(i,j,9) = 1.0_r8
     563             :         end do
     564             :       end if
     565          95 :       if (nyd.eq.1) then
     566          95 :         j = ny
     567        3135 :         do i=1,nx
     568       30400 :           do l=1,9
     569       30400 :             cf(i,j,l) = 0.0_r8
     570             :           end do
     571        3135 :           cf(i,j,9) = 1.0_r8
     572             :         end do
     573             :       end if
     574             : !
     575             : !     set and factor tridiagonal matrices for line relaxation(s) if flagged
     576             : !
     577          95 :       if (method.eq.1.or.method.eq.3) then
     578          95 :         if (nxa.ne.0) then
     579             : !
     580             : !    nonperiodic x line relaxation
     581             : !
     582           0 :           do i=1,nx
     583           0 :             im1 = max0(i-1,1)
     584           0 :             do j=1,ny
     585           0 :               tx(im1,j,1) = cf(i,j,5)
     586           0 :               tx(i,j,2) = cf(i,j,9)
     587           0 :               tx(i,j,3) = cf(i,j,1)
     588             :             end do
     589             :           end do
     590           0 :           call factri(ny,nx,tx(1,1,1),tx(1,1,2),tx(1,1,3))
     591             :         else
     592             : !
     593             : !     periodic x line relaxation
     594             : !
     595          95 :           if (nx .gt. 3) then
     596             : !
     597             : !     set and factor iff nx > 3
     598             : !
     599        3040 :             do i=1,nx-1
     600      103170 :               do j=1,ny
     601      100130 :                 tx(i,j,1) = cf(i,j,5)
     602      100130 :                 tx(i,j,2) = cf(i,j,9)
     603      103075 :                 tx(i,j,3) = cf(i,j,1)
     604             :               end do
     605             :             end do
     606          95 :             call factrp(ny,nx,tx,tx(1,1,2),tx(1,1,3),tx(1,1,4),&
     607          95 :                         tx(1,1,5),wk(kps))
     608             :           end if
     609             :         end if
     610             :       end if
     611             : 
     612          95 :       if (method.eq.2.or.method.eq.3) then
     613         190 :         if (nyc.ne.0) then
     614             : !
     615             : !     nonperiodic y line relaxation
     616             : !
     617        1957 :           do j=1,ny
     618        1862 :             jm1 = max0(j-1,1)
     619      103949 :             do i=1,nx
     620      101992 :               ty(jm1,i,1) = cf(i,j,7)
     621      101992 :               ty(j,i,2) = cf(i,j,9)
     622      103854 :               ty(j,i,3) = cf(i,j,3)
     623             :             end do
     624             :           end do
     625          95 :           call factri(nx,ny,ty(1,1,1),ty(1,1,2),ty(1,1,3))
     626             :         else
     627             : !
     628             : !      periodic y line relaxation
     629             : !
     630           0 :           if (ny .gt. 3) then
     631             : !
     632             : !     set and factor iff ny > 3
     633             : !
     634           0 :             do j=1,ny-1
     635           0 :               do i=1,nx
     636           0 :                 ty(j,i,1) = cf(i,j,7)
     637           0 :                 ty(j,i,2) = cf(i,j,9)
     638           0 :                 ty(j,i,3) = cf(i,j,3)
     639             :               end do
     640             :             end do
     641           0 :             call factrp(nx,ny,ty,ty(1,1,2),ty(1,1,3),ty(1,1,4),&
     642           0 :                         ty(1,1,5),wk(kps))
     643             :           end if
     644             :         end if
     645             :       end if
     646          95 :       return
     647             :       end subroutine dismd2cr
     648             : !-----------------------------------------------------------------------
     649          95 :       subroutine adjmd2cr(nx,ny,phi,cf)
     650             : !
     651             : !     adjust righthand side in cf(i,j,10) for boundary conditions
     652             : !
     653             :       integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess,&
     654             :                    maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur,&
     655             :                    kcycle,iprer,ipost,intpol,kps
     656             :       real(r8) :: xa,xb,yc,yd,tolmax,relmax
     657             :       integer nx,ny,i,j
     658             :       real(r8) :: cf(nx,ny,10),phi(0:nx+1,0:ny+1)
     659             :       common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,&
     660             :                      iguess, maxcy,method,nwork,lwork,itero,ngrid,&
     661             :                      klevel,kcur,kcycle,iprer,ipost,intpol,kps
     662             :       common/fmud2cr/xa,xb,yc,yd,tolmax,relmax
     663             : !
     664             : !     set specified boundaries in rhs from phi
     665             : !
     666          95 :       if (nxa.eq.1) then
     667           0 :         i = 1
     668           0 :         do j=1,ny
     669           0 :           cf(i,j,10) = phi(i,j)
     670             :         end do
     671             :       end if
     672          95 :       if (nxb.eq.1) then
     673           0 :         i = nx
     674           0 :         do j=1,ny
     675           0 :           cf(i,j,10) = phi(i,j)
     676             :         end do
     677             :       end if
     678          95 :       if (nyc.eq.1) then
     679           0 :         j = 1
     680           0 :         do i=1,nx
     681           0 :           cf(i,j,10) = phi(i,j)
     682             :         end do
     683             :       end if
     684          95 :       if (nyd.eq.1) then
     685          95 :         j = ny
     686        3135 :         do i=1,nx
     687        3135 :           cf(i,j,10) = phi(i,j)
     688             :         end do
     689             :       end if
     690          95 :       return
     691         665 :       end subroutine adjmd2cr
     692             : !-----------------------------------------------------------------------
     693        1273 :       subroutine resmd2cr(nx,ny,phi,ncx,ncy,phic,rhsc,cof,resf)
     694             : !
     695             : !     restrict residual from fine to coarse mesh using fully weighted
     696             : !     residual restriction
     697             : !
     698             :       integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess,&
     699             :                    maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur,&
     700             :                    kcycle,iprer,ipost,intpol,kps
     701             :       integer nx,ny,ncx,ncy,i,j,ic,jc
     702             :       common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,&
     703             :                      iguess, maxcy,method,nwork,lwork,itero,ngrid,&
     704             :                      klevel,kcur,kcycle,iprer,ipost,intpol,kps
     705             :       real(r8) :: rhsc(ncx,ncy),resf(nx,ny)
     706             :       real(r8) :: phi(0:nx+1,0:ny+1),phic(0:ncx+1,0:ncy+1)
     707             :       real(r8) :: cof(nx,ny,10)
     708             : !
     709             : !     set phic zero
     710             : !
     711       11533 :       do jc=0,ncy+1
     712      148333 :         do ic=0,ncx+1
     713      147060 :           phic(ic,jc) = 0.0_r8
     714             :         end do
     715             :       end do
     716             : !
     717             : !     compute residual on fine mesh in resf
     718             : !
     719       15428 :       do j=1,ny
     720      346313 :         do i=1,nx
     721      661770 :           resf(i,j) = cof(i,j,10)-(              &
     722      661770 :                       cof(i,j,1)*phi(i+1,j)+     &
     723      330885 :                       cof(i,j,2)*phi(i+1,j+1)+   &
     724      330885 :                       cof(i,j,3)*phi(i,j+1)+     &
     725      330885 :                       cof(i,j,4)*phi(i-1,j+1)+   &
     726             :                       cof(i,j,5)*phi(i-1,j)+     &
     727      330885 :                       cof(i,j,6)*phi(i-1,j-1)+   &
     728             :                       cof(i,j,7)*phi(i,j-1)+     &
     729             :                       cof(i,j,8)*phi(i+1,j-1)+   &
     730     2330350 :                       cof(i,j,9)*phi(i,j))
     731             :         end do
     732             :       end do
     733             : !
     734             : !     restrict resf to coarse mesh in rhsc
     735             : !
     736        1273 :       call res2(nx,ny,resf,ncx,ncy,rhsc,nxa,nxb,nyc,nyd)
     737        1273 :       return
     738          95 :       end subroutine resmd2cr
     739             : !-----------------------------------------------------------------------
     740        8379 :       subroutine relmd2cr(nx,ny,phi,cof,tx,ty,sum)
     741             : !
     742             : !     relaxation for mud2
     743             : !
     744             :       integer nx,ny
     745             :       real(r8) :: phi(*),cof(*),tx(*),ty(*),sum(*)
     746             :       integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess,&
     747             :                    maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur,&
     748             :                    kcycle,iprer,ipost,intpol,kps
     749             :       common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,&
     750             :                      iguess, maxcy,method,nwork,lwork,itero,ngrid,&
     751             :                      klevel,kcur,kcycle,iprer,ipost,intpol,kps
     752        8379 :       if (method.eq.0) then                ! point relaxation
     753           0 :         call relmd2crp(nx,ny,phi,cof)
     754        8379 :       else if (method.eq.1) then           ! line x relaxation
     755           0 :         call slxmd2cr(nx,ny,phi,cof,tx,sum)
     756        8379 :       else if (method.eq.2) then           ! line y relaxation
     757           0 :         call slymd2cr(nx,ny,phi,cof,ty,sum)
     758        8379 :       else if (method.eq.3) then           ! line x&y relaxation
     759        8379 :         call slxmd2cr(nx,ny,phi,cof,tx,sum)
     760        8379 :         call slymd2cr(nx,ny,phi,cof,ty,sum)
     761             :       end if
     762        8379 :       return
     763             :       end subroutine relmd2cr
     764             : !-----------------------------------------------------------------------
     765           0 :       subroutine relmd2crp(nx,ny,phi,cof)
     766             : !
     767             : !     gauss-seidel four color point relaxation
     768             : !
     769             :       integer nx,ny,i,j,lcolor,i1,i2,i3,i4,it
     770             :       integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess,&
     771             :                    maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur,&
     772             :                    kcycle,iprer,ipost,intpol,kps
     773             :       common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,&
     774             :                      iguess, maxcy,method,nwork,lwork,itero,ngrid,&
     775             :                      klevel,kcur,kcycle,iprer,ipost,intpol,kps
     776             :       real(r8) :: phi(0:nx+1,0:ny+1),cof(nx,ny,10)
     777           0 :       i1 = 1
     778           0 :       i2 = 4
     779           0 :       i3 = 3
     780           0 :       i4 = 2
     781             : !
     782             : !     sweep four colored grid points
     783             : !
     784           0 :       do lcolor=1,4
     785             : !$OMP PARALLEL DO SHARED(i1,cof,phi,nx,ny) PRIVATE(i,j)
     786           0 :         do j=1,ny,4
     787           0 :           do i=i1,nx,4
     788           0 :               phi(i,j) = (cof(i,j,10) - (           &
     789           0 :                           cof(i,j,1)*phi(i+1,j)   + &
     790           0 :                           cof(i,j,2)*phi(i+1,j+1) + &
     791             :                           cof(i,j,3)*phi(i,j+1)   + &
     792           0 :                           cof(i,j,4)*phi(i-1,j+1) + &
     793             :                           cof(i,j,5)*phi(i-1,j)   + &
     794           0 :                           cof(i,j,6)*phi(i-1,j-1) + &
     795             :                           cof(i,j,7)*phi(i,j-1)   + &
     796           0 :                           cof(i,j,8)*phi(i+1,j-1)))/cof(i,j,9)
     797             :           end do
     798             :         end do
     799             : !$OMP PARALLEL DO SHARED(i2,cof,phi,nx,ny) PRIVATE(i,j)
     800           0 :         do j=2,ny,4
     801           0 :           do i=i2,nx,4
     802           0 :               phi(i,j) = (cof(i,j,10) - (           &
     803           0 :                           cof(i,j,1)*phi(i+1,j)   + &
     804           0 :                           cof(i,j,2)*phi(i+1,j+1) + &
     805             :                           cof(i,j,3)*phi(i,j+1)   + &
     806           0 :                           cof(i,j,4)*phi(i-1,j+1) + &
     807             :                           cof(i,j,5)*phi(i-1,j)   + &
     808           0 :                           cof(i,j,6)*phi(i-1,j-1) + &
     809             :                           cof(i,j,7)*phi(i,j-1)   + &
     810           0 :                           cof(i,j,8)*phi(i+1,j-1)))/cof(i,j,9)
     811             :           end do
     812             :         end do
     813             : !$OMP PARALLEL DO SHARED(i3,cof,phi,nx,ny) PRIVATE(i,j)
     814           0 :         do j=3,ny,4
     815           0 :           do i=i3,nx,4
     816           0 :               phi(i,j) = (cof(i,j,10) - (           &
     817           0 :                           cof(i,j,1)*phi(i+1,j)   + &
     818           0 :                           cof(i,j,2)*phi(i+1,j+1) + &
     819             :                           cof(i,j,3)*phi(i,j+1)   + &
     820           0 :                           cof(i,j,4)*phi(i-1,j+1) + &
     821             :                           cof(i,j,5)*phi(i-1,j)   + &
     822           0 :                           cof(i,j,6)*phi(i-1,j-1) + &
     823             :                           cof(i,j,7)*phi(i,j-1)   + &
     824           0 :                           cof(i,j,8)*phi(i+1,j-1)))/cof(i,j,9)
     825             :           end do
     826             :         end do
     827             : !$OMP PARALLEL DO SHARED(i4,cof,phi,nx,ny) PRIVATE(i,j)
     828           0 :         do j=4,ny,4
     829           0 :           do i=i4,nx,4
     830           0 :               phi(i,j) = (cof(i,j,10) - (           &
     831           0 :                           cof(i,j,1)*phi(i+1,j)   + &
     832           0 :                           cof(i,j,2)*phi(i+1,j+1) + &
     833             :                           cof(i,j,3)*phi(i,j+1)   + &
     834           0 :                           cof(i,j,4)*phi(i-1,j+1) + &
     835             :                           cof(i,j,5)*phi(i-1,j)   + &
     836           0 :                           cof(i,j,6)*phi(i-1,j-1) + &
     837             :                           cof(i,j,7)*phi(i,j-1)   + &
     838           0 :                           cof(i,j,8)*phi(i+1,j-1)))/cof(i,j,9)
     839             :           end do
     840             :         end do
     841             : !
     842             : !     set periodic virtual boundaries as necessary
     843             : !
     844           0 :         if (nxa.eq.0) then
     845           0 :           do j=1,ny
     846           0 :             phi(0,j) = phi(nx-1,j)
     847           0 :             phi(nx+1,j) = phi(2,j)
     848             :           end do
     849             :         end if
     850           0 :         if (nyc.eq.0) then
     851           0 :           do i=1,nx
     852           0 :             phi(i,0) = phi(i,ny-1)
     853           0 :             phi(i,ny+1) = phi(i,2)
     854             :           end do
     855             :         end if
     856             : !
     857             : !    permute (i1,i2,i3,i4) for next color
     858             : !
     859           0 :         it = i4
     860           0 :         i4 = i3
     861           0 :         i3 = i2
     862           0 :         i2 = i1
     863           0 :         i1 = it
     864             :       end do
     865           0 :       return
     866        8379 :       end subroutine relmd2crp
     867             : !-----------------------------------------------------------------------
     868        8379 :       subroutine slxmd2cr(nx,ny,phi,cof,tx,sum)
     869             : !
     870             : !     line relaxation in the x direction (periodic or nonperiodic)
     871             : !
     872             : 
     873             :       integer nx,ny,i,ib,j
     874             :       integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess,&
     875             :                    maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur,&
     876             :                    kcycle,iprer,ipost,intpol,kps
     877             :       common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,&
     878             :                      iguess, maxcy,method,nwork,lwork,itero,ngrid,&
     879             :                      klevel,kcur,kcycle,iprer,ipost,intpol,kps
     880             :       real(r8) :: phi(0:nx+1,0:ny+1),cof(nx,ny,10),tx(nx,ny,*),sum(ny)
     881             : !
     882             : !     replace line x with point gauss-seidel if
     883             : !     x direction is periodic and nx = 3 (coarsest)
     884             : !
     885        8379 :       if (nxa .eq. 0 .and. nx .eq. 3) then
     886           0 :         call relmd2crp(nx,ny,phi,cof)
     887           0 :         return
     888             :       end if
     889             : !
     890             : !     set periodic y virtual boundary if necessary
     891             : !
     892        8379 :       if (nyc.eq.0) then
     893           0 :         do i=1,nx
     894           0 :           phi(i,0) = phi(i,ny-1)
     895           0 :           phi(i,ny+1) = phi(i,2)
     896             :         end do
     897             :       end if
     898             : 
     899        8379 :       if (nxa.ne.0) then
     900             : !
     901             : !     x direction not periodic, sweep odd j lines
     902             : !
     903             : !$OMP PARALLEL DO SHARED(cof,phi,tx,nx,ny) PRIVATE(i,ib,j)
     904           0 :         do j=1,ny,2
     905           0 :           do i=1,nx
     906           0 :             phi(i,j) = cof(i,j,10)-(cof(i,j,2)*phi(i+1,j+1)+ &
     907             :                                     cof(i,j,3)*phi(i,j+1)+   &
     908           0 :                                     cof(i,j,4)*phi(i-1,j+1)+ &
     909           0 :                                     cof(i,j,6)*phi(i-1,j-1)+ &
     910             :                                     cof(i,j,7)*phi(i,j-1)+   &
     911           0 :                                     cof(i,j,8)*phi(i+1,j-1))
     912             :           end do
     913             : !
     914             : !     forward sweep
     915             : !
     916           0 :           do i=2,nx
     917           0 :             phi(i,j) = phi(i,j)-tx(i-1,j,1)*phi(i-1,j)
     918             :           end do
     919             : !
     920             : !     backward sweep
     921             : !
     922           0 :           phi(nx,j) = phi(nx,j)/tx(nx,j,2)
     923           0 :           do ib=2,nx
     924           0 :             i = nx-ib+1
     925           0 :             phi(i,j) = (phi(i,j)-tx(i,j,3)*phi(i+1,j))/tx(i,j,2)
     926             :           end do
     927             :         end do
     928             : !
     929             : !     sweep even j lines forward and back
     930             : !
     931             : !$OMP PARALLEL DO SHARED(cof,phi,tx,nx,ny) PRIVATE(i,ib,j)
     932           0 :         do j=2,ny,2
     933           0 :           do i=1,nx
     934           0 :             phi(i,j) = cof(i,j,10)-(cof(i,j,2)*phi(i+1,j+1)+ &
     935             :                                     cof(i,j,3)*phi(i,j+1)+   &
     936           0 :                                     cof(i,j,4)*phi(i-1,j+1)+ &
     937           0 :                                     cof(i,j,6)*phi(i-1,j-1)+ &
     938             :                                     cof(i,j,7)*phi(i,j-1)+   &
     939           0 :                                     cof(i,j,8)*phi(i+1,j-1))
     940             :           end do
     941           0 :           do i=2,nx
     942           0 :             phi(i,j) = phi(i,j)-tx(i-1,j,1)*phi(i-1,j)
     943             :           end do
     944           0 :           phi(nx,j) = phi(nx,j)/tx(nx,j,2)
     945           0 :           do ib=2,nx
     946           0 :             i = nx-ib+1
     947           0 :             phi(i,j) = (phi(i,j)-tx(i,j,3)*phi(i+1,j))/tx(i,j,2)
     948             :           end do
     949             :         end do
     950             :       else
     951             : !
     952             : !     x direction periodic
     953             : !
     954       91656 :         do j=1,ny
     955       83277 :           sum(j) = 0.0_r8
     956       83277 :           phi(0,j) = phi(nx-1,j)
     957       91656 :           phi(nx+1,j) = phi(2,j)
     958             :         end do
     959             : !
     960             : !      sweep odd lines forward and back
     961             : !
     962             : !$OMP PARALLEL DO SHARED(sum,cof,phi,tx,nx,ny) PRIVATE(i,j,ib)
     963       52478 :         do j=1,ny,2
     964     1450479 :           do i=1,nx-1
     965     5625520 :             phi(i,j) = cof(i,j,10)-(cof(i,j,2)*phi(i+1,j+1)+ &
     966             :                                     cof(i,j,3)*phi(i,j+1)+   &
     967     1406380 :                                     cof(i,j,4)*phi(i-1,j+1)+ &
     968     1406380 :                                     cof(i,j,6)*phi(i-1,j-1)+ &
     969             :                                     cof(i,j,7)*phi(i,j-1)+   &
     970     9888759 :                                     cof(i,j,8)*phi(i+1,j-1))
     971             :           end do
     972             : !
     973             : !     forward sweep
     974             : !
     975     1362281 :           do i=2,nx-2
     976     1362281 :             phi(i,j) = phi(i,j)-tx(i,j,1)*phi(i-1,j)
     977             :           end do
     978     1406380 :           do i=1,nx-2
     979     1406380 :             sum(j) = sum(j)+tx(i,j,5)*phi(i,j)
     980             :           end do
     981       44099 :           phi(nx-1,j) = phi(nx-1,j)-sum(j)
     982             : !
     983             : !     backward sweep
     984             : !
     985       44099 :           phi(nx-1,j) = phi(nx-1,j)/tx(nx-1,j,2)
     986       88198 :           phi(nx-2,j) = (phi(nx-2,j)-tx(nx-2,j,4)*phi(nx-1,j))/ &
     987       88198 :                          tx(nx-2,j,2)
     988     1370660 :           do ib=4,nx
     989     1318182 :             i = nx-ib+1
     990     2636364 :             phi(i,j) = (phi(i,j)-tx(i,j,3)*phi(i+1,j)-tx(i,j,4)* &
     991     3998645 :                        phi(nx-1,j))/tx(i,j,2)
     992             :           end do
     993             :         end do
     994             : !
     995             : !     set periodic and virtual points for j odd
     996             : !
     997        8379 :         do j=1,ny,2
     998       44099 :           phi(nx,j) = phi(1,j)
     999       44099 :           phi(0,j) = phi(nx-1,j)
    1000       44099 :           phi(nx+1,j) = phi(2,j)
    1001             :         end do
    1002             : !
    1003             : !     sweep even j lines
    1004             : !
    1005             : !$OMP PARALLEL DO SHARED(sum,cof,phi,tx,nx,ny) PRIVATE(i,j,ib)
    1006       47557 :         do j=2,ny,2
    1007     1338018 :           do i=1,nx-1
    1008     5195360 :             phi(i,j) = cof(i,j,10)-(cof(i,j,2)*phi(i+1,j+1)+ &
    1009             :                                     cof(i,j,3)*phi(i,j+1)+   &
    1010     1298840 :                                     cof(i,j,4)*phi(i-1,j+1)+ &
    1011     1298840 :                                     cof(i,j,6)*phi(i-1,j-1)+ &
    1012             :                                     cof(i,j,7)*phi(i,j-1)+   &
    1013     9131058 :                                     cof(i,j,8)*phi(i+1,j-1))
    1014             :           end do
    1015             : !
    1016             : !     forward sweep
    1017             : !
    1018     1259662 :           do i=2,nx-2
    1019     1259662 :             phi(i,j) = phi(i,j)-tx(i,j,1)*phi(i-1,j)
    1020             :           end do
    1021     1298840 :           do i=1,nx-2
    1022     1298840 :             sum(j) = sum(j)+tx(i,j,5)*phi(i,j)
    1023             :           end do
    1024       39178 :           phi(nx-1,j) = phi(nx-1,j)-sum(j)
    1025             : !
    1026             : !     backward sweep
    1027             : !
    1028       39178 :           phi(nx-1,j) = phi(nx-1,j)/tx(nx-1,j,2)
    1029       78356 :           phi(nx-2,j) = (phi(nx-2,j)-tx(nx-2,j,4)*phi(nx-1,j))/ &
    1030       78356 :                          tx(nx-2,j,2)
    1031     1268041 :           do ib=4,nx
    1032     1220484 :             i = nx-ib+1
    1033     2440968 :             phi(i,j) = (phi(i,j)-tx(i,j,3)*phi(i+1,j)-tx(i,j,4)* &
    1034     3700630 :                        phi(nx-1,j))/tx(i,j,2)
    1035             :           end do
    1036             :         end do
    1037             : !
    1038             : !     set periodic and virtual points for j even
    1039             : !
    1040        8379 :         do j=2,ny,2
    1041       39178 :           phi(nx,j) = phi(1,j)
    1042       39178 :           phi(0,j) = phi(nx-1,j)
    1043       39178 :           phi(nx+1,j) = phi(2,j)
    1044             :         end do
    1045             :       end if
    1046             : !
    1047             : !     set periodic y virtual boundaries if necessary
    1048             : !
    1049        8379 :       if (nyc.eq.0) then
    1050           0 :         do i=1,nx
    1051           0 :           phi(i,0) = phi(i,ny-1)
    1052           0 :           phi(i,ny+1) = phi(i,2)
    1053             :         end do
    1054             :       end if
    1055             :       return
    1056           0 :       end subroutine slxmd2cr
    1057             : !-----------------------------------------------------------------------
    1058        8379 :       subroutine slymd2cr(nx,ny,phi,cof,ty,sum)
    1059             : 
    1060             :       integer nx,ny,i,j,jb
    1061             :       integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess, &
    1062             :                    maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur, &
    1063             :                    kcycle,iprer,ipost,intpol,kps
    1064             :       common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy, &
    1065             :                      iguess, maxcy,method,nwork,lwork,itero,ngrid, &
    1066             :                      klevel,kcur,kcycle,iprer,ipost,intpol,kps
    1067             :       real(r8) :: phi(0:nx+1,0:ny+1),cof(nx,ny,10),ty(ny,nx,*),sum(nx)
    1068             : !
    1069             : !     replace line y with point gauss-seidel if
    1070             : !     y direction is periodic and ny = 3
    1071             : !
    1072        8379 :       if (nyc .eq. 0 .and. ny .eq. 3) then
    1073           0 :         call relmd2crp(nx,ny,phi,cof)
    1074           0 :         return
    1075             :       end if
    1076             : !
    1077             : !      set periodic and virtual x boundaries if necessary
    1078             : !
    1079        8379 :       if (nxa.eq.0) then
    1080       91656 :         do j=1,ny
    1081       83277 :           phi(0,j) = phi(nx-1,j)
    1082       83277 :           phi(nx,j) = phi(1,j)
    1083       91656 :           phi(nx+1,j) = phi(2,j)
    1084             :         end do
    1085             :       end if
    1086             : 
    1087        8379 :       if (nyc.ne.0) then
    1088             : !
    1089             : !     y direction not periodic
    1090             : !
    1091             : !$OMP PARALLEL DO SHARED(cof,phi,ty,nx,ny) PRIVATE(i,j,jb)
    1092       77444 :         do i=1,nx,2
    1093     1498036 :           do j=1,ny
    1094     4286913 :             phi(i,j) = cof(i,j,10)-(cof(i,j,1)*phi(i+1,j)+   &
    1095     1428971 :                                     cof(i,j,2)*phi(i+1,j+1)+ &
    1096     1428971 :                                     cof(i,j,4)*phi(i-1,j+1)+ &
    1097             :                                     cof(i,j,5)*phi(i-1,j)+   &
    1098     1428971 :                                     cof(i,j,6)*phi(i-1,j-1)+ &
    1099    10071862 :                                     cof(i,j,8)*phi(i+1,j-1))
    1100             :           end do
    1101             : !
    1102             : !     forward sweep thru odd x lines
    1103             : !
    1104     1428971 :           do j=2,ny
    1105     1428971 :             phi(i,j) = phi(i,j)-ty(j-1,i,1)*phi(i,j-1)
    1106             :           end do
    1107             : !
    1108             : !      backward sweep
    1109             : !
    1110       69065 :           phi(i,ny) = phi(i,ny)/ty(ny,i,2)
    1111     1437350 :           do jb=2,ny
    1112     1359906 :             j = ny-jb+1
    1113     1428971 :             phi(i,j) = (phi(i,j)-ty(j,i,3)*phi(i,j+1))/ty(j,i,2)
    1114             :           end do
    1115             :         end do
    1116             : !
    1117             : !     forward sweep even x lines
    1118             : !
    1119             : !$OMP PARALLEL DO SHARED(cof,phi,ty,nx,ny) PRIVATE(i,j,jb)
    1120       72523 :         do i=2,nx,2
    1121     1423670 :           do j=1,ny
    1122     4078578 :             phi(i,j) = cof(i,j,10)-(cof(i,j,1)*phi(i+1,j)+   &
    1123     1359526 :                                     cof(i,j,2)*phi(i+1,j+1)+ &
    1124     1359526 :                                     cof(i,j,4)*phi(i-1,j+1)+ &
    1125             :                                     cof(i,j,5)*phi(i-1,j)+   &
    1126     1359526 :                                     cof(i,j,6)*phi(i-1,j-1)+ &
    1127     9580826 :                                     cof(i,j,8)*phi(i+1,j-1))
    1128             :           end do
    1129     1359526 :           do j=2,ny
    1130     1359526 :             phi(i,j) = phi(i,j)-ty(j-1,i,1)*phi(i,j-1)
    1131             :           end do
    1132             : !
    1133             : !      backward sweep
    1134             : !
    1135       64144 :           phi(i,ny) = phi(i,ny)/ty(ny,i,2)
    1136     1367905 :           do jb=2,ny
    1137     1295382 :             j = ny-jb+1
    1138     1359526 :             phi(i,j) = (phi(i,j)-ty(j,i,3)*phi(i,j+1))/ty(j,i,2)
    1139             :           end do
    1140             :         end do
    1141             :       else
    1142             : !
    1143             : !     y direction periodic
    1144             : !
    1145           0 :         do i=1,nx
    1146           0 :           sum(i) = 0.0_r8
    1147           0 :           phi(i,0) = phi(i,ny-1)
    1148           0 :           phi(i,ny) = phi(i,1)
    1149           0 :           phi(i,ny+1) = phi(i,2)
    1150             :         end do
    1151             : !
    1152             : !     forward sweep odd x lines
    1153             : !
    1154             : !$OMP PARALLEL DO SHARED(sum,cof,phi,ty,nx,ny) PRIVATE(i,j,jb)
    1155           0 :         do i=1,nx,2
    1156           0 :           do j=1,ny-1
    1157           0 :             phi(i,j) = cof(i,j,10)-(cof(i,j,1)*phi(i+1,j)+   &
    1158           0 :                                     cof(i,j,2)*phi(i+1,j+1)+ &
    1159           0 :                                     cof(i,j,4)*phi(i-1,j+1)+ &
    1160             :                                     cof(i,j,5)*phi(i-1,j)+   &
    1161           0 :                                     cof(i,j,6)*phi(i-1,j-1)+ &
    1162           0 :                                     cof(i,j,8)*phi(i+1,j-1))
    1163             :           end do
    1164           0 :           do j=2,ny-2
    1165           0 :             phi(i,j) = phi(i,j)-ty(j,i,1)*phi(i,j-1)
    1166             :           end do
    1167           0 :           do j=1,ny-2
    1168           0 :             sum(i) = sum(i)+ty(j,i,5)*phi(i,j)
    1169             :           end do
    1170           0 :           phi(i,ny-1) = phi(i,ny-1)-sum(i)
    1171             : !
    1172             : !     backward sweep
    1173             : !
    1174           0 :           phi(i,ny-1) = phi(i,ny-1)/ty(ny-1,i,2)
    1175           0 :           phi(i,ny-2) = (phi(i,ny-2)-ty(ny-2,i,4)*phi(i,ny-1))/ &
    1176           0 :                          ty(ny-2,i,2)
    1177           0 :           do jb=4,ny
    1178           0 :             j = ny-jb+1
    1179           0 :             phi(i,j) = (phi(i,j)-ty(j,i,3)*phi(i,j+1)-ty(j,i,4)* &
    1180           0 :                         phi(i,ny-1))/ty(j,i,2)
    1181             :           end do
    1182             :         end do
    1183             : !
    1184             : !       set odd periodic and virtual y boundaries
    1185             : !
    1186           0 :         do i=1,nx,2
    1187           0 :           phi(i,0) = phi(i,ny-1)
    1188           0 :           phi(i,ny) = phi(i,1)
    1189           0 :           phi(i,ny+1) = phi(i,2)
    1190             :         end do
    1191             : !
    1192             : !     forward sweep even x lines
    1193             : !
    1194             : !$OMP PARALLEL DO SHARED(sum,cof,phi,ty,nx,ny) PRIVATE(i,j,jb)
    1195           0 :         do i=2,nx,2
    1196           0 :           do j=1,ny-1
    1197           0 :             phi(i,j) = cof(i,j,10)-(cof(i,j,1)*phi(i+1,j)+   &
    1198           0 :                                     cof(i,j,2)*phi(i+1,j+1)+ &
    1199           0 :                                     cof(i,j,4)*phi(i-1,j+1)+ &
    1200             :                                     cof(i,j,5)*phi(i-1,j)+   &
    1201           0 :                                     cof(i,j,6)*phi(i-1,j-1)+ &
    1202           0 :                                     cof(i,j,8)*phi(i+1,j-1))
    1203             :           end do
    1204           0 :           do j=2,ny-2
    1205           0 :             phi(i,j) = phi(i,j)-ty(j,i,1)*phi(i,j-1)
    1206             :           end do
    1207           0 :           do j=1,ny-2
    1208           0 :             sum(i) = sum(i)+ty(j,i,5)*phi(i,j)
    1209             :           end do
    1210           0 :           phi(i,ny-1) = phi(i,ny-1)-sum(i)
    1211             : !
    1212             : !     backward sweep
    1213             : !
    1214           0 :           phi(i,ny-1) = phi(i,ny-1)/ty(ny-1,i,2)
    1215           0 :           phi(i,ny-2) = (phi(i,ny-2)-ty(ny-2,i,4)*phi(i,ny-1))/ &
    1216           0 :                          ty(ny-2,i,2)
    1217           0 :           do jb=4,ny
    1218           0 :             j = ny-jb+1
    1219           0 :             phi(i,j) = (phi(i,j)-ty(j,i,3)*phi(i,j+1)-ty(j,i,4)* &
    1220           0 :                         phi(i,ny-1))/ty(j,i,2)
    1221             :           end do
    1222             :         end do
    1223             : !
    1224             : !       set even periodic and virtual y boundaries
    1225             : !
    1226           0 :         do i=2,nx,2
    1227           0 :           phi(i,0) = phi(i,ny-1)
    1228           0 :           phi(i,ny) = phi(i,1)
    1229           0 :           phi(i,ny+1) = phi(i,2)
    1230             :         end do
    1231             :       end if
    1232             : !
    1233             : !      set periodic and virtual x boundaries if necessary
    1234             : !
    1235        8379 :       if (nxa.eq.0) then
    1236       91656 :         do j=1,ny
    1237       83277 :           phi(0,j) = phi(nx-1,j)
    1238       91656 :           phi(nx+1,j) = phi(2,j)
    1239             :         end do
    1240             :       end if
    1241             : 
    1242             :       return
    1243       16758 :       end subroutine slymd2cr
    1244             : !-----------------------------------------------------------------------
    1245             : end module edyn_mud

Generated by: LCOV version 1.14