LCOV - code coverage report
Current view: top level - physics/cam - ref_pres.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 43 49 87.8 %
Date: 2024-12-17 22:39:59 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             : use cam_history_support, only: add_vert_coord
      17             : use cam_logfile,         only: iulog
      18             : use error_messages,      only: alloc_err
      19             : 
      20             : implicit none
      21             : public
      22             : save
      23             : 
      24             : ! Reference pressures (Pa)
      25             : real(r8), protected :: pref_edge(pverp)     ! Layer edges
      26             : real(r8), protected :: pref_mid(pver)       ! Layer midpoints
      27             : real(r8), protected :: pref_mid_norm(pver)  ! Layer midpoints normalized by
      28             :                                             ! surface pressure ('eta' coordinate)
      29             : 
      30             : real(r8), protected :: ptop_ref             ! Top of model
      31             : real(r8), protected :: psurf_ref            ! reference pressure
      32             : 
      33             : ! Number of top levels using pure pressure representation
      34             : integer, protected :: num_pr_lev
      35             : 
      36             : ! Pressure used to set troposphere cloud physics top (Pa)
      37             : real(r8), protected :: trop_cloud_top_press = 0._r8
      38             : ! Top level for troposphere cloud physics
      39             : integer, protected :: trop_cloud_top_lev
      40             : 
      41             : ! Pressure used to set MAM process top (Pa)
      42             : real(r8), protected :: clim_modal_aero_top_press = 0._r8
      43             : ! Top level for MAM processes that impact climate
      44             : integer, protected :: clim_modal_aero_top_lev
      45             : 
      46             : ! Molecular diffusion is calculated only if the model top is below this
      47             : ! pressure (Pa).
      48             : real(r8), protected :: do_molec_press = 0.1_r8
      49             : ! Pressure used to set bottom of molecular diffusion region (Pa).
      50             : real(r8), protected :: molec_diff_bot_press = 50._r8
      51             : ! Flag for molecular diffusion, and molecular diffusion level index.
      52             : logical, protected :: do_molec_diff = .false.
      53             : integer, protected :: nbot_molec = 0
      54             : 
      55             : ! Data for the trop_pref coordinate.  It is the target of a pointer in a hist_coord_t
      56             : ! object in the cam_history_support module.  It is associated by the call to add_vert_coord.
      57             : real(r8), private, allocatable, target :: trop_pref(:)
      58             : real(r8), private, allocatable, target :: trop_prefi(:)
      59             : 
      60             : !====================================================================================
      61             : contains
      62             : !====================================================================================
      63             : 
      64        1536 : subroutine ref_pres_readnl(nlfile)
      65             : 
      66             :    use spmd_utils,      only: masterproc
      67             :    use cam_abortutils,  only: endrun
      68             :    use namelist_utils,  only: find_group_name
      69             :    use units,           only: getunit, freeunit
      70             :    use mpishorthand
      71             : 
      72             :    character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
      73             : 
      74             :    ! Local variables
      75             :    integer :: unitn, ierr
      76             :    character(len=*), parameter :: subname = 'ref_pres_readnl'
      77             : 
      78             :    namelist /ref_pres_nl/ trop_cloud_top_press, clim_modal_aero_top_press,&
      79             :         do_molec_press, molec_diff_bot_press
      80             :    !-----------------------------------------------------------------------------
      81             : 
      82        1536 :    if (masterproc) then
      83           2 :       unitn = getunit()
      84           2 :       open( unitn, file=trim(nlfile), status='old' )
      85           2 :       call find_group_name(unitn, 'ref_pres_nl', status=ierr)
      86           2 :       if (ierr == 0) then
      87           2 :          read(unitn, ref_pres_nl, iostat=ierr)
      88           2 :          if (ierr /= 0) then
      89           0 :             call endrun(subname // ':: ERROR reading namelist')
      90             :          end if
      91             :       end if
      92           2 :       close(unitn)
      93           2 :       call freeunit(unitn)
      94             : 
      95             :       ! Check that top for modal aerosols is not lower than
      96             :       ! top for clouds.
      97           2 :       if (clim_modal_aero_top_press > trop_cloud_top_press) &
      98             :            call endrun("ERROR: clim_modal_aero_top press must be less &
      99           0 :            &than or equal to trop_cloud_top_press.")
     100             :    end if
     101             : 
     102             : #ifdef SPMD
     103             :    ! Broadcast namelist variables
     104        1536 :    call mpibcast(trop_cloud_top_press,            1 , mpir8,   0, mpicom)
     105        1536 :    call mpibcast(clim_modal_aero_top_press,       1 , mpir8,   0, mpicom)
     106        1536 :    call mpibcast(do_molec_press,                  1 , mpir8,   0, mpicom)
     107        1536 :    call mpibcast(molec_diff_bot_press,            1 , mpir8,   0, mpicom)
     108             : #endif
     109             : 
     110        1536 : end subroutine ref_pres_readnl
     111             : 
     112             : !====================================================================================
     113             : 
     114        1536 : subroutine ref_pres_init(pref_edge_in, pref_mid_in, num_pr_lev_in)
     115             : 
     116             :    ! Initialize reference pressures
     117             : 
     118             :    ! arguments
     119             :    real(r8), intent(in) :: pref_edge_in(:) ! reference pressure at layer edges (Pa)
     120             :    real(r8), intent(in) :: pref_mid_in(:)  ! reference pressure at layer midpoints (Pa)
     121             :    integer,  intent(in) :: num_pr_lev_in   ! number of top levels using pure pressure representation
     122             : 
     123             :    ! local variables
     124             :    integer :: nlev
     125             :    integer :: istat
     126             :    character(len=*), parameter :: sub = 'ref_pres_init'
     127             :    !---------------------------------------------------------------------------
     128             : 
     129      145920 :    pref_edge = pref_edge_in
     130      144384 :    pref_mid  = pref_mid_in
     131        1536 :    num_pr_lev = num_pr_lev_in
     132             : 
     133        1536 :    ptop_ref = pref_edge(1)
     134        1536 :    psurf_ref = pref_edge(pverp)
     135             : 
     136      144384 :    pref_mid_norm = pref_mid/psurf_ref
     137             : 
     138             :    ! Find level corresponding to the top of troposphere clouds.
     139             :    trop_cloud_top_lev = press_lim_idx(trop_cloud_top_press, &
     140        1536 :       top=.true.)
     141             : 
     142             :    ! Find level corresponding to the top for MAM processes.
     143             :    clim_modal_aero_top_lev = press_lim_idx(clim_modal_aero_top_press, &
     144        1536 :       top=.true.)
     145             : 
     146             :    ! Find level corresponding to the molecular diffusion bottom.
     147        1536 :    do_molec_diff = (ptop_ref < do_molec_press)
     148        1536 :    if (do_molec_diff) then
     149             :       nbot_molec = press_lim_idx(molec_diff_bot_press, &
     150           0 :          top=.false.)
     151             :    end if
     152             : 
     153             :    ! Add vertical coordinates to history file for use with outputs that are only
     154             :    ! computed in the subdomain bounded by the top of troposphere clouds.
     155        1536 :    nlev = pver - trop_cloud_top_lev + 1
     156             : 
     157        4608 :    allocate(trop_pref(nlev), stat=istat)
     158        1536 :    call alloc_err(istat, sub, 'trop_pref', nlev)
     159      132096 :    trop_pref  = pref_mid(trop_cloud_top_lev:)*0.01_r8 ! convert Pa to hPa
     160             : 
     161             :    call add_vert_coord('trop_pref', nlev, 'troposphere reference pressures', &
     162        1536 :       'hPa', trop_pref, positive='down')
     163             : 
     164        4608 :    allocate(trop_prefi(nlev+1), stat=istat)
     165        1536 :    call alloc_err(istat, sub, 'trop_prefi', nlev+1)
     166      133632 :    trop_prefi = pref_edge(trop_cloud_top_lev:)*0.01_r8 ! convert Pa to hPa
     167             : 
     168             :    call add_vert_coord('trop_prefi', nlev+1, 'troposphere reference pressures (interfaces)', &
     169        1536 :       'hPa', trop_prefi, positive='down')
     170             : 
     171        1536 : end subroutine ref_pres_init
     172             : 
     173             : !====================================================================================
     174             : 
     175             : ! Convert pressure limiters to the appropriate level.
     176        3072 : pure function press_lim_idx(p, top) result(k_lim)
     177             :   ! Pressure
     178             :   real(r8), intent(in) :: p
     179             :   ! Is this a top or bottom limit?
     180             :   logical,  intent(in) :: top
     181             :   integer :: k_lim, k
     182             : 
     183        3072 :   if (top) then
     184       16896 :      k_lim = pver+1
     185       16896 :      do k = 1, pver
     186       16896 :         if (pref_mid(k) > p) then
     187             :            k_lim = k
     188             :            exit
     189             :         end if
     190             :      end do
     191             :   else
     192           0 :      k_lim = 0
     193           0 :      do k = pver, 1, -1
     194           0 :         if (pref_mid(k) < p) then
     195             :            k_lim = k
     196             :            exit
     197             :         end if
     198             :      end do
     199             :   end if
     200             : 
     201        3072 : end function press_lim_idx
     202             : 
     203             : !====================================================================================
     204             : 
     205             : end module ref_pres

Generated by: LCOV version 1.14