!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE ADVPTFCT ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE advptfct(nx,ny,nz,dtbig1,ptprt,u,v,w,wcont, & 1,12
rhostr,rhostri,ptbar,mapfct,j3,j3inv, &
ptadv, &
tem1,tem2,tem3,tem4,tem5,tem6,tem7,tem8, &
ustr,vstr,wstr,tem1_0,tem2_0,tem3_0,mp_tem)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Calculate the advection of total potential temperature
! using flux-correctd transport scheme.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Ming Xue and Yifeng Tang
! 1/6/93.
!
! 10/12/1996 (M. Xue)
! Code clean up. prprt*rhostr is now passed into advctsfct.
!
! 7/10/1997 (Fanyou Kong -- CMRP)
! Include MPDCD simple positive definite advection scheme
! (sadvopt = 5) through subroutine 'advmpdcd'
!
! 11/20/1997 (Fanyou Kong -- CMRP)
! Added map factor into both FCT and MPDCD schemes
!
! 7/17/1998 (Ming Xue)
! Significant modifications to call a new version of advctsfct.
!
! 10/5/1998 (Dan Weber)
! Added rhostri, mapfct 7-8 array's.
!
!-----------------------------------------------------------------------
!
! INPUT:
!
! nx Number of grid points in the x-direction (east/west)
! ny Number of grid points in the y-direction (north/south)
! nz Number of grid points in the vertical
!
! u x component of velocity (m/s)
! v y component of velocity (m/s)
! w Vertical component of Cartesian velocity (m/s)
! wcont Contravariant vertical velocity (m/s)
! ptprt Perturbation potential temperature at all time levels (K)
!
! rhostr Base state air density times j3 (kg/m**3)
! rhostri Inverse base state air density times j3 (kg/m**3)
! ptbar Base state potential temperature (K)
! mapfct Map factor for scalar point
!
! OUTPUT:
!
! ptadv Advection term of potential temperature eqn (kg/m**3)*K/s
!
! WORK ARRAYS:
!
!
! tem1 Temporary work array.
! tem2 Temporary work array.
! tem3 Temporary work array.
! tem4 Temporary work array.
! tem5 Temporary work array.
! tem6 Temporary work array.
! tem7 Temporary work array.
! tem8 Temporary work array.
! ustr Work array
! vstr Work array
! wstr Work array
!
! tem1_0 Temporary work array.
! tem2_0 Temporary work array.
! tem3_0 Temporary work array.
!
! mp_tem Temporary work array.
!
!-----------------------------------------------------------------------
!
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
INCLUDE 'timelvls.inc'
INTEGER :: nx,ny,nz ! Number of grid points in 3 directions
REAL :: dtbig1
REAL :: ptprt (nx,ny,nz,nt) ! Perturbation potential temperature (K)
REAL :: u (nx,ny,nz,nt) ! u-velocity (m/s)
REAL :: v (nx,ny,nz,nt) ! v-velocity (m/s)
REAL :: w (nx,ny,nz,nt) ! w-velocity (m/s)
REAL :: wcont (nx,ny,nz) ! Contravariant w-velocity (m/s)
!
REAL :: rhostr(nx,ny,nz) ! Base state air density times j3 (kg/m**3)
REAL :: rhostri(nx,ny,nz) ! Inv. base state air density times j3 (kg/m**3)
REAL :: ptbar (nx,ny,nz) ! Base state potential temperature (K)
REAL :: mapfct(nx,ny,8) ! Map factor for scalar point
REAL :: j3 (nx,ny,nz) ! Coordinate transformation Jacobian defined
! as d( zp )/d( z ).
REAL :: j3inv (nx,ny,nz) ! 1/J3.
!
REAL :: ptadv(nx,ny,nz) ! Advection of potential temperature
!
!
REAL :: tem1 (nx,ny,nz) ! temporary work array
REAL :: tem2 (nx,ny,nz) ! temporary work array
REAL :: tem3 (nx,ny,nz) ! temporary work array
REAL :: tem4 (nx,ny,nz) ! temporary work array
REAL :: tem5 (nx,ny,nz) ! temporary work array
REAL :: tem6 (nx,ny,nz) ! temporary work array
REAL :: tem7 (nx,ny,nz) ! temporary work array
REAL :: tem8 (nx,ny,nz) ! temporary work array
REAL :: ustr (nx,ny,nz) ! Work array holding u*rhostr/mapfct
REAL :: vstr (nx,ny,nz) ! Work array holding v*rhostr/mapfct
REAL :: wstr (nx,ny,nz) ! Work array holding wcont*rhostr
REAL :: tem1_0(0:nx,0:ny,0:nz) ! Work array
REAL :: tem2_0(0:nx,0:ny,0:nz) ! Work array
REAL :: tem3_0(0:nx,0:ny,0:nz) ! Work array
REAL :: mp_tem(MAX(nx+1,ny+1)*(nz+1)) ! Temporary message passing array.
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: i,j,k
REAL :: ptmin, ptmin1, ptmax1, ptmin2, ptmax2, tema
INTEGER :: advdiv ! = 0, neglect anelastic correction in FCT advection
! = 1, include anelastic correction in FCT advection
INTEGER :: mptag1,mptag2
!
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
!
INCLUDE 'globcst.inc' ! Global model control parameters
INCLUDE 'grid.inc' ! Grid parameters
INCLUDE 'bndry.inc' ! Boundary Condition Flags
INCLUDE 'mp.inc' ! Message passing parameters.
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!
advdiv = 1 ! Include the anelastic correction term? (recommended!)
IF( fctadvptprt == 1 .AND. sadvopt == 5 ) fctadvptprt = 2
IF( ptsmlstp == 1 ) fctadvptprt = 1 ! Do not reset this one
IF( fctadvptprt == 0 ) THEN
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
tem1_0(i,j,k)=ptprt(i,j,k,1)+ptbar(i,j,k)
tem2_0(i,j,k)=ptprt(i,j,k,2)+ptbar(i,j,k)
END DO
END DO
END DO
ELSE IF( fctadvptprt == 1 ) THEN
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
tem1_0(i,j,k)=ptprt(i,j,k,1)
tem2_0(i,j,k)=ptprt(i,j,k,2)
END DO
END DO
END DO
ELSE IF( fctadvptprt == 2 ) THEN
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
tem1(i,j,k)=ptprt(i,j,k,1)+ptbar(i,j,k)
tem2(i,j,k)=ptprt(i,j,k,2)+ptbar(i,j,k)
END DO
END DO
END DO
CALL a3dmax0
(tem1,1,nx,1,nx-1,1,ny,1,ny-1, &
1,nz,1,nz-1,ptmax1,ptmin1)
CALL a3dmax0
(tem2,1,nx,1,nx-1,1,ny,1,ny-1, &
1,nz,1,nz-1,ptmax2,ptmin2)
ptmin = AMIN1(ptmin1,ptmin2)
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
tem1_0(i,j,k)=tem1(i,j,k)-ptmin
tem2_0(i,j,k)=tem2(i,j,k)-ptmin
END DO
END DO
END DO
END IF
! IF (mp_opt > 0) THEN
! CALL acct_interrupt(mp_acct)
! CALL mpsendextew(tem1_0,nx,ny,nz,ebc,wbc,mptag1,mp_tem)
! CALL mpsendextew(tem2_0,nx,ny,nz,ebc,wbc,mptag2,mp_tem)
! CALL mprecvextew(tem1_0,nx,ny,nz,ebc,wbc,mptag1,mp_tem)
! CALL mprecvextew(tem2_0,nx,ny,nz,ebc,wbc,mptag2,mp_tem)
! CALL mpsendextns(tem1_0,nx,ny,nz,nbc,sbc,mptag1,mp_tem)
! CALL mpsendextns(tem2_0,nx,ny,nz,nbc,sbc,mptag2,mp_tem)
! CALL mprecvextns(tem1_0,nx,ny,nz,nbc,sbc,mptag1,mp_tem)
! CALL mprecvextns(tem2_0,nx,ny,nz,nbc,sbc,mptag2,mp_tem)
! END IF
CALL acct_interrupt
(bc_acct)
CALL extndsbc
(tem1_0,nx,ny,nz,0,ebc,wbc,nbc,sbc,tbc,bbc)
CALL extndsbc
(tem2_0,nx,ny,nz,0,ebc,wbc,nbc,sbc,tbc,bbc)
CALL acct_stop_inter
!test tmp: call test_dump (tem1_0,"XXXAtem1_0",nx+1,ny+1,nz+1,4,1)
!test tmp: call test_dump (tem2_0,"XXXAtem2_0",nx+1,ny+1,nz+1,4,1)
!
!-----------------------------------------------------------------------
!
! Calculate ustr, vstr and wstr.
!
!-----------------------------------------------------------------------
!
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
tem3_0(i,j,k)=rhostr(i,j,k)
END DO
END DO
END DO
! IF (mp_opt > 0) THEN
! CALL acct_interrupt(mp_acct)
! CALL mpsendextew(tem3_0,nx,ny,nz,ebc,wbc,mptag1,mp_tem)
! CALL mprecvextew(tem3_0,nx,ny,nz,ebc,wbc,mptag1,mp_tem)
! CALL mpsendextns(tem3_0,nx,ny,nz,nbc,sbc,mptag1,mp_tem)
! CALL mprecvextns(tem3_0,nx,ny,nz,nbc,sbc,mptag1,mp_tem)
! END IF
CALL acct_interrupt
(bc_acct)
CALL extndsbc
(tem3_0,nx,ny,nz,0,ebc,wbc,nbc,sbc,tbc,bbc)
CALL acct_stop_inter
!test tmp: call test_dump (tem3_0,"XXXAtem3_0",nx+1,ny+1,nz+1,4,1)
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx
ustr(i,j,k)=u(i,j,k,2)*(tem3_0(i-1,j,k)+tem3_0(i,j,k)) &
*mapfct(i,j,5)*0.5
END DO
END DO
END DO
DO k=1,nz-1
DO j=1,ny
DO i=1,nx-1
vstr(i,j,k)=v(i,j,k,2)*(tem3_0(i,j-1,k)+tem3_0(i,j,k)) &
*mapfct(i,j,6)*0.5
END DO
END DO
END DO
DO k=1,nz
DO j=1,ny-1
DO i=1,nx-1
wstr(i,j,k)=wcont(i,j,k) &
*(tem3_0(i,j,k-1)+tem3_0(i,j,k))*0.5
END DO
END DO
END DO
IF(advdiv == 1) THEN
!
!-----------------------------------------------------------------------
!
! Add the anelastic divergence correction term:
! -[m**2{d(rhostr*u/m)/dx+ d(rhostr*v/m)/dy}+ d(rhostr*wcont)/dz]*ptprt.
!
!-----------------------------------------------------------------------
!
DO k=2,nz-2
DO j=1,ny-1
DO i=1,nx-1
ptadv(i,j,k)= - tem2_0(i,j,k)*( &
((ustr(i+1,j,k)-ustr(i,j,k))*dxinv &
+(vstr(i,j+1,k)-vstr(i,j,k))*dyinv)*mapfct(i,j,7) &
+(wstr(i,j,k+1)-wstr(i,j,k))*dzinv )
END DO
END DO
END DO
ELSE
DO k=1,nz
DO j=1,ny
DO i=1,nx
ptadv(i,j,k)= 0.0
END DO
END DO
END DO
END IF
IF (sadvopt == 4) THEN
IF(fctadvptprt == 1.AND.ptsmlstp /= 1 ) THEN ! Advection of ptbar
tema = 0.25/dz
DO k=2,nz-1
DO j=1,ny-1
DO i=1,nx-1
tem2(i,j,k)=(rhostr(i,j,k )*j3inv(i,j,k ) &
+rhostr(i,j,k-1)*j3inv(i,j,k-1))*w(i,j,k,2) &
*(ptbar(i,j,k)-ptbar(i,j,k-1))*tema
END DO
END DO
END DO
DO k=2,nz-2
DO j=1,ny-1
DO i=1,nx-1
ptadv(i,j,k)=ptadv(i,j,k)+tem2(i,j,k)+tem2(i,j,k+1)
END DO
END DO
END DO
END IF
CALL advctsfct
(nx,ny,nz,nt,dtbig1,ustr,vstr,wstr, &
mapfct,tem1_0,tem2_0,tem3_0,rhostr,rhostri, &
ptadv, &
tem1,tem2,tem3,tem4,tem5,tem6,tem7,tem8)
ELSE IF(sadvopt == 5) THEN
IF(fctadvptprt /= 0 ) THEN
CALL arpsstop
( &
'Subourinte ADVMPDCD should never be used to advect '// &
'non-positive definite variable PTPRT.'// &
'Job Stopped in subroutine ADVPTFCT.',1)
END IF
CALL advmpdcd
(nx,ny,nz,nt,dtbig1, &
ustr,vstr,wstr,mapfct, tem1_0,tem2_0, rhostr, &
ptadv, &
tem1,tem2,tem3,tem4, tem3_0, mp_tem)
END IF
RETURN
END SUBROUTINE advptfct
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE ADVQFCT ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE advqfct(nx,ny,nz,dtbig1,q,u,v,wcont, ustr,vstr,wstr, & 3,6
rhostr,rhostri,mapfct,j3,qadv, &
tem1,tem2,tem3,tem4,tem5,tem6,tem7,tem8, &
tem1_0,tem2_0,tem3_0)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Calculate the advection of water substance
! using flux-correctd transport scheme.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Yifeng Tang and M. Xue
! 1/6/93.
!
! 10/12/1996 (M. Xue)
! Code clean up. q*rhostr is now passed into advctsfct.
!
! 7/10/1997 (Fanyou Kong -- CMRP)
! Include MPDCD simple positive definite advection scheme
! (sadvopt = 5) through subroutine 'advmpdcd'
!
! 11/20/1997 (Fanyou Kong -- CMRP)
! Added map factor into FCT and MPDCD schemes
!
! 7/17/1998 (Ming Xue)
! Significant modifications to call a new version of advctsfct.
!
! 9/28/1998 (Dan Weber)
! Moved calculation of u,v,wstr out of this subroutine and added
! rhostri and mapfct 7-8.
!
!-----------------------------------------------------------------------
!
! INPUT:
!
! nx Number of grid points in the x-direction (east/west)
! ny Number of grid points in the y-direction (north/south)
! nz Number of grid points in the vertical
!
! u x component of velocity (m/s)
! v y component of velocity (m/s)
! w Vertical component of Cartesian velocity (m/s)
! wcont Contravariant vertical velocity (m/s)
! ustr Appropriate ustr for advection
! vstr Appropriate ustr for advection
! wstr Appropriate ustr for advection
! q Water substance at all time levels (K)
!
! rhostr Base state air density times j3 (kg/m**3)
! rhostri Inverse base state air density times j3 (kg/m**3)
! mapfct Map factor for scalar point
!
! OUTPUT:
!
! qadv Advection term of water substance eqn (kg/m**3)*(kg/kg)/s
!
! WORK ARRAYS:
!
! tem1 Temporary work array.
! tem2 Temporary work array.
! tem3 Temporary work array.
! tem4 Temporary work array.
! tem5 Temporary work array.
! tem6 Temporary work array.
! tem7 Temporary work array.
! tem8 Temporary work array.
! tem1_0 Temporary work array.
! tem2_0 Temporary work array.
! tem3_0 Temporary work array.
!
!-----------------------------------------------------------------------
!
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
INCLUDE 'timelvls.inc'
!
INTEGER :: nx,ny,nz ! Number of grid points in 3 directions
REAL :: dtbig1
REAL :: q (nx,ny,nz,nt) ! Water substance (kg/kg)
REAL :: u (nx,ny,nz,nt) ! Total u-velocity (m/s)
REAL :: v (nx,ny,nz,nt) ! Total v-velocity (m/s)
REAL :: wcont (nx,ny,nz) ! Total w-velocity (m/s)
REAL :: ustr (nx,ny,nz) ! u*rhostr/mapfct
REAL :: vstr (nx,ny,nz) ! v*rhostr/mapfct
REAL :: wstr (nx,ny,nz) ! wcont*rhostr
!
REAL :: rhostr(nx,ny,nz) ! Base state air density times j3 (kg/m**3)
REAL :: rhostri(nx,ny,nz) ! Inv. base state air density times j3 (kg/m**3)
REAL :: mapfct(nx,ny,8) ! Map factor for scalar point
REAL :: j3 (nx,ny,nz) ! Coordinate transformation Jacobian defined
! as d( zp )/d( z ).
!
REAL :: qadv (nx,ny,nz) ! Advection of water substance
!
REAL :: tem1 (nx,ny,nz) ! temporary work array
REAL :: tem2 (nx,ny,nz) ! temporary work array
REAL :: tem3 (nx,ny,nz) ! temporary work array
REAL :: tem4 (nx,ny,nz) ! temporary work array
REAL :: tem5 (nx,ny,nz) ! temporary work array
REAL :: tem6 (nx,ny,nz) ! temporary work array
REAL :: tem7 (nx,ny,nz) ! temporary work array
REAL :: tem8 (nx,ny,nz) ! temporary work array
REAL :: tem1_0(0:nx,0:ny,0:nz) ! automatic work array
REAL :: tem2_0(0:nx,0:ny,0:nz) ! automatic work array
REAL :: tem3_0(0:nx,0:ny,0:nz) ! automatic work array
!
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: i,j,k
INTEGER :: advdiv
INTEGER :: mptag1,mptag2
!
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
!
INCLUDE 'globcst.inc' ! Global model control parameters
INCLUDE 'grid.inc' ! Grid parameters
INCLUDE 'bndry.inc' ! Boundary Condition Flags
INCLUDE 'mp.inc' ! Message passing parameters.
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
advdiv = 1 ! Include anelastic correction term in advection
!
!-----------------------------------------------------------------------
!
! Calculate the q(tfurture) with FCT correction.
!
!-----------------------------------------------------------------------
!
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
tem1_0(i,j,k)=q(i,j,k,1)
tem2_0(i,j,k)=q(i,j,k,2)
END DO
END DO
END DO
! IF (mp_opt > 0) THEN
! CALL acct_interrupt(mp_acct)
! CALL mpsendextew(tem1_0,nx,ny,nz,ebc,wbc,mptag1,tem1)
! CALL mpsendextew(tem2_0,nx,ny,nz,ebc,wbc,mptag2,tem1)
! CALL mprecvextew(tem1_0,nx,ny,nz,ebc,wbc,mptag1,tem1)
! CALL mprecvextew(tem2_0,nx,ny,nz,ebc,wbc,mptag2,tem1)
! CALL mpsendextns(tem1_0,nx,ny,nz,nbc,sbc,mptag1,tem1)
! CALL mpsendextns(tem2_0,nx,ny,nz,nbc,sbc,mptag2,tem1)
! CALL mprecvextns(tem1_0,nx,ny,nz,nbc,sbc,mptag1,tem1)
! CALL mprecvextns(tem2_0,nx,ny,nz,nbc,sbc,mptag2,tem1)
! END IF
CALL acct_interrupt
(bc_acct)
CALL extndsbc
(tem1_0,nx,ny,nz,0,ebc,wbc,nbc,sbc,tbc,bbc)
CALL extndsbc
(tem2_0,nx,ny,nz,0,ebc,wbc,nbc,sbc,tbc,bbc)
CALL acct_stop_inter
!test tmp: call test_dump (tem1_0,"XXXA1tem1_0",nx+1,ny+1,nz+1,4,1)
!test tmp: call test_dump (tem2_0,"XXXA1tem2_0",nx+1,ny+1,nz+1,4,1)
!
!-----------------------------------------------------------------------
!
! Calculate ustr, vstr and wstr.
!
!-----------------------------------------------------------------------
!
IF( advdiv == 1 ) THEN
!
!-----------------------------------------------------------------------
!
! Add the anelastic divergence correction term:
! -[d(rhostr*u)/dx+ d(rhostr*v)/dy+ d(rhostr*wcont)/dz]*q
!
!-----------------------------------------------------------------------
!
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
qadv(i,j,k)= - tem2_0(i,j,k)*( &
((ustr(i+1,j,k)-ustr(i,j,k))*dxinv &
+(vstr(i,j+1,k)-vstr(i,j,k))*dyinv)*mapfct(i,j,7) &
+(wstr(i,j,k+1)-wstr(i,j,k))*dzinv)
END DO
END DO
END DO
!test tmp: call test_dump (qadv,"XXXqadv",nx,ny,nz,0,0)
!test tmp: call test_dump (mapfct(1,1,7),"XXXqadv_mapfct",nx,ny,1,0,0)
!test tmp: call test_dump (tem2_0,"XXXqadv_tem2_0",nx+1,ny+1,nz+1,0,0)
!test tmp: call test_dump (ustr,"XXXqadv_ustr",nx,ny,nz,1,0)
!test tmp: call test_dump (vstr,"XXXqadv_vstr",nx,ny,nz,2,0)
!test tmp: call test_dump (wstr,"XXXqadv_wstr",nx,ny,nz,3,0)
ELSE
DO k=1,nz
DO j=1,ny
DO i=1,nx
qadv(i,j,k)= 0.0
END DO
END DO
END DO
END IF
IF(sadvopt == 4) THEN
CALL advctsfct
(nx,ny,nz,nt,dtbig1,ustr,vstr,wstr, &
mapfct(1,1,7),tem1_0,tem2_0,tem3_0,rhostr,rhostri, &
qadv, &
tem1,tem2,tem3,tem4,tem5,tem6,tem7,tem8)
ELSE IF(sadvopt == 5) THEN ! MPDCD positive definite advection
CALL advmpdcd
(nx,ny,nz,nt,dtbig1,ustr,vstr,wstr, &
mapfct(1,1,7),tem1_0,tem2_0,rhostr, &
qadv, &
tem1,tem2,tem3,tem4,tem3_0,tem5)
END IF
!test tmp: call test_dump (qadv,"XXX2qadv",nx,ny,nz,0,0)
RETURN
END SUBROUTINE advqfct
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE ADVCTSFCT ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE advctsfct(nx,ny,nz,nt,dtbig1, & 2,10
ustr,vstr,wstr,mapfct2, s1,s2, s3,rhostr,rhostri, &
sadv, &
fluxx,fluxy,fluxz,cx,cy,cz,tem1,tem2)
!
!----------------------------------------------------------------------
!
! PURPOSE:
!
! Integrate scalar field forward on time step using Zalesak's
! multi-dimensional version of FCT.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Ming Xue. Adaptied for ARPS by Y.F. Tang.
! 11/29/1992.
!
! 3/10/1993 (M. Xue)
! Code cleanup.
!
! 11/20/1997 (Fanyou Kong -- CMRP)
! Added map factor into FCT schemes
!
! 7/17/1998 (Ming Xue)
!
! The formulation of advective fluxes are now consistent with
! the regular advection. Array sadv is now accumulative.
!
! 10/5/1998 (Dan Weber)
! Added rhostri array.
!
! 2000/09/15 (Gene Bassett)
! Removed dx,dy,dz,dtbig & fctorderopt from argument list.
!
!-----------------------------------------------------------------------
!
! INPUT:
!
! nx Number of grid points in the x-direction (east/west)
! ny Number of grid points in the y-direction (north/south)
! nz Number of grid points in the vertical
! nt number of the time level
! dtbig1 Time step size
!
! ustr u*rhostr
! vstr v*rhostr
! wstr wcont*rhostr
! mapfct2 map factor for the scalar ** 2
! s1 scalar field at a given time n-1 level (scalar units)
! s2 scalar field at a given time n level (scalar units)
! rhostr rhobar*j3
! rhostri inverse rhobar*j3
! sadv Part of the advection term for scalar s
!
! OUTPUT:
!
! sadv Advection for scalar s
! s1,s2 and s3 modified.
!
! WORK ARRAYS:
!
! fluxx Temporary work array.
! fluxy Temporary work array.
! fluxz Temporary work array.
! cx Temporary work array.
! cy Temporary work array.
! cz Temporary work array.
! tem1 Temporary work array.
! tem2 Temporary work array.
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
INTEGER :: nx,ny,nz
INTEGER :: nt ! The no. of t-levels of t-dependent arrays.
REAL :: dtbig1
REAL :: ustr (nx,ny,nz) ! u*rhostr
REAL :: vstr (nx,ny,nz) ! v*rhostr
REAL :: wstr (nx,ny,nz) ! wcont*rhostr
REAL :: mapfct2(nx,ny) ! map factor for scalar **2
REAL :: s1 (0:nx,0:ny,0:nz)! Time lev. 1 of a scalar field to be advected.
REAL :: s2 (0:nx,0:ny,0:nz)! Time lev. 2 of a scalar field to be advected.
REAL :: s3 (0:nx,0:ny,0:nz)! Time lev. 3 of a scalar field to be advected.
REAL :: rhostr(nx,ny,nz) ! rhostr*j3
REAL :: rhostri(nx,ny,nz) ! Inverse rhostr*j3
REAL :: sadv (nx,ny,nz) ! Advection of scalar s
!
REAL :: fluxx (nx,ny,nz) ! temporary work array
REAL :: fluxy (nx,ny,nz) ! temporary work array
REAL :: fluxz (nx,ny,nz) ! temporary work array
REAL :: cx (nx,ny,nz) ! temporary work array
REAL :: cy (nx,ny,nz) ! temporary work array
REAL :: cz (nx,ny,nz) ! temporary work array
REAL :: tem1 (nx,ny,nz) ! temporary work array
REAL :: tem2 (nx,ny,nz) ! temporary work array
!
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: i,j,k
REAL :: tem, rdxyz,dxyz, tema,rdt,tem43,tem16
INTEGER :: mptag1,mptag2
!
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
!
INCLUDE 'globcst.inc' ! Global model control parameters
INCLUDE 'grid.inc' ! Grid parameters
INCLUDE 'bndry.inc' ! Boundary Condition Flags
INCLUDE 'mp.inc' ! Message passing parameters.
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
dxyz=dx*dy*dz
rdxyz=1./(dxyz)
tem43 = 4.0/3.0
tem16 = 1.0/6.0
!
!-----------------------------------------------------------------------
!
! Compute the second-order advective fluxes
!
!-----------------------------------------------------------------------
!
CALL advflxs
(nx,ny,nz,nt,dx,dy,dz,dtbig1, &
ustr,vstr,wstr,s2,fctorderopt, &
fluxx,fluxy,fluxz, &
s3,tem1) ! Attention: s3 is used as a work array here!
!
!-----------------------------------------------------------------------
!
! Compute the temperary scalar field at tfuture
!
!-----------------------------------------------------------------------
!
tem = 2.0 * rdxyz
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
s3(i,j,k)=s1(i,j,k)-((fluxx(i+1,j,k)-fluxx(i,j,k)+ &
fluxy(i,j+1,k)-fluxy(i,j,k))*mapfct2(i,j)+ &
fluxz(i,j,k+1)-fluxz(i,j,k))*tem &
*rhostri(i,j,k)
END DO
END DO
END DO
! IF (mp_opt > 0) THEN
! CALL acct_interrupt(mp_acct)
! CALL mpsendextew(s3,nx,ny,nz,ebc,wbc,mptag1,tem1)
! CALL mprecvextew(s3,nx,ny,nz,ebc,wbc,mptag1,tem1)
! CALL mpsendextns(s3,nx,ny,nz,nbc,sbc,mptag1,tem1)
! CALL mprecvextns(s3,nx,ny,nz,nbc,sbc,mptag1,tem1)
! END IF
CALL acct_interrupt
(bc_acct)
CALL extndsbc
(s3,nx,ny,nz,0,ebc,wbc,nbc,sbc,tbc,bbc)
CALL acct_stop_inter
!test tmp: call test_dump (s3,"XXXA1s3",nx+1,ny+1,nz+1,4,1)
!-----------------------------------------------------------------------
!
! Trapezoidal step:
!
!-----------------------------------------------------------------------
DO k=0,nz
DO j=0,ny
DO i=0,nx
s3(i,j,k)=(s3(i,j,k)+s2(i,j,k))*0.5
END DO
END DO
END DO
CALL advflxs
(nx,ny,nz,nt,dx,dy,dz,dtbig, &
ustr,vstr,wstr,s3,fctorderopt, &
fluxx,fluxy,fluxz, &
s1,tem1) ! Attention: s1 is used as a work array here!
!
!-----------------------------------------------------------------------
!
! Low order scheme: Donnor Cell.
! Calculate the donnor-cell fluxes
!
!-----------------------------------------------------------------------
tem = dtbig*dy*dz*0.5
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx
cx(i,j,k)=tem* &
((ustr(i,j,k)+ABS(ustr(i,j,k)))*s2(i-1,j,k) &
+(ustr(i,j,k)-ABS(ustr(i,j,k)))*s2(i ,j,k))
fluxx(i,j,k)=fluxx(i,j,k)-cx(i,j,k)
END DO
END DO
END DO
!
tem = dtbig*dx*dz*0.5
DO k=1,nz-1
DO j=1,ny
DO i=1,nx-1
cy(i,j,k)=tem* &
((vstr(i,j,k)+ABS(vstr(i,j,k)))*s2(i,j-1,k) &
+(vstr(i,j,k)-ABS(vstr(i,j,k)))*s2(i,j ,k))
fluxy(i,j,k)=fluxy(i,j,k)-cy(i,j,k)
END DO
END DO
END DO
!
tem = dtbig*dx*dy*0.5
DO k=1,nz
DO j=1,ny-1
DO i=1,nx-1
cz(i,j,k)=tem* &
((wstr(i,j,k)+ABS(wstr(i,j,k)))*s2(i,j,k-1) &
+(wstr(i,j,k)-ABS(wstr(i,j,k)))*s2(i,j,k ))
fluxz(i,j,k)=fluxz(i,j,k)-cz(i,j,k)
END DO
END DO
END DO
!
! Compute the low order time advanced solution for scalar
!
rdt=1.0/dtbig
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
tema = ((cx(i+1,j,k)-cx(i,j,k) &
+cy(i,j+1,k)-cy(i,j,k))*mapfct2(i,j) &
+cz(i,j,k+1)-cz(i,j,k))*rdxyz
s3(i,j,k)=s2(i,j,k)-tema*rhostri(i,j,k)
sadv(i,j,k) = sadv(i,j,k)+ tema * rdt
END DO
END DO
END DO
!test tmp: call test_dump (sadv,"XXXfct_sadv",nx,ny,nz,0,0)
!-----------------------------------------------------------------------
!
! Determine the flux limitor by calling fctlim.
! fctlim returns the limited/corrected anti-diffusive fluxes
! which are added to the lower order fluxes.
!
!c#######################################################################
! IF (mp_opt > 0) THEN
! CALL acct_interrupt(mp_acct)
! CALL mpsendextew(s2,nx,ny,nz,ebc,wbc,mptag1,tem1)
! CALL mpsendextew(s3,nx,ny,nz,ebc,wbc,mptag2,tem1)
! CALL mprecvextew(s2,nx,ny,nz,ebc,wbc,mptag1,tem1)
! CALL mprecvextew(s3,nx,ny,nz,ebc,wbc,mptag2,tem1)
! CALL mpsendextns(s2,nx,ny,nz,nbc,sbc,mptag1,tem1)
! CALL mpsendextns(s3,nx,ny,nz,nbc,sbc,mptag2,tem1)
! CALL mprecvextns(s2,nx,ny,nz,nbc,sbc,mptag1,tem1)
! CALL mprecvextns(s3,nx,ny,nz,nbc,sbc,mptag2,tem1)
! END IF
CALL acct_interrupt
(bc_acct)
CALL extndsbc
(s2,nx,ny,nz,0,ebc,wbc,nbc,sbc,tbc,bbc)
CALL extndsbc
(s3,nx,ny,nz,0,ebc,wbc,nbc,sbc,tbc,bbc)
CALL acct_stop_inter
!test tmp: call test_dump (s2,"XXXA2s2",nx+1,ny+1,nz+1,4,1)
!test tmp: call test_dump (s3,"XXXA2s3",nx+1,ny+1,nz+1,4,1)
CALL fctlim
(nx,ny,nz,dxyz,s3,s2,rhostr,mapfct2,fluxx,fluxy,fluxz, &
cx,cy,cz,tem1,tem2)
!-----------------------------------------------------------------------
!
! Add the flux-limitted adtidifusive fluxes.
! Note the flux nomal to the lateral boundaries are not applied.
!
!c#######################################################################
tem = 1.0/(dtbig*dx*dy*dz)
DO k=2,nz-2
DO j=1,ny-1
DO i=2,nx-2
sadv(i,j,k)=sadv(i,j,k)+(fluxx(i+1,j,k)-fluxx(i,j,k)) &
*mapfct2(i,j)*tem
END DO
END DO
DO j=2,ny-2
DO i=1,nx-1
sadv(i,j,k)=sadv(i,j,k)+(fluxy(i,j+1,k)-fluxy(i,j,k)) &
*mapfct2(i,j)*tem
END DO
END DO
DO j=1,ny-1
DO i=1,nx-1
sadv(i,j,k)=sadv(i,j,k)+(fluxz(i,j,k+1)-fluxz(i,j,k))*tem
END DO
END DO
END DO
!test tmp: call test_dump (fluxx,"XXXfct_fluxx",nx,ny,nz,1,0)
!test tmp: call test_dump (fluxy,"XXXfct_fluxy",nx,ny,nz,2,0)
!test tmp: call test_dump (fluxz,"XXXfct_fluxz",nx,ny,nz,3,0)
!test tmp: call test_dump (sadv,"XXX1fct_sadv",nx,ny,nz,0,0)
RETURN
END SUBROUTINE advctsfct
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE ADVFLXS ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE advflxs(nx,ny,nz,nt,dx,dy,dz,dt, & 3,9
ustr,vstr,wstr,s,advodropt, &
fluxx,fluxy,fluxz, &
tem1_0,mp_tem)
!
!----------------------------------------------------------------------
!
! PURPOSE:
!
! Calculate 2nd- and 4th-order fluxes for the advection of a scalar.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Ming Xue.
! 7/18/1998
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! INPUT:
!
! nx Number of grid points in the x-direction (east/west)
! ny Number of grid points in the y-direction (north/south)
! nz Number of grid points in the vertical
! nt number of the time level
! dx Grid interval in x direction
! dy Grid interval in x direction
! dz Grid interval in x direction
! dt Time step size
!
! ustr u*rhostr
! vstr v*rhostr
! wstr wcont*rhostr
! s Scalar whose advective fluxes are to be found
!
! OUTPUT:
!
! fluxx Advective flux in x direction.
! fluxy Advective flux in y direction.
! fluxz Advective flux in z direction.
!
! Work array:
! tem1_0 Work array
! mp_tem Work array
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
INTEGER :: nx,ny,nz
INTEGER :: nt ! The no. of t-levels of t-dependent arrays.
REAL :: dx,dy,dz,dt
REAL :: ustr (nx,ny,nz) ! u*rhostr
REAL :: vstr (nx,ny,nz) ! v*rhostr
REAL :: wstr (nx,ny,nz) ! wcont*rhostr
REAL :: s(0:nx,0:ny,0:nz) ! Scalar whose advective fluxes are to be found
!
REAL :: fluxx (nx,ny,nz) ! Advective flux in x direction.
REAL :: fluxy (nx,ny,nz) ! Advective flux in y direction.
REAL :: fluxz (nx,ny,nz) ! Advective flux in z direction.
REAL :: tem1_0(0:nx,0:ny,0:nz) ! Work array
REAL :: mp_tem(MAX(nx+1,ny+1)*(nz+1)) ! Temporary message passing array.
!
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: i,j,k
REAL :: tem, rdxyz,dxyz, tem43,tem16
INTEGER :: advodropt
INTEGER :: mptag
!
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
!
INCLUDE 'bndry.inc' ! the boundary flags
INCLUDE 'globcst.inc'
INCLUDE 'mp.inc' ! Message passing parameters.
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
dxyz=dx*dy*dz
rdxyz=1./(dxyz)
tem43 = 4.0/3.0
tem16 = 1.0/6.0
!
!-----------------------------------------------------------------------
!
! Compute the second-order advective fluxes
!
!-----------------------------------------------------------------------
!
tem = dt*dy*dz*0.5
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx
fluxx(i,j,k)=tem*ustr(i,j,k)*(s(i,j,k)+s(i-1,j,k))
END DO
END DO
END DO
!test tmp: call test_dump (fluxx,"XXXadvflxs_fluxx",nx,ny,nz,1,0)
IF( advodropt == 2) THEN ! For fourth order fluxes
tem = dt*dy*dz*0.25
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
tem1_0(i,j,k)= &
tem*(ustr(i,j,k)+ustr(i+1,j,k))*(s(i+1,j,k)+s(i-1,j,k))
END DO
END DO
END DO
! IF (mp_opt > 0) THEN
! CALL acct_interrupt(mp_acct)
! CALL mpsendextew(tem1_0,nx,ny,nz,ebc,wbc,mptag,mp_tem)
! CALL mprecvextew(tem1_0,nx,ny,nz,ebc,wbc,mptag,mp_tem)
! END IF
CALL acct_interrupt
(bc_acct)
CALL extndsbc
(tem1_0,nx,ny,nz,1,ebc,wbc,0,0,0,0)
CALL acct_stop_inter
!test tmp: call test_dump2(tem1_0,"XXXA3tem1_0",nx+1,ny+1,nz+1,1,nx+1,2,ny,2,nz)
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx
fluxx(i,j,k)=tem43*fluxx(i,j,k) &
-tem16*(tem1_0(i-1,j,k)+tem1_0(i,j,k))
END DO
END DO
END DO
!test tmp: call test_dump (fluxx,"XXX1advflxs_fluxx",nx,ny,nz,1,0)
END IF
tem = dt*dx*dz*0.5
DO k=1,nz-1
DO j=1,ny
DO i=1,nx-1
fluxy(i,j,k)=tem*vstr(i,j,k)*(s(i,j,k)+s(i,j-1,k))
END DO
END DO
END DO
!test tmp: call test_dump (fluxy,"XXXadvflxs_fluxy",nx,ny,nz,2,0)
IF( advodropt == 2) THEN ! For fourth order fluxes
tem = dt*dx*dz*0.25
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
tem1_0(i,j,k)= &
tem*(vstr(i,j,k)+vstr(i,j+1,k))*(s(i,j+1,k)+s(i,j-1,k))
END DO
END DO
END DO
! IF (mp_opt > 0) THEN
! CALL acct_interrupt(mp_acct)
! CALL mpsendextns(tem1_0,nx,ny,nz,nbc,sbc,mptag,mp_tem)
! CALL mprecvextns(tem1_0,nx,ny,nz,nbc,sbc,mptag,mp_tem)
! END IF
CALL acct_interrupt
(bc_acct)
CALL extndsbc
(tem1_0,nx,ny,nz,1,0,0,nbc,sbc,0,0)
CALL acct_stop_inter
!test tmp: call test_dump (tem1_0,"XXXA4tem1_0",nx+1,ny+1,nz+1,4,1)
DO k=1,nz-1
DO j=1,ny
DO i=1,nx-1
fluxy(i,j,k)=tem43*fluxy(i,j,k) &
-tem16*(tem1_0(i,j-1,k)+tem1_0(i,j,k))
END DO
END DO
END DO
!test tmp: call test_dump (fluxy,"XXX1advflxs_fluxy",nx,ny,nz,2,0)
END IF
tem = dt*dx*dy*0.5
DO k=1,nz
DO j=1,ny-1
DO i=1,nx-1
fluxz(i,j,k)=tem*wstr(i,j,k)*(s(i,j,k)+s(i,j,k-1))
END DO
END DO
END DO
!test tmp: call test_dump (fluxz,"XXXadvflxs_fluxz",nx,ny,nz,3,0)
IF( advodropt == 2) THEN ! For fourth order fluxes
tem = dt*dx*dy*0.25
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
tem1_0(i,j,k)= &
tem*(wstr(i,j,k)+wstr(i,j,k+1))*(s(i,j,k+1)+s(i,j,k-1))
END DO
END DO
END DO
CALL acct_interrupt
(bc_acct)
CALL extndsbc
(tem1_0,nx,ny,nz,1,0,0,0,0,tbc,bbc)
CALL acct_stop_inter
!test tmp: call test_dump (tem1_0,"XXXA5tem1_0",nx+1,ny+1,nz+1,4,1)
DO k=1,nz
DO j=1,ny-1
DO i=1,nx-1
fluxz(i,j,k)=tem43*fluxz(i,j,k) &
-tem16*(tem1_0(i,j,k-1)+tem1_0(i,j,k))
END DO
END DO
END DO
!test tmp: call test_dump (fluxz,"XXX1advflxs_fluxz",nx,ny,nz,3,0)
END IF
RETURN
END SUBROUTINE advflxs
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE ADVMPDCD ######
!###### ######
!###### Developed by ######
!###### Coastal Meteorology Research Program (CMRP) ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE advmpdcd(nx,ny,nz,nt,dtbig1, & 2,4
ustr,vstr,wstr,mapfct2,s1,s2,rhostr, &
sadv, &
fluxx,fluxy,fluxz,fout,bout,mp_tem)
!
!----------------------------------------------------------------------
!
! PURPOSE:
!
! MPDCD (Multidimensional Positive Definite Centered Difference
! Scheme) positive definite advection for scalars
!
!-----------------------------------------------------------------------
!
! AUTHOR: Fanyou Kong (CMRP)
! 07/10/1997.
!
! 11/20/1997 (Fanyou Kong -- CMRP)
! - Added map factor into MPDCD schemes
! - Added Loop 50 to record possible negative scalar values in "s1"
! and then force them positive to prevent possible floating
! point error, but report the situation in output file
!
! 7/17/1998 (Ming Xue)
! Modified the formulation of fluxes. sadv is now accumulative.
!
! 9/12/1999 (Pengfei Zhang & Ming Xue)
! Added a constant "eps" in the denominator of an equation to
! prevent overflow.
!
! 2000/09/15 (Gene Bassett)
! Removed dx,dy,dz & fctorderopt from argument list.
!
!-----------------------------------------------------------------------
!
! INPUT:
!
! nx Number of grid points in the x-direction (east/west)
! ny Number of grid points in the y-direction (north/south)
! nz Number of grid points in the vertical
! nt number of the time level
! dx Grid interval in x direction
! dy Grid interval in x direction
! dz Grid interval in x direction
! dtbig1 Time step size
!
! ustr u*rhostr
! vstr v*rhostr
! wstr wcont*rhostr
!
! mapfct2 map factor for scalar **2
! s1 scalar field at a given time n-1 level (scalar units)
! s2 scalar field at a given time n level (scalar units)
! rhostr rhobar*j3
! fctorderopt Option parameter for 2nd or 4th order high-order fluxes
!
! OUTPUT:
!
! sadv advection term [(kg/m**3) scalar unit/s]
!
! WORK ARRAYS:
!
! fluxx Temporary work array.
! fluxy Temporary work array.
! fluxz Temporary work array.
! bout Temporary work array.
! fout Temporary work array.
! mp_tem Temporary work array.
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
INTEGER :: nx,ny,nz
INTEGER :: nt ! The no. of t-levels of t-dependent arrays.
REAL :: dtbig1
REAL :: ustr (nx,ny,nz) ! u*rhostr
REAL :: vstr (nx,ny,nz) ! v*rhostr
REAL :: wstr (nx,ny,nz) ! wcont*rhostr
REAL :: mapfct2(nx,ny) ! map factor for scalar **2
REAL :: s1 (0:nx,0:ny,0:nz)! Time lev. 1 of a scalar field to be advected.
REAL :: s2 (0:nx,0:ny,0:nz)! Time lev. 2 of a scalar field to be advected.
REAL :: rhostr(nx,ny,nz) ! rhobar*j3
REAL :: sadv (nx,ny,nz) ! advection term
!
REAL :: fluxx (nx,ny,nz) ! temporary work array
REAL :: fluxy (nx,ny,nz) ! temporary work array
REAL :: fluxz (nx,ny,nz) ! temporary work array
REAL :: fout (nx,ny,nz) ! temporary work array
REAL :: bout (0:nx,0:ny,0:nz) ! temporary work array
REAL :: mp_tem(MAX(nx+1,ny+1)*(nz+1)) ! Temporary message passing array.
!
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: i,j,k, negnum
REAL :: tem, eps
REAL :: dtxy,dtxz,dtyz,rdxyz,dxyz
INTEGER :: mptag
!
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
!
INCLUDE 'bndry.inc' ! the boundary flags
INCLUDE 'globcst.inc' ! Global model control parameters
INCLUDE 'grid.inc' ! Grid parameters
INCLUDE 'mp.inc' ! Message passing parameters.
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
dtxy=dtbig1*dx*dy
dtxz=dtbig1*dz*dx
dtyz=dtbig1*dz*dy
dxyz=dx*dy*dz
rdxyz=1./(dxyz)
eps=1.e-20
!
!-----------------------------------------------------------------------
!
! Compute the second-order advective fluxes d(rhostr*u*s)/dx
!
!-----------------------------------------------------------------------
!
CALL advflxs
(nx,ny,nz,nt,dx,dy,dz,dtbig1, &
ustr,vstr,wstr,s2,fctorderopt, &
fluxx,fluxy,fluxz, &
bout,fout)
! Attention: bout & fout are used as a work arrays here!
!test tmp: call test_dump (fluxx,"XXX1fct5_fluxx",nx,ny,nz,1,0)
!test tmp: call test_dump (fluxy,"XXX1fct5_fluxy",nx,ny,nz,2,0)
!test tmp: call test_dump (fluxz,"XXX1fct5_fluxz",nx,ny,nz,3,0)
! compute the total outgoing flux for each grid cell (FOUT)
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
fout(i,j,k)=rdxyz*( mapfct2(i,j)*( &
(ABS(fluxx(i ,j,k))-fluxx(i ,j,k)) + &
(ABS(fluxx(i+1,j,k))+fluxx(i+1,j,k)) + &
(ABS(fluxy(i ,j,k))-fluxy(i ,j,k)) + &
(ABS(fluxy(i,j+1,k))+fluxy(i,j+1,k)))+ &
(ABS(fluxz(i,j ,k))-fluxz(i,j ,k)) + &
(ABS(fluxz(i,j,k+1))+fluxz(i,j,k+1)))
END DO
END DO
END DO
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
s1(i,j,k) = MAX(0.0, s1(i,j,k)) ! Set negative values to zero
IF(fout(i,j,k) <= s1(i,j,k)*rhostr(i,j,k)) THEN
bout(i,j,k) = 1.0
ELSE
bout(i,j,k) = (s1(i,j,k)*rhostr(i,j,k))/(fout(i,j,k)+eps)
END IF
END DO
END DO
END DO
! IF (mp_opt > 0) THEN
! CALL acct_interrupt(mp_acct)
! CALL mpsendextew(bout,nx,ny,nz,ebc,wbc,mptag,mp_tem)
! CALL mprecvextew(bout,nx,ny,nz,ebc,wbc,mptag,mp_tem)
! CALL mpsendextns(bout,nx,ny,nz,nbc,sbc,mptag,mp_tem)
! CALL mprecvextns(bout,nx,ny,nz,nbc,sbc,mptag,mp_tem)
! END IF
CALL acct_interrupt
(bc_acct)
CALL extndsbc
(bout,nx,ny,nz,0,ebc,wbc,nbc,sbc,tbc,bbc)
CALL acct_stop_inter
!test tmp: call test_dump (bout,"XXXAbout",nx+1,ny+1,nz+1,4,1)
!
!-----------------------------------------------------------------------
!
! Application of the flux limiter to fluxes
!
!-----------------------------------------------------------------------
!
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx
IF(fluxx(i,j,k) > 0.0) THEN
fluxx(i,j,k)=bout(i-1,j,k)*fluxx(i,j,k)
ELSE
fluxx(i,j,k)=bout(i,j,k) *fluxx(i,j,k)
END IF
END DO
END DO
END DO
!
DO k=1,nz-1
DO j=1,ny
DO i=1,nx-1
IF(fluxy(i,j,k) > 0.0) THEN
fluxy(i,j,k)=bout(i,j-1,k)*fluxy(i,j,k)
ELSE
fluxy(i,j,k)=bout(i,j,k) *fluxy(i,j,k)
END IF
END DO
END DO
END DO
DO k=1,nz
DO j=1,ny-1
DO i=1,nx-1
IF(fluxz(i,j,k) > 0.0) THEN
fluxz(i,j,k)=bout(i,j,k-1)*fluxz(i,j,k)
ELSE
fluxz(i,j,k)=bout(i,j,k) *fluxz(i,j,k)
END IF
END DO
END DO
END DO
!
!-----------------------------------------------------------------------
!
! Calculate advection term (sadv)
!
!-----------------------------------------------------------------------
!test tmp: call test_dump (sadv,"XXXfct5_sadv",nx,ny,nz,0,0)
tem = 1.0/(dtbig1*dx*dy*dz)
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
sadv(i,j,k)=sadv(i,j,k)+ &
((fluxx(i+1,j,k)-fluxx(i,j,k) + &
fluxy(i,j+1,k)-fluxy(i,j,k))*mapfct2(i,j) + &
fluxz(i,j,k+1)-fluxz(i,j,k))*tem
END DO
END DO
END DO
!test tmp: call test_dump (fluxx,"XXXfct5_fluxx",nx,ny,nz,1,0)
!test tmp: call test_dump (fluxy,"XXXfct5_fluxy",nx,ny,nz,2,0)
!test tmp: call test_dump (fluxz,"XXXfct5_fluxz",nx,ny,nz,3,0)
!test tmp: call test_dump (sadv,"XXX1fct5_sadv",nx,ny,nz,0,0)
RETURN
END SUBROUTINE advmpdcd
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE FCTLIM ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE fctlim(nx,ny,nz,dxyz,std,sa,rhostr,mapfct2, & 1
fluxx,fluxy,fluxz,cx,cy,cz,rminus,rplus)
!
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Perform 3-D flux limiting (Zalesak, 1979) on fluxx, fluxy, fluxz
! which are fluxes in x, y, and z direction respectivly.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Ming Xue
! 1/1/1988
!
! (Originally written for the sigma-coordinate model of
! Xue and Thorpe, 1991).
!
! MODIFICATION HISTORY
!
! 11/20/92 (Yifeng Tang)
! Adapted for ARPS, taking into account of various boundary condition
! options.
!
! 10/12/1996 (M. Xue)
! Cleaned up and portions rewritten for ARPS.
!
! 11/20/1997 (Fanyou Kong - CMRP)
! Added map factor
!
! 7/16/1998 (M. Xue and R. Richardson)
! Significant changes made. The extrema in the advected
! (instead of the previous rhostr multipled) field are now used
! in determining the flux correction coefficients.
! A one-dimensional prelimiter is included as an option,
! although it's not recommended for common use.
!
!-----------------------------------------------------------------------
!
! INPUT:
!
! nx Number of grid points in the x-direction (east/west)
! ny Number of grid points in the y-direction (north/south)
! nz Number of grid points in the vertical
!
! dxyz dx*dy*dz
!
! std the scalar at n+1 computed from donnor cell fluxes
! sa the scalar at time n
! std and sa are unchanged on return.
! rhostr rhobar * j3
! mapfct2 Map factor for scalars **2
! fluxx the antidiffusive flux in x direction
! fluxy the antidiffusive flux in y direction
! fluxz the antidiffusive flux in z direction
! cx the donnor cell flux in x direction
! cy the donnor cell flux in y direction
! cz the donnor cell flux in z direction
!
! OUTPUT:
!
! fluxx the limited antidiffusive flux in x direction
! fluxy the limited antidiffusive flux at y
! fluxz the limited antidiffusive flux at z
!
! WORK ARRAYS:
!
! rminus the work array
! rplus the work array
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
INTEGER :: nx,ny,nz
REAL :: std(0:nx,0:ny,0:nz)
REAL :: sa (0:nx,0:ny,0:nz)
REAL :: rhostr(nx,ny,nz)
REAL :: mapfct2(nx,ny)
REAL :: fluxx (nx,ny,nz)
REAL :: fluxy (nx,ny,nz)
REAL :: fluxz (nx,ny,nz)
REAL :: cx (nx,ny,nz)
REAL :: cy (nx,ny,nz)
REAL :: cz (nx,ny,nz)
REAL :: rminus(nx,ny,nz)
REAL :: rplus (nx,ny,nz)
REAL :: dxyz
REAL :: qplus,qminus,pplus,pminus
INTEGER :: fct1dlim ! Switch for 1D prelimiter
!
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: i,j,k
!
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
INCLUDE 'bndry.inc' ! the boundary flags
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
fct1dlim = 0
IF( fct1dlim == 1) THEN
!
!-----------------------------------------------------------------------
!
! Pre-limiting in x-direciton.
!
!-----------------------------------------------------------------------
!
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
pplus=(MAX(0.,fluxx(i,j,k))-MIN(0.,fluxx(i+1,j,k))) &
*mapfct2(i,j)
qplus=( MAX(std(i-1,j,k),std(i+1,j,k),std(i,j,k), &
sa (i-1,j,k),sa (i+1,j,k),sa (i,j,k)) &
-std(i,j,k) )*dxyz * rhostr(i,j,k)
IF( pplus < 1.0E-20) THEN
rplus(i,j,k)=0.0
ELSE
rplus(i,j,k)=MIN(1.,qplus/pplus )
END IF
END DO
END DO
END DO
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
pminus=(MAX(0.,fluxx(i+1,j,k))-MIN(0.,fluxx(i,j,k))) &
*mapfct2(i,j)
qminus=-( MIN(std(i-1,j,k),std(i+1,j,k),std(i,j,k), &
sa (i-1,j,k),sa (i+1,j,k),sa (i,j,k)) &
-std(i,j,k) )*dxyz * rhostr(i,j,k)
IF( pminus < 1.e-20 ) THEN
rminus(i,j,k)=0.0
ELSE
rminus(i,j,k)= MIN(1.,qminus/pminus)
END IF
END DO
END DO
END DO
!
! Determine the correction coefficient C
!
DO k=1,nz-1
DO j=1,ny-1
DO i=2,nx-1
IF( fluxx(i,j,k) >= 0.0) THEN
cx(i,j,k)=MIN(rplus (i,j,k),rminus(i-1,j,k))
ELSE
cx(i,j,k)=MIN(rminus(i,j,k),rplus (i-1,j,k))
END IF
END DO
END DO
END DO
!
!-----------------------------------------------------------------------
!
! Pre-limiting in y-direciton.
!
!-----------------------------------------------------------------------
!
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
pplus=(MAX(0.,fluxy(i,j,k))-MIN(0.,fluxy(i,j+1,k))) &
*mapfct2(i,j)
qplus=( MAX(std(i,j,k),std(i,j-1,k),std(i,j+1,k), &
sa (i,j,k),sa (i,j-1,k),sa (i,j+1,k)) &
-std(i,j,k) )*dxyz * rhostr(i,j,k)
IF( pplus < 1.0E-20) THEN
rplus(i,j,k)=0.0
ELSE
rplus(i,j,k)=MIN(1.,qplus/pplus )
END IF
END DO
END DO
END DO
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
pminus=(MAX(0.,fluxy(i,j+1,k))-MIN(0.,fluxy(i,j,k))) &
*mapfct2(i,j)
qminus=-( MIN(std(i,j,k),std(i,j-1,k),std(i,j+1,k), &
sa (i,j,k),sa (i,j-1,k),sa (i,j+1,k)) &
-std(i,j,k) )*dxyz * rhostr(i,j,k)
IF( pminus < 1.e-20 ) THEN
rminus(i,j,k)=0.0
ELSE
rminus(i,j,k)= MIN(1.,qminus/pminus)
END IF
END DO
END DO
END DO
DO k=1,nz-1
DO j=2,ny-1
DO i=1,nx-1
IF( fluxy(i,j,k) >= 0.0) THEN
cy(i,j,k)=MIN(rplus (i,j,k),rminus(i,j-1,k))
ELSE
cy(i,j,k)=MIN(rminus(i,j,k),rplus (i,j-1,k))
END IF
END DO
END DO
END DO
!
!-----------------------------------------------------------------------
!
! Pre-limiting in z-direciton.
!
!-----------------------------------------------------------------------
!
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
pplus=(MAX(0.,fluxz(i,j,k))-MIN(0.,fluxz(i,j,k+1)))
qplus=( MAX(std(i,j,k),std(i,j,k-1),std(i,j,k+1), &
sa (i,j,k),sa (i,j,k-1),sa (i,j,k+1)) &
-std(i,j,k) )*dxyz * rhostr(i,j,k)
IF( pplus < 1.0E-20) THEN
rplus(i,j,k)=0.0
ELSE
rplus(i,j,k)=MIN(1.,qplus/pplus )
END IF
END DO
END DO
END DO
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
pminus=(MAX(0.,fluxz(i,j,k+1))-MIN(0.,fluxz(i,j,k)))
qminus=-( MIN(std(i,j,k),std(i,j,k-1),std(i,j,k+1), &
sa (i,j,k),sa (i,j,k-1),sa (i,j,k+1)) &
-std(i,j,k) )*dxyz * rhostr(i,j,k)
IF( pminus < 1.e-20 ) THEN
rminus(i,j,k)=0.0
ELSE
rminus(i,j,k)= MIN(1.,qminus/pminus)
END IF
END DO
END DO
END DO
DO k=2,nz-1
DO j=1,ny-1
DO i=1,nx-1
IF( fluxz(i,j,k) >= 0.0) THEN
cz(i,j,k)=MIN(rplus (i,j,k),rminus(i,j,k-1))
ELSE
cz(i,j,k)=MIN(rminus(i,j,k),rplus (i,j,k-1))
END IF
END DO
END DO
END DO
!-----------------------------------------------------------------------
!
! Apply pre-limiting factor to the antidiffusive fluxes.
!
!-----------------------------------------------------------------------
!
DO k=1,nz-1
DO j=1,ny-1
DO i=2,nx-1
fluxx(i,j,k)=fluxx(i,j,k)*cx(i,j,k)
END DO
END DO
END DO
!
DO k=1,nz-1
DO j=2,ny-1
DO i=1,nx-1
fluxy(i,j,k)=fluxy(i,j,k)*cy(i,j,k)
END DO
END DO
END DO
!
DO k=2,nz-1
DO j=1,ny-1
DO i=1,nx-1
fluxz(i,j,k)=fluxz(i,j,k)*cz(i,j,k)
END DO
END DO
END DO
END IF ! End of 1D prelimiting step
!-----------------------------------------------------------------------
!
! Calculate total flux directing towards point (i,j,k) pplus
! then inward flux amplification factor r(i,j,k)+
! r+=min(1.,q+/p+).
!
!-----------------------------------------------------------------------
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
pplus=(MAX(0.,fluxx(i,j,k))-MIN(0.,fluxx(i+1,j,k)) &
+MAX(0.,fluxy(i,j,k))-MIN(0.,fluxy(i,j+1,k))) &
*mapfct2(i,j) &
+MAX(0.,fluxz(i,j,k))-MIN(0.,fluxz(i,j,k+1))
qplus=(MAX(std(i-1,j,k),std(i+1,j,k),std(i,j,k), &
std(i,j-1,k),std(i,j+1,k),std(i,j,k-1),std(i,j,k+1), &
sa (i-1,j,k),sa (i+1,j,k),sa (i,j,k), &
sa (i,j-1,k),sa (i,j+1,k),sa (i,j,k-1),sa (i,j,k+1)) &
-std(i,j,k) )*dxyz * rhostr(i,j,k)
IF( pplus < 1.0E-20) THEN
rplus(i,j,k)=0.0
ELSE
rplus(i,j,k)=MIN(1.,qplus/pplus )
END IF
END DO
END DO
END DO
!-----------------------------------------------------------------------
!
! Calculate total flux directing away from point (i,j,k) pminus
! then outward flux amplification factor r(i,j,k)-
! r- = min(1.,q-/p-).
!
!-----------------------------------------------------------------------
!
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
pminus=(MAX(0.,fluxx(i+1,j,k))-MIN(0.,fluxx(i,j,k)) &
+MAX(0.,fluxy(i,j+1,k))-MIN(0.,fluxy(i,j,k))) &
*mapfct2(i,j) &
+MAX(0.,fluxz(i,j,k+1))-MIN(0.,fluxz(i,j,k))
qminus=-(MIN(std(i-1,j,k),std(i+1,j,k),std(i,j,k), &
std(i,j-1,k),std(i,j+1,k),std(i,j,k-1),std(i,j,k+1), &
sa (i-1,j,k),sa (i+1,j,k),sa (i,j,k), &
sa (i,j-1,k),sa (i,j+1,k),sa (i,j,k-1),sa (i,j,k+1)) &
-std(i,j,k) )*dxyz * rhostr(i,j,k)
IF( pminus < 1.e-20 ) THEN
rminus(i,j,k)=0.0
ELSE
rminus(i,j,k)= MIN(1.,qminus/pminus)
END IF
END DO
END DO
END DO
!
! Determine the correction coefficient C
!
DO k=1,nz-1
DO j=1,ny-1
DO i=2,nx-1
IF( fluxx(i,j,k) >= 0.0) THEN
cx(i,j,k)=MIN(rplus (i,j,k),rminus(i-1,j,k))
ELSE
cx(i,j,k)=MIN(rminus(i,j,k),rplus (i-1,j,k))
END IF
END DO
END DO
END DO
DO k=1,nz-1
DO j=2,ny-1
DO i=1,nx-1
IF( fluxy(i,j,k) >= 0.0) THEN
cy(i,j,k)=MIN(rplus (i,j,k),rminus(i,j-1,k))
ELSE
cy(i,j,k)=MIN(rminus(i,j,k),rplus (i,j-1,k))
END IF
END DO
END DO
END DO
DO k=2,nz-1
DO j=1,ny-1
DO i=1,nx-1
IF( fluxz(i,j,k) >= 0.0) THEN
cz(i,j,k)=MIN(rplus (i,j,k),rminus(i,j,k-1))
ELSE
cz(i,j,k)=MIN(rminus(i,j,k),rplus (i,j,k-1))
END IF
END DO
END DO
END DO
!
! Apply final correction factors to the antidiffusive fluxes
!
DO k=1,nz-1
DO j=1,ny-1
DO i=2,nx-1
fluxx(i,j,k)=fluxx(i,j,k)*cx(i,j,k)
END DO
END DO
END DO
!
DO k=1,nz-1
DO j=2,ny-1
DO i=1,nx-1
fluxy(i,j,k)=fluxy(i,j,k)*cy(i,j,k)
END DO
END DO
END DO
!
DO k=2,nz-1
DO j=1,ny-1
DO i=1,nx-1
fluxz(i,j,k)=fluxz(i,j,k)*cz(i,j,k)
END DO
END DO
END DO
RETURN
END SUBROUTINE fctlim