LCOV - code coverage report
Current view: top level - atmos_phys/schemes/check_energy - check_energy_chng.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 105 135 77.8 %
Date: 2025-03-14 01:23:43 Functions: 3 3 100.0 %

          Line data    Source code
       1             : module check_energy_chng
       2             :   use ccpp_kinds, only: kind_phys
       3             : 
       4             :   implicit none
       5             :   private
       6             : 
       7             :   public  :: check_energy_chng_init
       8             :   public  :: check_energy_chng_timestep_init
       9             :   public  :: check_energy_chng_run
      10             : 
      11             :   ! Private module options.
      12             :   logical :: print_energy_errors = .false.    ! Turn on verbose output identifying columns that fail
      13             :                                               ! energy/water checks?
      14             : 
      15             : contains
      16             : 
      17             : !> \section arg_table_check_energy_chng_init Argument Table
      18             : !! \htmlinclude arg_table_check_energy_chng_init.html
      19        1536 :   subroutine check_energy_chng_init(print_energy_errors_in)
      20             :     ! Input arguments
      21             :     logical,            intent(in)    :: print_energy_errors_in
      22             : 
      23        1536 :     print_energy_errors = print_energy_errors_in
      24        1536 :   end subroutine check_energy_chng_init
      25             : 
      26             :   ! Compute initial values of energy and water integrals,
      27             :   ! and zero out cumulative boundary tendencies.
      28             : !> \section arg_table_check_energy_chng_timestep_init Argument Table
      29             : !! \htmlinclude arg_table_check_energy_chng_timestep_init.html
      30       80640 :   subroutine check_energy_chng_timestep_init( &
      31             :        ncol, pver, pcnst, &
      32             :        is_first_timestep, &
      33       80640 :        q, pdel, &
      34       80640 :        u, v, T, &
      35       80640 :        pintdry, phis, zm, &
      36       80640 :        cp_phys, &              ! cpairv generally, cpair fixed size for subcolumns code
      37       80640 :        cp_or_cv_dycore, &
      38      161280 :        te_ini_phys, te_ini_dyn, &
      39       80640 :        tw_ini, &
      40       80640 :        te_cur_phys, te_cur_dyn, &
      41       80640 :        tw_cur, &
      42       80640 :        tend_te_tnd, tend_tw_tnd, &
      43       80640 :        temp_ini, z_ini, &
      44             :        count, &
      45       80640 :        teout, &
      46             :        energy_formula_physics, energy_formula_dycore, &
      47       80640 :        errmsg, errflg)
      48             : 
      49             :     ! This scheme is non-portable due to dependencies on cam_thermo
      50             :     ! for hydrostatic energy calculation (physics and dycore formulas)
      51             :     use cam_thermo,         only: get_hydrostatic_energy
      52             :     use cam_thermo_formula, only: ENERGY_FORMULA_DYCORE_SE, ENERGY_FORMULA_DYCORE_MPAS
      53             : 
      54             :     ! Input arguments
      55             :     integer,            intent(in)    :: ncol           ! number of atmospheric columns
      56             :     integer,            intent(in)    :: pver           ! number of vertical layers
      57             :     integer,            intent(in)    :: pcnst          ! number of ccpp constituents
      58             :     logical,            intent(in)    :: is_first_timestep ! is first step of initial run?
      59             :     real(kind_phys),    intent(in)    :: q(:,:,:)       ! constituent mass mixing ratios [kg kg-1]
      60             :     real(kind_phys),    intent(in)    :: pdel(:,:)      ! layer thickness [Pa]
      61             :     real(kind_phys),    intent(in)    :: u(:,:)         ! zonal wind [m s-1]
      62             :     real(kind_phys),    intent(in)    :: v(:,:)         ! meridional wind [m s-1]
      63             :     real(kind_phys),    intent(in)    :: T(:,:)         ! temperature [K]
      64             :     real(kind_phys),    intent(in)    :: pintdry(:,:)   ! interface pressure dry [Pa]
      65             :     real(kind_phys),    intent(in)    :: phis(:)        ! surface geopotential [m2 s-2]
      66             :     real(kind_phys),    intent(in)    :: zm(:,:)        ! geopotential height at layer midpoints [m]
      67             :     real(kind_phys),    intent(in)    :: cp_phys(:,:)   ! enthalpy (cpairv generally) [J kg-1 K-1]
      68             :     real(kind_phys),    intent(in)    :: cp_or_cv_dycore(:,:)  ! enthalpy or heat capacity, dycore dependent [J K-1 kg-1]
      69             :     integer,            intent(in)    :: energy_formula_physics! total energy formulation physics
      70             :     integer,            intent(in)    :: energy_formula_dycore ! total energy formulation dycore
      71             : 
      72             :     ! Output arguments
      73             :     real(kind_phys),    intent(out)   :: temp_ini(:,:)  ! initial temperature [K]
      74             :     real(kind_phys),    intent(out)   :: z_ini(:,:)     ! initial geopotential height [m]
      75             :     integer,            intent(out)   :: count          ! count of values with significant energy or water imbalances [1]
      76             :     real(kind_phys),    intent(out)   :: teout(:)       ! total energy for global fixer in next timestep [J m-2]
      77             :     real(kind_phys),    intent(out)   :: tend_te_tnd(:) ! total energy tendency [J m-2 s-1]
      78             :     real(kind_phys),    intent(out)   :: tend_tw_tnd(:) ! total water tendency [kg m-2 s-1]
      79             : 
      80             :     ! Input/Output arguments
      81             :     real(kind_phys),    intent(inout) :: te_ini_phys(:) ! physics formula: initial total energy [J m-2]
      82             :     real(kind_phys),    intent(inout) :: te_ini_dyn (:) ! dycore  formula: initial total energy [J m-2]
      83             :     real(kind_phys),    intent(inout) :: tw_ini     (:) ! initial total water [kg m-2]
      84             :     real(kind_phys),    intent(inout) :: te_cur_phys(:) ! physics formula: current total energy [J m-2]
      85             :     real(kind_phys),    intent(inout) :: te_cur_dyn (:) ! dycore  formula: current total energy [J m-2]
      86             :     real(kind_phys),    intent(inout) :: tw_cur     (:) ! current total water [kg m-2]
      87             : 
      88             :     ! Output arguments
      89             :     character(len=512), intent(out)   :: errmsg         ! error message
      90             :     integer,            intent(out)   :: errflg         ! error flag
      91             : 
      92       80640 :     errmsg = ''
      93       80640 :     errflg = 0
      94             : 
      95             :     !------------------------------------------------
      96             :     ! Physics total energy.
      97             :     !------------------------------------------------
      98             :     call get_hydrostatic_energy(                           &
      99      241920 :         tracer             = q(1:ncol,1:pver,1:pcnst),     & ! moist mixing ratios
     100             :         moist_mixing_ratio = .true.,                       &
     101      161280 :         pdel_in            = pdel       (1:ncol,1:pver),   &
     102      161280 :         cp_or_cv           = cp_phys    (1:ncol,1:pver),   &
     103      161280 :         U                  = u          (1:ncol,1:pver),   &
     104      161280 :         V                  = v          (1:ncol,1:pver),   &
     105      161280 :         T                  = T          (1:ncol,1:pver),   &
     106             :         vcoord             = energy_formula_physics,       & ! energy formula for physics
     107       80640 :         ptop               = pintdry    (1:ncol,1),        &
     108       80640 :         phis               = phis       (1:ncol),          &
     109       80640 :         te                 = te_ini_phys(1:ncol),          & ! vertically integrated total energy
     110       80640 :         H2O                = tw_ini     (1:ncol)           & ! v.i. total water
     111     1451520 :     )
     112             : 
     113             :     ! Save initial state temperature and geopotential height for use in run phase
     114    87091200 :     temp_ini(:ncol,:) = T (:ncol, :)
     115    87091200 :     z_ini   (:ncol,:) = zm(:ncol, :)
     116             : 
     117             :     !------------------------------------------------
     118             :     ! Dynamical core total energy.
     119             :     !------------------------------------------------
     120       80640 :     if (energy_formula_dycore == ENERGY_FORMULA_DYCORE_SE) then
     121             :       ! SE dycore specific hydrostatic energy (enthalpy)
     122             :       call get_hydrostatic_energy(                               &
     123             :           tracer             = q(1:ncol,1:pver,1:pcnst),         & ! moist mixing ratios
     124             :           moist_mixing_ratio = .true.,                           &
     125             :           pdel_in            = pdel           (1:ncol,1:pver),   &
     126           0 :           cp_or_cv           = cp_or_cv_dycore(1:ncol,1:pver),   &
     127             :           U                  = u              (1:ncol,1:pver),   &
     128             :           V                  = v              (1:ncol,1:pver),   &
     129             :           T                  = T              (1:ncol,1:pver),   &
     130             :           vcoord             = energy_formula_dycore,            & ! energy formula for dycore
     131             :           ptop               = pintdry        (1:ncol,1),        &
     132             :           phis               = phis           (1:ncol),          &
     133           0 :           te                 = te_ini_dyn     (1:ncol)           & ! WRITE OPERATION - vertically integrated total energy
     134           0 :       )
     135             : 
     136       80640 :     else if (energy_formula_dycore == ENERGY_FORMULA_DYCORE_MPAS) then
     137             :       ! MPAS dycore: compute cv if vertical coordinate is height: cv = cp - R (internal energy)
     138             :       call get_hydrostatic_energy(                               &
     139             :           tracer             = q(1:ncol,1:pver,1:pcnst),         & ! moist mixing ratios
     140             :           moist_mixing_ratio = .true.,                           &
     141             :           pdel_in            = pdel           (1:ncol,1:pver),   &
     142           0 :           cp_or_cv           = cp_or_cv_dycore(1:ncol,1:pver),   &
     143             :           U                  = u              (1:ncol,1:pver),   &
     144             :           V                  = v              (1:ncol,1:pver),   &
     145             :           T                  = T              (1:ncol,1:pver),   & ! enthalpy-scaled temperature for energy consistency
     146             :           vcoord             = energy_formula_dycore,            & ! energy formula for dycore
     147             :           ptop               = pintdry        (1:ncol,1),        &
     148             :           phis               = phis           (1:ncol),          &
     149             :           z_mid              = z_ini          (1:ncol,:),        & ! unique for MPAS
     150           0 :           te                 = te_ini_dyn     (1:ncol)           & ! WRITE OPERATION - vertically integrated total energy
     151           0 :       )
     152             :     else
     153             :       ! FV dycore: dycore energy is the same as physics
     154     1322496 :       te_ini_dyn(:ncol) = te_ini_phys(:ncol)
     155             :     endif
     156             : 
     157             :     ! Set current state to be the same as initial
     158     1322496 :     te_cur_phys(:ncol) = te_ini_phys(:ncol)
     159     1322496 :     te_cur_dyn (:ncol) = te_ini_dyn (:ncol)
     160     1322496 :     tw_cur     (:ncol) = tw_ini     (:ncol)
     161             : 
     162             :     ! Zero out current energy unbalances count
     163       80640 :     count = 0
     164             : 
     165             :     ! Zero out cumulative boundary fluxes
     166     1322496 :     tend_te_tnd(:ncol) = 0._kind_phys
     167     1322496 :     tend_tw_tnd(:ncol) = 0._kind_phys
     168             : 
     169             :     ! If first timestep, initialize value of teout
     170       80640 :     if(is_first_timestep) then
     171       62976 :       teout(:ncol) = te_ini_dyn(:ncol)
     172             :     endif
     173             : 
     174       80640 :   end subroutine check_energy_chng_timestep_init
     175             : 
     176             : 
     177             :   ! Check that energy and water change matches the boundary fluxes.
     178             : !> \section arg_table_check_energy_chng_run Argument Table
     179             : !! \htmlinclude arg_table_check_energy_chng_run.html
     180     1317120 :   subroutine check_energy_chng_run( &
     181             :        ncol, pver, pcnst, &
     182             :        iulog, &
     183     1317120 :        q, pdel, &
     184     1317120 :        u, v, T, &
     185     1317120 :        pintdry, phis, zm, &
     186     1317120 :        cp_phys, &              ! cpairv generally, cpair fixed size for subcolumns code
     187     2634240 :        cp_or_cv_dycore, &
     188     1317120 :        scaling_dycore, &       ! From check_energy_scaling to work around subcolumns code
     189     2634240 :        te_cur_phys, te_cur_dyn, &
     190     1317120 :        tw_cur, &
     191     1317120 :        tend_te_tnd, tend_tw_tnd, &
     192     2634240 :        temp_ini, z_ini, &
     193             :        count, ztodt, &
     194             :        latice, latvap, &
     195             :        energy_formula_physics, energy_formula_dycore, &
     196     1317120 :        name, flx_vap, flx_cnd, flx_ice, flx_sen, &
     197           0 :        errmsg, errflg)
     198             : 
     199             :     ! This scheme is non-portable due to dependencies on cam_thermo
     200             :     ! for hydrostatic energy calculation (physics and dycore formulas)
     201             :     use cam_thermo,         only: get_hydrostatic_energy
     202             : 
     203             :     ! Dependency for energy formula used by physics and dynamical cores
     204             :     use cam_thermo_formula, only: ENERGY_FORMULA_DYCORE_FV, ENERGY_FORMULA_DYCORE_SE, ENERGY_FORMULA_DYCORE_MPAS
     205             : 
     206             :     ! Input arguments
     207             :     integer,            intent(in)    :: ncol           ! number of atmospheric columns
     208             :     integer,            intent(in)    :: pver           ! number of vertical layers
     209             :     integer,            intent(in)    :: pcnst          ! number of ccpp constituents
     210             :     integer,            intent(in)    :: iulog          ! log output unit
     211             :     real(kind_phys),    intent(in)    :: q(:,:,:)       ! constituent mass mixing ratios [kg kg-1]
     212             :     real(kind_phys),    intent(in)    :: pdel(:,:)      ! layer thickness [Pa]
     213             :     real(kind_phys),    intent(in)    :: u(:,:)         ! zonal wind [m s-1]
     214             :     real(kind_phys),    intent(in)    :: v(:,:)         ! meridional wind [m s-1]
     215             :     real(kind_phys),    intent(in)    :: T(:,:)         ! temperature [K]
     216             :     real(kind_phys),    intent(in)    :: pintdry(:,:)   ! interface pressure dry [Pa]
     217             :     real(kind_phys),    intent(in)    :: phis(:)        ! surface geopotential [m2 s-2]
     218             :     real(kind_phys),    intent(in)    :: zm(:,:)        ! geopotential height at layer midpoints [m]
     219             :     real(kind_phys),    intent(in)    :: temp_ini(:,:)  ! initial temperature [K]
     220             :     real(kind_phys),    intent(in)    :: z_ini(:,:)     ! initial geopotential height [m]
     221             :     real(kind_phys),    intent(in)    :: cp_phys(:,:)   ! enthalpy (cpairv generally) [J kg-1 K-1]
     222             :     real(kind_phys),    intent(in)    :: cp_or_cv_dycore(:,:)  ! enthalpy or heat capacity, dycore dependent [J K-1 kg-1]
     223             :     real(kind_phys),    intent(in)    :: scaling_dycore(:,:)   ! scaling for conversion of temperature increment [1]
     224             :     real(kind_phys),    intent(in)    :: ztodt          ! physics timestep [s]
     225             :     real(kind_phys),    intent(in)    :: latice         ! constant, latent heat of fusion of water at 0 C [J kg-1]
     226             :     real(kind_phys),    intent(in)    :: latvap         ! constant, latent heat of vaporization of water at 0 C [J kg-1]
     227             :     integer,            intent(in)    :: energy_formula_physics! total energy formulation physics
     228             :     integer,            intent(in)    :: energy_formula_dycore ! total energy formulation dycore
     229             : 
     230             :     ! Input from CCPP-scheme being checked:
     231             :     ! parameterization name; surface fluxes of (1) vapor, (2) liquid+ice, (3) ice, (4) sensible heat
     232             :     ! to pass in the values to be checked, call check_energy_zero_input_fluxes to reset these values
     233             :     ! before a parameterization that is checked, then update these values as-needed
     234             :     ! (can be all zero; in fact, most parameterizations calling _chng call with zero arguments)
     235             :     !
     236             :     ! Original comment from BAB:
     237             :     ! Note that the precip and ice fluxes are in precip units (m/s).
     238             :     ! I would prefer to have kg/m2/s.
     239             :     ! I would also prefer liquid (not total) and ice fluxes
     240             :     character(len=*),   intent(in)    :: name           ! parameterization name for fluxes
     241             :     real(kind_phys),    intent(in)    :: flx_vap(:)     ! boundary flux of vapor [kg m-2 s-1]
     242             :     real(kind_phys),    intent(in)    :: flx_cnd(:)     ! boundary flux of liquid+ice (precip?) [m s-1]
     243             :     real(kind_phys),    intent(in)    :: flx_ice(:)     ! boundary flux of ice [m s-1]
     244             :     real(kind_phys),    intent(in)    :: flx_sen(:)     ! boundary flux of sensible heat [W m-2]
     245             : 
     246             :     ! Input/Output arguments
     247             :     real(kind_phys),    intent(inout) :: te_cur_phys(:) ! physics formula: current total energy [J m-2]
     248             :     real(kind_phys),    intent(inout) :: te_cur_dyn (:) ! dycore  formula: current total energy [J m-2]
     249             :     real(kind_phys),    intent(inout) :: tw_cur     (:) ! current total water [kg m-2]
     250             :     integer,            intent(inout) :: count          ! count of columns with significant energy or water imbalances [1]
     251             :     real(kind_phys),    intent(inout) :: tend_te_tnd(:) ! total energy tendency [J m-2 s-1]
     252             :     real(kind_phys),    intent(inout) :: tend_tw_tnd(:) ! total water tendency [kg m-2 s-1]
     253             : 
     254             :     ! Output arguments
     255             :     character(len=512), intent(out)   :: errmsg         ! error message
     256             :     integer,            intent(out)   :: errflg         ! error flag
     257             : 
     258             :     ! Local variables
     259     2634240 :     real(kind_phys) :: te_xpd(ncol)                     ! expected value (f0 + dt*boundary_flux)
     260     2634240 :     real(kind_phys) :: te_dif(ncol)                     ! energy of input state - original energy
     261     2634240 :     real(kind_phys) :: te_tnd(ncol)                     ! tendency from last process
     262     2634240 :     real(kind_phys) :: te_rer(ncol)                     ! relative error in energy column
     263             : 
     264     2634240 :     real(kind_phys) :: tw_xpd(ncol)                     ! expected value (w0 + dt*boundary_flux)
     265     2634240 :     real(kind_phys) :: tw_dif(ncol)                     ! tw_inp - original water
     266     2634240 :     real(kind_phys) :: tw_tnd(ncol)                     ! tendency from last process
     267     2634240 :     real(kind_phys) :: tw_rer(ncol)                     ! relative error in water column
     268             : 
     269     2634240 :     real(kind_phys) :: te(ncol)                         ! vertical integral of total energy
     270     2634240 :     real(kind_phys) :: tw(ncol)                         ! vertical integral of total water
     271     2634240 :     real(kind_phys) :: temp(ncol,pver)                  ! temperature
     272             : 
     273     2634240 :     real(kind_phys) :: se(ncol)                         ! enthalpy or internal energy (J/m2)
     274     2634240 :     real(kind_phys) :: po(ncol)                         ! surface potential or potential energy (J/m2)
     275     2634240 :     real(kind_phys) :: ke(ncol)                         ! kinetic energy    (J/m2)
     276     2634240 :     real(kind_phys) :: wv(ncol)                         ! column integrated vapor       (kg/m2)
     277     2634240 :     real(kind_phys) :: liq(ncol)                        ! column integrated liquid      (kg/m2)
     278     1317120 :     real(kind_phys) :: ice(ncol)                        ! column integrated ice         (kg/m2)
     279             : 
     280             :     integer :: i
     281             : 
     282     1317120 :     errmsg = ''
     283     1317120 :     errflg = 0
     284             : 
     285             :     !------------------------------------------------
     286             :     ! Physics total energy.
     287             :     !------------------------------------------------
     288             :     call get_hydrostatic_energy(                       &
     289     3951360 :         tracer             = q(1:ncol,1:pver,1:pcnst), & ! moist mixing ratios
     290             :         moist_mixing_ratio = .true.,                   &
     291     2634240 :         pdel_in            = pdel   (1:ncol,1:pver),   &
     292     2634240 :         cp_or_cv           = cp_phys(1:ncol,1:pver),   &
     293     2634240 :         U                  = u      (1:ncol,1:pver),   &
     294     2634240 :         V                  = v      (1:ncol,1:pver),   &
     295     2634240 :         T                  = T      (1:ncol,1:pver),   &
     296             :         vcoord             = energy_formula_physics,   & ! energy formula for physics
     297     1317120 :         ptop               = pintdry(1:ncol,1),        &
     298     1317120 :         phis               = phis   (1:ncol),          &
     299             :         te                 = te     (1:ncol),          & ! vertically integrated total energy
     300             :         H2O                = tw     (1:ncol),          & ! v.i. total water
     301             :         se                 = se     (1:ncol),          & ! v.i. enthalpy
     302             :         po                 = po     (1:ncol),          & ! v.i. PHIS term
     303             :         ke                 = ke     (1:ncol),          & ! v.i. kinetic energy
     304             :         wv                 = wv     (1:ncol),          & ! v.i. water vapor
     305             :         liq                = liq    (1:ncol),          & ! v.i. liquid
     306             :         ice                = ice    (1:ncol)           & ! v.i. ice
     307    21073920 :     )
     308             : 
     309             :     ! compute expected values and tendencies
     310    20283648 :     do i = 1, ncol
     311             :        ! change in static energy and total water
     312    18966528 :        te_dif(i) = te(i) - te_cur_phys(i)
     313    18966528 :        tw_dif(i) = tw(i) - tw_cur     (i)
     314             : 
     315             :        ! expected tendencies from boundary fluxes for last process
     316    18966528 :        te_tnd(i) = flx_vap(i)*(latvap+latice) - (flx_cnd(i) - flx_ice(i))*1000._kind_phys*latice + flx_sen(i)
     317    18966528 :        tw_tnd(i) = flx_vap(i) - flx_cnd(i) *1000._kind_phys
     318             : 
     319             :        ! cummulative tendencies from boundary fluxes
     320    18966528 :        tend_te_tnd(i) = tend_te_tnd(i) + te_tnd(i)
     321    18966528 :        tend_tw_tnd(i) = tend_tw_tnd(i) + tw_tnd(i)
     322             : 
     323             :        ! expected new values from previous state plus boundary fluxes
     324    18966528 :        te_xpd(i) = te_cur_phys(i) + te_tnd(i)*ztodt
     325    18966528 :        tw_xpd(i) = tw_cur     (i) + tw_tnd(i)*ztodt
     326             : 
     327             :        ! relative error, expected value - input state / previous state
     328    20283648 :        te_rer(i) = (te_xpd(i) - te(i)) / te_cur_phys(i)
     329             :     end do
     330             : 
     331             :     ! relative error for total water (allow for dry atmosphere)
     332    20283648 :     tw_rer = 0._kind_phys
     333    20283648 :     where (tw_cur(:ncol) > 0._kind_phys)
     334     1317120 :        tw_rer(:ncol) = (tw_xpd(:ncol) - tw(:ncol)) / tw_cur(:ncol)
     335             :     end where
     336             : 
     337             :     ! error checking
     338     1317120 :     if (print_energy_errors) then
     339           0 :        if (any(abs(te_rer(1:ncol)) > 1.E-14_kind_phys .or. abs(tw_rer(1:ncol)) > 1.E-10_kind_phys)) then
     340           0 :           do i = 1, ncol
     341             :              ! the relative error threshold for the water budget has been reduced to 1.e-10
     342             :              ! to avoid messages generated by QNEG3 calls
     343             :              ! PJR- change to identify if error in energy or water
     344           0 :              if (abs(te_rer(i)) > 1.E-14_kind_phys ) then
     345           0 :                 count = count + 1
     346           0 :                 write(iulog,*) "significant energy conservation error after ", name,        &
     347           0 :                       " count", count, "col", i
     348           0 :                 write(iulog,*) te(i),te_xpd(i),te_dif(i),tend_te_tnd(i)*ztodt,  &
     349           0 :                       te_tnd(i)*ztodt,te_rer(i)
     350             :              endif
     351           0 :              if ( abs(tw_rer(i)) > 1.E-10_kind_phys) then
     352           0 :                 count = count + 1
     353           0 :                 write(iulog,*) "significant water conservation error after ", name,        &
     354           0 :                       " count", count, "col", i
     355           0 :                 write(iulog,*) tw(i),tw_xpd(i),tw_dif(i),tend_tw_tnd(i)*ztodt,  &
     356           0 :                       tw_tnd(i)*ztodt,tw_rer(i)
     357             :              end if
     358             :           end do
     359             :        end if
     360             :     end if
     361             : 
     362             :     ! WRITE OPERATION - copy new value to state, including total water.
     363             :     ! the total water operations are consistent regardless of energy formula,
     364             :     ! so it only has to be written once.
     365    20283648 :     do i = 1, ncol
     366    18966528 :       te_cur_phys(i) = te(i)
     367    20283648 :       tw_cur(i)      = tw(i)
     368             :     end do
     369             : 
     370             :     !------------------------------------------------
     371             :     ! Dynamical core total energy.
     372             :     !------------------------------------------------
     373     1317120 :     if (energy_formula_dycore == ENERGY_FORMULA_DYCORE_SE) then
     374             :       ! SE dycore specific hydrostatic energy
     375             : 
     376             :       ! enthalpy scaling for energy consistency
     377           0 :       temp(1:ncol,:)   = temp_ini(1:ncol,:)+scaling_dycore(1:ncol,:)*(T(1:ncol,:)-temp_ini(1:ncol,:))
     378             : 
     379             :       call get_hydrostatic_energy(                               &
     380             :           tracer             = q(1:ncol,1:pver,1:pcnst),         & ! moist mixing ratios
     381             :           moist_mixing_ratio = .true.,                           &
     382             :           pdel_in            = pdel           (1:ncol,1:pver),   &
     383           0 :           cp_or_cv           = cp_or_cv_dycore(1:ncol,1:pver),   &
     384             :           U                  = u              (1:ncol,1:pver),   &
     385             :           V                  = v              (1:ncol,1:pver),   &
     386             :           T                  = temp           (1:ncol,1:pver),   & ! enthalpy-scaled temperature for energy consistency
     387             :           vcoord             = energy_formula_dycore,            & ! energy formula for dycore
     388             :           ptop               = pintdry        (1:ncol,1),        &
     389             :           phis               = phis           (1:ncol),          &
     390           0 :           te                 = te_cur_dyn     (1:ncol)           & ! WRITE OPERATION - vertically integrated total energy
     391           0 :       )
     392             : 
     393     1317120 :     else if (energy_formula_dycore == ENERGY_FORMULA_DYCORE_MPAS) then
     394             :       ! MPAS dycore: compute cv if vertical coordinate is height: cv = cp - R
     395             : 
     396             :       ! REMOVECAM: note this scaling is different with subcols off/on which is why it was put into separate scheme (hplin, 9/5/24)
     397           0 :       temp(1:ncol,:) = temp_ini(1:ncol,:)+scaling_dycore(1:ncol,:)*(T(1:ncol,:)-temp_ini(1:ncol,:))
     398             : 
     399             :       call get_hydrostatic_energy(                               &
     400             :           tracer             = q(1:ncol,1:pver,1:pcnst),         & ! moist mixing ratios
     401             :           moist_mixing_ratio = .true.,                           &
     402             :           pdel_in            = pdel           (1:ncol,1:pver),   &
     403           0 :           cp_or_cv           = cp_or_cv_dycore(1:ncol,1:pver),   &
     404             :           U                  = u              (1:ncol,1:pver),   &
     405             :           V                  = v              (1:ncol,1:pver),   &
     406             :           T                  = temp           (1:ncol,1:pver),   & ! enthalpy-scaled temperature for energy consistency
     407             :           vcoord             = energy_formula_dycore,            & ! energy formula for dycore
     408             :           ptop               = pintdry        (1:ncol,1),        &
     409             :           phis               = phis           (1:ncol),          &
     410           0 :           z_mid              = z_ini          (1:ncol,:),        & ! unique for MPAS
     411           0 :           te                 = te_cur_dyn     (1:ncol)           & ! WRITE OPERATION - vertically integrated total energy
     412           0 :       )
     413             : 
     414             :     else
     415             :       ! FV dycore
     416    21600768 :       te_cur_dyn(1:ncol) = te(1:ncol)
     417             :     end if
     418     1317120 :   end subroutine check_energy_chng_run
     419             : 
     420             : end module check_energy_chng

Generated by: LCOV version 1.14