⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cd_core.f90

📁 CCSM Research Tools: Community Atmosphere Model (CAM)
💻 F90
📖 第 1 页 / 共 3 页
字号:
#include <misc.h>!-----------------------------------------------------------------------!BOP! !ROUTINE: cd_core --- Dynamical core for both C- and D-grid Lagrangian!                       dynamics!! !INTERFACE: subroutine cd_core(im,   jm,   km,    nq,     nx,                 &                    jfirst, jlast , kfirst, klast, klastp, u,      &                    v,   pt,   delp,   pe,     pk,                 &                    dt,   ptopin, umax,   ae,     rcap,            &                    cp,   akap, iord_c, jord_c, iord_d, jord_d,    &                    ng_c, ng_d, ng_s, ipe,    om,     hs,          &                    cx3  ,  cy3, mfx, mfy,                         &                    delpf, uc, vc, ptc, dpt, ptk,                  &                    wz3, pkc, wz,  hsxy, ptxy, pkxy,               &                    pexy, pkcc, wzc, wzxy, delpxy, pkkp, wzkp,     &                    pekp, ifirstxy, ilastxy, jfirstxy, jlastxy )! !USES:   use precision, only : r8   use sw_core, only : c_sw, d_sw   use pft_module, only : fftfax, pft2d, pft_cf   use dynamics_vars, only : sinp, cosp, cose, acosp,              &                       sinlon, coslon, cosl5, sinl5,               &                       ak, bk, ptop, ns, yzt   use pmgrid, only: twod_decomp, myid_y, myid_z, npr_y, npr_z, iam#if defined( SPMD )   use redistributemodule, only: redistributestart, redistributefinish   use spmd_dyn, only: comm_y, comm_z, inter_ijk, inter_ijkp   use mod_comm, only: mp_send3d_ns, mp_recv3d_ns,           &                       mp_send2_ns, mp_recv2_ns,             &                       mp_send2_n, mp_recv2_s,               &                       mp_send_s, mp_recv_n,                 &                       mp_send, mp_recv, mp_barrier,         &                       bufferpack3d, bufferunpack3d,         &                       buff_s, buff_r#define CPP_PRT_PREFIX  if(iam.eq.0)#else#define CPP_PRT_PREFIX#endif   implicit none! !INPUT PARAMETERS:! Input paraterers:  integer im, jm, km  integer nx                 ! # of split pieces in longitude direction  integer jfirst  integer jlast  integer kfirst  integer klast  integer klastp             ! klast, except km+1 when klast=km  integer ifirstxy,ilastxy   ! xy-decomp. longitude ranges  integer jfirstxy,jlastxy   ! xy-decomp. latitude ranges  integer ipe                ! ipe=1:  end of cd_core()                             ! ipe=-1: start of cd_core()                             ! ipe=0 :  integer nq                 ! # of tracers to be advected by trac2d  integer iord_c, jord_c     ! scheme order on C grid in X and Y dir.  integer iord_d, jord_d     ! scheme order on D grid in X and Y dir.  integer ng_c               ! ghost latitudes on C grid  integer ng_d               ! ghost lats on D (Max NS dependencies, ng_d >= ng_c)  integer ng_s               ! max(ng_c+1,ng_d) significant if ng_c = ng_d  real(r8) ae                ! Radius of the Earth (m)  real(r8) om                ! rotation rate  real(r8) ptopin  real(r8) umax  real(r8) dt            !small time step in seconds  real(r8) rcap  real(r8) cp  real(r8) akap! Input time independent arrays:  real(r8) hs(im,jfirst:jlast)         !surface geopotential  real(r8) hsxy(ifirstxy:ilastxy,jfirstxy:jlastxy) !surface geopotential XY-decomp.! !INPUT/OUTPUT PARAMETERS:! Prognostic variables:  real(r8)   u(im,jfirst-ng_d:jlast+ng_s,kfirst:klast)          ! Wind in X  real(r8)   v(im,jfirst-ng_s:jlast+ng_d,kfirst:klast)          ! Wind in Y  real(r8) delp(im,jfirst:jlast,kfirst:klast)          ! Delta pressure  real(r8)   pt(im,jfirst-ng_d:jlast+ng_d,kfirst:klast)! Potential temperature! Input/output: accumulated winds & mass fluxes on c-grid for large-!               time-step transport  real(r8) cx3(im,jfirst-ng_d:jlast+ng_d,kfirst:klast)! Accumulated Courant number in X  real(r8) cy3(im,jfirst:jlast+1,kfirst:klast)        ! Accumulated Courant number in Y  real(r8) mfx(im,jfirst:jlast,kfirst:klast)          ! Mass flux in X  (unghosted)  real(r8) mfy(im,jfirst:jlast+1,kfirst:klast)        ! Mass flux in Y! !OUTPUT PARAMETERS:  real(r8) pe(im,kfirst:klast+1,jfirst:jlast)         ! Edge pressure  real(r8) pk(im,jfirst:jlast,kfirst:klast+1)         ! Pressure to the kappa  real(r8) ptxy(ifirstxy:ilastxy,jfirstxy:jlastxy,km) ! Potential temperature XY decomp  real(r8) pkxy(ifirstxy:ilastxy,jfirstxy:jlastxy,km+1) ! P-to-the-kappa XY decomp  real(r8) pexy(ifirstxy:ilastxy,km+1,jfirstxy:jlastxy) ! Edge pressure XY decomp! Input work arrays:  real(r8) delpf(im,jfirst-ng_d:jlast+ng_d,kfirst:klast)  real(r8)   uc(im,jfirst-ng_d:jlast+ng_d,kfirst:klast)  real(r8)   vc(im,jfirst-2:   jlast+2,   kfirst:klast)  real(r8) ptc(im,jfirst:jlast,kfirst:klast)  real(r8) ptk(im,jfirst:jlast,kfirst:klast)  real(r8) dpt(im,jfirst-1:jlast+1,kfirst:klast)  real(r8) wz3(im,jfirst-1:jlast  ,kfirst:klast+1)  real(r8) pkc(im,jfirst-1:jlast+1,kfirst:klast+1)   real(r8)  wz(im,jfirst-1:jlast+1,kfirst:klast+1)  real(r8) pkcc(im,jfirst:jlast,kfirst:klast+1)   real(r8) wzc(im,jfirst:jlast,kfirst:klast+1)   real(r8) wzxy(ifirstxy:ilastxy,jfirstxy:jlastxy,km+1)  real(r8) delpxy(ifirstxy:ilastxy,jfirstxy:jlastxy,km)  real(r8) pkkp(im,jfirst:jlast,kfirst:klastp)  real(r8) wzkp(im,jfirst:jlast,kfirst:klastp)  real(r8) pekp(im,kfirst:klastp,jfirst:jlast)#if defined ( HIGH_P )  real(r8) wzz(im,jfirst:jlast+1,kfirst:klast+1)#endif! ! !DESCRIPTION:!    Perform a dynamical update for one small time step; the small!    time step is limitted by the fastest wave within the Lagrangian control-!    volume !! !REVISION HISTORY:!     SJL  99.01.01:   Original SMP version!     WS   99.04.13:   Added jfirst:jlast concept!     SJL  99.07.15:   Merged c_core and d_core to this routine!     WS   99.09.07:   Restructuring, cleaning, documentation!     WS   99.10.18:   Walkthrough corrections; frozen for 1.0.7!     WS   99.11.23:   Pruning of some 2-D arrays!     SJL  99.12.23:   More comments; general optimization; reduction!                      of redundant computation & communication!     WS   00.05.14:   Modified ghost indices per Kevin's definition!     WS   00.07.13:   Changed PILGRIM API!     WS   00.08.28:   Cosmetic changes: removed old loop limit comments!     AAM  00.08.30:   Introduced kfirst,klast!     WS   00.12.01:   Replaced MPI_ON with SPMD; hs now distributed!     WS   01.04.11:   PILGRIM optimizations for begin/endtransfer!     WS   01.05.08:   Optimizations in the call of c_sw and d_sw!     AAM  01.06.27:   Reinstituted 2D decomposition for use in ccm!     WS   01.12.10:   Ghosted PT, code now uses mod_comm primitives!     WS   01.12.31:   Removed vorticity damping, ghosted U,V,PT!     WS   02.01.15:   Completed transition to mod_comm!!EOP!---------------------------------------------------------------------!BOC! Local      real(r8)   ub(im,jfirst:  jlast+1)      real(r8)  wk1(im,jfirst-1:jlast+1)      real(r8)  wk2(im,jfirst-ng_d:jlast+ng_d)      real(r8)  wk3(im,jfirst-1:jlast+1)      real(r8) p1d(im)      real(r8) ptmp, pint, press      real(r8) p1, p2      real(r8)  rat, ycrit      real(r8)  dt0, dt5      real(r8)  dl, dp      integer i, j, k      integer ks      integer js1g1, js2g0, js2g1, js2gc, js1gc, js1gcp1, js1gd      integer jn2g0, jn1g1, jn1gc, jn1gcp1, jn1gd      integer iord , jord      integer ktot, ktotp      real(r8)  zt_c         real(r8)  zt_d        real(r8)  tau, fac, pk4      real(r8)  tiny      parameter (tiny = 1.e-10)      double precision pi! Declare permanent local arrays      integer  ifax(13)                      !ECMWF fft      real(r8), allocatable, save :: trigs(:)      real(r8), allocatable, save :: dc(:,:), de(:,:), sc(:), se(:)      real(r8), allocatable, save :: fc(:), f0(:)      real(r8), allocatable, save :: cdx(:,:), cdy(:,:)      real(r8), allocatable, save :: dtdx(:), dtdxe(:), txe5(:), dtxe5(:)      real(r8), allocatable, save :: dyce(:),   dx(:) ,  rdx(:),    cy(:)      real(r8), allocatable, save :: dtdx2(:), dtdx4(:),  dxdt(:), dxe(:)      real(r8), allocatable, save :: cye(:),    dycp(:),  rdxe(:)      real(r8) :: uxx(im,jfirst-ng_d:jlast+ng_d+1)  ! temporary only      real(r8) :: vxx(im,jfirst-ng_d-1:jlast+ng_d)  ! temporary only      real(r8) rdy, dtdy, dydt, dtdy5, tdy5      data  dt0 / 0./      save ifax      save dtdy, dydt, dtdy5, tdy5, rdy      save dl, dp      save zt_c, zt_d#if defined( SPMD )      integer :: incount, outcount#endif!******************************************************************!******************************************************************!! IMPORTANT CODE OPTIONS - SEE BELOW!!******************************************************************!******************************************************************! Option for which version of geopk to use with yz decomposition.! Version geopk16 (geopk16byte =true) uses 16-byte reals to preserve accuracy!   through round-off (order of summation varies with z decomposition).!   This version avoids transposes and instead involves semi-global!   communication in Z.! If geopk16byte=false, variables are transposed to/from xy decomposition!   for use in geopk.! On last small timestep (ipe=1) for D-grid, the version of geopk that uses transposes!   is called regardless, as some transposed quantities are required for!   the te_map phase.      logical geopk16byte!     data geopk16byte / .true. /      data geopk16byte / .false. /      logical geopkc16, geopkd16      geopkc16 = .false.      geopkd16 = .false.      if (geopk16byte) then        geopkc16 = .true.        if (ipe .ne. 1) geopkd16 = .true.      endif!******************************************************************      ktot = klast - kfirst + 1      ktotp = ktot + 1! Set general loop limits! jfirst >= 1; jlast <= jm      js1g1  = max(1,jfirst-1)      js2g0  = max(2,jfirst)      js2g1  = max(2,jfirst-1)      jn2g0  = min(jm-1,jlast)      jn1g1  = min(jm,jlast+1)! Construct C-grid dependent loop limits      js1gc  = max(1,jfirst-ng_c)     ! ng_c latitudes on S (starting at 1)      js1gcp1= max(1,jfirst-ng_c-1)   ! ng_c+1 latitudes on S (starting at 1)      jn1gc  = min(jm,jlast+ng_c)     ! ng_c latitudes on N (ending at jm)      jn1gcp1= min(jm,jlast+ng_c+1)   ! ng_c+1 latitudes on N (ending at jm)!! WS: 00.04.13 : An ugly hack to handle JORD>1 JCD=1!      js2gc  = max(2,jfirst-ng_c)     ! NG latitudes on S (starting at 2)      if ( ng_c == 1 .AND. ng_d > 1 ) THEN        js2gc  = max(2,jfirst-2)       endif! Construct D-grid dependent loop limits      js1gd  = max(1,jfirst-ng_d)     ! ng_d latitudes on S (starting at 1)      jn1gd  = min(jm,jlast+ng_d)     ! ng_d latitudes on N (ending at jm)      if( abs(dt0-dt) > 0.1 ) then        if ( .not. allocated( dtdx ) ) then          allocate(dtdx(jm),dtdx2(jm), dtdx4(jm), dtdxe(jm), dxdt(jm), &                   dxe(jm),  cye(jm),dycp(jm),rdxe(jm),                &                   txe5(jm), dtxe5(jm),dyce(jm),                       &                   dx(jm),rdx(jm),cy(jm) )          allocate( trigs(3*im/2+1) )          allocate( sc(js2g0:jn2g0),    se(js2g0:jn1g1)    )          allocate( dc(im,js2g0:jn2g0), de(im,js2g0:jn1g1) )          call fftfax(im, ifax, trigs)! Determine ycrit such that effective DX >= DY          pi  = 4.d0 * datan(1.d0)          rat = float(im)/float(2*(jm-1))          ycrit = acos( min(0.81, rat) ) * (180./pi)          call pft_cf(im, jm, js2g0, jn2g0, jn1g1, sc, se, dc, de,  &                      cosp, cose, ycrit)          allocate( cdx(js2g0:jn1g1,kfirst:klast) )          allocate( cdy(js2g0:jn1g1,kfirst:klast) )          allocate( f0(jfirst-ng_s:jlast+ng_d) ) ! 000304 bug fix: ng_s not ng_d          allocate( fc(js2gc:jn1gc) )          do j=max(1,jfirst-ng_s),min(jm,jlast+ng_d)        ! 000304 bug fix             f0(j) = (om+om)*sinp(j)          enddo! Compute coriolis parameter at cell corners.          do j=js2gc, jn1gc                    ! Not the issue with ng_c = ng_d              fc(j) = 0.5*(f0(j) + f0(j-1))          enddo        endif        dt0 = dt        dt5 = 0.5*dt        pi  = 4.d0 * datan(1.d0)        dl  = (pi+pi)/im        dp  = pi/(jm-1)        rdy   = 1./(ae*dp)        dtdy  = dt *rdy        dtdy5 = dt5*rdy        dydt  = (ae*dp) / dt        tdy5  = 0.5/dtdy        do j=2,jm-1          dx(j)    = dl*ae*cosp(j)          rdx(j)   = 1. / dx(j)          dtdx(j)  = dt / dx(j)          dxdt(j)  = dx(j) / dt          dtdx2(j) = 0.5*dtdx(j)          dtdx4(j) = 0.5*dtdx2(j)          dycp(j)  = ae*dp/cosp(j)          cy(j)    =  rdy * acosp(j)        enddo        do j=2,jm          dxe(j)   = ae*dl*cose(j)          rdxe(j)  = 1. / dxe(j)          dtdxe(j) = dt / dxe(j)          dtxe5(j) = 0.5*dtdxe(j)          txe5(j)  = 0.5/dtdxe(j)           cye(j)  =  1. / (ae*cose(j)*dp)          dyce(j)  = ae*dp/cose(j)        enddo! C-grid        zt_c = abs(umax*dt5) / (dl*ae)!       CPP_PRT_PREFIX write(6,*) 'c-core: ', (180./pi)*acos(zt_c)! D-grid        zt_d = abs(umax*dt) / (dl*ae)!       CPP_PRT_PREFIX write(6,*) 'd-coret: ', (180./pi)*acos(zt_d)        if ( ptopin .ne. ptop) then             write(6,*) 'PTOP as input to cd_core != ptop from dynamics_vars'             stop        endif!-----------------------------------------! Divergence damping coeff. dx(2)*dy/(TAU)!-----------------------------------------          do k=kfirst,klast             press = 0.5 * ( ak(k)+ak(k+1) + (bk(k)+bk(k+1))*1.E5 )             tau = 8. * (1.+ tanh(1.0*log(ptop/press)) )             tau = max(1., tau) / (128.*abs(dt))            do j=js2g0,jn1g1               fac = tau * ae / cose(j)               cdx(j,k) = fac*dp               cdy(j,k) = fac*dl            enddo            CPP_PRT_PREFIX write(6,*)                   &                 k, 0.01*press, cdx(js2g0,k)*ae*dl*cose(js2g0)/1.E6          enddo      endif#if defined( SPMD )      call t_startf('send_1')      call mp_send3d_ns(im, jm, jfirst, jlast, kfirst, klast, &                        ng_s, ng_d, u, 1)      call mp_send3d_ns(im, jm, jfirst, jlast, kfirst, klast, &                        ng_d, ng_s, v, 2)      call t_stopf('send_1')#endif      if ( ipe == -1 .or. ns == 1 ) then          ! starting cd_core!$omp parallel do private(i, j, k)         do k=kfirst,klast            do j=jfirst,jlast               do i=1,im                  delpf(i,j,k) = delp(i,j,k)               enddo            enddo            call pft2d( delpf(1,js2g0,k), sc(js2g0), dc(1,js2g0),  &                        im, jn2g0-js2g0+1,   ifax, trigs )         enddo      endif#if defined( SPMD )      call t_startf('recv_1')      call mp_barrier()      call mp_recv3d_ns(im, jm, jfirst, jlast, kfirst, klast, &                        ng_s, ng_d, u, 1)      call mp_recv3d_ns(im, jm, jfirst, jlast, kfirst, klast, &                        ng_d, ng_s, v, 2)      call mp_send3d_ns(im, jm, jfirst, jlast, kfirst, klast, &                        ng_d, ng_d, pt, 1)      if ( ipe == -1 .or. ns == 1 ) then          ! starting cd_core         call mp_send3d_ns(im, jm, jfirst, jlast, kfirst, klast, &                           ng_d, ng_d, delpf, 2 )      endif                          ! end if ipe = -1 check      call mp_barrier()      call mp_recv3d_ns(im, jm, jfirst, jlast, kfirst, klast, &                        ng_d, ng_d, pt, 1)      if ( ipe == -1 .or. ns == 1 ) then          ! starting cd_core         call mp_recv3d_ns(im, jm, jfirst, jlast, kfirst, klast, &                           ng_d, ng_d, delpf, 2)      endif                          ! end if ipe = -1 check      call t_stopf('recv_1')

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -