LCOV - code coverage report
Current view: top level - physics/cam - ref_pres.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 34 40 85.0 %
Date: 2025-03-13 18:42:46 Functions: 3 3 100.0 %

          Line data    Source code
       1             : module ref_pres
       2             : !--------------------------------------------------------------------------
       3             : !
       4             : ! Provides access to reference pressures for use by the physics
       5             : ! parameterizations.  The pressures are provided by the dynamical core
       6             : ! since it determines the grid used by the physics.
       7             : !
       8             : ! Note that the init method for this module is called before the init
       9             : ! method in physpkg; therefore, most physics modules can use these
      10             : ! reference pressures during their init phases.
      11             : !
      12             : !--------------------------------------------------------------------------
      13             : 
      14             : use shr_kind_mod, only: r8=>shr_kind_r8
      15             : use ppgrid,       only: pver, pverp
      16             : 
      17             : implicit none
      18             : public
      19             : save
      20             : 
      21             : ! Reference pressures (Pa)
      22             : real(r8), protected :: pref_edge(pverp)     ! Layer edges
      23             : real(r8), protected :: pref_mid(pver)       ! Layer midpoints
      24             : real(r8), protected :: pref_mid_norm(pver)  ! Layer midpoints normalized by
      25             :                                             ! surface pressure ('eta' coordinate)
      26             : 
      27             : real(r8), protected :: ptop_ref             ! Top of model
      28             : real(r8), protected :: psurf_ref            ! reference pressure
      29             : 
      30             : ! Number of top levels using pure pressure representation
      31             : integer, protected :: num_pr_lev
      32             : 
      33             : ! Pressure used to set troposphere cloud physics top (Pa)
      34             : real(r8), protected :: trop_cloud_top_press = 0._r8
      35             : ! Top level for troposphere cloud physics
      36             : integer, protected :: trop_cloud_top_lev
      37             : 
      38             : ! Pressure used to set MAM process top (Pa)
      39             : real(r8), protected :: clim_modal_aero_top_press = 0._r8
      40             : ! Top level for MAM processes that impact climate
      41             : integer, protected :: clim_modal_aero_top_lev
      42             : 
      43             : ! Molecular diffusion is calculated only if the model top is below this
      44             : ! pressure (Pa).
      45             : real(r8), protected :: do_molec_press = 0.1_r8
      46             : ! Pressure used to set bottom of molecular diffusion region (Pa).
      47             : real(r8), protected :: molec_diff_bot_press = 50._r8
      48             : ! Flag for molecular diffusion, and molecular diffusion level index.
      49             : logical, protected :: do_molec_diff = .false.
      50             : integer, protected :: nbot_molec = 0
      51             : 
      52             : !====================================================================================
      53             : contains
      54             : !====================================================================================
      55             : 
      56        1536 : subroutine ref_pres_readnl(nlfile)
      57             : 
      58             :    use spmd_utils,      only: masterproc
      59             :    use cam_abortutils,  only: endrun
      60             :    use namelist_utils,  only: find_group_name
      61             :    use units,           only: getunit, freeunit
      62             :    use mpishorthand
      63             : 
      64             :    character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
      65             : 
      66             :    ! Local variables
      67             :    integer :: unitn, ierr
      68             :    character(len=*), parameter :: subname = 'ref_pres_readnl'
      69             : 
      70             :    namelist /ref_pres_nl/ trop_cloud_top_press, clim_modal_aero_top_press,&
      71             :         do_molec_press, molec_diff_bot_press
      72             :    !-----------------------------------------------------------------------------
      73             : 
      74        1536 :    if (masterproc) then
      75           2 :       unitn = getunit()
      76           2 :       open( unitn, file=trim(nlfile), status='old' )
      77           2 :       call find_group_name(unitn, 'ref_pres_nl', status=ierr)
      78           2 :       if (ierr == 0) then
      79           2 :          read(unitn, ref_pres_nl, iostat=ierr)
      80           2 :          if (ierr /= 0) then
      81           0 :             call endrun(subname // ':: ERROR reading namelist')
      82             :          end if
      83             :       end if
      84           2 :       close(unitn)
      85           2 :       call freeunit(unitn)
      86             : 
      87             :       ! Check that top for modal aerosols is not lower than
      88             :       ! top for clouds.
      89           2 :       if (clim_modal_aero_top_press > trop_cloud_top_press) &
      90             :            call endrun("ERROR: clim_modal_aero_top press must be less &
      91           0 :            &than or equal to trop_cloud_top_press.")
      92             :    end if
      93             : 
      94             : #ifdef SPMD
      95             :    ! Broadcast namelist variables
      96        1536 :    call mpibcast(trop_cloud_top_press,            1 , mpir8,   0, mpicom)
      97        1536 :    call mpibcast(clim_modal_aero_top_press,       1 , mpir8,   0, mpicom)
      98        1536 :    call mpibcast(do_molec_press,                  1 , mpir8,   0, mpicom)
      99        1536 :    call mpibcast(molec_diff_bot_press,            1 , mpir8,   0, mpicom)
     100             : #endif
     101             : 
     102        1536 : end subroutine ref_pres_readnl
     103             : 
     104             : !====================================================================================
     105             : 
     106        1536 : subroutine ref_pres_init(pref_edge_in, pref_mid_in, num_pr_lev_in)
     107             : 
     108             :    ! Initialize reference pressures
     109             : 
     110             :    ! arguments
     111             :    real(r8), intent(in) :: pref_edge_in(:) ! reference pressure at layer edges (Pa)
     112             :    real(r8), intent(in) :: pref_mid_in(:)  ! reference pressure at layer midpoints (Pa)
     113             :    integer,  intent(in) :: num_pr_lev_in   ! number of top levels using pure pressure representation
     114             :    !---------------------------------------------------------------------------
     115             : 
     116      145920 :    pref_edge = pref_edge_in
     117      144384 :    pref_mid  = pref_mid_in
     118        1536 :    num_pr_lev = num_pr_lev_in
     119             : 
     120        1536 :    ptop_ref = pref_edge(1)
     121        1536 :    psurf_ref = pref_edge(pverp)
     122             : 
     123      144384 :    pref_mid_norm = pref_mid/psurf_ref
     124             : 
     125             :    ! Find level corresponding to the top of troposphere clouds.
     126             :    trop_cloud_top_lev = press_lim_idx(trop_cloud_top_press, &
     127        1536 :       top=.true.)
     128             : 
     129             :    ! Find level corresponding to the top for MAM processes.
     130             :    clim_modal_aero_top_lev = press_lim_idx(clim_modal_aero_top_press, &
     131        1536 :       top=.true.)
     132             : 
     133             :    ! Find level corresponding to the molecular diffusion bottom.
     134        1536 :    do_molec_diff = (ptop_ref < do_molec_press)
     135        1536 :    if (do_molec_diff) then
     136             :       nbot_molec = press_lim_idx(molec_diff_bot_press, &
     137           0 :          top=.false.)
     138             :    end if
     139             : 
     140        1536 : end subroutine ref_pres_init
     141             : 
     142             : !====================================================================================
     143             : 
     144             : ! Convert pressure limiters to the appropriate level.
     145        3072 : pure function press_lim_idx(p, top) result(k_lim)
     146             :   ! Pressure
     147             :   real(r8), intent(in) :: p
     148             :   ! Is this a top or bottom limit?
     149             :   logical,  intent(in) :: top
     150             :   integer :: k_lim, k
     151             : 
     152        3072 :   if (top) then
     153       16896 :      k_lim = pver+1
     154       16896 :      do k = 1, pver
     155       16896 :         if (pref_mid(k) > p) then
     156             :            k_lim = k
     157             :            exit
     158             :         end if
     159             :      end do
     160             :   else
     161           0 :      k_lim = 0
     162           0 :      do k = pver, 1, -1
     163           0 :         if (pref_mid(k) < p) then
     164             :            k_lim = k
     165             :            exit
     166             :         end if
     167             :      end do
     168             :   end if
     169             : 
     170        3072 : end function press_lim_idx
     171             : 
     172             : !====================================================================================
     173             : 
     174             : end module ref_pres

Generated by: LCOV version 1.14