! Colarco, Jan. 9, 2007
! sed command to replace F77 comments with F90: sed 's/^c/\!/g'
! F90-version of original CARMA vertical.f routine (see comments below from
! original routine header).
!
! Notes:
! 1) #preprocessor directives turn off the advection of air density,
! gases, ptc
! 2) outer do loop over iy, ix (old way was ixy)
! 3) hard coded the following assumptions for particle transport
! ibbnd = itbnd = I_FLUX_SPEC
! ftop = fbot = 0
! move out of way divcor portion
! assumes only particle transport due to sedimentation (no winds,
! no diffusion)
! 4) A departure from the original CARMA, have to think this through. On
! our assumption of a sigma coordinate, on return from setupvf the
! particle fall velocity is a positive number. In here, then, vtrans
! is equal to the fall velocity (vtrans = vf) and the particles move
! toward higher sigma (toward the ground).
!
subroutine vertical ( carma, rc ) 1,14
!
! Define variables and usages
use carma_types_mod
implicit none
! Input/Output
integer, intent(out) :: rc ! Error return code:
! 0 - all is well
! 1 -
! Local
integer :: ix, iy, k, ibin, ielem, ios
integer, parameter :: ig = 1
integer :: itbnd, ibbnd
real(kind=f) :: fbot, ftop
real(kind=f), pointer, dimension(:) :: vtrans, &
vertadvu, vertadvd, &
vertdifu, vertdifd, &
cvert
real(kind=f) :: cvert_bbnd, cvert_tbnd
real(kind=f) :: colwght_before, colwght_after
#include "carma_globaer.h"
#ifdef DEBUG
write(*,*) '+ vertical'
#endif
allocate( vtrans(carma%NZP1), vertadvu(carma%NZP1), vertadvd(carma%NZP1), &
vertdifu(carma%NZP1), vertdifd(carma%NZP1), cvert(carma%NZ), &
stat=ios)
if(ios /= 0) then
rc = 1
return
endif
!
!
! @(#) vertical.f Jensen Mar-1995
! This routine drives the vertical transport calculations.
!
! Modified Sep-1997 (McKie)
! Remove <ixy> from arg list of called routines.
! <ixy> now available as a global var in common block.
!
! Argument list input:
! None.
!
! Argument list output:
! None.
!
!
! Include global constants and variables.
!
! include 'globaer.h'
!
!
! Declare local variables
!
! dimension drho_dt_flux_spec(NZ), drho_dt_fixed_conc(NZ)
!
!
! Define formats
!
! 3 format(i3,3x,6e13.4)
! 4 format(i3,3x,i3,3x,i3,3x,6f9.2)
!
!
! Announce entry to this routine.
!
! if( DEBUG ) write(LUNOPRT,'(/,a)') 'Enter vertical'
!
!=======================================================================
!
!
!
! Loop over horizontal grid points
!
do iy = 1,NY
do ix = 1, NX
vf => carma%vf(ix,iy)%data3d
!
!=======================================================================
#undef RHOATRANS
#ifdef RHOATRANS
!
! Treat vertical transport of air density
!
!
! First calculate change in density for the case when boundary
! fluxes are zero
!
itbnd = I_FLUX_SPEC
ibbnd = I_FLUX_SPEC
ftop = 0.
fbot = 0.
!
!
! Store temporary (work) values in <cvert>,
! evaluate vertical velocities at layer boundaries,
! and set divergence correction term to zero.
!
do k = 1,NZP1
vtrans(k) = w2(ixy,k)
if( k .le. NZ )then
cvert(k) = rhoa2(ixy,k)
divcor(k) = 0.
endif
enddo
vtrans(1) = 0.
vtrans(NZP1) = 0.
!
!
! Since diffusion does not occur for air density, set diffusion
! fluxes to zero.
!
do k = 1,NZP1
vertdifu(k) = 0.
vertdifd(k) = 0.
enddo
!
!
! Calculate particle transport rates due to vertical advection
! (note: no diffusion for air density), and solve for air density
! at end of time step.
!
call vertadv
call versol
if( NXY .eq. 1 )then
!
!
! In 1D, assume assume any vertical divergence is
! balanced by horizontal convergence: don't allow air density
! to change in time, but calculate rate of change that would have
! resulted from advection -- this tendency is then used below for
! a divergence correction.
!
do k = 1,NZ
drho_dt_flux_spec(k) = ( rhoa2(ixy,k) - cvert(k) ) / &
( rhoa2(ixy,k) * dtime )
enddo
else
!
!
! Update air density when not in 1D.
!
do k = 1,NZ
rhoa2(ixy,k) = cvert(k)
enddo
endif
!
!
! Next, calculate change in density for the case when the
! concentration just beyond the boundary is fixed
!
itbnd = I_FIXED_CONC
ibbnd = I_FIXED_CONC
do k = 1,NZP1
vtrans(k) = w2(ixy,k)
enddo
do k = 1,NZ
cvert(k) = rhoa2(ixy,k)
enddo
cvert_tbnd = cvert(NZ)
cvert_bbnd = cvert(1)
call vertadv
call versol
if( NXY .eq. 1 )then
do k = 1,NZ
drho_dt_fixed_conc(k) = ( rhoa2(ixy,k) - cvert(k) ) / &
( rhoa2(ixy,k) * dtime )
enddo
endif
!
#endif
! RHOATRANS
!=======================================================================
!
! Treat vertical transport of particles.
!
itbnd = itbnd_pc
ibbnd = ibbnd_pc
do ielem = 1,NELEM ! Loop over particle elements
! ig = igelem(ielem) ! particle group
do ibin = 1,NBIN ! Loop over particle mass bins
!
!
! Fluxes across top and bottom of model
!
ftop = ftoppart(ix,iy,ibin,ielem)
fbot = fbotpart(ix,iy,ibin,ielem)
!
!
! Store temporary (work) values in <cvert>,
! evaluate vertical velocities at layer boundaries, and
! when 1D, assign divergence correction term
!
do k = 1,NZP1
! vtrans(k) = w2(ixy,k) - vf(k,ibin,ig)
vtrans(k) = - vf(k,ibin,ig)
enddo
if( ibbnd .eq. I_FLUX_SPEC ) vtrans(1) = 0._f
if( itbnd .eq. I_FLUX_SPEC ) vtrans(NZP1) = 0._f
cvert_tbnd = 0._f
cvert_bbnd = 0._f
if( itbnd .eq. I_FIXED_CONC ) &
cvert_tbnd = pc(ix,iy,NZ,ibin,ielem)
if( ibbnd .eq. I_FIXED_CONC ) &
cvert_bbnd = pc(ix,iy,1,ibin,ielem)
do k = 1,NZ
cvert(k) = pc(ix,iy,k,ibin,ielem)
! if( NXY. eq. 1 ) divcor(k) = cvert(k) *
! $ drho_dt_flux_spec(k)
enddo
! if( NXY .eq. 1 ) then
! if( ibbnd .eq. I_FIXED_CONC )
! $ divcor(1) = cvert(1) * drho_dt_fixed_conc(1)
! if( itbnd .eq. I_FIXED_CONC )
! $ divcor(NZ) = cvert(NZ) * drho_dt_fixed_conc(NZ)
! endif
!
!
! Calculate particle transport rates due to vertical advection
! and vertical diffusion, and solve for concentrations at end of time step.
!
!
call vertadv
( ix, iy, NZ, ibbnd, itbnd, vtrans, cvert, &
cvert_bbnd, cvert_tbnd, vertadvu, vertadvd, carma, rc )
call vertdif
( ix, iy, NZ, ibbnd, itbnd, vertdifu, vertdifd, carma, rc )
call versol
( ix, iy, NZ, ibbnd, itbnd, fbot, ftop, &
vertadvu, vertadvd, vertdifu, vertdifd, &
cvert_bbnd, cvert_tbnd, cvert, carma, rc )
!
!
! Update particle concentrations.
!
do k = 1,NZ
pc(ix,iy,k,ibin,ielem) = cvert(k)
enddo
enddo
enddo
!
!=======================================================================
#undef GASTRANS
#ifdef GASTRANS
!
! Treat vertical transport of gases
! (for comments, see above treatment of particles).
!
!
itbnd = itbnd_gc
ibbnd = ibbnd_gc
do k = 1,NZP1
vtrans(k) = w2(ixy,k)
enddo
if( ibbnd .eq. I_FLUX_SPEC ) vtrans(1) = 0.
if( itbnd .eq. I_FLUX_SPEC ) vtrans(NZP1) = 0.
do igas = 1,NGAS
ftop = ftopgas(ixy,igas)
fbot = fbotgas(ixy,igas)
if( itbnd .eq. I_FIXED_CONC )
$ cvert_tbnd = gc_topbnd(ixy,igas)
if( ibbnd .eq. I_FIXED_CONC )
$ cvert_bbnd = gc_botbnd(ixy,igas)
do k = 1,NZ
cvert(k) = gc2(ixy,k,igas)
if( NXY. eq. 1 ) divcor(k) = cvert(k) * drho_dt_flux_spec(k)
enddo
if( NXY .eq. 1 ) then
if( ibbnd .eq. I_FIXED_CONC )
$ divcor(1) = cvert(1) * drho_dt_fixed_conc(1)
if( itbnd .eq. I_FIXED_CONC )
$ divcor(NZ) = cvert(NZ) * drho_dt_fixed_conc(NZ)
endif
call vertadv
call vertdif
call versol
do k = 1,NZ
gc2(ixy,k,igas) = cvert(k)
enddo
enddo
!
#endif
! GASTRANS
!=======================================================================
#undef PTCTRANS
#ifdef PTCTRANS
!
! Treat vertical transport of potential temperature
! (for comments, see above treatment of particles).
!
itbnd = itbnd_ptc
ibbnd = ibbnd_ptc
ftop = 0.
fbot = 0.
do k = 1,NZP1
vtrans(k) = w2(ixy,k)
enddo
if( ibbnd .eq. I_FLUX_SPEC ) vtrans(1) = 0.
if( itbnd .eq. I_FLUX_SPEC ) vtrans(NZP1) = 0.
if( itbnd .eq. I_FIXED_CONC ) cvert_tbnd = ptc_topbnd(ixy)
if( ibbnd .eq. I_FIXED_CONC ) cvert_bbnd = ptc_botbnd(ixy)
do k = 1,NZ
cvert(k) = ptc2(ixy,k)
if( NXY. eq. 1 ) divcor(k) = cvert(k) * drho_dt_flux_spec(k)
enddo
if( NXY .eq. 1 ) then
if( ibbnd .eq. I_FIXED_CONC )
$ divcor(1) = cvert(1) * drho_dt_fixed_conc(1)
if( itbnd .eq. I_FIXED_CONC )
$ divcor(NZ) = cvert(NZ) * drho_dt_fixed_conc(NZ)
endif
call vertadv
call vertdif
call versol
do k = 1,NZ
ptc2(ixy,k) = cvert(k)
enddo
!
#endif
! PTCTRANS
!=======================================================================
!
end do ! ix
end do ! iy
!
!=======================================================================
!
!
! Return to caller with new particle, gas, and potential temperature
! concentrations and air density.
!
rc = 0
deallocate( vtrans, vertadvd, vertadvu, vertdifd, vertdifu, &
cvert, stat=ios)
if(ios /= 0) rc = 1
return
end