CESE CAM模块学习(3)

今天先来看vertical_diffusion_tend子例程源码,比较经典的参数化方案之一

因为要尝试构建自己的AI参数化方案,对于没有气象学基础的苦命计算机学科学生只能努力先看源码DeBug,再仿写出自己的方案

call vertical_diffusion_tend (ztodt ,state ,cam_in%wsx, cam_in%wsy,   &
     cam_in%shf     ,cam_in%cflx     ,surfric  ,obklen   ,ptend    ,ast    ,&
     cam_in%ocnfrac  , cam_in%landfrac ,        &
     sgh30    ,pbuf )

在调用时使用了大量cam_in中的变量,包括海洋模块和陆地模块

主要使用变量如下:

  • ztodt:两个时间步长(2 delta-t)。
  • state:物理状态变量。
  • taux:x方向地表应力(N/m²)。
  • tauy:y方向地表应力(N/m²)。
  • shflx:地表感热通量(W/m²)。
  • cflx:地表组分通量(kg/m²/s)。
  • cldn:新的层积云分数。
  • ocnfrac:海洋分数。
  • landfrac:陆地分数。
  • sgh:地形标准差。
  • ptend:各个参数化趋势。
  • pbuf:物理缓冲区描述符。

其中state基本包括了CAM所有关键物理变量

! ---------------------- !
! Input-Output Arguments !
! ---------------------- !

type(physics_ptend), intent(out) :: ptend                       ! Individual parameterization tendencies
type(physics_buffer_desc), pointer :: pbuf(:)

! ---------------- !
! Output Arguments !
! ---------------- !

real(r8),            intent(out)   :: ustar(pcols)              ! Surface friction velocity [ m/s ]
real(r8),            intent(out)   :: obklen(pcols)             ! Obukhov length [ m ]

输出变量中主要是地表摩擦速度(m/s),Obukhov长度(m),还有ptend梯度

接下来是大量的局部变量定义

logical  :: kvinit                                              ! Tell compute_eddy_diff/ caleddy
                                                                ! to initialize kvh, kvm (uses kvf)
character(128) :: errstring                                     ! Error status for compute_vdiff
real(r8), pointer, dimension(:,:) :: qrl                        ! LW radiative cooling rate
real(r8), pointer, dimension(:,:) :: wsedl                      ! Sedimentation velocity
                                                                ! of stratiform liquid cloud droplet [ m/s ]

integer  :: lchnk                                               ! Chunk identifier
integer  :: ncol                                                ! Number of atmospheric columns
integer  :: i, k, l, m                                          ! column, level, constituent indices
integer  :: ierr                                                ! status for allocate/deallocate

real(r8) :: dtk(pcols,pver)                                     ! T tendency from KE dissipation
real(r8), pointer   :: tke(:,:)                                 ! Turbulent kinetic energy [ m2/s2 ]
integer(i4),pointer :: turbtype(:,:)                            ! Turbulent interface types [ no unit ]
real(r8), pointer   :: smaw(:,:)                                ! Normalized Galperin instability function
                                                                ! ( 0<= <=4.964 and 1 at neutral )
real(r8) :: cgs(pcols,pverp)                                    ! Counter-gradient star  [ cg/flux ]
real(r8) :: cgh(pcols,pverp)                                    ! Counter-gradient term for heat
real(r8) :: rztodt                                              ! 1./ztodt [ 1/s ]
real(r8) :: ksrftms(pcols)                                      ! Turbulent mountain stress surface drag coefficient [ kg/s/m2 ]
real(r8) :: tautmsx(pcols)                                      ! U component of turbulent mountain stress [ N/m2 ]
real(r8) :: tautmsy(pcols)                                      ! V component of turbulent mountain stress [ N/m2 ]
real(r8) :: tautotx(pcols)                                      ! U component of total surface stress [ N/m2 ]
real(r8) :: tautoty(pcols)                                      ! V component of total surface stress [ N/m2 ]

real(r8), pointer :: kvh_in(:,:)                                ! kvh from previous timestep [ m2/s ]
real(r8), pointer :: kvm_in(:,:)                                ! kvm from previous timestep [ m2/s ]
real(r8), pointer :: kvt(:,:)                                   ! Molecular kinematic conductivity for temperature [  ]
real(r8) :: kvq(pcols,pverp)                                    ! Eddy diffusivity for constituents [ m2/s ]
real(r8) :: kvh(pcols,pverp)                                    ! Eddy diffusivity for heat [ m2/s ]
real(r8) :: kvm(pcols,pverp)                                    ! Eddy diffusivity for momentum [ m2/s ]
real(r8) :: bprod(pcols,pverp)                                  ! Buoyancy production of tke [ m2/s3 ]
real(r8) :: sprod(pcols,pverp)                                  ! Shear production of tke [ m2/s3 ]
real(r8) :: sfi(pcols,pverp)                                    ! Saturation fraction at interfaces [ fraction ]
real(r8) :: sl(pcols,pver)
real(r8) :: qt(pcols,pver)
real(r8) :: slv(pcols,pver)
real(r8) :: sl_prePBL(pcols,pver)
real(r8) :: qt_prePBL(pcols,pver)
real(r8) :: slv_prePBL(pcols,pver)
real(r8) :: slten(pcols,pver)
real(r8) :: qtten(pcols,pver)
real(r8) :: slvten(pcols,pver)
real(r8) :: slflx(pcols,pverp)
real(r8) :: qtflx(pcols,pverp)
real(r8) :: uflx(pcols,pverp)
real(r8) :: vflx(pcols,pverp)
real(r8) :: slflx_cg(pcols,pverp)
real(r8) :: qtflx_cg(pcols,pverp)
real(r8) :: uflx_cg(pcols,pverp)
real(r8) :: vflx_cg(pcols,pverp)
real(r8) :: th(pcols,pver)                                      ! Potential temperature
real(r8) :: topflx(pcols)                                       ! Molecular heat flux at top interface
real(r8) :: wpert(pcols)                                        ! Turbulent wind gusts
real(r8) :: rhoair

real(r8) :: ri(pcols,pver)                                      ! richardson number (HB output)

! for obklen calculation outside HB
real(r8) :: thvs(pcols)                                         ! Virtual potential temperature at surface
real(r8) :: rrho(pcols)                                         ! Reciprocal of density at surface
real(r8) :: khfs(pcols)                                         ! sfc kinematic heat flux [mK/s]
real(r8) :: kqfs(pcols)                                         ! sfc kinematic water vapor flux [m/s]
real(r8) :: kbfs(pcols)                                         ! sfc kinematic buoyancy flux [m^2/s^3]

real(r8) :: ftem(pcols,pver)                                    ! Saturation vapor pressure before PBL
real(r8) :: ftem_prePBL(pcols,pver)                             ! Saturation vapor pressure before PBL
real(r8) :: ftem_aftPBL(pcols,pver)                             ! Saturation vapor pressure after PBL
real(r8) :: tem2(pcols,pver)                                    ! Saturation specific humidity and RH
real(r8) :: t_aftPBL(pcols,pver)                                ! Temperature after PBL diffusion
real(r8) :: tten(pcols,pver)                                    ! Temperature tendency by PBL diffusion
real(r8) :: rhten(pcols,pver)                                   ! RH tendency by PBL diffusion
real(r8) :: qv_aft_PBL(pcols,pver)                              ! qv after PBL diffusion
real(r8) :: ql_aft_PBL(pcols,pver)                              ! ql after PBL diffusion
real(r8) :: qi_aft_PBL(pcols,pver)                              ! qi after PBL diffusion
real(r8) :: s_aft_PBL(pcols,pver)                               ! s after PBL diffusion
real(r8) :: u_aft_PBL(pcols,pver)                               ! u after PBL diffusion
real(r8) :: v_aft_PBL(pcols,pver)                               ! v after PBL diffusion
real(r8) :: qv_pro(pcols,pver) 
real(r8) :: ql_pro(pcols,pver)
real(r8) :: qi_pro(pcols,pver)
real(r8) :: s_pro(pcols,pver)
real(r8) :: t_pro(pcols,pver)
real(r8), pointer :: tauresx(:)                                      ! Residual stress to be added in vdiff to correct
real(r8), pointer :: tauresy(:)                                      ! for turb stress mismatch between sfc and atm accumulated.
real(r8) :: ipbl(pcols)
real(r8) :: kpblh(pcols)
real(r8) :: wstarPBL(pcols)
real(r8) :: tpertPBL(pcols)
real(r8) :: qpertPBL(pcols)
real(r8) :: rairi(pcols,pver+1)                                 ! interface gas constant needed for compute_vdiff

real(r8), pointer :: tpert(:)
real(r8), pointer :: qpert(:)
real(r8), pointer :: pblh(:)

real(r8) :: tmp1(pcols)                                         ! Temporary storage

integer  :: nstep
real(r8) :: sum1, sum2, sum3, pdelx 
real(r8) :: sflx

! Copy state so we can pass to intent(inout) routines that return
! new state instead of a tendency.
real(r8) :: s_tmp(pcols,pver)
real(r8) :: u_tmp(pcols,pver)
real(r8) :: v_tmp(pcols,pver)
real(r8) :: q_tmp(pcols,pver,pcnst)

大量变量都是关于边界层定义的物理变量,等到用到的时候再回来看

! ----------------------- !
! Main Computation Begins !
! ----------------------- !

rztodt = 1._r8 / ztodt
lchnk  = state%lchnk
ncol   = state%ncol

call pbuf_get_field(pbuf, tauresx_idx,  tauresx)
call pbuf_get_field(pbuf, tauresy_idx,  tauresy)
call pbuf_get_field(pbuf, tpert_idx,    tpert)
call pbuf_get_field(pbuf, qpert_idx,    qpert)
call pbuf_get_field(pbuf, pblh_idx,     pblh)
call pbuf_get_field(pbuf, turbtype_idx, turbtype)

在计算开始之前,从state和pbuf中获取了一些变量

这里我发现了一个重要的点,大量有用的物理变量其实都存在物理缓存区之中

为了管理pbuf物理缓存,CAM中有大量相关的代码,之后需要留意有哪些需要使用的变量在物理缓存之中

整个vertical_diffusion有大量的参数化方案,因为目的只是学习就只挑eddy_scheme来详细阅读

select case (eddy_scheme)
case ( 'diag_TKE' ) 

   ! ---------------------------------------------------------------- !
   ! At first time step, have eddy_diff.F90:caleddy() use kvh=kvm=kvf !
   ! This has to be done in compute_eddy_diff after kvf is calculated !
   ! ---------------------------------------------------------------- !

   if( is_first_step() ) then
       kvinit = .true.
   else
       kvinit = .false.
   endif

   ! ---------------------------------------------- !
   ! Get LW radiative heating out of physics buffer !
   ! ---------------------------------------------- !
   call pbuf_get_field(pbuf, qrl_idx,   qrl   )

   call pbuf_get_field(pbuf, wsedl_idx, wsedl )

   ! Retrieve eddy diffusivities for heat and momentum from physics buffer
   ! from last timestep ( if first timestep, has been initialized by inidat.F90 )

   call compute_eddy_diff( lchnk    ,                                                                    &
                           pcols    , pver        , ncol       , state%t    , state%q(:,:,1) , ztodt   , &
                           state%q(:,:,ixcldliq)  , state%q(:,:,ixcldice)   ,                            &
                           state%s  , state%rpdel , cldn       , qrl        , wsedl          ,           &
                           state%zm , state%zi    , state%pmid , state%pint , state%u        , state%v , &
                           taux     , tauy        , shflx      , cflx(:,1)  , wstarent       , nturb   , &
                           rrho     , ustar       , pblh       , kvm_in     , kvh_in         , kvm     , &
                           kvh      , kvq         , cgh        ,                                         &
                           cgs      , tpert       , qpert      , wpert      , tke            , bprod   , &
                           sprod    , sfi         , kvinit     ,                                         &
                           tauresx  , tauresy     , ksrftms    ,                                         &
                           ipbl(:)  , kpblh(:)    , wstarPBL(:), turbtype   , smaw )

代码核心便是调用compute_eddy_diff过程计算热量和动量的涡流扩散率。这些扩散率从上一个时间步获取,并在第一个时间步初始化。

在调用中传递了各种变量,包括模型状态、水汽和液态水的混合比、表面风应力、能量通量等。这个过程会根据给定的参数计算涡流扩散率,并更新这些变量的值。

进入该子例程内部,跳过关于输入输出以及变量准备等具体过程

do iturb = 1, nturb

 ! Total stress includes 'tms'.
 ! Here, in computing 'tms', we can use either iteratively changed 'ufd,vfd' or the
 ! initially given 'u,v' to the PBL scheme. Note that normal stress, 'taux, tauy'
 ! are not changed by iteration. In order to treat 'tms' in a fully implicit way,
 ! I am using updated wind, here.

 ! Compute ustar
   call calc_ustar( tfd(:ncol,pver), pmid(:ncol,pver), &
                    taux(:ncol) - ksrftms(:ncol) * ufd(:ncol,pver), & ! Zonal wind stress
                    tauy(:ncol) - ksrftms(:ncol) * vfd(:ncol,pver), & ! Meridional wind stress
                    rrho(:ncol), ustar(:ncol))
   minpblh(:ncol) = 100.0_r8 * ustar(:ncol)   ! By construction, 'minpblh' is larger than 1 [m] when 'ustar_min = 0.01'.

 ! Calculate (qt,sl,n2,s2,ri) from a given set of (t,qv,ql,qi,u,v)

   call trbintd( &
                 pcols    , pver    , ncol  , z       , ufd     , vfd     , tfd   , pmid    , &
                 s2       , n2      , ri    , zi      , pi      , cldn    , qtfd  , qvfd    , &
                 qlfd     , qi      , sfi   , sfuh    , sflh    , slfd    , slv   , slslope , &
                 qtslope  , chs     , chu   , cms     , cmu     )

整个方案计算过程最重要部分就是按算涡流扩散率的迭代步骤数nturb循环迭代计算

注释写的挺全,封装也做的挺完整的

首先计算ustar和minpblh

再给定的(tfdqvfduv)计算(qtsln2s2ri)。

 ! Save initial (i.e., before iterative diffusion) profile of (qt,sl) at each iteration.         
   ! Only necessary for (qt,sl) not (u,v) because (qt,sl) are newly calculated variables. 

     if( iturb .eq. 1 ) then
         qt(:ncol,:) = qtfd(:ncol,:)
         sl(:ncol,:) = slfd(:ncol,:)
     endif

   ! Get free atmosphere exchange coefficients. This 'kvf' is not used in UW moist PBL scheme

     call austausch_atm( pcols, pver, ncol, ri, s2, kvf )

   ! Initialize kvh/kvm to send to caleddy, depending on model timestep and iteration number
   ! This is necessary for 'wstar-based' entrainment closure.

     if( iturb .eq. 1 ) then
         if( kvinit ) then
         ! First iteration of first model timestep : Use free tropospheric value or zero.
           if( use_kvf ) then
               kvh(:ncol,:) = kvf(:ncol,:)
               kvm(:ncol,:) = kvf(:ncol,:)
           else
               kvh(:ncol,:) = 0._r8
               kvm(:ncol,:) = 0._r8
           endif
         else
           ! First iteration on any model timestep except the first : Use value from previous timestep
           kvh(:ncol,:) = kvh_in(:ncol,:)
           kvm(:ncol,:) = kvm_in(:ncol,:)
         endif
     else
      ! Not the first iteration : Use from previous iteration
        kvh(:ncol,:) = kvh_out(:ncol,:)
        kvm(:ncol,:) = kvm_out(:ncol,:)
     endif

   ! Calculate eddy diffusivity (kvh_out,kvm_out) and (tke,bprod,sprod) using
   ! a given (kvh,kvm) which are used only for initializing (bprod,sprod)  at
   ! the first part of caleddy. (bprod,sprod) are fully updated at the end of
   ! caleddy after calculating (kvh_out,kvm_out) 

     call caleddy( pcols     , pver      , ncol      ,                     &
                   slfd      , qtfd      , qlfd      , slv      ,ufd     , &
                   vfd       , pi        , z         , zi       ,          &
                   qflx      , shflx     , slslope   , qtslope  ,          &
                   chu       , chs       , cmu       , cms      ,sfuh    , &
                   sflh      , n2        , s2        , ri       ,rrho    , &
                   pblh      , ustar     ,                                 &
                   kvh       , kvm       , kvh_out   , kvm_out  ,          &
                   tpert     , qpert     , qrl       , kvf      , tke    , &
                   wstarent  , bprod     , sprod     , minpblh  , wpert  , &
                   tkes      , turbtype  , sm_aw     ,                     & 
                   kbase_o   , ktop_o    , ncvfin_o  ,                     &
                   kbase_mg  , ktop_mg   , ncvfin_mg ,                     &                  
                   kbase_f   , ktop_f    , ncvfin_f  ,                     &                  
                   wet       , web       , jtbu      , jbbu     ,          &
                   evhc      , jt2slv    , n2ht      , n2hb     ,          & 
                   lwp       , opt_depth , radinvfrac, radf     ,          &
                   wstar     , wstar3fact,                                 &
                   ebrk      , wbrk      , lbrk      , ricl     , ghcl   , & 
                   shcl      , smcl      , ghi       , shi      , smi    , &
                   rii       , lengi     , wcap      , pblhp    , cldn   , &
                   ipbl      , kpblh     , wsedl)

   ! Calculate errorPBL to check whether PBL produced convergent solutions or not.

     if( iturb .eq. nturb ) then
         do i = 1, ncol
            errorPBL(i) = 0._r8 
            do k = 1, pver
               errorPBL(i) = errorPBL(i) + ( kvh(i,k) - kvh_out(i,k) )**2 
            end do 
            errorPBL(i) = sqrt(errorPBL(i)/pver)
         end do
     end if

   ! Eddy diffusivities which will be used for the initialization of (bprod,
   ! sprod) in 'caleddy' at the next iteration step.

     if( iturb .gt. 1 .and. iturb .lt. nturb ) then
         kvm_out(:ncol,:) = lambda * kvm_out(:ncol,:) + ( 1._r8 - lambda ) * kvm(:ncol,:)
         kvh_out(:ncol,:) = lambda * kvh_out(:ncol,:) + ( 1._r8 - lambda ) * kvh(:ncol,:)
     endif

   ! Set nonlocal terms to zero for flux diagnostics, since not used by caleddy.

     cgh(:ncol,:) = 0._r8
     cgs(:ncol,:) = 0._r8      

     if( iturb .lt. nturb ) then

       ! Each time we diffuse the original state

         slfd(:ncol,:)  = sl(:ncol,:)
         qtfd(:ncol,:)  = qt(:ncol,:)
         ufd(:ncol,:)   = u(:ncol,:)
         vfd(:ncol,:)   = v(:ncol,:)

       !------------------------------------------------------------------------ 
       !  Check to see if constituent dependent gas constant needed (WACCM-X)
       !------------------------------------------------------------------------
       if ( waccmx_is('ionosphere') .or. waccmx_is('neutral') ) then 
         rairi(:ncol,1) = rairv(:ncol,1,lchnk)
         do k = 2, pver
           do i = 1, ncol
             rairi(i,k) = 0.5_r8 * (rairv(i,k,lchnk)+rairv(i,k-1,lchnk))
           end do
         end do      
       else
         rairi(:ncol,:pver+1) = rair          
       endif

       ! Diffuse initial profile of each time step using a given (kvh_out,kvm_out)
       ! In the below 'compute_vdiff', (slfd,qtfd,ufd,vfd) are 'inout' variables.

       call compute_vdiff( lchnk   ,                                                 &
                           pcols   , pver     , 1        , ncol         , pmid      , &
                           pi      , rpdel    , t        , ztodt        , taux      , &
                           tauy    , shflx    , qflx     , ntop_turb    , nbot_turb , &
                           kvh_out , kvm_out  , kvh_out  , cgs          , cgh       , &
                           zi      , ksrftms  , zero     , fieldlist_wet, fieldlist_molec, &
                           ufd     , vfd      , qtfd     , slfd         ,             &
                           jnk1d   , jnk1d    , jnk2d    , jnk1d        , errstring , &
                           tauresx , tauresy  , 0        , cpairv(:,:,lchnk), rairi , .false. )

       call handle_errmsg(errstring, subname="compute_vdiff", &
            extra_msg="compute_vdiff called from eddy_diff")

       ! Retrieve (tfd,qvfd,qlfd) from (slfd,qtfd) in order to 
       ! use 'trbintd' at the next iteration.
        
        do k = 1, pver
           do i = 1, ncol
            ! ----------------------------------------------------- ! 
            ! Compute the condensate 'qlfd' in the updated profiles !
            ! ----------------------------------------------------- !  
            ! Option.1 : Assume grid-mean condensate is homogeneously diffused by the moist turbulence scheme.
            !            This should bs used if 'pseudodiff = .false.' in vertical_diffusion.F90.
            ! Modification : Need to be check whether below is correct in the presence of ice, qi.       
            !                I should understand why the variation of ice, qi is neglected during diffusion.
              templ     = ( slfd(i,k) - g*z(i,k) ) / cpair
              call qsat( templ, pmid(i,k), es, qs)
              ep2       =  .622_r8 
              temps     =   templ + ( qtfd(i,k) - qs ) / ( cpair / latvap + latvap * qs / ( rair * templ**2 ) )
              call qsat( temps, pmid(i,k), es, qs)
              qlfd(i,k) =   max( qtfd(i,k) - qi(i,k) - qs ,0._r8 )
            ! Option.2 : Assume condensate is not diffused by the moist turbulence scheme. 
            !            This should bs used if 'pseudodiff = .true.'  in vertical_diffusion.F90.       
            ! qlfd(i,k) = ql(i,k)
            ! ----------------------------- !
            ! Compute the other 'qvfd, tfd' ! 
            ! ----------------------------- !
              qvfd(i,k) = max( 0._r8, qtfd(i,k) - qi(i,k) - qlfd(i,k) )
              tfd(i,k)  = ( slfd(i,k) + latvap * qlfd(i,k) + latsub * qi(i,k) - g*z(i,k)) / cpair
           end do
        end do
     endif

   ! Debug 
   ! icol = phys_debug_col(lchnk) 
   ! if( icol > 0 .and. get_nstep() .ge. 1 ) then
   !     write(iulog,*) ' '
   !     write(iulog,*) 'eddy_diff debug at the end of iteration' 
   !     write(iulog,*) 't,     qv,     ql,     cld,     u,     v'
   !     do k = pver-3, pver
   !        write (iulog,*) k, tfd(icol,k), qvfd(icol,k), qlfd(icol,k), cldn(icol,k), ufd(icol,k), vfd(icol,k)
   !     end do
   ! endif
   ! Debug

  end do  ! End of 'iturb' iteration

如果是第一个迭代,保存初始(即在迭代扩散之前)的(qtsl)的剖面。

获取自由大气交换系数kvf

初始化kvhkvm,以在下一个时间步骤中用于初始化caleddy的(bprodsprod)。

调用caleddy计算涡流扩散率和(tkebprodsprod)。

如果不是最后一次迭代,则更新kvh_outkvm_out,以在下一个迭代步骤中用于初始化caleddy的(bprodsprod)。

将非本地项设置为零,以便用于通量诊断。

如果不是最后一次迭代,则将初始状态(slfdqtfdufdvfd)扩散为下一次迭代的输入。

计算迭代的误差errorPBL

 kvq(:ncol,:) = kvh_out(:ncol,:)

  ! Compute 'wstar' within the PBL for use in the future convection scheme.

    do i = 1, ncol
       if( ipbl(i) .eq. 1._r8 ) then 
           wstarPBL(i) = max( 0._r8, wstar(i,1) )
       else
           wstarPBL(i) = 0._r8
       endif
    end do

    ! --------------------------------------------------------------- !
    ! Writing for detailed diagnostic analysis of UW moist PBL scheme !
    ! --------------------------------------------------------------- !

    call outfld( 'UW_errorPBL',    errorPBL,   pcols,   lchnk )

    call outfld( 'UW_n2',          n2,         pcols,   lchnk )
    call outfld( 'UW_s2',          s2,         pcols,   lchnk )
    call outfld( 'UW_ri',          ri,         pcols,   lchnk )

    call outfld( 'UW_sfuh',        sfuh,       pcols,   lchnk )
    call outfld( 'UW_sflh',        sflh,       pcols,   lchnk )
    call outfld( 'UW_sfi',         sfi,        pcols,   lchnk )

    call outfld( 'UW_cldn',        cldn,       pcols,   lchnk )
    call outfld( 'UW_qrl',         qrl,        pcols,   lchnk )
    call outfld( 'UW_ql',          qlfd,       pcols,   lchnk )

    call outfld( 'UW_chu',         chu,        pcols,   lchnk )
    call outfld( 'UW_chs',         chs,        pcols,   lchnk )
    call outfld( 'UW_cmu',         cmu,        pcols,   lchnk )
    call outfld( 'UW_cms',         cms,        pcols,   lchnk )

    call outfld( 'UW_tke',         tke,        pcols,   lchnk )
    call outfld( 'UW_wcap',        wcap,       pcols,   lchnk )
    call outfld( 'UW_bprod',       bprod,      pcols,   lchnk )
    call outfld( 'UW_sprod',       sprod,      pcols,   lchnk )

    call outfld( 'UW_kvh',         kvh_out,    pcols,   lchnk )
    call outfld( 'UW_kvm',         kvm_out,    pcols,   lchnk )

    call outfld( 'UW_pblh',        pblh,       pcols,   lchnk )
    call outfld( 'UW_pblhp',       pblhp,      pcols,   lchnk )
    call outfld( 'UW_tpert',       tpert,      pcols,   lchnk )
    call outfld( 'UW_qpert',       qpert,      pcols,   lchnk )
    call outfld( 'UW_wpert',       wpert,      pcols,   lchnk )

    call outfld( 'UW_ustar',       ustar,      pcols,   lchnk )
    call outfld( 'UW_tkes',        tkes,       pcols,   lchnk )
    call outfld( 'UW_minpblh',     minpblh,    pcols,   lchnk )

    call outfld( 'UW_turbtype',    real(turbtype,r8),   pcols,   lchnk )

    call outfld( 'UW_kbase_o',     kbase_o,    pcols,   lchnk )
    call outfld( 'UW_ktop_o',      ktop_o,     pcols,   lchnk )
    call outfld( 'UW_ncvfin_o',    ncvfin_o,   pcols,   lchnk )

    call outfld( 'UW_kbase_mg',    kbase_mg,   pcols,   lchnk )
    call outfld( 'UW_ktop_mg',     ktop_mg,    pcols,   lchnk )
    call outfld( 'UW_ncvfin_mg',   ncvfin_mg,  pcols,   lchnk )

    call outfld( 'UW_kbase_f',     kbase_f,    pcols,   lchnk )
    call outfld( 'UW_ktop_f',      ktop_f,     pcols,   lchnk )
    call outfld( 'UW_ncvfin_f',    ncvfin_f,   pcols,   lchnk ) 

    call outfld( 'UW_wet',         wet,        pcols,   lchnk )
    call outfld( 'UW_web',         web,        pcols,   lchnk )
    call outfld( 'UW_jtbu',        jtbu,       pcols,   lchnk )
    call outfld( 'UW_jbbu',        jbbu,       pcols,   lchnk )
    call outfld( 'UW_evhc',        evhc,       pcols,   lchnk )
    call outfld( 'UW_jt2slv',      jt2slv,     pcols,   lchnk )
    call outfld( 'UW_n2ht',        n2ht,       pcols,   lchnk )
    call outfld( 'UW_n2hb',        n2hb,       pcols,   lchnk )
    call outfld( 'UW_lwp',         lwp,        pcols,   lchnk )
    call outfld( 'UW_optdepth',    opt_depth,  pcols,   lchnk )
    call outfld( 'UW_radfrac',     radinvfrac, pcols,   lchnk )
    call outfld( 'UW_radf',        radf,       pcols,   lchnk )
    call outfld( 'UW_wstar',       wstar,      pcols,   lchnk )
    call outfld( 'UW_wstar3fact',  wstar3fact, pcols,   lchnk )
    call outfld( 'UW_ebrk',        ebrk,       pcols,   lchnk )
    call outfld( 'UW_wbrk',        wbrk,       pcols,   lchnk )
    call outfld( 'UW_lbrk',        lbrk,       pcols,   lchnk )
    call outfld( 'UW_ricl',        ricl,       pcols,   lchnk )
    call outfld( 'UW_ghcl',        ghcl,       pcols,   lchnk )
    call outfld( 'UW_shcl',        shcl,       pcols,   lchnk )
    call outfld( 'UW_smcl',        smcl,       pcols,   lchnk )

    call outfld( 'UW_gh',          ghi,        pcols,   lchnk )
    call outfld( 'UW_sh',          shi,        pcols,   lchnk )
    call outfld( 'UW_sm',          smi,        pcols,   lchnk )
    call outfld( 'UW_ria',         rii,        pcols,   lchnk )
    call outfld( 'UW_leng',        lengi,      pcols,   lchnk )

    return
    
  end subroutine compute_eddy_diff

最后是该方案的结尾工作

  • 将一个数组的值赋给另一个数组:kvq(:ncol,:) = kvh_out(:ncol,:)
  • 计算并保存在 PBL 内部的 wstar 值以备将来对对流方案的使用
  • 输出一系列诊断字段,包括但不限于 errorPBLn2s2risfuhsflhsficldnqrlqlfdchuchscmucmstkewcapbprodsprodkvh_outkvm_outpblhpblhptpertqpertwpertustartkesminpblhturbtypekbase_okbase_mgkbase_f 等。这些输出用于进一步分析 UW 湿润边界层方案的性能和行为。

该方案与我的研究内容无关,但也是第一次较为完整的阅读完了整个过程,在不深究物理过程的细节下,整个代码对一个外行来说阅读难度不高,所以希望自己打起精神来,要做的东西很难,但是总有突破口。凡事都是有代价的,越难的东西做出来就越有价值。

接下来想看看深对流过程的代码,再和学长学姐讨论下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值