!----------------------------------------------------------------------- !BOP ! !ROUTINE: te_map --- Map vertical Lagrangian coordinates to normal grid ! ! !INTERFACE: subroutine te_map(grid, consv, convt, ps, omga, & 1,36 pe, delp, pkz, pk, mdt, & nx, u, v, pt, tracer, & hs, cp, akap, kord, peln, & te0, te, dz, mfx, mfy, & te_method ) ! ! !USES: use shr_kind_mod, only : r8 => shr_kind_r8 use dynamics_vars, only : T_FVDYCORE_GRID use mapz_module, only : map1_cubic_te, map1_ppm, mapn_ppm_tracer use cam_logfile, only : iulog #if defined( SPMD ) use mod_comm, only : mp_send3d, mp_recv3d #endif implicit none #if defined( SPMD ) #define CPP_PRT_PREFIX if(grid%iam==0) #else #define CPP_PRT_PREFIX #endif ! !INPUT PARAMETERS: type (T_FVDYCORE_GRID), intent(inout) :: grid ! grid for XY decomp logical consv ! flag to force TE conservation logical convt ! flag to control pt output (see below) integer mdt ! mapping time step (same as phys) integer nx ! number of SMP "decomposition" in x real(r8) hs(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy) ! surface geopotential real(r8) cp real(r8) te0 integer, intent(in) :: te_method ! Method for vertical total energy remapping ! 0 : piecewise-parabolic ! 1 : cubic interpolation ! !INPUT/OUTPUT PARAMETERS: real(r8) pk(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km+1) ! pe to the kappa real(r8) u(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km) ! u-wind (m/s) real(r8) v(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km) ! v-wind (m/s) ! tracers including specific humidity !!! real(r8) q(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km,grid%ntotq) real(r8), intent(inout) :: & tracer(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km,grid%ntotq) ! Tracer array real(r8) pe(grid%ifirstxy:grid%ilastxy,grid%km+1,grid%jfirstxy:grid%jlastxy) ! pressure at layer edges real(r8) ps(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy) ! surface pressure real(r8) pt(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km) ! virtual potential temperature as input ! Output: virtual temperature if convt is true ! false: output is (virtual) potential temperature real(r8) te(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km) ! Work array (cache performance) real(r8) dz(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km) ! Work array (cache performance) real(r8) mfx(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km) real(r8) mfy(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km) ! !OUTPUT PARAMETERS: real(r8) delp(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km) ! pressure thickness real(r8) omga(grid%ifirstxy:grid%ilastxy,grid%km,grid%jfirstxy:grid%jlastxy) ! vertical press. velocity (pascal/sec) real(r8) peln(grid%ifirstxy:grid%ilastxy,grid%km+1,grid%jfirstxy:grid%jlastxy) ! log(pe) real(r8) pkz(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km) ! layer-mean pk for converting t to pt ! !DESCRIPTION: ! ! !REVISION HISTORY: ! ! WS 99.05.19 : Replaced IMR, JMR, JNP and NL with IM, JM-1, JM and KM ! WS 99.05.25 : Revised conversions with IMR and JMR; removed fvcore.h ! WS 99.07.29 : Reduced computation region to grid%jfirstxy:jlast ! WS 99.07.30 : Tested concept with message concatenation of te_map calls ! WS 99.10.01 : Documentation; indentation; cleaning ! SJL 99.12.31: SMP "decomposition" in-E-W direction ! WS 00.05.14 : Renamed ghost indices as per Kevin's definitions ! WS 00.07.13 : Changed PILGRIM API ! AM 00.08.29 : Variables in this routine will ultimately be decomposed in (i,j). ! AM 01.06.13 : 2-D decomposition; reordering summation causes roundoff difference. ! WS 01.06.10 : Removed "if(first)" section in favor of a variable module ! AM 01.06.27 : Merged yz decomposition technology into ccm code. ! WS 02.01.14 : Upgraded to mod_comm ! WS 02.04.22 : Use mapz_module from FVGCM ! WS 02.04.25 : New mod_comm interfaces ! WS 03.08.12 : Introduced unorth ! WS 03.11.19 : Merged in CAM changes by Mirin ! WS 03.12.03 : Added GRID as argument, dynamics_vars removed ! WS 04.08.25 : Simplified interface by using GRID ! WS 04.10.07 : Removed dependency on spmd_dyn; info now in GRID ! WS 05.03.25 : Changed tracer to type T_TRACERS ! WS 05.04.12 : Call mapn_ppm_tracer instead of mapn_ppm ! AT 05.05.11 : Merged with the version Cerebus (unique pole issues) ! WS 05.05.18 : Merged CAM and GEOS5 versions (mostly GEOS5) ! LT 05.11.14 : Call map1_cubic_te for Cubic Interpolation of Total Energy ! WP 06.01.18 : Added calls to map1_ppm for horizontal mass fluxes ! LT 06.02.08 : Implement code for partial remapping option ! WS 06.11.29 : Merge CAM/GEOS5; magic numbers isolated; te_method ! CC 07.01.29 : Additions for proper calculation of OMGA ! !EOP !----------------------------------------------------------------------- !BOC ! !LOCAL VARIABLES: ! Magic numbers used in this module real(r8), parameter :: D0_0 = 0.0_r8 real(r8), parameter :: D0_25 = 0.25_r8 real(r8), parameter :: D0_5 = 0.5_r8 real(r8), parameter :: D1_0 = 1.0_r8 real(r8), parameter :: D2_0 = 2.0_r8 real(r8), parameter :: D10_0 = 10.0_r8 real(r8), parameter :: D1E4 = 1.0e4_r8 integer :: im, jm, km ! x, y, z dimensions integer :: nq ! number of tracers to be advected integer :: ntotq ! Total number of tracers integer :: ifirst, ilast ! starting & ending longitude index integer :: jfirst, jlast ! starting & ending latitude index integer :: myidxy_y, iam integer :: nprxy_x, nprxy_y ! Local variables for Partial Remapping ! ------------------------------------- real(r8) :: pref(grid%km+1) real(r8) :: fac(grid%km+1) real(r8) :: zz(grid%km+1) real(r8) :: z1,z2 real(r8), parameter :: alf = 0.042_r8 real(r8), parameter :: pa = 1.0_r8 real(r8), parameter :: pb = 500.0_r8 real(r8), parameter :: psurf = 100001.0_r8 real(r8), parameter :: bet = D2_0*alf/(D1_0+alf) ! Local arrays: ! ------------- real(r8) rmin(nx*grid%jm), rmax(nx*grid%jm) real(r8) tte(grid%jm) ! x-y real(r8) u2(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy+1) real(r8) v2(grid%ifirstxy:grid%ilastxy+1,grid%jfirstxy:grid%jlastxy) real(r8) t2(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy) real(r8) veast(grid%jfirstxy:grid%jlastxy,grid%km) ! y-z real(r8) pe0(grid%ifirstxy:grid%ilastxy,grid%km+1) real(r8) pe1(grid%ifirstxy:grid%ilastxy,grid%km+1) real(r8) pe2(grid%ifirstxy:grid%ilastxy,grid%km+1) real(r8) pe3(grid%ifirstxy:grid%ilastxy,grid%km+1) real(r8) phis(grid%ifirstxy:grid%ilastxy,grid%km+1) real(r8) u2_sp(grid%ifirstxy:grid%ilastxy,grid%km) real(r8) v2_sp(grid%ifirstxy:grid%ilastxy,grid%km) real(r8) t2_sp(grid%ifirstxy:grid%ilastxy,grid%km) real(r8) u2_np(grid%ifirstxy:grid%ilastxy,grid%km) real(r8) v2_np(grid%ifirstxy:grid%ilastxy,grid%km) real(r8) t2_np(grid%ifirstxy:grid%ilastxy,grid%km) ! x real(r8) gz(grid%ifirstxy:grid%ilastxy) real(r8) ratio(grid%ifirstxy:grid%ilastxy) real(r8) bte(grid%ifirstxy:grid%ilastxy) ! z real(r8) pe1w(grid%km+1) real(r8) pe2w(grid%km+1) integer i1w, nxu integer i, j, k, js2g0, jn2g0, jn1g1 integer kord integer krd real(r8) akap, dak, bkh, qmax, qmin real(r8) te_sp(grid%km), te_np(grid%km) real(r8) xysum(grid%jfirstxy:grid%jlastxy,2) real(r8) tmpik(grid%ifirstxy:grid%ilastxy,grid%km) real(r8) tmpij(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,2) real(r8) omga_ik(grid%ifirstxy:grid%ilastxy,grid%km) ! vertical press. velocity (tmp 2-d array) real(r8) dtmp real(r8) sum real(r8) rdt5 real(r8) rg real(r8) te1 real(r8) dlnp real(r8) tvm integer ixj, jp, it, i1, i2 #if defined( SPMD ) integer :: dest, src real(r8) unorth(grid%ifirstxy:grid%ilastxy,grid%km) real(r8) pewest(grid%km+1,grid%jfirstxy:grid%jlastxy) real(r8), allocatable :: pesouth(:,:) #endif integer comm_use, npry_use, itot logical diag data diag /.false./ z1 = log(pa/psurf) z2 = log(pb/psurf) im = grid%im jm = grid%jm km = grid%km nq = grid%nq ifirst = grid%ifirstxy ilast = grid%ilastxy jfirst = grid%jfirstxy jlast = grid%jlastxy iam = grid%iam myidxy_y = grid%myidxy_y nprxy_x = grid%nprxy_x nprxy_y = grid%nprxy_y ! Intialize PREF and FAC for Partial Remapping (above 100-mb) ! ----------------------------------------------------------- do k=1,km+1 pref(k) = grid%ak(k) + grid%bk(k)*psurf enddo zz = log( pref/psurf ) zz = D10_0*(zz-z2)/z1 zz = (D1_0-bet)*tanh(zz) do k=1,km+1 ! if( pref(k).le.D1E4 ) then ! fac(k) = (D1_0-zz(k))/(D2_0-bet) ! else fac(k) = D1_0 ! endif enddo ! WS 99.07.27 : Set loop limits appropriately ! -------------------------------------------- js2g0 = max(2,jfirst) jn1g1 = min(jm,jlast+1) jn2g0 = min(jm-1,jlast) do j=jfirst,jlast xysum(j,1) = D0_0 xysum(j,2) = D0_0 enddo do j=jfirst,jlast do i=ifirst,ilast tmpij(i,j,1) = D0_0 tmpij(i,j,2) = D0_0 enddo enddo do k=1,km do i=ifirst,ilast tmpik(i,k) = D0_0 enddo enddo itot = ilast-ifirst+1 nxu = 1 if (itot == im) nxu = nx #if defined( SPMD ) comm_use = grid%commxy_y npry_use = nprxy_y call mp_send3d( grid%commxy, iam-nprxy_x, iam+nprxy_x, im, jm, km, & ifirst, ilast, jfirst, jlast, 1, km, & ifirst, ilast, jfirst, jfirst, 1, km, u ) ! Nontrivial x decomposition if (itot /= im) then dest = myidxy_y*nprxy_x + MOD(iam+nprxy_x-1,nprxy_x) src = myidxy_y*nprxy_x + MOD(iam+1,nprxy_x) call mp_send3d( grid%commxy, dest, src, im, jm, km, & ifirst, ilast, jfirst, jlast, 1,km, & ifirst, ifirst, jfirst, jlast, 1, km, v ) endif #endif call pkez(nxu, im, km, jfirst, jlast, 1, km, ifirst, ilast, & pe, pk, akap, grid%ks, peln, pkz, .false.) ! Single subdomain case (periodic) do k=1,km do j=jfirst,jlast veast(j,k) = v(ifirst,j,k) enddo enddo #if defined( SPMD ) call mp_recv3d( grid%commxy, iam+nprxy_x, im, jm, km, & ifirst, ilast, jlast+1, jlast+1, 1, km, & ifirst, ilast, jlast+1, jlast+1, 1, km, unorth ) ! Nontrivial x decomposition if (itot /= im) then call mp_recv3d( grid%commxy, src, im, jm, km, & ilast+1, ilast+1, jfirst, jlast, 1, km, & ilast+1, ilast+1, jfirst, jlast, 1, km, veast ) dest = myidxy_y*nprxy_x + MOD(iam+1,nprxy_x) src = myidxy_y*nprxy_x + MOD(iam+nprxy_x-1,nprxy_x) call mp_send3d( grid%commxy, dest, src, im, km+1, jm, & ifirst, ilast, 1, km+1, jfirst, jlast, & ilast, ilast, 1, km+1, jfirst, jlast, pe ) endif call mp_send3d( grid%commxy, iam+nprxy_x, iam-nprxy_x, im, km+1,jm, & ifirst, ilast, 1, km+1, jfirst, jlast, & ifirst, ilast, 1, km+1, jlast, jlast, pe ) #endif !$omp parallel do & !$omp default(shared) & !$omp private(i,j, k, u2, v2, t2) ! Compute cp*T + KE do 1000 k=1,km do j=js2g0,jlast do i=ifirst,ilast u2(i,j) = u(i,j,k)**2 enddo enddo #if defined( SPMD ) if ( jlast < jm ) then do i=ifirst,ilast u2(i,jlast+1) = unorth(i,k)**2 ! fill ghost zone enddo endif #endif do j=js2g0,jn2g0 do i=ifirst,ilast v2(i,j) = v(i,j,k)**2 enddo v2(ilast+1,j) = veast(j,k)**2 enddo do j=jfirst,jlast do i=ifirst,ilast t2(i,j) = cp*pt(i,j,k) enddo enddo do j=js2g0,jn2g0 do i=ifirst,ilast te(i,j,k) = D0_25 * ( u2(i,j) + u2(i,j+1) + & v2(i,j) + v2(i+1,j) ) + & t2(i,j)*pkz(i,j,k) enddo enddo ! WS 99.07.29 : Restructuring creates small round-off. Not clear why... ! Do collective Mpisum (in i) for te_sp and te_np below (AAM) ! if ( jfirst == 1 ) then ! South pole do i=ifirst,ilast u2_sp(i,k) = u2(i,2) v2_sp(i,k) = v2(i,2) t2_sp(i,k) = t2(i,1) enddo endif if ( jlast == jm ) then ! North pole do i=ifirst,ilast u2_np(i,k) = u2(i,jm) v2_np(i,k) = v2(i,jm-1) t2_np(i,k) = t2(i,jm) enddo endif ! Compute dz; geo-potential increments do j=jfirst,jlast do i=ifirst,ilast dz(i,j,k) = t2(i,j)*(pk(i,j,k+1)-pk(i,j,k)) enddo enddo 1000 continue #if defined( SPMD ) allocate( pesouth(ifirst:ilast,km+1) ) if (itot /= im) then call mp_recv3d( grid%commxy, src, im, km+1, jm, & ifirst-1, ifirst-1, 1, km+1, jfirst, jlast, & ifirst-1, ifirst-1, 1, km+1, jfirst, jlast, pewest ) endif call mp_recv3d( grid%commxy, iam-nprxy_x, im, km+1, jm, & ifirst, ilast, 1, km+1, jfirst-1, jfirst-1, & ifirst, ilast, 1, km+1, jfirst-1, jfirst-1, pesouth ) #endif if ( jfirst == 1 ) then !$omp parallel do & !$omp default(shared) & !$omp private(i, k) do k = 1, km do i=ifirst,ilast tmpik(i,k) = D0_5*( u2_sp(i,k) + v2_sp(i,k) ) + t2_sp(i,k)*pkz(i,1,k) enddo enddo call par_xsum( grid, tmpik, km, te_sp) !$omp parallel do & !$omp default(shared) & !$omp private(i, k) do k = 1, km te_sp(k) = te_sp(k)/real(im,r8) do i=ifirst,ilast te(i, 1,k) = te_sp(k) enddo enddo endif if ( jlast == jm ) then !$omp parallel do & !$omp default(shared) & !$omp private(i, k) do k = 1, km do i=ifirst,ilast tmpik(i,k) = D0_5*( u2_np(i,k) + v2_np(i,k) ) + t2_np(i,k)*pkz(i,jm,k) enddo enddo call par_xsum( grid, tmpik, km, te_np) !$omp parallel do & !$omp default(shared) & !$omp private(i, k) do k = 1, km te_np(k) = te_np(k)/real(im,r8) do i=ifirst,ilast te(i,jm,k) = te_np(k) enddo enddo endif it = itot / nxu jp = nxu * ( jlast - jfirst + 1 ) !$omp parallel do & !$omp default(shared) & !$omp private(i,j,k,i1w,pe0,pe1,pe2,pe3,ratio) & !$omp private(dak,bkh,rdt5,phis,krd, ixj,i1,i2) & !$omp private(pe1w, pe2w, omga_ik ) ! do 2000 j=jfirst,jlast do 2000 ixj=1,jp j = jfirst + (ixj-1) / nxu i1 = ifirst + it * mod(ixj-1, nxu) i2 = i1 + it - 1 ! Copy data to local 2D arrays. i1w = i1-1 if (i1 == 1) i1w = im do k=1,km+1 do i=i1,i2 pe1(i,k) = pe(i,k,j) enddo if( itot == im ) then pe1w(k) = pe(i1w,k,j) #if defined( SPMD ) else pe1w(k) = pewest(k,j) #endif endif enddo do k=1,grid%ks+1 do i=i1,i2 pe0(i,k) = grid%ak(k) pe2(i,k) = grid%ak(k) pe3(i,k) = grid%ak(k) enddo enddo do k=grid%ks+2,km do i=i1,i2 pe0(i,k) = grid%ak(k) + grid%bk(k)* ps(i,j) ! Remapped PLE based on Old PS pe2(i,k) = grid%ak(k) + grid%bk(k)*pe1(i,km+1) ! Remapped PLE based on Updated PS enddo enddo do i=i1,i2 pe0(i,km+1) = ps(i,j) pe2(i,km+1) = pe1(i,km+1) enddo ! Ghosting for v mapping do k=grid%ks+2,km pe2w(k) = grid%ak(k) + grid%bk(k)*pe1w(km+1) enddo pe2w(km+1) = pe1w(km+1) ! update ps ! --------- do i=i1,i2 ps(i,j) = pe1(i,km+1) enddo ! Compute GeoPotential Heights and add to Total Energy ! Note: GeoPotential Height(L) => d(Pe*PHI)/dPe ! ---------------------------------------------------- do i=i1,i2 phis(i,km+1) = hs(i,j) enddo do k=km,1,-1 do i=i1,i2 phis(i,k) = phis(i,k+1) + dz(i,j,k) enddo enddo do k=1,km+1 do i=i1,i2 phis(i,k) = phis(i,k) * pe1(i,k) enddo enddo do k=1,km do i=i1,i2 te(i,j,k) = te(i,j,k) + (phis(i,k+1) - phis(i,k)) / & (pe1(i,k+1) - pe1(i,k) ) enddo enddo ! ####################################################################### ! # ReMap Total Energy ! ####################################################################### ! Compute Target Pressures for Partial Remapping ! ---------------------------------------------- do k=1,km+1 do i=i1,i2 pe2(i,k) = fac(k)*pe2(i,k) + (D1_0-fac(k))*pe1(i,k) enddo enddo ! Update Delta-Pressure (from final remapped pressures) ! ----------------------------------------------------- do k=1,km do i=i1,i2 delp(i,j,k) = pe2(i,k+1) - pe2(i,k) enddo enddo ! Compute omga (dp/dt) ! -------------------- rdt5 = D0_5 / real(mdt,r8) do k=2,km+1 do i=i1,i2 pe0(i,k) = pe1(i,k) - pe0(i,k) ! Delta-P: PLE(After CD_Core) minus PLE(Remapped based on old PS) enddo enddo ! ReMap Total Energy ! ------------------ select case ( te_method ) case (0) call map1_ppm ( km, pe1, te, & km, pe2, te, 0, 0, & itot, i1-ifirst+1, i2-ifirst+1, & j, jfirst, jlast, 1, kord) case (1) call map1_cubic_te ( km, pe1, te, & km, pe2, te, 0, 0, & itot, i1-ifirst+1, i2-ifirst+1, & j, jfirst, jlast, 1, kord) case default call map1_ppm ( km, pe1, te, & km, pe2, te, 0, 0, & itot, i1-ifirst+1, i2-ifirst+1, & j, jfirst, jlast, 1, kord) endselect ! C.-C. Chen ! Map omga do k=1,km do i=i1,i2 omga_ik(i,k) = omga(i,k,j) end do end do call map1_ppm ( km, pe1, omga_ik, & km, pe2, omga_ik, 0, 0, & itot, i1-ifirst+1, i2-ifirst+1, & 1, 1, 1, 1, kord) do k=1,km do i=i1,i2 omga(i,k,j) = omga_ik(i,k) end do end do ! ####################################################################### ! # ReMap Constituents ! ####################################################################### if( nq /= 0 ) then if(kord == 8) then krd = 8 else krd = 7 endif call mapn_ppm_tracer ( km, pe1, tracer, nq, & km, pe2, i1, i2, & j, ifirst, ilast, jfirst, jlast, 0, krd) endif ! ####################################################################### ! # ReMap U-Wind ! ####################################################################### if(j /= 1) then ! WS 99.07.29 : protect j==jfirst case if (j > jfirst) then do k=2,km+1 do i=i1,i2 pe0(i,k) = D0_5*(pe1(i,k)+pe(i,k,j-1)) enddo enddo do k=grid%ks+2,km+1 bkh = D0_5*grid%bk(k) do i=i1,i2 pe3(i,k) = grid%ak(k) + bkh*(pe1(i,km+1)+pe(i,km+1,j-1)) enddo enddo #if defined( SPMD ) else ! WS 99.10.01 : Read in pe(:,:,jfirst-1) from the pesouth buffer do k=2,km+1 do i=i1,i2 pe0(i,k) = D0_5*(pe1(i,k)+pesouth(i,k)) enddo enddo do k=grid%ks+2,km+1 bkh = D0_5*grid%bk(k) do i=i1,i2 pe3(i,k) = grid%ak(k) + bkh*(pe1(i,km+1)+pesouth(i,km+1)) enddo enddo #endif endif ! Compute Target Pressures for Partial Remapping ! ---------------------------------------------- do k=1,km+1 do i=i1,i2 pe3(i,k) = fac(k)*pe3(i,k) + (D1_0-fac(k))*pe0(i,k) enddo enddo ! ReMap U-Wind (D-Grid Location) ! ------------------------------ call map1_ppm ( km, pe0, u, km, pe3, u, & 0, 0, itot, i1-ifirst+1, i2-ifirst+1, & j, jfirst, jlast, -1, kord) ! ReMap Y-Mass Flux (C-Grid Location) ! ----------------------------------- do k=1,km do i=i1,i2 mfy(i,j,k) = mfy(i,j,k)/(pe0(i,k+1)-pe0(i,k)) enddo enddo call map1_ppm ( km, pe0, mfy, km, pe3, mfy, & 0, 0, itot, i1-ifirst+1, i2-ifirst+1, & j, jfirst, jlast, -1, kord) do k=1,km do i=i1,i2 mfy(i,j,k) = mfy(i,j,k)*(pe3(i,k+1)-pe3(i,k)) enddo enddo endif ! ####################################################################### ! # ReMap V-Wind ! ####################################################################### if(j /= 1 .and. j /= jm) then do k=2,km+1 ! pe1(i1-1,1:km+1) must be ghosted pe0(i1,k) = D0_5*(pe1(i1,k)+pe1w(k)) do i=i1+1,i2 pe0(i ,k) = D0_5*(pe1(i,k)+pe1(i-1,k)) enddo enddo do k=grid%ks+2,km+1 ! pe2(i1-1,grid%ks+2:km+1) must be ghosted pe3(i1,k) = D0_5*(pe2(i1,k)+pe2w(k)) do i=i1+1,i2 pe3(i,k) = D0_5*(pe2(i,k)+pe2(i-1,k)) enddo enddo ! Compute Target Pressures for Partial Remapping ! ---------------------------------------------- do k=1,km+1 do i=i1,i2 pe3(i,k) = fac(k)*pe3(i,k) + (D1_0-fac(k))*pe0(i,k) enddo enddo ! ReMap V-Wind (D-Grid Location) ! ------------------------------ call map1_ppm ( km, pe0, v, km, pe3, v, & 0, 0, itot, i1-ifirst+1, i2-ifirst+1, & j, jfirst, jlast, -1, kord) ! ReMap X-Mass Flux (C-Grid Location) ! ----------------------------------- do k=1,km do i=i1,i2 mfx(i,j,k) = mfx(i,j,k)/(pe0(i,k+1)-pe0(i,k)) enddo enddo call map1_ppm ( km, pe0, mfx, km, pe3, mfx, & 0, 0, itot, i1-ifirst+1, i2-ifirst+1, & j, jfirst, jlast, -1, kord) do k=1,km do i=i1,i2 mfx(i,j,k) = mfx(i,j,k)*(pe3(i,k+1)-pe3(i,k)) enddo enddo endif ! Save new PE to temp storage peln ! -------------------------------- do k=2,km do i=i1,i2 peln(i,k,j) = pe2(i,k) enddo enddo ! Check deformation. if( diag ) then rmax(ixj) = D0_0 rmin(ixj) = D1_0 do k=1,km do i=i1,i2 ratio(i) = (pe1(i,k+1)-pe1(i,k)) / (pe2(i,k+1)-pe2(i,k)) enddo do i=i1,i2 if(ratio(i) > rmax(ixj)) then rmax(ixj) = ratio(i) elseif(ratio(i) < rmin(ixj)) then rmin(ixj) = ratio(i) endif enddo enddo endif 2000 continue #if defined( SPMD ) deallocate( pesouth ) ! Send u southward call mp_send3d( grid%commxy, iam-nprxy_x, iam+nprxy_x, im, jm, km,& ifirst, ilast, jfirst, jlast, 1, km, & ifirst, ilast, jfirst, jfirst, 1, km, u ) if (itot /= im) then dest = myidxy_y*nprxy_x + MOD(iam+nprxy_x-1,nprxy_x) src = myidxy_y*nprxy_x + MOD(iam+1,nprxy_x) call mp_send3d( grid%commxy, dest, src, im, jm, km, & ifirst, ilast, jfirst, jlast, 1, km, & ifirst, ifirst, jfirst, jlast, 1, km, v ) endif #endif if( diag ) then qmin = rmin(1) do ixj=2, jp if(rmin(ixj) < qmin) then qmin = rmin(ixj) endif enddo CPP_PRT_PREFIX write(iulog,*) 'rmin=', qmin qmax = rmax(1) do ixj=2, jp if(rmax(ixj) > qmax) then qmax = rmax(ixj) endif enddo CPP_PRT_PREFIX write(iulog,*) 'rmax=', qmax endif ! Recover Final Edge-Pressures and Compute Mid-Level PKZ ! ------------------------------------------------------ !$omp parallel do & !$omp default(shared) & !$omp private(i,j,k) do j=jfirst,jlast do k=2,km do i=ifirst,ilast pe(i,k,j) = peln(i,k,j) enddo enddo enddo do k=1,km+1 do j=jfirst,jlast do i=ifirst,ilast pk(i,j,k) = pe(i,k,j)**akap enddo enddo enddo call pkez(nxu, im, km, jfirst, jlast, 1, km, ifirst, ilast, & pe, pk, akap, grid%ks, peln, pkz, .false.) ! Single x-subdomain case (periodic) do k = 1, km do j = jfirst, jlast veast(j,k) = v(ifirst,j,k) enddo enddo #if defined( SPMD ) ! Recv u from north call mp_recv3d( grid%commxy, iam+nprxy_x, im, jm, km, & ifirst, ilast, jlast+1, jlast+1, 1, km, & ifirst, ilast, jlast+1, jlast+1, 1, km, unorth ) if (itot /= im) then call mp_recv3d( grid%commxy, src, im, jm, km, & ilast+1, ilast+1, jfirst, jlast, 1, km, & ilast+1, ilast+1, jfirst, jlast, 1, km, veast ) endif #endif ! ((((((((((((((((( compute globally integrated TE ))))))))))))))))) if( consv ) then !$omp parallel do & !$omp default(shared) & !$omp private(i,j,k) do k=1,km do j=jfirst,jlast do i=ifirst,ilast dz(i,j,k) = te(i,j,k) * delp(i,j,k) enddo enddo enddo !$omp parallel do & !$omp default(shared) & !$omp private(i,j,k,bte) ! Perform vertical integration do 4000 j=jfirst,jlast if ( j == 1 ) then ! SP tte(1) = D0_0 do k=1,km tte(1) = tte(1) + dz(ifirst,1,k) enddo elseif ( j == jm) then ! NP tte(jm) = D0_0 do k=1,km tte(jm) = tte(jm) + dz(ifirst,jm,k) enddo else ! Interior do i=ifirst,ilast bte(i) = D0_0 enddo do k=1,km do i=ifirst,ilast bte(i) = bte(i) + dz(i,j,k) enddo enddo do i=ifirst,ilast tmpij(i,j,1) = bte(i) enddo endif 4000 continue call par_xsum( grid, tmpij, jlast-jfirst+1, xysum) !$omp parallel do & !$omp default(shared) & !$omp private(j) do j = max(jfirst,2), min(jlast,jm-1) tte(j) = xysum(j,1)*grid%cosp(j) enddo if ( jfirst == 1 ) tte(1) = grid%acap * tte(1) if ( jlast == jm ) tte(jm) = grid%acap * tte(jm) te1 = D0_0 call par_vecsum(jm, jfirst, jlast, tte, te1, comm_use, npry_use) endif ! consv if( consv ) then !$omp parallel do & !$omp& default(shared) & !$omp& private(i,j) do j=js2g0, jn2g0 do i=ifirst,ilast tmpij(i,j,1) = ps(i,j) tmpij(i,j,2) = peln(i,km+1,j) enddo enddo call par_xsum( grid, tmpij, 2*(jlast-jfirst+1), xysum) !$omp parallel do & !$omp default(shared) & !$omp private(j) do j=js2g0, jn2g0 tte(j) = cp*grid%cosp(j)*(xysum(j,1) - grid%ptop*real(im,r8) - & akap*grid%ptop*(xysum(j,2) - peln(ifirst,1,j)*real(im,r8)) ) ! peln(i,1,j) should be independent of i (AAM) enddo if ( jfirst == 1 ) tte(1) = grid%acap*cp * (ps(ifirst,1) - grid%ptop - & akap*grid%ptop*(peln(ifirst,km+1,1) - peln(ifirst,1,1) ) ) if ( jlast == jm ) tte(jm)= grid%acap*cp * (ps(ifirst,jm) - grid%ptop - & akap*grid%ptop*(peln(ifirst,km+1,jm) - peln(ifirst,1,jm) ) ) endif ! consv if (consv) then sum=D0_0 call par_vecsum(jm, jfirst, jlast, tte, sum, comm_use, npry_use) dtmp = (te0 - te1) / sum if( diag ) then CPP_PRT_PREFIX write(iulog,*) 'te=',te0, ' Energy deficit in T = ', dtmp endif endif ! end consv check !$omp parallel do & !$omp default(shared) & !$omp private(i,j,k, u2, v2) ! -------------------------------------------------------------------- ! --- Recover Tv from remapped Total Energy and its components --- ! -------------------------------------------------------------------- do 8000 k=1,km ! Intialize Kinetic Energy ! ------------------------ do j=js2g0,jlast do i=ifirst,ilast u2(i,j) = u(i,j,k)**2 enddo enddo #if defined( SPMD ) if ( jlast < jm ) then do i=ifirst,ilast u2(i,jlast+1) = unorth(i,k)**2 ! fill ghost zone enddo endif #endif do j=js2g0,jn2g0 do i=ifirst,ilast v2(i,j) = v(i,j,k)**2 enddo v2(ilast+1,j) = veast(j,k)**2 enddo ! Subtract Kinetic Energy from Total Energy (Leaving Internal + Potential) ! ------------------------------------------------------------------------ do j=js2g0,jn2g0 do i=ifirst,ilast te(i,j,k) = te(i,j,k) - D0_25 * ( u2(i,j) + u2(i,j+1) & +v2(i,j) + v2(i+1,j) ) enddo enddo ! South pole ! ---------- if ( jfirst == 1 ) then do i=ifirst,ilast u2_sp(i,k) = u2(i,2) v2_sp(i,k) = v2(i,2) enddo endif ! North pole ! ---------- if ( jlast == jm ) then do i=ifirst,ilast u2_np(i,k) = u2(i,jm) v2_np(i,k) = v2(i,jm-1) enddo endif 8000 continue ! South pole ! ---------- if ( jfirst == 1 ) then !$omp parallel do & !$omp default(shared) & !$omp private(i, k) do k = 1, km do i=ifirst,ilast tmpik(i,k) = D0_5*( u2_sp(i,k) + v2_sp(i,k) ) enddo enddo call par_xsum( grid, tmpik, km, te_sp) !$omp parallel do & !$omp default(shared) & !$omp private(i, k) do k = 1, km te_sp(k) = te_sp(k)/real(im,r8) do i=ifirst,ilast te(i,1,k) = te(i,1,k) - te_sp(k) enddo enddo endif ! North pole ! ---------- if ( jlast == jm ) then !$omp parallel do & !$omp default(shared) & !$omp private(i, k) do k = 1, km do i=ifirst,ilast tmpik(i,k) = D0_5*( u2_np(i,k) + v2_np(i,k) ) enddo enddo call par_xsum( grid, tmpik, km, te_np) !$omp parallel do & !$omp default(shared) & !$omp private(i, k) do k = 1, km te_np(k) = te_np(k)/real(im,r8) do i=ifirst,ilast te(i,jm,k) = te(i,jm,k) - te_np(k) enddo enddo endif !$omp parallel do & !$omp default(shared) & !$omp private(ixj, i1, i2, i, j, k, rg, gz, tvm, dlnp) ! Recover Tv from remapped Total Energy and its components ! -------------------------------------------------------- do 9000 ixj=1,jp j = jfirst + (ixj-1) / nxu i1 = ifirst + it * mod(ixj-1, nxu) i2 = i1 + it - 1 rg = akap * cp do i=i1,i2 gz(i) = hs(i,j) ! Initialize GeoPotential Heights enddo do k=km,1,-1 do i=i1,i2 dlnp = rg*(peln(i,k+1,j) - peln(i,k,j)) tvm = delp(i,j,k)*(te(i,j,k) - gz(i)) / & ( cp*delp(i,j,k) - pe(i,k,j)*dlnp ) gz(i) = gz(i) + dlnp*tvm ! Update GeoPotential Heights pt(i,j,k) = tvm ! pt is now (virtual) temperature enddo if( consv ) then do i=i1,i2 pt(i,j,k) = pt(i,j,k) + dtmp enddo endif if( .not. convt ) then do i=i1,i2 pt(i,j,k) = pt(i,j,k) / pkz(i,j,k) ! Scaled Virtual Potential Temperature enddo endif enddo ! end k-loop 9000 continue return !EOC end subroutine te_map !-----------------------------------------------------------------------