! 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