vtf-logo

src/2d/integrator_extended/flux2ex.f

c
c
c     =====================================================
      subroutine flux2(ixy,maxm,meqn,maux,mwaves,mbc,mx,
     &                 q1d,dtdx1d,aux1,aux2,aux3,method,mthlim,
     &                 faddm,faddp,gaddm,gaddp,cfl1d,wave,s,
     &                 amdq,apdq,cqxx,bmasdq,bpasdq,work,mwork,
     &                 rpn2,rpt2)
c     =====================================================
c
c     Author:  Randall J. LeVeque
c     Modified for AMROC: Ralf Deiterding
c
c     # Compute the modification to fluxes f and g that are generated by
c     # all interfaces along a 1D slice of the 2D grid. 
c     #    ixy = 1  if it is a slice in x
c     #          2  if it is a slice in y
c     # This value is passed into the Riemann solvers. The flux modifications
c     # go into the arrays fadd and gadd.  The notation is written assuming
c     # we are solving along a 1D slice in the x-direction.
c
c     # fadd(i,.) modifies F to the left of cell i
c     # gadd(i,.,1) modifies G below cell i
c     # gadd(i,.,2) modifies G above cell i
c
c     # The method used is specified by method(2:3):
c
c         method(2) = 1 if only first order increment waves are to be used.
c                   = 2 if second order correction terms are to be added, with
c                       a flux-limiter as specified by mthlim.  
c                   = 3   ==>  Slope-limiting of the conserved variables, with a 
c                       slope-limiter as specified by mthlim(1).  
c                   > 3   ==>  User defined slope-limiter method.  
c                       Slope-limiting is intended to be used with dimensional 
c                       splitting, but schemes that return the fluctuations might 
c                       also be used in combination with transverse wave 
c                       propagation. Note, that the application of MUSCL before 
c                       transverse propagation corresponds to method(3)=2 
c                       although internally the algorithm of method(3)=1 is 
c                       used.
c
c         method(3) = -1 0 Gives dimensional splitting using Godunov
c                        splitting, i.e. formally first order accurate.
c                   = -2 Dimensional splitting using Godunov splitting with
c                        boundary update after each directional step.
c                        The necessary ghost cell synchronization is done by
c                        the surrounding AMROC framework. 
c                        This selection ensures that the solution of the
c                        splitting method is independent of the number of 
c                        computational nodes.
c                    = 0 Gives the Donor cell method. No transverse
c                        propagation of neither the increment wave
c                        nor the correction wave.
c                   = 1 if transverse propagation of increment waves 
c                       (but not correction waves, if any) is to be applied.
c                   = 2 if transverse propagation of correction waves is also
c                       to be included.  
c
c     Note that if mcapa>0 then the capa array comes into the second 
c     order correction terms, and is already included in dtdx1d:
c     If ixy = 1 then
c        dtdx1d(i) = dt/dx                      if mcapa= 0
c                  = dt/(dx*aux(i,jcom,mcapa))  if mcapa = 1
c     If ixy = 2 then
c        dtdx1d(j) = dt/dy                      if mcapa = 0
c                  = dt/(dy*aux(icom,j,mcapa))  if mcapa = 1
c
c     Notation:
c        The jump in q (q1d(i,:)-q1d(i-1,:))  is split by rpn2 into
c            amdq =  the left-going flux difference  A^- Delta q  
c            apdq = the right-going flux difference  A^+ Delta q  
c        Each of these is split by rpt2 into 
c            bmasdq = the down-going transverse flux difference B^- A^* Delta q
c            bpasdq =   the up-going transverse flux difference B^+ A^* Delta q
c        where A^* represents either A^- or A^+.
c
c
      implicit double precision (a-h,o-z)
      include "call.i"
c
      dimension    q1d(1-mbc:maxm+mbc, meqn)
      dimension   amdq(1-mbc:maxm+mbc, meqn)
      dimension   apdq(1-mbc:maxm+mbc, meqn)
      dimension bmasdq(1-mbc:maxm+mbc, meqn)
      dimension bpasdq(1-mbc:maxm+mbc, meqn)
      dimension   cqxx(1-mbc:maxm+mbc, meqn)
      dimension  faddm(1-mbc:maxm+mbc, meqn)
      dimension  faddp(1-mbc:maxm+mbc, meqn)
      dimension  gaddm(1-mbc:maxm+mbc, meqn, 2)
      dimension  gaddp(1-mbc:maxm+mbc, meqn, 2)
      dimension dtdx1d(1-mbc:maxm+mbc)
      dimension aux1(1-mbc:maxm+mbc, maux)
      dimension aux2(1-mbc:maxm+mbc, maux)
      dimension aux3(1-mbc:maxm+mbc, maux)
      dimension    s(1-mbc:maxm+mbc, mwaves)
      dimension wave(1-mbc:maxm+mbc, meqn, mwaves)
      dimension method(7),mthlim(mwaves)
      dimension work(mwork)
      external rpn2, rpt2
      logical limit
      common /rpnflx/ mrpnflx
c
      i0ql = 1
      i0qr = i0ql + (maxm+2*mbc)*meqn
      i0fl = i0qr + (maxm+2*mbc)*meqn
      i0fr = i0fl + (maxm+2*mbc)*meqn
      iused = i0fr + (maxm+2*mbc)*meqn - 1
c
      if (iused.gt.mwork) then
         write(6,*) '*** not enough work space in flux2ex'
         write(6,*) '*** iused = ', iused, '   mwork =',mwork
         stop 
      endif
c
      limit = .false.
      do 5 mw=1,mwaves
         if (mthlim(mw) .gt. 0) limit = .true.
   5  continue
c
c     # initialize flux increments:
c     -----------------------------
c
      do 30 jside=1,2
         do 20 m=1,meqn
            do 10 i = 1-mbc, mx+mbc
               faddm(i,m) = 0.d0
               faddp(i,m) = 0.d0
               gaddm(i,m,jside) = 0.d0
               gaddp(i,m,jside) = 0.d0
   10       continue
   20    continue
   30 continue
c
c
c     # solve Riemann problem at each interface and compute Godunov updates
c     ---------------------------------------------------------------------
c
      if (method(2).le.2) then
         call rpn2(ixy,maxm,meqn,mwaves,mbc,mx,q1d,q1d,maux,
     &             aux2,aux2,wave,s,amdq,apdq)
c
      else
         call slope2(ixy,maxm,meqn,maux,mwaves,mbc,mx,q1d,aux2,dx,dt,
     &               method,mthlim,wave,s,amdq,apdq,dtdx1d,rpn2,
     &               work(i0ql),work(i0qr),work(i0fl),work(i0fr))
      endif
c
c     # Set fadd for the donor-cell upwind method (Godunov)
      do 40 m=1,meqn
         do 40 i=1,mx+1
            faddp(i,m) = faddp(i,m) - apdq(i,m)
            faddm(i,m) = faddm(i,m) + amdq(i,m)
   40 continue
c
c     # compute maximum wave speed for checking Courant number:
      cfl1d = 0.d0
      do 50 mw=1,mwaves
         do 50 i=1,mx+1
            cfl1d = dmax1(cfl1d, dtdx1d(i)*dabs(s(i,mw)))
   50 continue
c
      if (method(2).le.1.or.method(2).ge.3) go to 130
c
      if (mrpnflx.ne.0) then
         write(6,*) '*** Riemann solver returns fluxes.'
         write(6,*) '*** Wave limiting not possible.'
         write(6,*) '*** Set method(2)>=3 for slope limiting.'
         stop 
      endif
c
c     # modify F fluxes for second order q_{xx} correction terms:
c     -----------------------------------------------------------
c
c     # apply limiter to waves:
      if (limit) call limiter(maxm,meqn,mwaves,mbc,mx,wave,s,mthlim)
c
      do 120 i = 1, mx+1
c
c        # For correction terms below, need average of dtdx in cell
c        # i-1 and i.  Compute these and overwrite dtdx1d:
c
         dtdx1d(i-1) = 0.5d0 * (dtdx1d(i-1) + dtdx1d(i))
c
         do 120 m=1,meqn
            cqxx(i,m) = 0.d0
            do 119 mw=1,mwaves
c
c              # second order corrections:
               cqxx(i,m) = cqxx(i,m) + dabs(s(i,mw))
     &             * (1.d0 - dabs(s(i,mw))*dtdx1d(i-1)) * wave(i,m,mw)
c
 119        continue
            faddm(i,m) = faddm(i,m) + 0.5d0 * cqxx(i,m)
            faddp(i,m) = faddp(i,m) + 0.5d0 * cqxx(i,m)
 120  continue
c
      if (method(3).eq.2) then
c     # incorporate cqxx into amdq and apdq so that it is split also.
         do 150 m=1,meqn
            do 150 i = 1, mx+1
               amdq(i,m) = amdq(i,m) + cqxx(i,m)
               apdq(i,m) = apdq(i,m) - cqxx(i,m)
 150     continue
      endif
c
 130  continue
c
      if (method(3).le.0) go to 999 !# no transverse propagation
c
      if (mrpnflx.ne.0) then
         write(6,*) '*** Riemann solver returns fluxes.'
         write(6,*) '*** Transverse wave propagation not possible.'
         write(6,*) '*** Set method(3)<0 for dimensional splitting.'
         stop 
      endif
c
c     # modify G fluxes for transverse propagation
c     --------------------------------------------
c
c
c     # split the left-going flux difference into down-going and up-going:
      call rpt2(ixy,maxm,meqn,mwaves,mbc,mx,
     &          q1d,q1d,maux,aux1,aux2,aux3,
     &          1,amdq,bmasdq,bpasdq)
c
c     # modify flux below and above by B^- A^- Delta q and  B^+ A^- Delta q:
      do 160 m=1,meqn
         do 160 i = 1, mx+1
            gupdate = 0.5d0*dtdx1d(i-1) * bmasdq(i,m)
            gaddm(i-1,m,1) = gaddm(i-1,m,1) - gupdate
            gaddp(i-1,m,1) = gaddp(i-1,m,1) - gupdate
c
            gupdate = 0.5d0*dtdx1d(i-1) * bpasdq(i,m)
            gaddm(i-1,m,2) = gaddm(i-1,m,2) - gupdate
            gaddp(i-1,m,2) = gaddp(i-1,m,2) - gupdate
  160 continue
c
c     # split the right-going flux difference into down-going and up-going:
      call rpt2(ixy,maxm,meqn,mwaves,mbc,mx,
     &          q1d,q1d,maux,aux1,aux2,aux3,
     &          2,apdq,bmasdq,bpasdq)
c
c     # modify flux below and above by B^- A^+ Delta q and  B^+ A^+ Delta q:
      do 180 m=1,meqn
         do 180 i = 1, mx+1
            gupdate = 0.5d0*dtdx1d(i-1) * bmasdq(i,m)
            gaddm(i,m,1) = gaddm(i,m,1) - gupdate
            gaddp(i,m,1) = gaddp(i,m,1) - gupdate
c
            gupdate = 0.5d0*dtdx1d(i-1) * bpasdq(i,m)
            gaddm(i,m,2) = gaddm(i,m,2) - gupdate
            gaddp(i,m,2) = gaddp(i,m,2) - gupdate
  180 continue
c
  999 continue
      return
      end
c
c
c ===================================================================
      subroutine slope2(ixy,maxm,meqn,maux,mwaves,mbc,mx,
     &                  q,aux,dx,dt,method,mthlim,
     &                  wave,s,amdq,apdq,dtdx,rpn2,
     &                  ql,qr,fl,fr)
c ===================================================================
c
c     # Implements the standard MUSCL-Hancock method. MUSCL must
c     # be used to obtain 2nd order accuracy with conventional 
c     # finite-volume schemes that return the numerical fluxes instead 
c     # of fluctuations. Schemes returning the fluctuations can use MUSCL
c     # slope-limiting or wave-limiting. Slope-limiting is intended to 
c     # be used with dimensional splitting, but wave propagation schemes
c     # also can apply it in combination with transverse wave propagation.
c
c     # Author:  Ralf Deiterding, ralf@amroc.net
c
      implicit double precision (a-h,o-z)
      include "call.i"
      common /rpnflx/ mrpnflx
c
      dimension    q(1-mbc:maxm+mbc, meqn)
      dimension   ql(1-mbc:maxm+mbc, meqn)
      dimension   qr(1-mbc:maxm+mbc, meqn)
      dimension  aux(1-mbc:maxm+mbc, maux)
      dimension   fl(1-mbc:maxm+mbc, meqn)
      dimension   fr(1-mbc:maxm+mbc, meqn)
      dimension wave(1-mbc:maxm+mbc, meqn, mwaves)
      dimension    s(1-mbc:maxm+mbc, mwaves)
      dimension amdq(1-mbc:maxm+mbc, meqn)
      dimension apdq(1-mbc:maxm+mbc, meqn)
      dimension dtdx(1-mbc:maxm+mbc)
      dimension method(7),mthlim(mwaves)
      external rpn2
c     
      mlim = 0
      do 90 mw=1,mwaves
         if (mthlim(mw) .gt. 0) then
            mlim = mthlim(mw)
            goto 95
         endif
 90   continue
 95   continue
c
      do 100 m=1,meqn
         ql(1-mbc,m) = q(1-mbc,m)
         qr(1-mbc,m) = q(1-mbc,m)
         ql(mx+mbc,m) = q(mx+mbc,m)
         qr(mx+mbc,m) = q(mx+mbc,m)
 100  continue
c
      if (method(2).gt.3) then
         call rec2(ixy,maxm,meqn,mwaves,mbc,mx,q,method,mthlim,ql,qr)
c
c     # MUSCL reconstruction with slope-limiting for conserved 
c     # variables. Linear reconstruction: om=0.d0
c     # Quadratic spatial reconstuction: om!=0.d0 
c     # 2nd order spatial reconstruction: om=1.d0/3.d0 
c     # Reconstructions with om!=0.d0 are not conservative!
c
      else
         om = 0.d0
         do 110 i=2-mbc,mx+mbc-1
            do 110 m=1,meqn
               call reclim(q(i,m),q(i-1,m),q(i+1,m),
     &                     mlim,om,ql(i,m),qr(i,m))
 110     continue
      endif
c
      call flx2(ixy,maxm,meqn,mbc,mx,ql,maux,aux,fl)
      call flx2(ixy,maxm,meqn,mbc,mx,qr,maux,aux,fr)
c
      do 200 i=2-mbc,mx+mbc-1
         do 200 m=1,meqn
            ql(i,m) = ql(i,m) + 0.5d0*dtdx(i)*(fl(i,m)-fr(i,m))
            qr(i,m) = qr(i,m) + 0.5d0*dtdx(i)*(fl(i,m)-fr(i,m))
 200  continue
c
      call rpn2(ixy,maxm,meqn,mwaves,mbc,mx,ql,qr,maux,
     &          aux,aux,wave,s,amdq,apdq)
c
c     # Add differences of fluxes between original and reconstructed values
c     # to fluctuations, if a wave propagation scheme is applied.
c
      if (mrpnflx.eq.0) then
         call flx2(ixy,maxm,meqn,mbc,mx,ql,maux,aux,fl)
         call flx2(ixy,maxm,meqn,mbc,mx,qr,maux,aux,fr)
         do 300 i=2-mbc,mx+mbc-1
            do 300 m=1,meqn
               amdq(i,m) = amdq(i,m) + fr(i-1,m)
               apdq(i,m) = apdq(i,m) - fl(i  ,m)
 300     continue
         call flx2(ixy,maxm,meqn,mbc,mx,q,maux,aux,fl)
         do 310 i=2-mbc,mx+mbc-1
            do 310 m=1,meqn
               amdq(i,m) = amdq(i,m) - fl(i-1,m)
               apdq(i,m) = apdq(i,m) + fl(i  ,m)
 310     continue
      endif   
c
      return
      end
c
c
c ===================================================================
      subroutine saverec2(ixy,maxm,maxmx,maxmy,mvar,meqn,mbc,mx,my,
     &                    q,qls,qrs,qbs,qts,ql,qr)
c ===================================================================
c
c     # Store reconstructed values for later use.
c
      implicit double precision (a-h,o-z)
      include "call.i"
c
      dimension   q(mvar, 1-mbc:maxmx+mbc, 1-mbc:maxmy+mbc)
      dimension qls(mvar, 1-mbc:maxmx+mbc, 1-mbc:maxmy+mbc)
      dimension qrs(mvar, 1-mbc:maxmx+mbc, 1-mbc:maxmy+mbc)
      dimension qbs(mvar, 1-mbc:maxmx+mbc, 1-mbc:maxmy+mbc)
      dimension qts(mvar, 1-mbc:maxmx+mbc, 1-mbc:maxmy+mbc)
      dimension  ql(1-mbc:maxm+mbc, meqn)
      dimension  qr(1-mbc:maxm+mbc, meqn)
c
      if (ixy.eq.1) then
         do 10 i = 1-mbc, mx+mbc
            do m=1,meqn
               qls(m,i,jcom) = ql(i,m)
               qrs(m,i,jcom) = qr(i,m)
            enddo
            do m=meqn+1,mvar
               qls(m,i,jcom) = q(m,i,jcom)
               qrs(m,i,jcom) = q(m,i,jcom)
            enddo
 10      continue        
      endif
c
      if (ixy.eq.2) then
         do 20 j = 1-mbc, my+mbc
            do m=1,meqn
               qbs(m,icom,j) = ql(j,m)
               qts(m,icom,j) = qr(j,m)
            enddo
            do m=meqn+1,mvar
               qbs(m,icom,j) = q(m,icom,j)
               qts(m,icom,j) = q(m,icom,j)
            enddo
 20      continue        
      endif
c
      return
      end
c

<