LCOV - code coverage report
Current view: top level - physics/cam - eddy_diff_cam.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 393 0.0 %
Date: 2024-12-17 22:39:59 Functions: 0 5 0.0 %

          Line data    Source code
       1             : module eddy_diff_cam
       2             : 
       3             : use shr_kind_mod, only: i4 => shr_kind_i4, r8 => shr_kind_r8
       4             : use ppgrid, only: pcols, pver, pverp
       5             : use cam_logfile, only: iulog
       6             : use cam_abortutils, only: endrun
       7             : use physconst, only: gravit, cpair, rair, zvir, latvap, latice, karman
       8             : use diffusion_solver, only: vdiff_selector
       9             : use eddy_diff, only: ncvmax
      10             : use time_manager, only: is_first_step
      11             : use physics_buffer, only: physics_buffer_desc
      12             : use spmd_utils, only: masterproc
      13             : use phys_control, only: phys_getopts
      14             : 
      15             : implicit none
      16             : private
      17             : 
      18             : public :: eddy_diff_readnl
      19             : public :: eddy_diff_register
      20             : public :: eddy_diff_init
      21             : public :: eddy_diff_tend
      22             : 
      23             : ! Is UNICON switched on (and thus interacting with eddy_diff via pbuf)?
      24             : logical :: unicon_is_on
      25             : 
      26             : ! Number of iterations for solution
      27             : integer, parameter :: nturb = 5
      28             : 
      29             : ! Logical switches for moist mixing ratio diffusion
      30             : type(vdiff_selector) :: fieldlist_wet
      31             : ! Logical switches for molecular diffusion
      32             : ! (Molecular diffusion is not done here.)
      33             : type(vdiff_selector) :: fieldlist_molec
      34             : 
      35             : integer :: ntop_eddy, nbot_eddy
      36             : 
      37             : ! Cloud mass constituent indices
      38             : integer :: ixcldliq, ixcldice
      39             : 
      40             : ! input pbuf field indices
      41             : integer :: qrl_idx   = -1
      42             : integer :: wsedl_idx = -1
      43             : 
      44             : ! output pbuf field indices for UNICON
      45             : integer :: bprod_idx    = -1
      46             : integer :: ipbl_idx     = -1
      47             : integer :: kpblh_idx    = -1
      48             : integer :: wstarPBL_idx = -1
      49             : integer :: tkes_idx     = -1
      50             : integer :: went_idx     = -1
      51             : 
      52             : ! Mixing lengths squared.
      53             : ! Used for computing free air diffusivity.
      54             : real(r8) :: ml2(pver+1)
      55             : 
      56             : ! Various namelist options to limit or tweak the effects of eddy diffusion.
      57             : 
      58             : ! Pressure defining the bottom of the upper atmosphere for kvh scaling (Pa)
      59             : real(r8) :: kv_top_pressure = 0._r8
      60             : ! Eddy diffusivity scale factor for upper atmosphere
      61             : real(r8) :: kv_top_scale = 1._r8
      62             : ! Eddy diffusivity scale factor for the free troposphere
      63             : real(r8) :: kv_freetrop_scale = 1._r8
      64             : 
      65             : ! The following all have to be set in all cases.
      66             : real(r8), parameter  :: unset_r8 = huge(1._r8)
      67             : ! Maximum master length for diag_TKE
      68             : real(r8) :: eddy_lbulk_max = unset_r8
      69             : ! Maximum dissipation length for diag_TKE
      70             : real(r8) :: eddy_leng_max = unset_r8
      71             : ! Bottom pressure level (hPa) for eddy_leng_max
      72             : real(r8) :: eddy_max_bot_pressure = unset_r8
      73             : ! Moist entrainment enhancement param
      74             : real(r8) :: eddy_moist_entrain_a2l = unset_r8
      75             : 
      76             : contains
      77             : 
      78           0 : subroutine eddy_diff_readnl(nlfile)
      79             :   use namelist_utils, only: find_group_name
      80             :   use units, only: getunit, freeunit
      81             :   use spmd_utils, only: masterprocid, mpi_real8, mpicom
      82             :   use shr_log_mod, only: errMsg => shr_log_errMsg
      83             : 
      84             :   ! filepath for file containing namelist input
      85             :   character(len=*), intent(in) :: nlfile
      86             : 
      87             :   ! file unit and error code
      88             :   integer :: unitn, ierr
      89             : 
      90             :   character(len=*), parameter :: subname = 'eddy_diff_readnl'
      91             : 
      92             :   namelist /eddy_diff_nl/ kv_top_pressure, kv_top_scale, &
      93             :        kv_freetrop_scale, eddy_lbulk_max, eddy_leng_max, &
      94             :        eddy_max_bot_pressure, eddy_moist_entrain_a2l
      95             : 
      96           0 :   if (masterproc) then
      97           0 :      unitn = getunit()
      98           0 :      open( unitn, file=trim(nlfile), status='old' )
      99           0 :      call find_group_name(unitn, 'eddy_diff_nl', status=ierr)
     100           0 :      if (ierr == 0) then
     101           0 :         read(unitn, eddy_diff_nl, iostat=ierr)
     102             :      end if
     103           0 :      if (ierr /= 0) then
     104           0 :         call endrun(subname // ':: ERROR reading namelist')
     105             :      end if
     106           0 :      close(unitn)
     107           0 :      call freeunit(unitn)
     108             :   end if
     109             : 
     110           0 :   call mpi_bcast(kv_top_pressure,   1,   mpi_real8, masterprocid, mpicom, ierr)
     111           0 :   if (ierr /= 0) call endrun(errMsg(__FILE__, __LINE__)//" mpi_bcast error")
     112           0 :   call mpi_bcast(kv_top_scale,      1,   mpi_real8, masterprocid, mpicom, ierr)
     113           0 :   if (ierr /= 0) call endrun(errMsg(__FILE__, __LINE__)//" mpi_bcast error")
     114           0 :   call mpi_bcast(kv_freetrop_scale, 1,   mpi_real8, masterprocid, mpicom, ierr)
     115           0 :   if (ierr /= 0) call endrun(errMsg(__FILE__, __LINE__)//" mpi_bcast error")
     116             : 
     117           0 :   call mpi_bcast(eddy_lbulk_max,    1,   mpi_real8, masterprocid, mpicom, ierr)
     118           0 :   if (ierr /= 0) call endrun(errMsg(__FILE__, __LINE__)//" mpi_bcast error")
     119           0 :   call mpi_bcast(eddy_leng_max,     1,   mpi_real8, masterprocid, mpicom, ierr)
     120           0 :   if (ierr /= 0) call endrun(errMsg(__FILE__, __LINE__)//" mpi_bcast error")
     121           0 :   call mpi_bcast(eddy_max_bot_pressure,     1,   mpi_real8, masterprocid, mpicom, ierr)
     122           0 :   if (ierr /= 0) call endrun(errMsg(__FILE__, __LINE__)//" mpi_bcast error")
     123           0 :   call mpi_bcast(eddy_moist_entrain_a2l,    1,   mpi_real8, masterprocid, mpicom, ierr)
     124           0 :   if (ierr /= 0) call endrun(errMsg(__FILE__, __LINE__)//" mpi_bcast error")
     125             : 
     126           0 : end subroutine eddy_diff_readnl
     127             : 
     128           0 : subroutine eddy_diff_register()
     129             :   use physics_buffer, only: pbuf_add_field, dtype_r8, dtype_i4
     130             : 
     131             :   character(len=16) :: shallow_scheme
     132             : 
     133             :   ! Check for UNICON and add relevant pbuf entries.
     134           0 :   call phys_getopts(shallow_scheme_out=shallow_scheme)
     135             : 
     136           0 :   unicon_is_on = (shallow_scheme == "UNICON")
     137             : 
     138           0 :   if (unicon_is_on) then
     139           0 :      call pbuf_add_field('bprod',    'global', dtype_r8, (/pcols,pverp/), bprod_idx)
     140           0 :      call pbuf_add_field('ipbl',     'global', dtype_i4, (/pcols/),       ipbl_idx)
     141           0 :      call pbuf_add_field('kpblh',    'global', dtype_i4, (/pcols/),       kpblh_idx)
     142           0 :      call pbuf_add_field('wstarPBL', 'global', dtype_r8, (/pcols/),       wstarPBL_idx)
     143           0 :      call pbuf_add_field('tkes',     'global', dtype_r8, (/pcols/),       tkes_idx)
     144           0 :      call pbuf_add_field('went',     'global', dtype_r8, (/pcols/),       went_idx)
     145             :   end if
     146             : 
     147           0 : end subroutine eddy_diff_register
     148             : 
     149           0 : subroutine eddy_diff_init(pbuf2d, ntop_eddy_in, nbot_eddy_in)
     150             : 
     151           0 :   use error_messages, only: handle_errmsg
     152             :   use cam_history, only: addfld, add_default, horiz_only
     153             :   use constituents, only: cnst_get_ind
     154             :   use ref_pres, only: pref_mid
     155             :   use diffusion_solver, only: new_fieldlist_vdiff, vdiff_select
     156             :   use eddy_diff, only: init_eddy_diff
     157             :   use physics_buffer, only: pbuf_set_field, pbuf_get_index
     158             : 
     159             :   type(physics_buffer_desc), pointer :: pbuf2d(:,:) ! Physics buffer
     160             :   integer,  intent(in) :: ntop_eddy_in ! Top interface level to which eddy vertical diffusivity is applied ( = 1 )
     161             :   integer,  intent(in) :: nbot_eddy_in ! Bottom interface level to which eddy vertical diffusivity is applied ( = pver )
     162             : 
     163             :   character(len=128) :: errstring
     164             : 
     165             :   real(r8) :: leng_max(pver)
     166             :   integer :: k
     167             : 
     168             :   logical :: history_amwg
     169             : 
     170           0 :   ntop_eddy = ntop_eddy_in
     171           0 :   nbot_eddy = nbot_eddy_in
     172             : 
     173           0 :   do k = 1, pver
     174           0 :      if (pref_mid(k) <= eddy_max_bot_pressure*1.e2_r8) then
     175           0 :         leng_max(k) = eddy_leng_max
     176             :      else
     177           0 :         leng_max(k) = 40.e3_r8
     178             :      end if
     179             :   end do
     180             : 
     181           0 :   if (masterproc) then
     182           0 :      write(iulog,*)'init_eddy_diff: nturb=',nturb
     183           0 :      write(iulog,*)'init_eddy_diff: eddy_leng_max=',eddy_leng_max,' lbulk_max=',eddy_lbulk_max
     184           0 :      do k = 1,pver
     185           0 :         write(iulog,*)'init_eddy_diff:',k,pref_mid(k),'leng_max=',leng_max(k)
     186             :      end do
     187             :   end if
     188             : 
     189             :   call init_eddy_diff(pver, gravit, cpair, rair, zvir, &
     190             :        latvap, latice, ntop_eddy, nbot_eddy, karman, &
     191             :        eddy_lbulk_max, leng_max, &
     192           0 :        eddy_moist_entrain_a2l, errstring)
     193             : 
     194           0 :   call handle_errmsg(errstring, subname="init_eddy_diff")
     195             : 
     196             :   ! Set the square of the mixing lengths.
     197           0 :   ml2(1:ntop_eddy) = 0._r8
     198           0 :   do k = ntop_eddy + 1, nbot_eddy
     199           0 :      ml2(k) = 30.0_r8**2
     200             :   end do
     201           0 :   ml2(nbot_eddy+1:pver+1) = 0._r8
     202             : 
     203             :   ! Get fieldlists to pass to diffusion solver.
     204           0 :   fieldlist_wet   = new_fieldlist_vdiff(1)
     205           0 :   fieldlist_molec = new_fieldlist_vdiff(1)
     206             : 
     207             :   call handle_errmsg(vdiff_select(fieldlist_wet,'s'), &
     208           0 :        subname="vdiff_select")
     209             :   call handle_errmsg(vdiff_select(fieldlist_wet,'q',1), &
     210           0 :        subname="vdiff_select")
     211             :   call handle_errmsg(vdiff_select(fieldlist_wet,'u'), &
     212           0 :        subname="vdiff_select")
     213             :   call handle_errmsg(vdiff_select(fieldlist_wet,'v'), &
     214           0 :        subname="vdiff_select")
     215             : 
     216             :   ! Cloud mass constituents
     217           0 :   call cnst_get_ind('CLDLIQ', ixcldliq)
     218           0 :   call cnst_get_ind('CLDICE', ixcldice)
     219             : 
     220             :   ! Input pbuf fields
     221           0 :   qrl_idx   = pbuf_get_index('QRL')
     222           0 :   wsedl_idx = pbuf_get_index('WSEDL')
     223             : 
     224             :   ! Initialize output pbuf fields
     225           0 :   if (is_first_step() .and. unicon_is_on) then
     226           0 :      call pbuf_set_field(pbuf2d, bprod_idx,    1.0e-5_r8)
     227           0 :      call pbuf_set_field(pbuf2d, ipbl_idx,     0    )
     228           0 :      call pbuf_set_field(pbuf2d, kpblh_idx,    1    )
     229           0 :      call pbuf_set_field(pbuf2d, wstarPBL_idx, 0.0_r8)
     230           0 :      call pbuf_set_field(pbuf2d, tkes_idx,     0.0_r8)
     231           0 :      call pbuf_set_field(pbuf2d, went_idx,     0.0_r8)
     232             :   end if
     233             : 
     234             :   ! Scheme-specific default output.
     235           0 :   call phys_getopts(history_amwg_out=history_amwg)
     236             : 
     237           0 :   call addfld('WGUSTD', horiz_only,  'A',          'm/s',  'wind gusts from turbulence'                            )
     238           0 :   if (history_amwg) then
     239           0 :      call add_default( 'WGUSTD  ', 1, ' ' )
     240             :   end if
     241             : 
     242             :   ! ------------------------------------------------------------------- !
     243             :   ! Writing outputs for detailed analysis of UW moist turbulence scheme !
     244             :   ! ------------------------------------------------------------------- !
     245             : 
     246           0 :   call addfld( 'BPROD',   ['ilev'],  'A',        'm2/s3',  'Buoyancy Production'                                   )
     247           0 :   call addfld( 'SFI',     ['ilev'],  'A',            '1',  'Interface-layer sat frac'                              )
     248           0 :   call addfld( 'SPROD',   ['ilev'],  'A',        'm2/s3',  'Shear Production'                                      )
     249             : 
     250             : 
     251           0 :   call addfld('UW_errorPBL',horiz_only,'A',         'm2/s',  'Error function of UW PBL')
     252           0 :   call addfld('UW_n2',        ['lev'], 'A',          's-2',  'Buoyancy Frequency, LI')
     253           0 :   call addfld('UW_s2',        ['lev'], 'A',          's-2',  'Shear Frequency, LI')
     254           0 :   call addfld('UW_ri',        ['lev'], 'A',            '1',  'Interface Richardson Number, I')
     255           0 :   call addfld('UW_sfuh',      ['lev'], 'A',            '1',  'Upper-Half Saturation Fraction, L')
     256           0 :   call addfld('UW_sflh',      ['lev'], 'A',            '1',  'Lower-Half Saturation Fraction, L')
     257           0 :   call addfld('UW_sfi',      ['ilev'], 'A',            '1',  'Interface Saturation Fraction, I')
     258           0 :   call addfld('UW_cldn',      ['lev'], 'A',            '1',  'Cloud Fraction, L')
     259           0 :   call addfld('UW_qrl',       ['lev'], 'A', 'gravity W/m2',  'LW cooling rate, L')
     260           0 :   call addfld('UW_ql',        ['lev'], 'A',        'kg/kg',  'ql(LWC), L')
     261           0 :   call addfld('UW_chu',      ['ilev'], 'A', 'gravity kg/J',  'Buoyancy Coefficient, chu, I')
     262           0 :   call addfld('UW_chs',      ['ilev'], 'A', 'gravity kg/J',  'Buoyancy Coefficient, chs, I')
     263           0 :   call addfld('UW_cmu',      ['ilev'], 'A','gravity/kg/kg',  'Buoyancy Coefficient, cmu, I')
     264           0 :   call addfld('UW_cms',      ['ilev'], 'A','gravity/kg/kg',  'Buoyancy Coefficient, cms, I')
     265           0 :   call addfld('UW_tke',      ['ilev'], 'A',        'm2/s2',  'TKE, I')
     266           0 :   call addfld('UW_wcap',     ['ilev'], 'A',        'm2/s2',  'Wcap, I')
     267           0 :   call addfld('UW_bprod',    ['ilev'], 'A',        'm2/s3',  'Buoyancy production, I')
     268           0 :   call addfld('UW_sprod',    ['ilev'], 'A',        'm2/s3',  'Shear production, I')
     269           0 :   call addfld('UW_kvh',      ['ilev'], 'A',         'm2/s',  'Eddy diffusivity of heat, I')
     270           0 :   call addfld('UW_kvm',      ['ilev'], 'A',         'm2/s',  'Eddy diffusivity of uv, I')
     271           0 :   call addfld('UW_pblh',   horiz_only, 'A',            'm',  'PBLH, 1')
     272           0 :   call addfld('UW_pblhp',  horiz_only, 'A',           'Pa',  'PBLH pressure, 1')
     273           0 :   call addfld('UW_tpert',  horiz_only, 'A',            'K',  'Convective T excess, 1')
     274           0 :   call addfld('UW_qpert',  horiz_only, 'A',        'kg/kg',  'Convective qt excess, I')
     275           0 :   call addfld('UW_wpert',  horiz_only, 'A',          'm/s',  'Convective W excess, I')
     276           0 :   call addfld('UW_ustar',  horiz_only, 'A',          'm/s',  'Surface Frictional Velocity, 1')
     277           0 :   call addfld('UW_tkes',   horiz_only, 'A',        'm2/s2',  'Surface TKE, 1')
     278           0 :   call addfld('UW_minpblh',horiz_only, 'A',            'm',  'Minimum PBLH, 1')
     279           0 :   call addfld('UW_turbtype', ['ilev'], 'A',            '1',  'Interface Turbulence Type, I')
     280           0 :   call addfld('UW_kbase_o',   ['lev'], 'A',            '1',  'Initial CL Base Exterbal Interface Index, CL')
     281           0 :   call addfld('UW_ktop_o',    ['lev'], 'A',            '1',  'Initial Top Exterbal Interface Index, CL')
     282           0 :   call addfld('UW_ncvfin_o',horiz_only,'A',            '1',  'Initial Total Number of CL regimes, CL')
     283           0 :   call addfld('UW_kbase_mg',  ['lev'], 'A',            '1',  'kbase after merging, CL')
     284           0 :   call addfld('UW_ktop_mg',   ['lev'], 'A',            '1',  'ktop after merging, CL')
     285           0 :   call addfld('UW_ncvfin_mg',horiz_only,'A',           '1',  'ncvfin after merging, CL')
     286           0 :   call addfld('UW_kbase_f',   ['lev'], 'A',            '1',  'Final kbase with SRCL, CL')
     287           0 :   call addfld('UW_ktop_f',    ['lev'], 'A',            '1',  'Final ktop with SRCL, CL')
     288           0 :   call addfld('UW_ncvfin_f',horiz_only,'A',            '1',  'Final ncvfin with SRCL, CL')
     289           0 :   call addfld('UW_wet',       ['lev'], 'A',          'm/s',  'Entrainment rate at CL top, CL')
     290           0 :   call addfld('UW_web',       ['lev'], 'A',          'm/s',  'Entrainment rate at CL base, CL')
     291           0 :   call addfld('UW_jtbu',      ['lev'], 'A',         'm/s2',  'Buoyancy jump across CL top, CL')
     292           0 :   call addfld('UW_jbbu',      ['lev'], 'A',         'm/s2',  'Buoyancy jump across CL base, CL')
     293           0 :   call addfld('UW_evhc',      ['lev'], 'A',            '1',  'Evaporative enhancement factor, CL')
     294           0 :   call addfld('UW_jt2slv',    ['lev'], 'A',         'J/kg',  'slv jump for evhc, CL')
     295           0 :   call addfld('UW_n2ht',      ['lev'], 'A',          's-2',  'n2 at just below CL top interface, CL')
     296           0 :   call addfld('UW_n2hb',      ['lev'], 'A',          's-2',  'n2 at just above CL base interface')
     297           0 :   call addfld('UW_lwp',       ['lev'], 'A',        'kg/m2',  'LWP in the CL top layer, CL')
     298           0 :   call addfld('UW_optdepth',  ['lev'], 'A',            '1',  'Optical depth of the CL top layer, CL')
     299           0 :   call addfld('UW_radfrac',   ['lev'], 'A',            '1',  'Fraction of radiative cooling confined in the CL top')
     300           0 :   call addfld('UW_radf',      ['lev'], 'A',        'm2/s3',  'Buoyancy production at the CL top by radf, I')
     301           0 :   call addfld('UW_wstar',     ['lev'], 'A',          'm/s',  'Convective velocity, Wstar, CL')
     302           0 :   call addfld('UW_wstar3fact',['lev'], 'A',            '1',  'Enhancement of wstar3 due to entrainment, CL')
     303           0 :   call addfld('UW_ebrk',      ['lev'], 'A',        'm2/s2',  'CL-averaged TKE, CL')
     304           0 :   call addfld('UW_wbrk',      ['lev'], 'A',        'm2/s2',  'CL-averaged W, CL')
     305           0 :   call addfld('UW_lbrk',      ['lev'], 'A',            'm',  'CL internal thickness, CL')
     306           0 :   call addfld('UW_ricl',      ['lev'], 'A',            '1',  'CL-averaged Ri, CL')
     307           0 :   call addfld('UW_ghcl',      ['lev'], 'A',            '1',  'CL-averaged gh, CL')
     308           0 :   call addfld('UW_shcl',      ['lev'], 'A',            '1',  'CL-averaged sh, CL')
     309           0 :   call addfld('UW_smcl',      ['lev'], 'A',            '1',  'CL-averaged sm, CL')
     310           0 :   call addfld('UW_gh',       ['ilev'], 'A',            '1',  'gh at all interfaces, I')
     311           0 :   call addfld('UW_sh',       ['ilev'], 'A',            '1',  'sh at all interfaces, I')
     312           0 :   call addfld('UW_sm',       ['ilev'], 'A',            '1',  'sm at all interfaces, I')
     313           0 :   call addfld('UW_ria',      ['ilev'], 'A',            '1',  'ri at all interfaces, I')
     314           0 :   call addfld('UW_leng',     ['ilev'], 'A',          'm/s',  'Turbulence length scale, I')
     315             :   ! For sedimentation-entrainment feedback analysis
     316           0 :   call addfld('UW_wsed',      ['lev'], 'A',          'm/s',  'Sedimentation velocity at CL top, CL')
     317             : 
     318           0 : end subroutine eddy_diff_init
     319             : 
     320           0 : subroutine eddy_diff_tend(state, pbuf, cam_in, &
     321             :      ztodt, p, tint, rhoi, cldn, wstarent, &
     322             :      kvm_in, kvh_in, ksrftms, dragblj,tauresx, tauresy, &
     323             :      rrho, ustar, pblh, kvm, kvh, kvq, cgh, cgs, tpert, qpert, &
     324             :      tke, sprod, sfi)
     325             : 
     326           0 :   use physics_types, only: physics_state
     327             :   use camsrfexch, only: cam_in_t
     328             :   use coords_1d, only: Coords1D
     329             : 
     330             :   type(physics_state), intent(in) :: state
     331             :   type(physics_buffer_desc), pointer, intent(in) :: pbuf(:)
     332             :   type(cam_in_t), intent(in) :: cam_in
     333             :   real(r8), intent(in) :: ztodt
     334             :   type(Coords1D), intent(in) :: p
     335             :   real(r8), intent(in) :: tint(pcols,pver+1)
     336             :   real(r8), intent(in) :: rhoi(pcols,pver+1)
     337             :   real(r8), intent(in) :: cldn(pcols,pver)
     338             :   logical, intent(in) :: wstarent
     339             :   real(r8), intent(in) :: kvm_in(pcols,pver+1)
     340             :   real(r8), intent(in) :: kvh_in(pcols,pver+1)
     341             :   real(r8), intent(in) :: ksrftms(pcols)
     342             :   real(r8), intent(in) :: dragblj(pcols,pver)       ! Drag profile from Beljaars SGO form drag [ 1/s ]
     343             :   real(r8), intent(inout) :: tauresx(pcols)
     344             :   real(r8), intent(inout) :: tauresy(pcols)
     345             :   real(r8), intent(out) :: rrho(pcols)
     346             :   real(r8), intent(out) :: ustar(pcols)
     347             :   real(r8), intent(out) :: pblh(pcols)
     348             :   real(r8), intent(out) :: kvm(pcols,pver+1)
     349             :   real(r8), intent(out) :: kvh(pcols,pver+1)
     350             :   real(r8), intent(out) :: kvq(pcols,pver+1)
     351             :   real(r8), intent(out) :: cgh(pcols,pver+1)
     352             :   real(r8), intent(out) :: cgs(pcols,pver+1)
     353             :   real(r8), intent(out) :: tpert(pcols)
     354             :   real(r8), intent(out) :: qpert(pcols)
     355             :   real(r8), intent(out) :: tke(pcols,pver+1)
     356             :   real(r8), intent(out) :: sprod(pcols,pver+1)
     357             :   real(r8), intent(out) :: sfi(pcols,pver+1)
     358             : 
     359             :   integer :: i, k
     360             : 
     361             :   call compute_eddy_diff( pbuf, state%lchnk    ,                                     &
     362             :        pcols    , pver        , state%ncol       , state%t    , tint, state%q(:,:,1) , ztodt   , &
     363             :        state%q(:,:,ixcldliq)  , state%q(:,:,ixcldice)   ,                            &
     364             :        state%s  , p           , rhoi, cldn       , &
     365             :        state%zm , state%zi    , state%pmid , state%pint , state%u        , state%v , &
     366             :        cam_in%wsx, cam_in%wsy , cam_in%shf , cam_in%cflx(:,1) , wstarent           , &
     367             :        rrho     , ustar       , pblh       , kvm_in     , kvh_in         , kvm     , &
     368             :        kvh      , kvq         , cgh        ,                                         &
     369             :        cgs      , tpert       , qpert      , tke            ,                        &
     370             :        sprod    , sfi         ,                                                      &
     371           0 :        tauresx  , tauresy     , ksrftms    , dragblj )
     372             : 
     373             :   ! The diffusivities from diag_TKE can be much larger than from HB in the free
     374             :   ! troposphere and upper atmosphere. These seem to be larger than observations,
     375             :   ! and in WACCM the gw_drag code is already applying an eddy diffusivity in the
     376             :   ! upper atmosphere. Optionally, adjust the diffusivities in the free troposphere
     377             :   ! or the upper atmosphere.
     378             :   !
     379             :   ! NOTE: Further investigation should be done as to why the diffusivities are
     380             :   ! larger in diag_TKE.
     381           0 :   if ((kv_freetrop_scale /= 1._r8) .or. ((kv_top_scale /= 1._r8) .and. (kv_top_pressure > 0._r8))) then
     382           0 :      do i = 1, state%ncol
     383           0 :         do k = 1, pverp
     384             :            ! Outside of the boundary layer?
     385           0 :            if (state%zi(i,k) > pblh(i)) then
     386             :               ! In the upper atmosphere?
     387           0 :               if (state%pint(i,k) <= kv_top_pressure) then
     388           0 :                  kvh(i,k) = kvh(i,k) * kv_top_scale
     389           0 :                  kvm(i,k) = kvm(i,k) * kv_top_scale
     390           0 :                  kvq(i,k) = kvq(i,k) * kv_top_scale
     391             :               else
     392           0 :                  kvh(i,k) = kvh(i,k) * kv_freetrop_scale
     393           0 :                  kvm(i,k) = kvm(i,k) * kv_freetrop_scale
     394           0 :                  kvq(i,k) = kvq(i,k) * kv_freetrop_scale
     395             :               end if
     396             :            else
     397             :               exit
     398             :            end if
     399             :         end do
     400             :      end do
     401             :   end if
     402             : 
     403           0 : end subroutine eddy_diff_tend
     404             : 
     405             : !=============================================================================== !
     406             : !                                                                                !
     407             : !=============================================================================== !
     408             : 
     409           0 : subroutine compute_eddy_diff( pbuf, lchnk  ,                                                      &
     410           0 :                               pcols  , pver   , ncol     , t       , tint, qv       , ztodt   ,   &
     411           0 :                               ql     , qi     , s        , p       , rhoi, cldn     ,             &
     412           0 :                               z      , zi     , pmid     , pi      , u        , v       ,         &
     413           0 :                               taux   , tauy   , shflx    , qflx    , wstarent ,           rrho  , &
     414           0 :                               ustar  , pblh   , kvm_in   , kvh_in  , kvm_out  , kvh_out , kvq   , &
     415           0 :                               cgh    , cgs    , tpert    , qpert   , tke     ,                    &
     416           0 :                               sprod  , sfi    ,                                                   &
     417           0 :                               tauresx, tauresy, ksrftms, dragblj )
     418             : 
     419             :   !-------------------------------------------------------------------- !
     420             :   ! Purpose: Interface to compute eddy diffusivities.                   !
     421             :   !          Eddy diffusivities are calculated in a fully implicit way  !
     422             :   !          through iteration process.                                 !
     423             :   ! Author:  Sungsu Park. August. 2006.                                 !
     424             :   !                       May.    2008.                                 !
     425             :   !-------------------------------------------------------------------- !
     426             : 
     427           0 :   use diffusion_solver, only: compute_vdiff
     428             :   use cam_history,      only: outfld
     429             :   use phys_debug_util,  only: phys_debug_col
     430             :   use air_composition,  only: cpairv
     431             :   use pbl_utils,        only: calc_ustar, austausch_atm
     432             :   use error_messages,   only: handle_errmsg
     433             :   use coords_1d,        only: Coords1D
     434             :   use wv_saturation,    only: qsat
     435             :   use eddy_diff,        only: trbintd, caleddy
     436             :   use physics_buffer,   only: pbuf_get_field
     437             : 
     438             :   ! --------------- !
     439             :   ! Input Variables !
     440             :   ! --------------- !
     441             : 
     442             :   type(physics_buffer_desc), pointer, intent(in) :: pbuf(:)
     443             :   integer,  intent(in)    :: lchnk
     444             :   integer,  intent(in)    :: pcols                     ! Number of atmospheric columns [ # ]
     445             :   integer,  intent(in)    :: pver                      ! Number of atmospheric layers  [ # ]
     446             :   integer,  intent(in)    :: ncol                      ! Number of atmospheric columns [ # ]
     447             :   logical,  intent(in)    :: wstarent                  ! .true. means use the 'wstar' entrainment closure.
     448             :   real(r8), intent(in)    :: ztodt                     ! Physics integration time step 2 delta-t [ s ]
     449             :   real(r8), intent(in)    :: t(pcols,pver)             ! Temperature [ K ]
     450             :   real(r8), intent(in)    :: tint(pcols,pver+1)        ! Temperature defined on interfaces [ K ]
     451             :   real(r8), intent(in)    :: qv(pcols,pver)            ! Water vapor  specific humidity [ kg/kg ]
     452             :   real(r8), intent(in)    :: ql(pcols,pver)            ! Liquid water specific humidity [ kg/kg ]
     453             :   real(r8), intent(in)    :: qi(pcols,pver)            ! Ice specific humidity [ kg/kg ]
     454             :   real(r8), intent(in)    :: s(pcols,pver)             ! Dry static energy [ J/kg ]
     455             :   type(Coords1D), intent(in) :: p                      ! Pressure coordinates for solver [ Pa ]
     456             :   real(r8), intent(in)    :: rhoi(pcols,pver+1)        ! Density at interfaces [ kg/m3 ]
     457             :   real(r8), intent(in)    :: cldn(pcols,pver)          ! Stratiform cloud fraction [ fraction ]
     458             :   real(r8), intent(in)    :: z(pcols,pver)             ! Layer mid-point height above surface [ m ]
     459             :   real(r8), intent(in)    :: zi(pcols,pver+1)          ! Interface height above surface [ m ]
     460             :   real(r8), intent(in)    :: pmid(pcols,pver)          ! Layer mid-point pressure [ Pa ]
     461             :   real(r8), intent(in)    :: pi(pcols,pver+1)          ! Interface pressure [ Pa ]
     462             :   real(r8), intent(in)    :: u(pcols,pver)             ! Zonal velocity [ m/s ]
     463             :   real(r8), intent(in)    :: v(pcols,pver)             ! Meridional velocity [ m/s ]
     464             :   real(r8), intent(in)    :: taux(pcols)               ! Zonal wind stress at surface [ N/m2 ]
     465             :   real(r8), intent(in)    :: tauy(pcols)               ! Meridional wind stress at surface [ N/m2 ]
     466             :   real(r8), intent(in)    :: shflx(pcols)              ! Sensible heat flux at surface [ unit ? ]
     467             :   real(r8), intent(in)    :: qflx(pcols)               ! Water vapor flux at surface [ unit ? ]
     468             :   real(r8), intent(in)    :: kvm_in(pcols,pver+1)      ! kvm saved from last timestep [ m2/s ]
     469             :   real(r8), intent(in)    :: kvh_in(pcols,pver+1)      ! kvh saved from last timestep [ m2/s ]
     470             :   real(r8), intent(in)    :: ksrftms(pcols)            ! Surface drag coefficient of turbulent mountain stress [ unit ? ]
     471             :   real(r8), intent(in)    :: dragblj(pcols,pver)       ! Drag profile from Beljaars SGO form drag [ 1/s ]
     472             : 
     473             :   ! ---------------- !
     474             :   ! Output Variables !
     475             :   ! ---------------- !
     476             : 
     477             :   real(r8), intent(out)   :: kvm_out(pcols,pver+1)     ! Eddy diffusivity for momentum [ m2/s ]
     478             :   real(r8), intent(out)   :: kvh_out(pcols,pver+1)     ! Eddy diffusivity for heat [ m2/s ]
     479             :   real(r8), intent(out)   :: kvq(pcols,pver+1)         ! Eddy diffusivity for constituents, moisture and tracers [ m2/s ]
     480             :                                                        ! (note not having '_out')
     481             :   real(r8), intent(out)   :: rrho(pcols)               ! Reciprocal of density at the lowest layer
     482             :   real(r8), intent(out)   :: ustar(pcols)              ! Surface friction velocity [ m/s ]
     483             :   real(r8), intent(out)   :: pblh(pcols)               ! PBL top height [ m ]
     484             :   real(r8), intent(out)   :: cgh(pcols,pver+1)         ! Counter-gradient term for heat [ J/kg/m ]
     485             :   real(r8), intent(out)   :: cgs(pcols,pver+1)         ! Counter-gradient star [ cg/flux ]
     486             :   real(r8), intent(out)   :: tpert(pcols)              ! Convective temperature excess [ K ]
     487             :   real(r8), intent(out)   :: qpert(pcols)              ! Convective humidity excess [ kg/kg ]
     488             :   real(r8), intent(out)   :: tke(pcols,pver+1)         ! Turbulent kinetic energy [ m2/s2 ]
     489             :   real(r8), intent(out)   :: sprod(pcols,pver+1)       ! Shear production [ m2/s3 ]
     490             :   real(r8), intent(out)   :: sfi(pcols,pver+1)         ! Interfacial layer saturation fraction [ fraction ]
     491             : 
     492             :   ! ---------------------- !
     493             :   ! Input-Output Variables !
     494             :   ! ---------------------- !
     495             : 
     496             :   real(r8), intent(inout) :: tauresx(pcols)            ! Residual stress to be added in vdiff to correct for turb
     497             :   real(r8), intent(inout) :: tauresy(pcols)            ! Stress mismatch between sfc and atm accumulated in prior timesteps
     498             : 
     499             :   ! -------------- !
     500             :   ! pbuf Variables !
     501             :   ! -------------- !
     502             : 
     503           0 :   real(r8), pointer :: qrl(:,:)                        ! LW radiative cooling rate
     504           0 :   real(r8), pointer :: wsedl(:,:)                      ! Sedimentation velocity
     505             :                                                        ! of stratiform liquid cloud droplet [ m/s ]
     506             : 
     507           0 :   real(r8), pointer :: bprod(:,:)                      ! Buoyancy production of tke [ m2/s3 ]
     508           0 :   integer(i4), pointer :: ipbl(:)                      ! If 1, PBL is CL, while if 0, PBL is STL.
     509           0 :   integer(i4), pointer :: kpblh(:)                     ! Layer index containing PBL top within or at the base interface
     510           0 :   real(r8), pointer :: wstarPBL(:)                     ! Convective velocity within PBL [ m/s ]
     511           0 :   real(r8), pointer :: tkes(:)                         ! TKE at surface interface [ m2/s2 ]
     512           0 :   real(r8), pointer :: went(:)                         ! Entrainment rate at the PBL top interface [ m/s ]
     513             : 
     514             :   ! --------------- !
     515             :   ! Local Variables !
     516             :   ! --------------- !
     517             : 
     518             :   integer                    icol
     519             :   integer                    i, k, iturb, status
     520             : 
     521             :   character(2048)         :: warnstring                ! Warning(s) to print
     522             :   character(128)          :: errstring                 ! Error message
     523             : 
     524           0 :   real(r8)                :: kvf(pcols,pver+1)         ! Free atmospheric eddy diffusivity [ m2/s ]
     525           0 :   real(r8)                :: kvm(pcols,pver+1)         ! Eddy diffusivity for momentum [ m2/s ]
     526           0 :   real(r8)                :: kvh(pcols,pver+1)         ! Eddy diffusivity for heat [ m2/s ]
     527             :   real(r8)                :: kvm_preo(pcols,pver+1)    ! Eddy diffusivity for momentum [ m2/s ]
     528             :   real(r8)                :: kvh_preo(pcols,pver+1)    ! Eddy diffusivity for heat [ m2/s ]
     529             :   real(r8)                :: kvm_pre(pcols,pver+1)     ! Eddy diffusivity for momentum [ m2/s ]
     530             :   real(r8)                :: kvh_pre(pcols,pver+1)     ! Eddy diffusivity for heat [ m2/s ]
     531           0 :   real(r8)                :: errorPBL(pcols)           ! Error function showing whether PBL produced convergent solution or not.
     532             :                                                        ! [ unit ? ]
     533           0 :   real(r8)                :: s2(pcols,pver)            ! Shear squared, defined at interfaces except surface [ s-2 ]
     534           0 :   real(r8)                :: n2(pcols,pver)            ! Buoyancy frequency, defined at interfaces except surface [ s-2 ]
     535           0 :   real(r8)                :: ri(pcols,pver)            ! Richardson number, 'n2/s2', defined at interfaces except surface [ s-2 ]
     536           0 :   real(r8)                :: pblhp(pcols)              ! PBL top pressure [ Pa ]
     537           0 :   real(r8)                :: minpblh(pcols)            ! Minimum PBL height based on surface stress
     538             : 
     539           0 :   real(r8)                :: qt(pcols,pver)            ! Total specific humidity [ kg/kg ]
     540           0 :   real(r8)                :: sfuh(pcols,pver)          ! Saturation fraction in upper half-layer [ fraction ]
     541           0 :   real(r8)                :: sflh(pcols,pver)          ! Saturation fraction in lower half-layer [ fraction ]
     542           0 :   real(r8)                :: sl(pcols,pver)            ! Liquid water static energy [ J/kg ]
     543           0 :   real(r8)                :: slv(pcols,pver)           ! Liquid water virtual static energy [ J/kg ]
     544           0 :   real(r8)                :: slslope(pcols,pver)       ! Slope of 'sl' in each layer
     545           0 :   real(r8)                :: qtslope(pcols,pver)       ! Slope of 'qt' in each layer
     546           0 :   real(r8)                :: qvfd(pcols,pver)          ! Specific humidity for diffusion [ kg/kg ]
     547           0 :   real(r8)                :: tfd(pcols,pver)           ! Temperature for diffusion [ K ]
     548           0 :   real(r8)                :: slfd(pcols,pver)          ! Liquid static energy [ J/kg ]
     549           0 :   real(r8)                :: qtfd(pcols,pver)          ! Total specific humidity [ kg/kg ]
     550           0 :   real(r8)                :: qlfd(pcols,pver)          ! Liquid water specific humidity for diffusion [ kg/kg ]
     551           0 :   real(r8)                :: ufd(pcols,pver)           ! U-wind for diffusion [ m/s ]
     552           0 :   real(r8)                :: vfd(pcols,pver)           ! V-wind for diffusion [ m/s ]
     553             : 
     554             :   ! Buoyancy coefficients : w'b' = ch * w'sl' + cm * w'qt'
     555             : 
     556           0 :   real(r8)                :: chu(pcols,pver+1)         ! Heat buoyancy coef for dry states, defined at each interface, finally.
     557           0 :   real(r8)                :: chs(pcols,pver+1)         ! Heat buoyancy coef for sat states, defined at each interface, finally.
     558           0 :   real(r8)                :: cmu(pcols,pver+1)         ! Moisture buoyancy coef for dry states,
     559             :                                                        ! defined at each interface, finally.
     560           0 :   real(r8)                :: cms(pcols,pver+1)         ! Moisture buoyancy coef for sat states,
     561             :                                                        ! defined at each interface, finally.
     562             : 
     563           0 :   real(r8)                :: jnk1d(pcols)
     564           0 :   real(r8)                :: jnk2d(pcols,pver+1)
     565           0 :   real(r8)                :: zero(pcols)
     566           0 :   real(r8)                :: zero2d(pcols,pver+1)
     567             :   real(r8)                :: es                     ! Saturation vapor pressure
     568             :   real(r8)                :: qs                     ! Saturation specific humidity
     569             :   real(r8)                :: ep2, templ, temps
     570             : 
     571             :   ! ------------------------------- !
     572             :   ! Variables for diagnostic output !
     573             :   ! ------------------------------- !
     574             : 
     575           0 :   real(r8)                :: wpert(pcols)              ! Turbulent velocity excess [ m/s ]
     576             : 
     577           0 :   real(r8)                :: kbase_o(pcols,ncvmax)     ! Original external base interface index of CL from 'exacol'
     578           0 :   real(r8)                :: ktop_o(pcols,ncvmax)      ! Original external top  interface index of CL from 'exacol'
     579           0 :   real(r8)                :: ncvfin_o(pcols)           ! Original number of CLs from 'exacol'
     580           0 :   real(r8)                :: kbase_mg(pcols,ncvmax)    ! 'kbase' after extending-merging from 'zisocl'
     581           0 :   real(r8)                :: ktop_mg(pcols,ncvmax)     ! 'ktop' after extending-merging from 'zisocl'
     582           0 :   real(r8)                :: ncvfin_mg(pcols)          ! 'ncvfin' after extending-merging from 'zisocl'
     583           0 :   real(r8)                :: kbase_f(pcols,ncvmax)     ! Final 'kbase' after extending-merging & including SRCL
     584           0 :   real(r8)                :: ktop_f(pcols,ncvmax)      ! Final 'ktop' after extending-merging & including SRCL
     585           0 :   real(r8)                :: ncvfin_f(pcols)           ! Final 'ncvfin' after extending-merging & including SRCL
     586           0 :   real(r8)                :: wet(pcols,ncvmax)         ! Entrainment rate at the CL top  [ m/s ]
     587           0 :   real(r8)                :: web(pcols,ncvmax)         ! Entrainment rate at the CL base [ m/s ].
     588             :                                                        ! Set to zero if CL is based at surface.
     589           0 :   real(r8)                :: jtbu(pcols,ncvmax)        ! Buoyancy jump across the CL top  [ m/s2 ]
     590           0 :   real(r8)                :: jbbu(pcols,ncvmax)        ! Buoyancy jump across the CL base [ m/s2 ]
     591           0 :   real(r8)                :: evhc(pcols,ncvmax)        ! Evaporative enhancement factor at the CL top
     592           0 :   real(r8)                :: jt2slv(pcols,ncvmax)      ! Jump of slv ( across two layers ) at CL top used only for evhc [ J/kg ]
     593           0 :   real(r8)                :: n2ht(pcols,ncvmax)        ! n2 defined at the CL top  interface but using
     594             :                                                        ! sfuh(kt)   instead of sfi(kt) [ s-2 ]
     595           0 :   real(r8)                :: n2hb(pcols,ncvmax)        ! n2 defined at the CL base interface but using
     596             :                                                        ! sflh(kb-1) instead of sfi(kb) [ s-2 ]
     597           0 :   real(r8)                :: lwp(pcols,ncvmax)         ! LWP in the CL top layer [ kg/m2 ]
     598           0 :   real(r8)                :: opt_depth(pcols,ncvmax)   ! Optical depth of the CL top layer
     599           0 :   real(r8)                :: radinvfrac(pcols,ncvmax)  ! Fraction of radiative cooling confined in the top portion of CL top layer
     600           0 :   real(r8)                :: radf(pcols,ncvmax)        ! Buoyancy production at the CL top due to LW radiative cooling [ m2/s3 ]
     601           0 :   real(r8)                :: wstar(pcols,ncvmax)       ! Convective velocity in each CL [ m/s ]
     602           0 :   real(r8)                :: wstar3fact(pcols,ncvmax)  ! Enhancement of 'wstar3' due to entrainment (inverse) [ no unit ]
     603           0 :   real(r8)                :: ebrk(pcols,ncvmax)        ! Net mean TKE of CL including entrainment effect [ m2/s2 ]
     604           0 :   real(r8)                :: wbrk(pcols,ncvmax)        ! Net mean normalized TKE (W) of CL,
     605             :                                                        ! 'ebrk/b1' including entrainment effect [ m2/s2 ]
     606           0 :   real(r8)                :: lbrk(pcols,ncvmax)        ! Energetic internal thickness of CL [m]
     607           0 :   real(r8)                :: ricl(pcols,ncvmax)        ! CL internal mean Richardson number
     608           0 :   real(r8)                :: ghcl(pcols,ncvmax)        ! Half of normalized buoyancy production of CL
     609           0 :   real(r8)                :: shcl(pcols,ncvmax)        ! Galperin instability function of heat-moisture of CL
     610           0 :   real(r8)                :: smcl(pcols,ncvmax)        ! Galperin instability function of mementum of CL
     611           0 :   real(r8)                :: ghi(pcols,pver+1)         ! Half of normalized buoyancy production at all interfaces
     612           0 :   real(r8)                :: shi(pcols,pver+1)         ! Galperin instability function of heat-moisture at all interfaces
     613           0 :   real(r8)                :: smi(pcols,pver+1)         ! Galperin instability function of heat-moisture at all interfaces
     614           0 :   real(r8)                :: rii(pcols,pver+1)         ! Interfacial Richardson number defined at all interfaces
     615           0 :   real(r8)                :: lengi(pcols,pver+1)       ! Turbulence length scale at all interfaces [ m ]
     616           0 :   real(r8)                :: wcap(pcols,pver+1)        ! Normalized TKE at all interfaces [ m2/s2 ]
     617             :   ! For sedimentation-entrainment feedback
     618           0 :   real(r8)                :: wsed(pcols,ncvmax)        ! Sedimentation velocity at the top of each CL [ m/s ]
     619             : 
     620           0 :   integer(i4)             :: turbtype(pcols,pver+1)    ! Turbulence type identifier at all interfaces [ no unit ]
     621             : 
     622             :   ! ---------- !
     623             :   ! Parameters !
     624             :   ! ---------- !
     625             : 
     626             :   logical,          parameter :: use_kvf        =  .false.      ! .true. (.false.) : initialize kvh/kvm =  kvf ( 0. )
     627             :   real(r8),         parameter :: lambda         =   0.5_r8      ! Under-relaxation factor ( 0 < lambda =< 1 )
     628             : 
     629             :   ! ---------- !
     630             :   ! Initialize !
     631             :   ! ---------- !
     632             : 
     633           0 :   zero(:)     = 0._r8
     634           0 :   zero2d(:,:) = 0._r8
     635             : 
     636             :   ! ---------------------------------------------- !
     637             :   ! Get LW radiative heating out of physics buffer !
     638             :   ! ---------------------------------------------- !
     639           0 :   call pbuf_get_field(pbuf, qrl_idx,   qrl)
     640           0 :   call pbuf_get_field(pbuf, wsedl_idx, wsedl)
     641             : 
     642             :   ! These fields are put into the pbuf for UNICON only.
     643           0 :   if (unicon_is_on) then
     644           0 :      call pbuf_get_field(pbuf, bprod_idx,    bprod)
     645           0 :      call pbuf_get_field(pbuf, ipbl_idx,     ipbl)
     646           0 :      call pbuf_get_field(pbuf, kpblh_idx,    kpblh)
     647           0 :      call pbuf_get_field(pbuf, wstarPBL_idx, wstarPBL)
     648           0 :      call pbuf_get_field(pbuf, tkes_idx,     tkes)
     649           0 :      call pbuf_get_field(pbuf, went_idx,     went)
     650             :   else
     651           0 :      allocate(bprod(pcols,pverp), ipbl(pcols), kpblh(pcols), wstarPBL(pcols), tkes(pcols), went(pcols))
     652             :   end if
     653             : 
     654             :   ! ----------------------- !
     655             :   ! Main Computation Begins !
     656             :   ! ----------------------- !
     657             : 
     658           0 :   ufd(:ncol,:)  = u(:ncol,:)
     659           0 :   vfd(:ncol,:)  = v(:ncol,:)
     660           0 :   tfd(:ncol,:)  = t(:ncol,:)
     661           0 :   qvfd(:ncol,:) = qv(:ncol,:)
     662           0 :   qlfd(:ncol,:) = ql(:ncol,:)
     663             : 
     664           0 :   do iturb = 1, nturb
     665             : 
     666             :      ! Total stress includes 'tms'.
     667             :      ! Here, in computing 'tms', we can use either iteratively changed 'ufd,vfd' or the
     668             :      ! initially given 'u,v' to the PBL scheme. Note that normal stress, 'taux, tauy'
     669             :      ! are not changed by iteration. In order to treat 'tms' in a fully implicit way,
     670             :      ! I am using updated wind, here.
     671             : 
     672             :      ! Compute ustar
     673             :      call calc_ustar( ncol, tfd(:ncol,pver), pmid(:ncol,pver), &
     674           0 :                       taux(:ncol) - ksrftms(:ncol) * ufd(:ncol,pver), & ! Zonal wind stress
     675             :                       tauy(:ncol) - ksrftms(:ncol) * vfd(:ncol,pver), & ! Meridional wind stress
     676           0 :                       rrho(:ncol), ustar(:ncol))
     677           0 :      minpblh(:ncol) = 100.0_r8 * ustar(:ncol)   ! By construction, 'minpblh' is larger than 1 [m] when 'ustar_min = 0.01'.
     678             : 
     679             :      ! Calculate (qt,sl,n2,s2,ri) from a given set of (t,qv,ql,qi,u,v)
     680             : 
     681             :      call trbintd( &
     682             :                    pcols    , pver    , ncol  , z       , ufd     , vfd     , tfd   , pmid    , &
     683             :                    s2       , n2      , ri    , zi      , pi      , cldn    , qtfd  , qvfd    , &
     684             :                    qlfd     , qi      , sfi   , sfuh    , sflh    , slfd    , slv   , slslope , &
     685           0 :                    qtslope  , chs     , chu   , cms     , cmu     )
     686             : 
     687             :      ! Save initial (i.e., before iterative diffusion) profile of (qt,sl) at each iteration.
     688             :      ! Only necessary for (qt,sl) not (u,v) because (qt,sl) are newly calculated variables.
     689             : 
     690           0 :      if( iturb == 1 ) then
     691           0 :         qt(:ncol,:) = qtfd(:ncol,:)
     692           0 :         sl(:ncol,:) = slfd(:ncol,:)
     693             :      endif
     694             : 
     695             :      ! Get free atmosphere exchange coefficients. This 'kvf' is not used in UW moist PBL scheme
     696             :      if (use_kvf) then
     697             :         call austausch_atm(pcols, ncol, pver, ntop_eddy, nbot_eddy, &
     698             :              ml2, ri, s2, kvf )
     699             :      else
     700           0 :         kvf = 0._r8
     701             :      end if
     702             : 
     703             :      ! Initialize kvh/kvm to send to caleddy, depending on model timestep and iteration number
     704             :      ! This is necessary for 'wstar-based' entrainment closure.
     705             : 
     706           0 :      if( iturb == 1 ) then
     707           0 :         if( is_first_step() ) then
     708             :            ! First iteration of first model timestep : Use free tropospheric value or zero.
     709           0 :            kvh(:ncol,:) = kvf(:ncol,:)
     710           0 :            kvm(:ncol,:) = kvf(:ncol,:)
     711             :         else
     712             :            ! First iteration on any model timestep except the first : Use value from previous timestep
     713           0 :            kvh(:ncol,:) = kvh_in(:ncol,:)
     714           0 :            kvm(:ncol,:) = kvm_in(:ncol,:)
     715             :         endif
     716             :      else
     717             :         ! Not the first iteration : Use from previous iteration
     718           0 :         kvh(:ncol,:) = kvh_out(:ncol,:)
     719           0 :         kvm(:ncol,:) = kvm_out(:ncol,:)
     720             :      endif
     721             : 
     722             :      ! Calculate eddy diffusivity (kvh_out,kvm_out) and (tke,bprod,sprod) using
     723             :      ! a given (kvh,kvm) which are used only for initializing (bprod,sprod)  at
     724             :      ! the first part of caleddy. (bprod,sprod) are fully updated at the end of
     725             :      ! caleddy after calculating (kvh_out,kvm_out)
     726             : 
     727             :      call caleddy( pcols     , pver      , ncol      ,                     &
     728             :                    slfd      , qtfd      , qlfd      , slv      ,ufd     , &
     729             :                    vfd       , pi        , z         , zi       ,          &
     730             :                    qflx      , shflx     , slslope   , qtslope  ,          &
     731             :                    chu       , chs       , cmu       , cms      ,sfuh    , &
     732             :                    sflh      , n2        , s2        , ri       ,rrho    , &
     733             :                    pblh      , ustar     ,                                 &
     734             :                    kvh       , kvm       , kvh_out   , kvm_out  ,          &
     735             :                    tpert     , qpert     , qrl       , kvf      , tke    , &
     736             :                    wstarent  , bprod     , sprod     , minpblh  , wpert  , &
     737             :                    tkes      , went      , turbtype  ,                     &
     738             :                    kbase_o   , ktop_o    , ncvfin_o  ,                     &
     739             :                    kbase_mg  , ktop_mg   , ncvfin_mg ,                     &
     740             :                    kbase_f   , ktop_f    , ncvfin_f  ,                     &
     741             :                    wet       , web       , jtbu      , jbbu     ,          &
     742             :                    evhc      , jt2slv    , n2ht      , n2hb     ,          &
     743             :                    lwp       , opt_depth , radinvfrac, radf     ,          &
     744             :                    wstar     , wstar3fact,                                 &
     745             :                    ebrk      , wbrk      , lbrk      , ricl     , ghcl   , &
     746             :                    shcl      , smcl      , ghi       , shi      , smi    , &
     747             :                    rii       , lengi     , wcap      , pblhp    , cldn   , &
     748             :                    ipbl      , kpblh     , wsedl     , wsed, &
     749           0 :                    warnstring, errstring)
     750             : 
     751           0 :      if (trim(warnstring) /= "") then
     752           0 :         write(iulog,*) "eddy_diff_cam: Messages from caleddy follow."
     753           0 :         write(iulog,*) warnstring
     754             :      end if
     755             : 
     756           0 :      call handle_errmsg(errstring, subname="caleddy")
     757             : 
     758             :      ! Calculate errorPBL to check whether PBL produced convergent solutions or not.
     759             : 
     760           0 :      if( iturb == nturb ) then
     761           0 :         do i = 1, ncol
     762           0 :            errorPBL(i) = 0._r8
     763           0 :            do k = 1, pver
     764           0 :               errorPBL(i) = errorPBL(i) + ( kvh(i,k) - kvh_out(i,k) )**2
     765             :            end do
     766           0 :            errorPBL(i) = sqrt(errorPBL(i)/pver)
     767             :         end do
     768             :      end if
     769             : 
     770             :      ! Eddy diffusivities which will be used for the initialization of (bprod,
     771             :      ! sprod) in 'caleddy' at the next iteration step.
     772             : 
     773           0 :      if( iturb > 1 .and. iturb < nturb ) then
     774           0 :         kvm_out(:ncol,:) = lambda * kvm_out(:ncol,:) + ( 1._r8 - lambda ) * kvm(:ncol,:)
     775           0 :         kvh_out(:ncol,:) = lambda * kvh_out(:ncol,:) + ( 1._r8 - lambda ) * kvh(:ncol,:)
     776             :      endif
     777             : 
     778             :      ! Set nonlocal terms to zero for flux diagnostics, since not used by caleddy.
     779             : 
     780           0 :      cgh(:ncol,:) = 0._r8
     781           0 :      cgs(:ncol,:) = 0._r8
     782             : 
     783           0 :      if( iturb < nturb ) then
     784             : 
     785             :         ! Each time we diffuse the original state
     786             : 
     787           0 :         slfd(:ncol,:)  = sl(:ncol,:)
     788           0 :         qtfd(:ncol,:)  = qt(:ncol,:)
     789           0 :         ufd(:ncol,:)   = u(:ncol,:)
     790           0 :         vfd(:ncol,:)   = v(:ncol,:)
     791             : 
     792             :         ! Diffuse initial profile of each time step using a given (kvh_out,kvm_out)
     793             :         ! In the below 'compute_vdiff', (slfd,qtfd,ufd,vfd) are 'inout' variables.
     794             : 
     795             :         call compute_vdiff( lchnk   ,                                                  &
     796             :                             pcols   , pver     , 1        , ncol         , tint, &
     797             :                             p        , t        , rhoi, ztodt        , taux      , &
     798             :                             tauy    , shflx    , qflx     , &
     799             :                             kvh_out , kvm_out  , kvh_out  , cgs          , cgh       , &
     800             :                             zi      , ksrftms  , dragblj  , & 
     801             :                             zero    , fieldlist_wet, fieldlist_molec, &
     802             :                             ufd     , vfd      , qtfd     , slfd         ,             &
     803             :                             jnk1d   , jnk1d    , jnk2d    , jnk1d        , errstring , &
     804             :                             tauresx , tauresy  , 0        , cpairv(:,:,lchnk), zero, &
     805           0 :                             .false., .false. )
     806             : 
     807             :         call handle_errmsg(errstring, subname="compute_vdiff", &
     808           0 :              extra_msg="compute_vdiff called from eddy_diff_cam")
     809             : 
     810             :         ! Retrieve (tfd,qvfd,qlfd) from (slfd,qtfd) in order to
     811             :         ! use 'trbintd' at the next iteration.
     812             : 
     813           0 :         do k = 1, pver
     814           0 :            do i = 1, ncol
     815             :               ! ----------------------------------------------------- !
     816             :               ! Compute the condensate 'qlfd' in the updated profiles !
     817             :               ! ----------------------------------------------------- !
     818             :               ! Option.1 : Assume grid-mean condensate is homogeneously diffused by the moist turbulence scheme.
     819             :               !            This should be used if 'pseudodiff = .false.' in vertical_diffusion.F90.
     820             :               ! Modification : Need to be check whether below is correct in the presence of ice, qi.
     821             :               !                I should understand why the variation of ice, qi is neglected during diffusion.
     822           0 :               templ     = ( slfd(i,k) - gravit*z(i,k) ) / cpair
     823           0 :               call qsat( templ, pmid(i,k), es, qs)
     824           0 :               ep2       =  .622_r8
     825           0 :               temps     =   templ + ( qtfd(i,k) - qs ) / ( cpair / latvap + latvap * qs / ( rair * templ**2 ) )
     826           0 :               call qsat( temps, pmid(i,k), es, qs)
     827           0 :               qlfd(i,k) =   max( qtfd(i,k) - qi(i,k) - qs ,0._r8 )
     828             :               ! Option.2 : Assume condensate is not diffused by the moist turbulence scheme.
     829             :               !            This should bs used if 'pseudodiff = .true.'  in vertical_diffusion.F90.
     830             :               ! qlfd(i,k) = ql(i,k)
     831             :               ! ----------------------------- !
     832             :               ! Compute the other 'qvfd, tfd' !
     833             :               ! ----------------------------- !
     834           0 :               qvfd(i,k) = max( 0._r8, qtfd(i,k) - qi(i,k) - qlfd(i,k) )
     835           0 :               tfd(i,k)  = ( slfd(i,k) + latvap * qlfd(i,k) + (latvap+latice) * qi(i,k) - gravit*z(i,k)) / cpair
     836             :            end do
     837             :         end do
     838             :      endif
     839             : 
     840             :   end do  ! End of 'iturb' iteration
     841             : 
     842           0 :   kvq(:ncol,:) = kvh_out(:ncol,:)
     843             : 
     844             :   ! Compute 'wstar' within the PBL for use in the future convection scheme.
     845             : 
     846           0 :   do i = 1, ncol
     847           0 :      if(ipbl(i) == 1) then
     848           0 :         wstarPBL(i) = max( 0._r8, wstar(i,1) )
     849             :      else
     850           0 :         wstarPBL(i) = 0._r8
     851             :      endif
     852             :   end do
     853             : 
     854             :   ! --------------------------------------------------------------- !
     855             :   ! Writing for detailed diagnostic analysis of UW moist PBL scheme !
     856             :   ! --------------------------------------------------------------- !
     857             : 
     858           0 :   call outfld( 'WGUSTD' , wpert, pcols, lchnk )
     859             : 
     860           0 :   call outfld( 'BPROD   ', bprod, pcols, lchnk )
     861           0 :   call outfld( 'SPROD   ', sprod, pcols, lchnk )
     862           0 :   call outfld( 'SFI     ', sfi,   pcols, lchnk )
     863             : 
     864           0 :   call outfld( 'UW_errorPBL',    errorPBL,   pcols,   lchnk )
     865             : 
     866           0 :   call outfld( 'UW_n2',          n2,         pcols,   lchnk )
     867           0 :   call outfld( 'UW_s2',          s2,         pcols,   lchnk )
     868           0 :   call outfld( 'UW_ri',          ri,         pcols,   lchnk )
     869             : 
     870           0 :   call outfld( 'UW_sfuh',        sfuh,       pcols,   lchnk )
     871           0 :   call outfld( 'UW_sflh',        sflh,       pcols,   lchnk )
     872           0 :   call outfld( 'UW_sfi',         sfi,        pcols,   lchnk )
     873             : 
     874           0 :   call outfld( 'UW_cldn',        cldn,       pcols,   lchnk )
     875           0 :   call outfld( 'UW_qrl',         qrl,        pcols,   lchnk )
     876           0 :   call outfld( 'UW_ql',          qlfd,       pcols,   lchnk )
     877             : 
     878           0 :   call outfld( 'UW_chu',         chu,        pcols,   lchnk )
     879           0 :   call outfld( 'UW_chs',         chs,        pcols,   lchnk )
     880           0 :   call outfld( 'UW_cmu',         cmu,        pcols,   lchnk )
     881           0 :   call outfld( 'UW_cms',         cms,        pcols,   lchnk )
     882             : 
     883           0 :   call outfld( 'UW_tke',         tke,        pcols,   lchnk )
     884           0 :   call outfld( 'UW_wcap',        wcap,       pcols,   lchnk )
     885           0 :   call outfld( 'UW_bprod',       bprod,      pcols,   lchnk )
     886           0 :   call outfld( 'UW_sprod',       sprod,      pcols,   lchnk )
     887             : 
     888           0 :   call outfld( 'UW_kvh',         kvh_out,    pcols,   lchnk )
     889           0 :   call outfld( 'UW_kvm',         kvm_out,    pcols,   lchnk )
     890             : 
     891           0 :   call outfld( 'UW_pblh',        pblh,       pcols,   lchnk )
     892           0 :   call outfld( 'UW_pblhp',       pblhp,      pcols,   lchnk )
     893           0 :   call outfld( 'UW_tpert',       tpert,      pcols,   lchnk )
     894           0 :   call outfld( 'UW_qpert',       qpert,      pcols,   lchnk )
     895           0 :   call outfld( 'UW_wpert',       wpert,      pcols,   lchnk )
     896             : 
     897           0 :   call outfld( 'UW_ustar',       ustar,      pcols,   lchnk )
     898           0 :   call outfld( 'UW_tkes',        tkes,       pcols,   lchnk )
     899           0 :   call outfld( 'UW_minpblh',     minpblh,    pcols,   lchnk )
     900             : 
     901           0 :   call outfld( 'UW_turbtype',    real(turbtype,r8),   pcols,   lchnk )
     902             : 
     903           0 :   call outfld( 'UW_kbase_o',     kbase_o,    pcols,   lchnk )
     904           0 :   call outfld( 'UW_ktop_o',      ktop_o,     pcols,   lchnk )
     905           0 :   call outfld( 'UW_ncvfin_o',    ncvfin_o,   pcols,   lchnk )
     906             : 
     907           0 :   call outfld( 'UW_kbase_mg',    kbase_mg,   pcols,   lchnk )
     908           0 :   call outfld( 'UW_ktop_mg',     ktop_mg,    pcols,   lchnk )
     909           0 :   call outfld( 'UW_ncvfin_mg',   ncvfin_mg,  pcols,   lchnk )
     910             : 
     911           0 :   call outfld( 'UW_kbase_f',     kbase_f,    pcols,   lchnk )
     912           0 :   call outfld( 'UW_ktop_f',      ktop_f,     pcols,   lchnk )
     913           0 :   call outfld( 'UW_ncvfin_f',    ncvfin_f,   pcols,   lchnk )
     914             : 
     915           0 :   call outfld( 'UW_wet',         wet,        pcols,   lchnk )
     916           0 :   call outfld( 'UW_web',         web,        pcols,   lchnk )
     917           0 :   call outfld( 'UW_jtbu',        jtbu,       pcols,   lchnk )
     918           0 :   call outfld( 'UW_jbbu',        jbbu,       pcols,   lchnk )
     919           0 :   call outfld( 'UW_evhc',        evhc,       pcols,   lchnk )
     920           0 :   call outfld( 'UW_jt2slv',      jt2slv,     pcols,   lchnk )
     921           0 :   call outfld( 'UW_n2ht',        n2ht,       pcols,   lchnk )
     922           0 :   call outfld( 'UW_n2hb',        n2hb,       pcols,   lchnk )
     923           0 :   call outfld( 'UW_lwp',         lwp,        pcols,   lchnk )
     924           0 :   call outfld( 'UW_optdepth',    opt_depth,  pcols,   lchnk )
     925           0 :   call outfld( 'UW_radfrac',     radinvfrac, pcols,   lchnk )
     926           0 :   call outfld( 'UW_radf',        radf,       pcols,   lchnk )
     927           0 :   call outfld( 'UW_wstar',       wstar,      pcols,   lchnk )
     928           0 :   call outfld( 'UW_wstar3fact',  wstar3fact, pcols,   lchnk )
     929           0 :   call outfld( 'UW_ebrk',        ebrk,       pcols,   lchnk )
     930           0 :   call outfld( 'UW_wbrk',        wbrk,       pcols,   lchnk )
     931           0 :   call outfld( 'UW_lbrk',        lbrk,       pcols,   lchnk )
     932           0 :   call outfld( 'UW_ricl',        ricl,       pcols,   lchnk )
     933           0 :   call outfld( 'UW_ghcl',        ghcl,       pcols,   lchnk )
     934           0 :   call outfld( 'UW_shcl',        shcl,       pcols,   lchnk )
     935           0 :   call outfld( 'UW_smcl',        smcl,       pcols,   lchnk )
     936             : 
     937           0 :   call outfld( 'UW_gh',          ghi,        pcols,   lchnk )
     938           0 :   call outfld( 'UW_sh',          shi,        pcols,   lchnk )
     939           0 :   call outfld( 'UW_sm',          smi,        pcols,   lchnk )
     940           0 :   call outfld( 'UW_ria',         rii,        pcols,   lchnk )
     941           0 :   call outfld( 'UW_leng',        lengi,      pcols,   lchnk )
     942             : 
     943           0 :   call outfld( 'UW_wsed',        wsed,       pcols,   lchnk )
     944             : 
     945           0 :   if (.not. unicon_is_on) then
     946           0 :      deallocate(bprod, ipbl, kpblh, wstarPBL, tkes, went)
     947             :   end if
     948             : 
     949           0 : end subroutine compute_eddy_diff
     950             : 
     951             : end module eddy_diff_cam

Generated by: LCOV version 1.14