From 120fc0c1b71c7d62cbaa4d85ce930bfc083368a6 Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Mon, 6 Jul 2026 20:53:30 +0000 Subject: [PATCH 1/6] Add RRTMGP to convection-permitting suite --- .../suite_convection_permitting.xml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/test/test_suites/suite_convection_permitting.xml b/test/test_suites/suite_convection_permitting.xml index 527a2b7d..1bbd7225 100644 --- a/test/test_suites/suite_convection_permitting.xml +++ b/test/test_suites/suite_convection_permitting.xml @@ -3,6 +3,8 @@ + prescribe_radiative_gas_concentrations + to_be_ccppized_temporary calc_atmosphere_layer_thickness calc_exner temp_to_potential_temp @@ -20,6 +22,53 @@ mmm_physics_compat + + rrtmgp_pre + rrtmgp_cloud_optics_setup + tropopause_find + rrtmgp_variables + rrtmgp_inputs + rrtmgp_sw_cloud_optics + rrtmgp_sw_mcica_subcol_gen + rrtmgp_cloud_diagnostics + + + rrtmgp_constituents + rrtmgp_sw_gas_optics_pre + rrtmgp_sw_gas_optics + solar_irradiance_data + rrtmgp_sw_solar_var + rrtmgp_sw_aerosols + rrtmgp_sw_rte + rrtmgp_sw_calculate_fluxes + rrtmgp_sw_calculate_heating_rate + rrtmgp_sw_diagnostics + rrtmgp_subcycle + + + rrtmgp_lw_cloud_optics + rrtmgp_lw_mcica_subcol_gen + + + rrtmgp_constituents + rrtmgp_lw_gas_optics_pre + rrtmgp_lw_gas_optics + rrtmgp_lw_aerosols + rrtmgp_lw_rte + rrtmgp_lw_calculate_fluxes + rrtmgp_lw_calculate_heating_rate + rrtmgp_lw_diagnostics + rrtmgp_subcycle + + + rrtmgp_inputs_setup + rrtmgp_sw_solar_var_setup + rrtmgp_dry_static_energy_tendency + calculate_net_heating + rrtmgp_post + rrtmgp_diagnostics + + sf_mynn_compat_pre sf_mynn_compat From 4a886d306e46cb0d99b8204f35ff758fa758438c Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Wed, 8 Jul 2026 18:07:27 +0000 Subject: [PATCH 2/6] Update standard names and add interstitial for RRTMGP --- schemes/mmm/bl_mynn_compat.meta | 8 +- schemes/mmm/cu_ntiedtke_compat.meta | 4 +- schemes/mmm/mmm_physics_compat.F90 | 40 +++++++ schemes/mmm/mmm_physics_compat.meta | 106 +++++++++++++++++- .../suite_convection_permitting.xml | 4 + 5 files changed, 152 insertions(+), 10 deletions(-) diff --git a/schemes/mmm/bl_mynn_compat.meta b/schemes/mmm/bl_mynn_compat.meta index 78eca9a1..c1ea9ba9 100644 --- a/schemes/mmm/bl_mynn_compat.meta +++ b/schemes/mmm/bl_mynn_compat.meta @@ -24,13 +24,13 @@ dimensions = () intent = in [ rthratenlw ] - standard_name = tendency_of_air_potential_temperature_due_to_longwave_heating + standard_name = tendency_of_air_potential_temperature_due_to_longwave_radiation units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = in [ rthratensw ] - standard_name = tendency_of_air_potential_temperature_due_to_shortwave_heating + standard_name = tendency_of_air_potential_temperature_due_to_shortwave_radiation units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) @@ -156,7 +156,7 @@ dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = out [ rthraten ] - standard_name = tendency_of_air_potential_temperature_due_to_radiative_heating + standard_name = tendency_of_air_potential_temperature_due_to_radiation units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) @@ -1201,7 +1201,7 @@ dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = in [ rthraten ] - standard_name = tendency_of_air_potential_temperature_due_to_radiative_heating + standard_name = tendency_of_air_potential_temperature_due_to_radiation units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) diff --git a/schemes/mmm/cu_ntiedtke_compat.meta b/schemes/mmm/cu_ntiedtke_compat.meta index c776621c..6c007517 100644 --- a/schemes/mmm/cu_ntiedtke_compat.meta +++ b/schemes/mmm/cu_ntiedtke_compat.meta @@ -30,13 +30,13 @@ dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = in [ rthratenlw ] - standard_name = tendency_of_air_potential_temperature_due_to_longwave_heating + standard_name = tendency_of_air_potential_temperature_due_to_longwave_radiation units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = in [ rthratensw ] - standard_name = tendency_of_air_potential_temperature_due_to_shortwave_heating + standard_name = tendency_of_air_potential_temperature_due_to_shortwave_radiation units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) diff --git a/schemes/mmm/mmm_physics_compat.F90 b/schemes/mmm/mmm_physics_compat.F90 index 4119c252..2204d8b7 100644 --- a/schemes/mmm/mmm_physics_compat.F90 +++ b/schemes/mmm/mmm_physics_compat.F90 @@ -14,6 +14,8 @@ module mmm_physics_compat public :: compute_hydrostatic_upward_air_velocity_run public :: geopotential_height_wrt_sfc_at_interface_to_msl_run public :: geopotential_height_wrt_sfc_to_msl_run + public :: lw_heating_rate_to_air_potential_temperature_tendency_run + public :: sw_heating_rate_to_air_potential_temperature_tendency_run contains !> \section arg_table_mmm_physics_compat_init Argument Table !! \htmlinclude mmm_physics_compat_init.html @@ -417,4 +419,42 @@ pure subroutine geopotential_height_wrt_sfc_to_msl_run( & zmmsl(i, :) = phis(i) / gravit + zmsfc(i, :) end do end subroutine geopotential_height_wrt_sfc_to_msl_run + + !> \section arg_table_lw_heating_rate_to_air_potential_temperature_tendency_run Argument Table + !! \htmlinclude lw_heating_rate_to_air_potential_temperature_tendency_run.html + pure subroutine lw_heating_rate_to_air_potential_temperature_tendency_run( & + cpairv, exner, lw_heating_rate, & + rthratenlw, & + errmsg, errflg) + use ccpp_kinds, only: kind_phys + + real(kind_phys), intent(in) :: cpairv(:, :), exner(:, :), lw_heating_rate(:, :) + real(kind_phys), intent(out) :: rthratenlw(:, :) + character(*), intent(out) :: errmsg + integer, intent(out) :: errflg + + errmsg = '' + errflg = 0 + + rthratenlw(:, :) = lw_heating_rate(:, :) / cpairv(:, :) / exner(:, :) + end subroutine lw_heating_rate_to_air_potential_temperature_tendency_run + + !> \section arg_table_sw_heating_rate_to_air_potential_temperature_tendency_run Argument Table + !! \htmlinclude sw_heating_rate_to_air_potential_temperature_tendency_run.html + pure subroutine sw_heating_rate_to_air_potential_temperature_tendency_run( & + cpairv, exner, sw_heating_rate, & + rthratensw, & + errmsg, errflg) + use ccpp_kinds, only: kind_phys + + real(kind_phys), intent(in) :: cpairv(:, :), exner(:, :), sw_heating_rate(:, :) + real(kind_phys), intent(out) :: rthratensw(:, :) + character(*), intent(out) :: errmsg + integer, intent(out) :: errflg + + errmsg = '' + errflg = 0 + + rthratensw(:, :) = sw_heating_rate(:, :) / cpairv(:, :) / exner(:, :) + end subroutine sw_heating_rate_to_air_potential_temperature_tendency_run end module mmm_physics_compat diff --git a/schemes/mmm/mmm_physics_compat.meta b/schemes/mmm/mmm_physics_compat.meta index 7548818f..81e978cc 100644 --- a/schemes/mmm/mmm_physics_compat.meta +++ b/schemes/mmm/mmm_physics_compat.meta @@ -235,13 +235,13 @@ dimensions = (horizontal_dimension, vertical_layer_dimension) intent = out [ rthratenlw ] - standard_name = tendency_of_air_potential_temperature_due_to_longwave_heating + standard_name = tendency_of_air_potential_temperature_due_to_longwave_radiation units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_dimension, vertical_layer_dimension) intent = out [ rthratensw ] - standard_name = tendency_of_air_potential_temperature_due_to_shortwave_heating + standard_name = tendency_of_air_potential_temperature_due_to_shortwave_radiation units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_dimension, vertical_layer_dimension) @@ -476,13 +476,13 @@ dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rthratenlw ] - standard_name = tendency_of_air_potential_temperature_due_to_longwave_heating + standard_name = tendency_of_air_potential_temperature_due_to_longwave_radiation units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rthratensw ] - standard_name = tendency_of_air_potential_temperature_due_to_shortwave_heating + standard_name = tendency_of_air_potential_temperature_due_to_shortwave_radiation units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) @@ -903,3 +903,101 @@ type = integer dimensions = () intent = out + +# ---------- + +[ccpp-table-properties] + name = lw_heating_rate_to_air_potential_temperature_tendency + type = scheme + +[ccpp-arg-table] + name = lw_heating_rate_to_air_potential_temperature_tendency_run + type = scheme +[ cpairv ] + standard_name = composition_dependent_specific_heat_of_dry_air_at_constant_pressure + units = J kg-1 K-1 + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + type = real | kind = kind_phys + intent = in +[ exner ] + standard_name = dimensionless_exner_function + long_name = exner function + units = 1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = in +[ lw_heating_rate ] + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_longwave_radiation + units = J kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = in +[ rthratenlw ] + standard_name = tendency_of_air_potential_temperature_due_to_longwave_radiation + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = out +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=* + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out + +# ---------- + +[ccpp-table-properties] + name = sw_heating_rate_to_air_potential_temperature_tendency + type = scheme + +[ccpp-arg-table] + name = sw_heating_rate_to_air_potential_temperature_tendency_run + type = scheme +[ cpairv ] + standard_name = composition_dependent_specific_heat_of_dry_air_at_constant_pressure + units = J kg-1 K-1 + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + type = real | kind = kind_phys + intent = in +[ exner ] + standard_name = dimensionless_exner_function + long_name = exner function + units = 1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = in +[ sw_heating_rate ] + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_shortwave_radiation + units = J kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = in +[ rthratensw ] + standard_name = tendency_of_air_potential_temperature_due_to_shortwave_radiation + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = out +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=* + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out diff --git a/test/test_suites/suite_convection_permitting.xml b/test/test_suites/suite_convection_permitting.xml index 1bbd7225..70094cbb 100644 --- a/test/test_suites/suite_convection_permitting.xml +++ b/test/test_suites/suite_convection_permitting.xml @@ -67,6 +67,10 @@ calculate_net_heating rrtmgp_post rrtmgp_diagnostics + + lw_heating_rate_to_air_potential_temperature_tendency + sw_heating_rate_to_air_potential_temperature_tendency + mmm_physics_accumulate_tendencies From 114038ef79b6bde44b090df463c39e4c7379863e Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Wed, 8 Jul 2026 16:22:58 -0600 Subject: [PATCH 3/6] Enable surface coupling --- test/test_suites/suite_convection_permitting.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test_suites/suite_convection_permitting.xml b/test/test_suites/suite_convection_permitting.xml index 70094cbb..162a54ed 100644 --- a/test/test_suites/suite_convection_permitting.xml +++ b/test/test_suites/suite_convection_permitting.xml @@ -110,6 +110,10 @@ mmm_physics_persist_states sima_state_diagnostics + + + calc_dry_air_ideal_gas_density + set_surface_coupling_vars sima_tend_diagnostics From ed2e311e2324b2d505a7b96a8cb6560e4578b143 Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Wed, 8 Jul 2026 18:30:08 +0000 Subject: [PATCH 4/6] Fix metadata --- schemes/mmm/mmm_physics_compat.meta | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/schemes/mmm/mmm_physics_compat.meta b/schemes/mmm/mmm_physics_compat.meta index 81e978cc..b58b8141 100644 --- a/schemes/mmm/mmm_physics_compat.meta +++ b/schemes/mmm/mmm_physics_compat.meta @@ -415,30 +415,35 @@ type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout + advected = True [ ni ] standard_name = mass_number_concentration_of_cloud_ice_water_crystals_in_dry_air units = kg-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout + advected = True [ nwfa ] standard_name = mass_number_concentration_of_hygroscopic_aerosols_in_dry_air units = kg-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout + advected = True [ nifa ] standard_name = mass_number_concentration_of_nonhygroscopic_ice_nucleating_aerosols_in_dry_air units = kg-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout + advected = True [ nbca ] standard_name = mass_number_concentration_of_hydrophobic_black_carbon_in_dry_air units = kg-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout + advected = True [ rublten ] standard_name = tendency_of_eastward_wind_due_to_pbl_processes units = m s-2 From 3b0e2e4f53a2f34eb8376875e4bb2647828e8792 Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Fri, 10 Jul 2026 12:12:35 -0600 Subject: [PATCH 5/6] Fix inconsistent tendency behaviors in MMM physics schemes --- schemes/mmm/bl_gwdo_compat.meta | 4 +- schemes/mmm/bl_mynn_compat.meta | 26 +- schemes/mmm/cu_ntiedtke_compat.meta | 12 +- schemes/mmm/mmm_physics_compat.F90 | 225 +++++++- schemes/mmm/mmm_physics_compat.meta | 546 ++++++++++++++++++ .../suite_convection_permitting.xml | 8 +- 6 files changed, 793 insertions(+), 28 deletions(-) diff --git a/schemes/mmm/bl_gwdo_compat.meta b/schemes/mmm/bl_gwdo_compat.meta index b955a4c3..dbf81b8e 100644 --- a/schemes/mmm/bl_gwdo_compat.meta +++ b/schemes/mmm/bl_gwdo_compat.meta @@ -97,13 +97,13 @@ dimensions = (horizontal_loop_extent) intent = in [ rublten ] - standard_name = tendency_of_eastward_wind_due_to_pbl_processes + standard_name = pending_tendency_of_eastward_wind_due_to_pbl_processes units = m s-2 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rvblten ] - standard_name = tendency_of_northward_wind_due_to_pbl_processes + standard_name = pending_tendency_of_northward_wind_due_to_pbl_processes units = m s-2 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) diff --git a/schemes/mmm/bl_mynn_compat.meta b/schemes/mmm/bl_mynn_compat.meta index c1ea9ba9..d800e207 100644 --- a/schemes/mmm/bl_mynn_compat.meta +++ b/schemes/mmm/bl_mynn_compat.meta @@ -793,79 +793,79 @@ dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rublten ] - standard_name = tendency_of_eastward_wind_due_to_pbl_processes + standard_name = pending_tendency_of_eastward_wind_due_to_pbl_processes units = m s-2 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rvblten ] - standard_name = tendency_of_northward_wind_due_to_pbl_processes + standard_name = pending_tendency_of_northward_wind_due_to_pbl_processes units = m s-2 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rthblten ] - standard_name = tendency_of_air_potential_temperature_due_to_pbl_processes + standard_name = pending_tendency_of_air_potential_temperature_due_to_pbl_processes units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rqvblten ] - standard_name = tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_pbl_processes + standard_name = pending_tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_pbl_processes units = kg kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rqcblten ] - standard_name = tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_pbl_processes + standard_name = pending_tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_pbl_processes units = kg kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rqiblten ] - standard_name = tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_pbl_processes + standard_name = pending_tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_pbl_processes units = kg kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rqsblten ] - standard_name = tendency_of_snow_mixing_ratio_wrt_dry_air_due_to_pbl_processes + standard_name = pending_tendency_of_snow_mixing_ratio_wrt_dry_air_due_to_pbl_processes units = kg kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rqncblten ] - standard_name = tendency_of_mass_number_concentration_of_cloud_liquid_water_droplets_in_dry_air_due_to_pbl_processes + standard_name = pending_tendency_of_mass_number_concentration_of_cloud_liquid_water_droplets_in_dry_air_due_to_pbl_processes units = kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rqniblten ] - standard_name = tendency_of_mass_number_concentration_of_cloud_ice_water_crystals_in_dry_air_due_to_pbl_processes + standard_name = pending_tendency_of_mass_number_concentration_of_cloud_ice_water_crystals_in_dry_air_due_to_pbl_processes units = kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rqnwfablten ] - standard_name = tendency_of_mass_number_concentration_of_hygroscopic_aerosols_in_dry_air_due_to_pbl_processes + standard_name = pending_tendency_of_mass_number_concentration_of_hygroscopic_aerosols_in_dry_air_due_to_pbl_processes units = kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rqnifablten ] - standard_name = tendency_of_mass_number_concentration_of_nonhygroscopic_ice_nucleating_aerosols_in_dry_air_due_to_pbl_processes + standard_name = pending_tendency_of_mass_number_concentration_of_nonhygroscopic_ice_nucleating_aerosols_in_dry_air_due_to_pbl_processes units = kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rqnbcablten ] - standard_name = tendency_of_mass_number_concentration_of_hydrophobic_black_carbon_in_dry_air_due_to_pbl_processes + standard_name = pending_tendency_of_mass_number_concentration_of_hydrophobic_black_carbon_in_dry_air_due_to_pbl_processes units = kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = inout [ rqozblten ] - standard_name = tendency_of_O3_due_to_pbl_processes + standard_name = pending_tendency_of_O3_due_to_pbl_processes units = kg kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) diff --git a/schemes/mmm/cu_ntiedtke_compat.meta b/schemes/mmm/cu_ntiedtke_compat.meta index 6c007517..6926159a 100644 --- a/schemes/mmm/cu_ntiedtke_compat.meta +++ b/schemes/mmm/cu_ntiedtke_compat.meta @@ -295,37 +295,37 @@ dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = in [ rucuten ] - standard_name = tendency_of_eastward_wind_due_to_convection + standard_name = pending_tendency_of_eastward_wind_due_to_convection units = m s-2 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = out [ rvcuten ] - standard_name = tendency_of_northward_wind_due_to_convection + standard_name = pending_tendency_of_northward_wind_due_to_convection units = m s-2 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = out [ rthcuten ] - standard_name = tendency_of_air_potential_temperature_due_to_convection + standard_name = pending_tendency_of_air_potential_temperature_due_to_convection units = K s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = out [ rqvcuten ] - standard_name = tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_convection + standard_name = pending_tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_convection units = kg kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = out [ rqccuten ] - standard_name = tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_convection + standard_name = pending_tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_convection units = kg kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) intent = out [ rqicuten ] - standard_name = tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_convection + standard_name = pending_tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_convection units = kg kg-1 s-1 type = real | kind = kind_phys dimensions = (horizontal_loop_extent, vertical_layer_dimension) diff --git a/schemes/mmm/mmm_physics_compat.F90 b/schemes/mmm/mmm_physics_compat.F90 index 2204d8b7..741a739a 100644 --- a/schemes/mmm/mmm_physics_compat.F90 +++ b/schemes/mmm/mmm_physics_compat.F90 @@ -7,6 +7,8 @@ module mmm_physics_compat public :: mmm_physics_compat_run public :: mmm_physics_accumulate_tendencies_timestep_init public :: mmm_physics_accumulate_tendencies_run + public :: mmm_physics_save_tendencies_timestep_init + public :: mmm_physics_save_tendencies_run public :: mmm_physics_persist_states_init public :: mmm_physics_persist_states_timestep_final public :: compute_characteristic_grid_length_scale_init @@ -135,7 +137,7 @@ pure subroutine mmm_physics_accumulate_tendencies_timestep_init( & dvdt(:, :) = 0.0_kind_phys dtdt(:, :) = 0.0_kind_phys - ! Tendencies generated by MMM physics. + ! Tendencies collected from MMM physics schemes. rublten(:, :) = 0.0_kind_phys rucuten(:, :) = 0.0_kind_phys rvblten(:, :) = 0.0_kind_phys @@ -202,7 +204,7 @@ pure subroutine mmm_physics_accumulate_tendencies_run( & errmsg = '' errflg = 0 - ! Accumulate tendencies for feeding back to CAM-SIMA. + ! Accumulate the states and tendencies for feeding back to CAM-SIMA. dudt(:, :) = dudt(:, :) + (rublten(:, :) + rucuten(:, :)) dvdt(:, :) = dvdt(:, :) + (rvblten(:, :) + rvcuten(:, :)) dtdt(:, :) = dtdt(:, :) + (rthblten(:, :) + rthcuten(:, :) + rthratenlw(:, :) + rthratensw(:, :)) * exner(:, :) @@ -220,7 +222,7 @@ pure subroutine mmm_physics_accumulate_tendencies_run( & nifa(:, :) = nifa(:, :) + rnifablten(:, :) * dt nbca(:, :) = nbca(:, :) + rnbcablten(:, :) * dt - ! After the accumulation, zero out tendencies generated by MMM physics so that this subroutine is idempotent. + ! After accumulating, zero out the tendencies collected from MMM physics schemes to make this subroutine idempotent. rublten(:, :) = 0.0_kind_phys rucuten(:, :) = 0.0_kind_phys rvblten(:, :) = 0.0_kind_phys @@ -251,6 +253,223 @@ pure subroutine mmm_physics_accumulate_tendencies_run( & rnbcablten(:, :) = 0.0_kind_phys end subroutine mmm_physics_accumulate_tendencies_run + !> \section arg_table_mmm_physics_save_tendencies_timestep_init Argument Table + !! \htmlinclude mmm_physics_save_tendencies_timestep_init.html + pure subroutine mmm_physics_save_tendencies_timestep_init( & + rublten_p, rucuten_p, rvblten_p, rvcuten_p, & + rthblten_p, rthcuten_p, rthratenlw_p, rthratensw_p, & + rqvblten_p, rqvcuten_p, & + rqcblten_p, rncblten_p, rqccuten_p, & + rqiblten_p, rniblten_p, rqicuten_p, & + rqsblten_p, & + rozblten_p, & + rnwfablten_p, rnifablten_p, rnbcablten_p, & + rublten, rucuten, rvblten, rvcuten, & + rthblten, rthcuten, rthratenlw, rthratensw, & + rqvblten, rqvcuten, & + rqcblten, rncblten, rqccuten, & + rqiblten, rniblten, rqicuten, & + rqsblten, & + rozblten, & + rnwfablten, rnifablten, rnbcablten, & + errmsg, errflg) + use ccpp_kinds, only: kind_phys + + real(kind_phys), intent(out) :: rublten_p(:, :), rucuten_p(:, :), rvblten_p(:, :), rvcuten_p(:, :), & + rthblten_p(:, :), rthcuten_p(:, :), rthratenlw_p(:, :), rthratensw_p(:, :), & + rqvblten_p(:, :), rqvcuten_p(:, :), & + rqcblten_p(:, :), rncblten_p(:, :), rqccuten_p(:, :), & + rqiblten_p(:, :), rniblten_p(:, :), rqicuten_p(:, :), & + rqsblten_p(:, :), & + rozblten_p(:, :), & + rnwfablten_p(:, :), rnifablten_p(:, :), rnbcablten_p(:, :) + real(kind_phys), intent(out) :: rublten(:, :), rucuten(:, :), rvblten(:, :), rvcuten(:, :), & + rthblten(:, :), rthcuten(:, :), rthratenlw(:, :), rthratensw(:, :), & + rqvblten(:, :), rqvcuten(:, :), & + rqcblten(:, :), rncblten(:, :), rqccuten(:, :), & + rqiblten(:, :), rniblten(:, :), rqicuten(:, :), & + rqsblten(:, :), & + rozblten(:, :), & + rnwfablten(:, :), rnifablten(:, :), rnbcablten(:, :) + character(*), intent(out) :: errmsg + integer, intent(out) :: errflg + + errmsg = '' + errflg = 0 + + ! Zero out tendencies at the beginning of each time step. + + ! "Pending" tendencies that serve as temporary working areas for each MMM physics scheme. + rublten_p(:, :) = 0.0_kind_phys + rucuten_p(:, :) = 0.0_kind_phys + rvblten_p(:, :) = 0.0_kind_phys + rvcuten_p(:, :) = 0.0_kind_phys + + rthblten_p(:, :) = 0.0_kind_phys + rthcuten_p(:, :) = 0.0_kind_phys + rthratenlw_p(:, :) = 0.0_kind_phys + rthratensw_p(:, :) = 0.0_kind_phys + + rqvblten_p(:, :) = 0.0_kind_phys + rqvcuten_p(:, :) = 0.0_kind_phys + + rqcblten_p(:, :) = 0.0_kind_phys + rncblten_p(:, :) = 0.0_kind_phys + rqccuten_p(:, :) = 0.0_kind_phys + + rqiblten_p(:, :) = 0.0_kind_phys + rniblten_p(:, :) = 0.0_kind_phys + rqicuten_p(:, :) = 0.0_kind_phys + + rqsblten_p(:, :) = 0.0_kind_phys + + rozblten_p(:, :) = 0.0_kind_phys + + rnwfablten_p(:, :) = 0.0_kind_phys + rnifablten_p(:, :) = 0.0_kind_phys + rnbcablten_p(:, :) = 0.0_kind_phys + + ! "Final" tendencies collected from MMM physics schemes. + rublten(:, :) = 0.0_kind_phys + rucuten(:, :) = 0.0_kind_phys + rvblten(:, :) = 0.0_kind_phys + rvcuten(:, :) = 0.0_kind_phys + + rthblten(:, :) = 0.0_kind_phys + rthcuten(:, :) = 0.0_kind_phys + rthratenlw(:, :) = 0.0_kind_phys + rthratensw(:, :) = 0.0_kind_phys + + rqvblten(:, :) = 0.0_kind_phys + rqvcuten(:, :) = 0.0_kind_phys + + rqcblten(:, :) = 0.0_kind_phys + rncblten(:, :) = 0.0_kind_phys + rqccuten(:, :) = 0.0_kind_phys + + rqiblten(:, :) = 0.0_kind_phys + rniblten(:, :) = 0.0_kind_phys + rqicuten(:, :) = 0.0_kind_phys + + rqsblten(:, :) = 0.0_kind_phys + + rozblten(:, :) = 0.0_kind_phys + + rnwfablten(:, :) = 0.0_kind_phys + rnifablten(:, :) = 0.0_kind_phys + rnbcablten(:, :) = 0.0_kind_phys + end subroutine mmm_physics_save_tendencies_timestep_init + + !> \section arg_table_mmm_physics_save_tendencies_run Argument Table + !! \htmlinclude mmm_physics_save_tendencies_run.html + pure subroutine mmm_physics_save_tendencies_run( & + rublten_p, rucuten_p, rvblten_p, rvcuten_p, & + rthblten_p, rthcuten_p, rthratenlw_p, rthratensw_p, & + rqvblten_p, rqvcuten_p, & + rqcblten_p, rncblten_p, rqccuten_p, & + rqiblten_p, rniblten_p, rqicuten_p, & + rqsblten_p, & + rozblten_p, & + rnwfablten_p, rnifablten_p, rnbcablten_p, & + rublten, rucuten, rvblten, rvcuten, & + rthblten, rthcuten, rthratenlw, rthratensw, & + rqvblten, rqvcuten, & + rqcblten, rncblten, rqccuten, & + rqiblten, rniblten, rqicuten, & + rqsblten, & + rozblten, & + rnwfablten, rnifablten, rnbcablten, & + errmsg, errflg) + use ccpp_kinds, only: kind_phys + + real(kind_phys), intent(inout) :: rublten_p(:, :), rucuten_p(:, :), rvblten_p(:, :), rvcuten_p(:, :), & + rthblten_p(:, :), rthcuten_p(:, :), rthratenlw_p(:, :), rthratensw_p(:, :), & + rqvblten_p(:, :), rqvcuten_p(:, :), & + rqcblten_p(:, :), rncblten_p(:, :), rqccuten_p(:, :), & + rqiblten_p(:, :), rniblten_p(:, :), rqicuten_p(:, :), & + rqsblten_p(:, :), & + rozblten_p(:, :), & + rnwfablten_p(:, :), rnifablten_p(:, :), rnbcablten_p(:, :) + real(kind_phys), intent(inout) :: rublten(:, :), rucuten(:, :), rvblten(:, :), rvcuten(:, :), & + rthblten(:, :), rthcuten(:, :), rthratenlw(:, :), rthratensw(:, :), & + rqvblten(:, :), rqvcuten(:, :), & + rqcblten(:, :), rncblten(:, :), rqccuten(:, :), & + rqiblten(:, :), rniblten(:, :), rqicuten(:, :), & + rqsblten(:, :), & + rozblten(:, :), & + rnwfablten(:, :), rnifablten(:, :), rnbcablten(:, :) + character(*), intent(out) :: errmsg + integer, intent(out) :: errflg + + errmsg = '' + errflg = 0 + + ! Save pending tendencies to final tendencies. + ! + ! The reason for this mechanism is to mitigate the inconsistent tendency behaviors across various MMM physics schemes. + ! Although some schemes correctly accumulate their tendencies with others, there are certain schemes that outright + ! overwrite the tendencies from others. Instead of wrestling with the problematic schemes individually like MPAS does, + ! which is very error-prone, a suite-level scheme is introduced to blanketly enforce the correct behavior. + rublten(:, :) = rublten(:, :) + rublten_p(:, :) + rucuten(:, :) = rucuten(:, :) + rucuten_p(:, :) + rvblten(:, :) = rvblten(:, :) + rvblten_p(:, :) + rvcuten(:, :) = rvcuten(:, :) + rvcuten_p(:, :) + + rthblten(:, :) = rthblten(:, :) + rthblten_p(:, :) + rthcuten(:, :) = rthcuten(:, :) + rthcuten_p(:, :) + rthratenlw(:, :) = rthratenlw(:, :) + rthratenlw_p(:, :) + rthratensw(:, :) = rthratensw(:, :) + rthratensw_p(:, :) + + rqvblten(:, :) = rqvblten(:, :) + rqvblten_p(:, :) + rqvcuten(:, :) = rqvcuten(:, :) + rqvcuten_p(:, :) + + rqcblten(:, :) = rqcblten(:, :) + rqcblten_p(:, :) + rncblten(:, :) = rncblten(:, :) + rncblten_p(:, :) + rqccuten(:, :) = rqccuten(:, :) + rqccuten_p(:, :) + + rqiblten(:, :) = rqiblten(:, :) + rqiblten_p(:, :) + rniblten(:, :) = rniblten(:, :) + rniblten_p(:, :) + rqicuten(:, :) = rqicuten(:, :) + rqicuten_p(:, :) + + rqsblten(:, :) = rqsblten(:, :) + rqsblten_p(:, :) + + rozblten(:, :) = rozblten(:, :) + rozblten_p(:, :) + + rnwfablten(:, :) = rnwfablten(:, :) + rnwfablten_p(:, :) + rnifablten(:, :) = rnifablten(:, :) + rnifablten_p(:, :) + rnbcablten(:, :) = rnbcablten(:, :) + rnbcablten_p(:, :) + + ! After saving, zero out pending tendencies to make this subroutine idempotent. + rublten_p(:, :) = 0.0_kind_phys + rucuten_p(:, :) = 0.0_kind_phys + rvblten_p(:, :) = 0.0_kind_phys + rvcuten_p(:, :) = 0.0_kind_phys + + rthblten_p(:, :) = 0.0_kind_phys + rthcuten_p(:, :) = 0.0_kind_phys + rthratenlw_p(:, :) = 0.0_kind_phys + rthratensw_p(:, :) = 0.0_kind_phys + + rqvblten_p(:, :) = 0.0_kind_phys + rqvcuten_p(:, :) = 0.0_kind_phys + + rqcblten_p(:, :) = 0.0_kind_phys + rncblten_p(:, :) = 0.0_kind_phys + rqccuten_p(:, :) = 0.0_kind_phys + + rqiblten_p(:, :) = 0.0_kind_phys + rniblten_p(:, :) = 0.0_kind_phys + rqicuten_p(:, :) = 0.0_kind_phys + + rqsblten_p(:, :) = 0.0_kind_phys + + rozblten_p(:, :) = 0.0_kind_phys + + rnwfablten_p(:, :) = 0.0_kind_phys + rnifablten_p(:, :) = 0.0_kind_phys + rnbcablten_p(:, :) = 0.0_kind_phys + end subroutine mmm_physics_save_tendencies_run + !> \section arg_table_mmm_physics_persist_states_init Argument Table !! \htmlinclude mmm_physics_persist_states_init.html pure subroutine mmm_physics_persist_states_init( & diff --git a/schemes/mmm/mmm_physics_compat.meta b/schemes/mmm/mmm_physics_compat.meta index b58b8141..16cdc7b5 100644 --- a/schemes/mmm/mmm_physics_compat.meta +++ b/schemes/mmm/mmm_physics_compat.meta @@ -587,6 +587,552 @@ # ---------- +[ccpp-table-properties] + name = mmm_physics_save_tendencies + type = scheme + +[ccpp-arg-table] + name = mmm_physics_save_tendencies_timestep_init + type = scheme +[ rublten_p ] + standard_name = pending_tendency_of_eastward_wind_due_to_pbl_processes + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rucuten_p ] + standard_name = pending_tendency_of_eastward_wind_due_to_convection + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rvblten_p ] + standard_name = pending_tendency_of_northward_wind_due_to_pbl_processes + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rvcuten_p ] + standard_name = pending_tendency_of_northward_wind_due_to_convection + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rthblten_p ] + standard_name = pending_tendency_of_air_potential_temperature_due_to_pbl_processes + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rthcuten_p ] + standard_name = pending_tendency_of_air_potential_temperature_due_to_convection + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rthratenlw_p ] + standard_name = pending_tendency_of_air_potential_temperature_due_to_longwave_radiation + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rthratensw_p ] + standard_name = pending_tendency_of_air_potential_temperature_due_to_shortwave_radiation + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqvblten_p ] + standard_name = pending_tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqvcuten_p ] + standard_name = pending_tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqcblten_p ] + standard_name = pending_tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rncblten_p ] + standard_name = pending_tendency_of_mass_number_concentration_of_cloud_liquid_water_droplets_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqccuten_p ] + standard_name = pending_tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqiblten_p ] + standard_name = pending_tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rniblten_p ] + standard_name = pending_tendency_of_mass_number_concentration_of_cloud_ice_water_crystals_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqicuten_p ] + standard_name = pending_tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqsblten_p ] + standard_name = pending_tendency_of_snow_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rozblten_p ] + standard_name = pending_tendency_of_O3_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rnwfablten_p ] + standard_name = pending_tendency_of_mass_number_concentration_of_hygroscopic_aerosols_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rnifablten_p ] + standard_name = pending_tendency_of_mass_number_concentration_of_nonhygroscopic_ice_nucleating_aerosols_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rnbcablten_p ] + standard_name = pending_tendency_of_mass_number_concentration_of_hydrophobic_black_carbon_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rublten ] + standard_name = tendency_of_eastward_wind_due_to_pbl_processes + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rucuten ] + standard_name = tendency_of_eastward_wind_due_to_convection + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rvblten ] + standard_name = tendency_of_northward_wind_due_to_pbl_processes + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rvcuten ] + standard_name = tendency_of_northward_wind_due_to_convection + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rthblten ] + standard_name = tendency_of_air_potential_temperature_due_to_pbl_processes + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rthcuten ] + standard_name = tendency_of_air_potential_temperature_due_to_convection + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rthratenlw ] + standard_name = tendency_of_air_potential_temperature_due_to_longwave_radiation + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rthratensw ] + standard_name = tendency_of_air_potential_temperature_due_to_shortwave_radiation + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqvblten ] + standard_name = tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqvcuten ] + standard_name = tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqcblten ] + standard_name = tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rncblten ] + standard_name = tendency_of_mass_number_concentration_of_cloud_liquid_water_droplets_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqccuten ] + standard_name = tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqiblten ] + standard_name = tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rniblten ] + standard_name = tendency_of_mass_number_concentration_of_cloud_ice_water_crystals_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqicuten ] + standard_name = tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rqsblten ] + standard_name = tendency_of_snow_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rozblten ] + standard_name = tendency_of_O3_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rnwfablten ] + standard_name = tendency_of_mass_number_concentration_of_hygroscopic_aerosols_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rnifablten ] + standard_name = tendency_of_mass_number_concentration_of_nonhygroscopic_ice_nucleating_aerosols_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ rnbcablten ] + standard_name = tendency_of_mass_number_concentration_of_hydrophobic_black_carbon_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_dimension, vertical_layer_dimension) + intent = out +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=* + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out + +[ccpp-arg-table] + name = mmm_physics_save_tendencies_run + type = scheme +[ rublten_p ] + standard_name = pending_tendency_of_eastward_wind_due_to_pbl_processes + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rucuten_p ] + standard_name = pending_tendency_of_eastward_wind_due_to_convection + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rvblten_p ] + standard_name = pending_tendency_of_northward_wind_due_to_pbl_processes + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rvcuten_p ] + standard_name = pending_tendency_of_northward_wind_due_to_convection + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rthblten_p ] + standard_name = pending_tendency_of_air_potential_temperature_due_to_pbl_processes + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rthcuten_p ] + standard_name = pending_tendency_of_air_potential_temperature_due_to_convection + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rthratenlw_p ] + standard_name = pending_tendency_of_air_potential_temperature_due_to_longwave_radiation + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rthratensw_p ] + standard_name = pending_tendency_of_air_potential_temperature_due_to_shortwave_radiation + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqvblten_p ] + standard_name = pending_tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqvcuten_p ] + standard_name = pending_tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqcblten_p ] + standard_name = pending_tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rncblten_p ] + standard_name = pending_tendency_of_mass_number_concentration_of_cloud_liquid_water_droplets_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqccuten_p ] + standard_name = pending_tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqiblten_p ] + standard_name = pending_tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rniblten_p ] + standard_name = pending_tendency_of_mass_number_concentration_of_cloud_ice_water_crystals_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqicuten_p ] + standard_name = pending_tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqsblten_p ] + standard_name = pending_tendency_of_snow_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rozblten_p ] + standard_name = pending_tendency_of_O3_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rnwfablten_p ] + standard_name = pending_tendency_of_mass_number_concentration_of_hygroscopic_aerosols_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rnifablten_p ] + standard_name = pending_tendency_of_mass_number_concentration_of_nonhygroscopic_ice_nucleating_aerosols_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rnbcablten_p ] + standard_name = pending_tendency_of_mass_number_concentration_of_hydrophobic_black_carbon_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rublten ] + standard_name = tendency_of_eastward_wind_due_to_pbl_processes + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rucuten ] + standard_name = tendency_of_eastward_wind_due_to_convection + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rvblten ] + standard_name = tendency_of_northward_wind_due_to_pbl_processes + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rvcuten ] + standard_name = tendency_of_northward_wind_due_to_convection + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rthblten ] + standard_name = tendency_of_air_potential_temperature_due_to_pbl_processes + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rthcuten ] + standard_name = tendency_of_air_potential_temperature_due_to_convection + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rthratenlw ] + standard_name = tendency_of_air_potential_temperature_due_to_longwave_radiation + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rthratensw ] + standard_name = tendency_of_air_potential_temperature_due_to_shortwave_radiation + units = K s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqvblten ] + standard_name = tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqvcuten ] + standard_name = tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqcblten ] + standard_name = tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rncblten ] + standard_name = tendency_of_mass_number_concentration_of_cloud_liquid_water_droplets_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqccuten ] + standard_name = tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqiblten ] + standard_name = tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rniblten ] + standard_name = tendency_of_mass_number_concentration_of_cloud_ice_water_crystals_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqicuten ] + standard_name = tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rqsblten ] + standard_name = tendency_of_snow_mixing_ratio_wrt_dry_air_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rozblten ] + standard_name = tendency_of_O3_due_to_pbl_processes + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rnwfablten ] + standard_name = tendency_of_mass_number_concentration_of_hygroscopic_aerosols_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rnifablten ] + standard_name = tendency_of_mass_number_concentration_of_nonhygroscopic_ice_nucleating_aerosols_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ rnbcablten ] + standard_name = tendency_of_mass_number_concentration_of_hydrophobic_black_carbon_in_dry_air_due_to_pbl_processes + units = kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = inout +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=* + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out + +# ---------- + [ccpp-table-properties] name = mmm_physics_persist_states type = scheme diff --git a/test/test_suites/suite_convection_permitting.xml b/test/test_suites/suite_convection_permitting.xml index 162a54ed..cadea951 100644 --- a/test/test_suites/suite_convection_permitting.xml +++ b/test/test_suites/suite_convection_permitting.xml @@ -70,7 +70,6 @@ lw_heating_rate_to_air_potential_temperature_tendency sw_heating_rate_to_air_potential_temperature_tendency - mmm_physics_accumulate_tendencies @@ -82,21 +81,22 @@ bl_mynn_compat_pre bl_mynn_compat bl_mynn_diagnostics - mmm_physics_accumulate_tendencies + mmm_physics_save_tendencies bl_gwdo_compat_pre bl_gwdo_compat bl_gwdo_diagnostics - mmm_physics_accumulate_tendencies + mmm_physics_save_tendencies cu_ntiedtke_compat_pre cu_ntiedtke_compat cu_ntiedtke_diagnostics - mmm_physics_accumulate_tendencies + mmm_physics_save_tendencies + mmm_physics_accumulate_tendencies apply_tendency_of_eastward_wind apply_tendency_of_northward_wind apply_tendency_of_air_temperature From 8fbe7637d8fa868cc73451fd8063546209bf4f45 Mon Sep 17 00:00:00 2001 From: Kuan-Chih Wang Date: Sat, 11 Jul 2026 03:21:41 +0000 Subject: [PATCH 6/6] Add unit tests --- .../tests/mmm/mmm_physics_compat_tests.pf | 639 +++++++++++++++++- 1 file changed, 633 insertions(+), 6 deletions(-) diff --git a/test/unit-test/tests/mmm/mmm_physics_compat_tests.pf b/test/unit-test/tests/mmm/mmm_physics_compat_tests.pf index 8e4888d8..35587a25 100644 --- a/test/unit-test/tests/mmm/mmm_physics_compat_tests.pf +++ b/test/unit-test/tests/mmm/mmm_physics_compat_tests.pf @@ -352,7 +352,7 @@ subroutine test_mmm_physics_accumulate_tendencies_run() rnwfablten, rnifablten, rnbcablten, & errmsg, errflg) - ! Should accumulate MMM tendencies into CAM-SIMA ones. + ! Should accumulate MMM tendencies into the equivalent CAM-SIMA ones correctly. @assertEqual(0.2_kind_phys, dudt, spacing(0.2_kind_phys)) @assertEqual(0.2_kind_phys, dvdt, spacing(0.2_kind_phys)) @assertEqual(0.4_kind_phys, dtdt, spacing(0.4_kind_phys)) @@ -370,7 +370,7 @@ subroutine test_mmm_physics_accumulate_tendencies_run() @assertEqual(1.005E8_kind_phys, nifa, spacing(1.005E8_kind_phys)) @assertEqual(1.005E8_kind_phys, nbca, spacing(1.005E8_kind_phys)) - ! After the accumulation, tendencies should be zeroed out. + ! After accumulating, MMM tendencies should be zeroed out. @assertEqual(0.0_kind_phys, rublten) @assertEqual(0.0_kind_phys, rucuten) @assertEqual(0.0_kind_phys, rvblten) @@ -447,7 +447,7 @@ subroutine test_mmm_physics_accumulate_tendencies_run() rnwfablten, rnifablten, rnbcablten, & errmsg, errflg) - ! Should accumulate MMM tendencies into CAM-SIMA ones. + ! Should accumulate MMM tendencies into the equivalent CAM-SIMA ones correctly. @assertEqual(0.4_kind_phys, dudt, spacing(0.4_kind_phys)) @assertEqual(0.4_kind_phys, dvdt, spacing(0.4_kind_phys)) @assertEqual(0.8_kind_phys, dtdt, spacing(0.8_kind_phys)) @@ -465,7 +465,7 @@ subroutine test_mmm_physics_accumulate_tendencies_run() @assertEqual(1.01E8_kind_phys, nifa, spacing(1.01E8_kind_phys)) @assertEqual(1.01E8_kind_phys, nbca, spacing(1.01E8_kind_phys)) - ! After the accumulation, tendencies should be zeroed out. + ! After accumulating, MMM tendencies should be zeroed out. @assertEqual(0.0_kind_phys, rublten) @assertEqual(0.0_kind_phys, rucuten) @assertEqual(0.0_kind_phys, rvblten) @@ -528,7 +528,7 @@ subroutine test_mmm_physics_accumulate_tendencies_run() rnwfablten, rnifablten, rnbcablten, & errmsg, errflg) - ! Should accumulate MMM tendencies into CAM-SIMA ones. + ! Consecutive calls should be idempotent. @assertEqual(0.4_kind_phys, dudt, spacing(0.4_kind_phys)) @assertEqual(0.4_kind_phys, dvdt, spacing(0.4_kind_phys)) @assertEqual(0.8_kind_phys, dtdt, spacing(0.8_kind_phys)) @@ -546,7 +546,7 @@ subroutine test_mmm_physics_accumulate_tendencies_run() @assertEqual(1.01E8_kind_phys, nifa, spacing(1.01E8_kind_phys)) @assertEqual(1.01E8_kind_phys, nbca, spacing(1.01E8_kind_phys)) - ! After the accumulation, tendencies should be zeroed out. + ! Consecutive calls should be idempotent. @assertEqual(0.0_kind_phys, rublten) @assertEqual(0.0_kind_phys, rucuten) @assertEqual(0.0_kind_phys, rvblten) @@ -580,6 +580,551 @@ subroutine test_mmm_physics_accumulate_tendencies_run() @assertEqual(0, errflg) end subroutine test_mmm_physics_accumulate_tendencies_run +@test +subroutine test_mmm_physics_save_tendencies_timestep_init() + use ccpp_kinds, only: kind_phys + use funit + use mmm_physics_compat, only: mmm_physics_save_tendencies_timestep_init + + integer, parameter :: ncol = 100, pver = 10 + real(kind_phys) :: rublten_p(ncol, pver), rucuten_p(ncol, pver), rvblten_p(ncol, pver), rvcuten_p(ncol, pver) + real(kind_phys) :: rthblten_p(ncol, pver), rthcuten_p(ncol, pver), rthratenlw_p(ncol, pver), rthratensw_p(ncol, pver) + real(kind_phys) :: rqvblten_p(ncol, pver), rqvcuten_p(ncol, pver) + real(kind_phys) :: rqcblten_p(ncol, pver), rncblten_p(ncol, pver), rqccuten_p(ncol, pver) + real(kind_phys) :: rqiblten_p(ncol, pver), rniblten_p(ncol, pver), rqicuten_p(ncol, pver) + real(kind_phys) :: rqsblten_p(ncol, pver) + real(kind_phys) :: rozblten_p(ncol, pver) + real(kind_phys) :: rnwfablten_p(ncol, pver), rnifablten_p(ncol, pver), rnbcablten_p(ncol, pver) + real(kind_phys) :: rublten(ncol, pver), rucuten(ncol, pver), rvblten(ncol, pver), rvcuten(ncol, pver) + real(kind_phys) :: rthblten(ncol, pver), rthcuten(ncol, pver), rthratenlw(ncol, pver), rthratensw(ncol, pver) + real(kind_phys) :: rqvblten(ncol, pver), rqvcuten(ncol, pver) + real(kind_phys) :: rqcblten(ncol, pver), rncblten(ncol, pver), rqccuten(ncol, pver) + real(kind_phys) :: rqiblten(ncol, pver), rniblten(ncol, pver), rqicuten(ncol, pver) + real(kind_phys) :: rqsblten(ncol, pver) + real(kind_phys) :: rozblten(ncol, pver) + real(kind_phys) :: rnwfablten(ncol, pver), rnifablten(ncol, pver), rnbcablten(ncol, pver) + character(100) :: errmsg + integer :: errflg + + rublten_p(:, :) = huge(0.0_kind_phys) + rucuten_p(:, :) = huge(0.0_kind_phys) + rvblten_p(:, :) = huge(0.0_kind_phys) + rvcuten_p(:, :) = huge(0.0_kind_phys) + + rthblten_p(:, :) = huge(0.0_kind_phys) + rthcuten_p(:, :) = huge(0.0_kind_phys) + rthratenlw_p(:, :) = huge(0.0_kind_phys) + rthratensw_p(:, :) = huge(0.0_kind_phys) + + rqvblten_p(:, :) = huge(0.0_kind_phys) + rqvcuten_p(:, :) = huge(0.0_kind_phys) + + rqcblten_p(:, :) = huge(0.0_kind_phys) + rncblten_p(:, :) = huge(0.0_kind_phys) + rqccuten_p(:, :) = huge(0.0_kind_phys) + + rqiblten_p(:, :) = huge(0.0_kind_phys) + rniblten_p(:, :) = huge(0.0_kind_phys) + rqicuten_p(:, :) = huge(0.0_kind_phys) + + rqsblten_p(:, :) = huge(0.0_kind_phys) + + rozblten_p(:, :) = huge(0.0_kind_phys) + + rnwfablten_p(:, :) = huge(0.0_kind_phys) + rnifablten_p(:, :) = huge(0.0_kind_phys) + rnbcablten_p(:, :) = huge(0.0_kind_phys) + + rublten(:, :) = huge(0.0_kind_phys) + rucuten(:, :) = huge(0.0_kind_phys) + rvblten(:, :) = huge(0.0_kind_phys) + rvcuten(:, :) = huge(0.0_kind_phys) + + rthblten(:, :) = huge(0.0_kind_phys) + rthcuten(:, :) = huge(0.0_kind_phys) + rthratenlw(:, :) = huge(0.0_kind_phys) + rthratensw(:, :) = huge(0.0_kind_phys) + + rqvblten(:, :) = huge(0.0_kind_phys) + rqvcuten(:, :) = huge(0.0_kind_phys) + + rqcblten(:, :) = huge(0.0_kind_phys) + rncblten(:, :) = huge(0.0_kind_phys) + rqccuten(:, :) = huge(0.0_kind_phys) + + rqiblten(:, :) = huge(0.0_kind_phys) + rniblten(:, :) = huge(0.0_kind_phys) + rqicuten(:, :) = huge(0.0_kind_phys) + + rqsblten(:, :) = huge(0.0_kind_phys) + + rozblten(:, :) = huge(0.0_kind_phys) + + rnwfablten(:, :) = huge(0.0_kind_phys) + rnifablten(:, :) = huge(0.0_kind_phys) + rnbcablten(:, :) = huge(0.0_kind_phys) + + call mmm_physics_save_tendencies_timestep_init( & + rublten_p, rucuten_p, rvblten_p, rvcuten_p, & + rthblten_p, rthcuten_p, rthratenlw_p, rthratensw_p, & + rqvblten_p, rqvcuten_p, & + rqcblten_p, rncblten_p, rqccuten_p, & + rqiblten_p, rniblten_p, rqicuten_p, & + rqsblten_p, & + rozblten_p, & + rnwfablten_p, rnifablten_p, rnbcablten_p, & + rublten, rucuten, rvblten, rvcuten, & + rthblten, rthcuten, rthratenlw, rthratensw, & + rqvblten, rqvcuten, & + rqcblten, rncblten, rqccuten, & + rqiblten, rniblten, rqicuten, & + rqsblten, & + rozblten, & + rnwfablten, rnifablten, rnbcablten, & + errmsg, errflg) + + ! Everything should be zeroed out. + @assertEqual(0.0_kind_phys, rublten_p) + @assertEqual(0.0_kind_phys, rucuten_p) + @assertEqual(0.0_kind_phys, rvblten_p) + @assertEqual(0.0_kind_phys, rvcuten_p) + + @assertEqual(0.0_kind_phys, rthblten_p) + @assertEqual(0.0_kind_phys, rthcuten_p) + @assertEqual(0.0_kind_phys, rthratenlw_p) + @assertEqual(0.0_kind_phys, rthratensw_p) + + @assertEqual(0.0_kind_phys, rqvblten_p) + @assertEqual(0.0_kind_phys, rqvcuten_p) + + @assertEqual(0.0_kind_phys, rqcblten_p) + @assertEqual(0.0_kind_phys, rncblten_p) + @assertEqual(0.0_kind_phys, rqccuten_p) + + @assertEqual(0.0_kind_phys, rqiblten_p) + @assertEqual(0.0_kind_phys, rniblten_p) + @assertEqual(0.0_kind_phys, rqicuten_p) + + @assertEqual(0.0_kind_phys, rqsblten_p) + + @assertEqual(0.0_kind_phys, rozblten_p) + + @assertEqual(0.0_kind_phys, rnwfablten_p) + @assertEqual(0.0_kind_phys, rnifablten_p) + @assertEqual(0.0_kind_phys, rnbcablten_p) + + @assertEqual(0.0_kind_phys, rublten) + @assertEqual(0.0_kind_phys, rucuten) + @assertEqual(0.0_kind_phys, rvblten) + @assertEqual(0.0_kind_phys, rvcuten) + + @assertEqual(0.0_kind_phys, rthblten) + @assertEqual(0.0_kind_phys, rthcuten) + @assertEqual(0.0_kind_phys, rthratenlw) + @assertEqual(0.0_kind_phys, rthratensw) + + @assertEqual(0.0_kind_phys, rqvblten) + @assertEqual(0.0_kind_phys, rqvcuten) + + @assertEqual(0.0_kind_phys, rqcblten) + @assertEqual(0.0_kind_phys, rncblten) + @assertEqual(0.0_kind_phys, rqccuten) + + @assertEqual(0.0_kind_phys, rqiblten) + @assertEqual(0.0_kind_phys, rniblten) + @assertEqual(0.0_kind_phys, rqicuten) + + @assertEqual(0.0_kind_phys, rqsblten) + + @assertEqual(0.0_kind_phys, rozblten) + + @assertEqual(0.0_kind_phys, rnwfablten) + @assertEqual(0.0_kind_phys, rnifablten) + @assertEqual(0.0_kind_phys, rnbcablten) + + @assertEqual('', errmsg) + @assertEqual(0, errflg) +end subroutine test_mmm_physics_save_tendencies_timestep_init + +@test +subroutine test_mmm_physics_save_tendencies_run() + use ccpp_kinds, only: kind_phys + use funit + use mmm_physics_compat, only: mmm_physics_save_tendencies_run + + integer, parameter :: ncol = 100, pver = 10 + real(kind_phys) :: rublten_p(ncol, pver), rucuten_p(ncol, pver), rvblten_p(ncol, pver), rvcuten_p(ncol, pver) + real(kind_phys) :: rthblten_p(ncol, pver), rthcuten_p(ncol, pver), rthratenlw_p(ncol, pver), rthratensw_p(ncol, pver) + real(kind_phys) :: rqvblten_p(ncol, pver), rqvcuten_p(ncol, pver) + real(kind_phys) :: rqcblten_p(ncol, pver), rncblten_p(ncol, pver), rqccuten_p(ncol, pver) + real(kind_phys) :: rqiblten_p(ncol, pver), rniblten_p(ncol, pver), rqicuten_p(ncol, pver) + real(kind_phys) :: rqsblten_p(ncol, pver) + real(kind_phys) :: rozblten_p(ncol, pver) + real(kind_phys) :: rnwfablten_p(ncol, pver), rnifablten_p(ncol, pver), rnbcablten_p(ncol, pver) + real(kind_phys) :: rublten(ncol, pver), rucuten(ncol, pver), rvblten(ncol, pver), rvcuten(ncol, pver) + real(kind_phys) :: rthblten(ncol, pver), rthcuten(ncol, pver), rthratenlw(ncol, pver), rthratensw(ncol, pver) + real(kind_phys) :: rqvblten(ncol, pver), rqvcuten(ncol, pver) + real(kind_phys) :: rqcblten(ncol, pver), rncblten(ncol, pver), rqccuten(ncol, pver) + real(kind_phys) :: rqiblten(ncol, pver), rniblten(ncol, pver), rqicuten(ncol, pver) + real(kind_phys) :: rqsblten(ncol, pver) + real(kind_phys) :: rozblten(ncol, pver) + real(kind_phys) :: rnwfablten(ncol, pver), rnifablten(ncol, pver), rnbcablten(ncol, pver) + character(100) :: errmsg + integer :: errflg + + rublten_p(:, :) = 0.1_kind_phys + rucuten_p(:, :) = 0.1_kind_phys + rvblten_p(:, :) = 0.1_kind_phys + rvcuten_p(:, :) = 0.1_kind_phys + + rthblten_p(:, :) = 0.1_kind_phys + rthcuten_p(:, :) = 0.1_kind_phys + rthratenlw_p(:, :) = 0.1_kind_phys + rthratensw_p(:, :) = 0.1_kind_phys + + rqvblten_p(:, :) = 0.00025_kind_phys + rqvcuten_p(:, :) = 0.00025_kind_phys + + rqcblten_p(:, :) = 0.00025_kind_phys + rncblten_p(:, :) = 25000.0_kind_phys + rqccuten_p(:, :) = 0.00025_kind_phys + + rqiblten_p(:, :) = 0.00025_kind_phys + rniblten_p(:, :) = 250.0_kind_phys + rqicuten_p(:, :) = 0.00025_kind_phys + + rqsblten_p(:, :) = 0.00025_kind_phys + + rozblten_p(:, :) = 2.5E-10_kind_phys + + rnwfablten_p(:, :) = 25000.0_kind_phys + rnifablten_p(:, :) = 25000.0_kind_phys + rnbcablten_p(:, :) = 25000.0_kind_phys + + rublten(:, :) = 0.0_kind_phys + rucuten(:, :) = 0.0_kind_phys + rvblten(:, :) = 0.0_kind_phys + rvcuten(:, :) = 0.0_kind_phys + + rthblten(:, :) = 0.0_kind_phys + rthcuten(:, :) = 0.0_kind_phys + rthratenlw(:, :) = 0.0_kind_phys + rthratensw(:, :) = 0.0_kind_phys + + rqvblten(:, :) = 0.0_kind_phys + rqvcuten(:, :) = 0.0_kind_phys + + rqcblten(:, :) = 0.0_kind_phys + rncblten(:, :) = 0.0_kind_phys + rqccuten(:, :) = 0.0_kind_phys + + rqiblten(:, :) = 0.0_kind_phys + rniblten(:, :) = 0.0_kind_phys + rqicuten(:, :) = 0.0_kind_phys + + rqsblten(:, :) = 0.0_kind_phys + + rozblten(:, :) = 0.0_kind_phys + + rnwfablten(:, :) = 0.0_kind_phys + rnifablten(:, :) = 0.0_kind_phys + rnbcablten(:, :) = 0.0_kind_phys + + call mmm_physics_save_tendencies_run( & + rublten_p, rucuten_p, rvblten_p, rvcuten_p, & + rthblten_p, rthcuten_p, rthratenlw_p, rthratensw_p, & + rqvblten_p, rqvcuten_p, & + rqcblten_p, rncblten_p, rqccuten_p, & + rqiblten_p, rniblten_p, rqicuten_p, & + rqsblten_p, & + rozblten_p, & + rnwfablten_p, rnifablten_p, rnbcablten_p, & + rublten, rucuten, rvblten, rvcuten, & + rthblten, rthcuten, rthratenlw, rthratensw, & + rqvblten, rqvcuten, & + rqcblten, rncblten, rqccuten, & + rqiblten, rniblten, rqicuten, & + rqsblten, & + rozblten, & + rnwfablten, rnifablten, rnbcablten, & + errmsg, errflg) + + ! Should save pending tendencies to final tendencies correctly. + @assertEqual(0.1_kind_phys, rublten, spacing(0.1_kind_phys)) + @assertEqual(0.1_kind_phys, rucuten, spacing(0.1_kind_phys)) + @assertEqual(0.1_kind_phys, rvblten, spacing(0.1_kind_phys)) + @assertEqual(0.1_kind_phys, rvcuten, spacing(0.1_kind_phys)) + + @assertEqual(0.1_kind_phys, rthblten, spacing(0.1_kind_phys)) + @assertEqual(0.1_kind_phys, rthcuten, spacing(0.1_kind_phys)) + @assertEqual(0.1_kind_phys, rthratenlw, spacing(0.1_kind_phys)) + @assertEqual(0.1_kind_phys, rthratensw, spacing(0.1_kind_phys)) + + @assertEqual(0.00025_kind_phys, rqvblten, spacing(0.00025_kind_phys)) + @assertEqual(0.00025_kind_phys, rqvcuten, spacing(0.00025_kind_phys)) + + @assertEqual(0.00025_kind_phys, rqcblten, spacing(0.00025_kind_phys)) + @assertEqual(25000.0_kind_phys, rncblten, spacing(25000.0_kind_phys)) + @assertEqual(0.00025_kind_phys, rqccuten, spacing(0.00025_kind_phys)) + + @assertEqual(0.00025_kind_phys, rqiblten, spacing(0.00025_kind_phys)) + @assertEqual(250.0_kind_phys, rniblten, spacing(250.0_kind_phys)) + @assertEqual(0.00025_kind_phys, rqicuten, spacing(0.00025_kind_phys)) + + @assertEqual(0.00025_kind_phys, rqsblten, spacing(0.00025_kind_phys)) + + @assertEqual(2.5E-10_kind_phys, rozblten, spacing(2.5E-10_kind_phys)) + + @assertEqual(25000.0_kind_phys, rnwfablten, spacing(25000.0_kind_phys)) + @assertEqual(25000.0_kind_phys, rnifablten, spacing(25000.0_kind_phys)) + @assertEqual(25000.0_kind_phys, rnbcablten, spacing(25000.0_kind_phys)) + + ! After saving, pending tendencies should be zeroed out. + @assertEqual(0.0_kind_phys, rublten_p) + @assertEqual(0.0_kind_phys, rucuten_p) + @assertEqual(0.0_kind_phys, rvblten_p) + @assertEqual(0.0_kind_phys, rvcuten_p) + + @assertEqual(0.0_kind_phys, rthblten_p) + @assertEqual(0.0_kind_phys, rthcuten_p) + @assertEqual(0.0_kind_phys, rthratenlw_p) + @assertEqual(0.0_kind_phys, rthratensw_p) + + @assertEqual(0.0_kind_phys, rqvblten_p) + @assertEqual(0.0_kind_phys, rqvcuten_p) + + @assertEqual(0.0_kind_phys, rqcblten_p) + @assertEqual(0.0_kind_phys, rncblten_p) + @assertEqual(0.0_kind_phys, rqccuten_p) + + @assertEqual(0.0_kind_phys, rqiblten_p) + @assertEqual(0.0_kind_phys, rniblten_p) + @assertEqual(0.0_kind_phys, rqicuten_p) + + @assertEqual(0.0_kind_phys, rqsblten_p) + + @assertEqual(0.0_kind_phys, rozblten_p) + + @assertEqual(0.0_kind_phys, rnwfablten_p) + @assertEqual(0.0_kind_phys, rnifablten_p) + @assertEqual(0.0_kind_phys, rnbcablten_p) + + @assertEqual('', errmsg) + @assertEqual(0, errflg) + + rublten_p(:, :) = 0.1_kind_phys + rucuten_p(:, :) = 0.1_kind_phys + rvblten_p(:, :) = 0.1_kind_phys + rvcuten_p(:, :) = 0.1_kind_phys + + rthblten_p(:, :) = 0.1_kind_phys + rthcuten_p(:, :) = 0.1_kind_phys + rthratenlw_p(:, :) = 0.1_kind_phys + rthratensw_p(:, :) = 0.1_kind_phys + + rqvblten_p(:, :) = 0.00025_kind_phys + rqvcuten_p(:, :) = 0.00025_kind_phys + + rqcblten_p(:, :) = 0.00025_kind_phys + rncblten_p(:, :) = 25000.0_kind_phys + rqccuten_p(:, :) = 0.00025_kind_phys + + rqiblten_p(:, :) = 0.00025_kind_phys + rniblten_p(:, :) = 250.0_kind_phys + rqicuten_p(:, :) = 0.00025_kind_phys + + rqsblten_p(:, :) = 0.00025_kind_phys + + rozblten_p(:, :) = 2.5E-10_kind_phys + + rnwfablten_p(:, :) = 25000.0_kind_phys + rnifablten_p(:, :) = 25000.0_kind_phys + rnbcablten_p(:, :) = 25000.0_kind_phys + + call mmm_physics_save_tendencies_run( & + rublten_p, rucuten_p, rvblten_p, rvcuten_p, & + rthblten_p, rthcuten_p, rthratenlw_p, rthratensw_p, & + rqvblten_p, rqvcuten_p, & + rqcblten_p, rncblten_p, rqccuten_p, & + rqiblten_p, rniblten_p, rqicuten_p, & + rqsblten_p, & + rozblten_p, & + rnwfablten_p, rnifablten_p, rnbcablten_p, & + rublten, rucuten, rvblten, rvcuten, & + rthblten, rthcuten, rthratenlw, rthratensw, & + rqvblten, rqvcuten, & + rqcblten, rncblten, rqccuten, & + rqiblten, rniblten, rqicuten, & + rqsblten, & + rozblten, & + rnwfablten, rnifablten, rnbcablten, & + errmsg, errflg) + + ! Should save pending tendencies to final tendencies correctly. + @assertEqual(0.2_kind_phys, rublten, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rucuten, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rvblten, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rvcuten, spacing(0.2_kind_phys)) + + @assertEqual(0.2_kind_phys, rthblten, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rthcuten, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rthratenlw, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rthratensw, spacing(0.2_kind_phys)) + + @assertEqual(0.0005_kind_phys, rqvblten, spacing(0.0005_kind_phys)) + @assertEqual(0.0005_kind_phys, rqvcuten, spacing(0.0005_kind_phys)) + + @assertEqual(0.0005_kind_phys, rqcblten, spacing(0.0005_kind_phys)) + @assertEqual(50000.0_kind_phys, rncblten, spacing(50000.0_kind_phys)) + @assertEqual(0.0005_kind_phys, rqccuten, spacing(0.0005_kind_phys)) + + @assertEqual(0.0005_kind_phys, rqiblten, spacing(0.0005_kind_phys)) + @assertEqual(500.0_kind_phys, rniblten, spacing(500.0_kind_phys)) + @assertEqual(0.0005_kind_phys, rqicuten, spacing(0.0005_kind_phys)) + + @assertEqual(0.0005_kind_phys, rqsblten, spacing(0.0005_kind_phys)) + + @assertEqual(5.0E-10_kind_phys, rozblten, spacing(5.0E-10_kind_phys)) + + @assertEqual(50000.0_kind_phys, rnwfablten, spacing(50000.0_kind_phys)) + @assertEqual(50000.0_kind_phys, rnifablten, spacing(50000.0_kind_phys)) + @assertEqual(50000.0_kind_phys, rnbcablten, spacing(50000.0_kind_phys)) + + ! After saving, pending tendencies should be zeroed out. + @assertEqual(0.0_kind_phys, rublten_p) + @assertEqual(0.0_kind_phys, rucuten_p) + @assertEqual(0.0_kind_phys, rvblten_p) + @assertEqual(0.0_kind_phys, rvcuten_p) + + @assertEqual(0.0_kind_phys, rthblten_p) + @assertEqual(0.0_kind_phys, rthcuten_p) + @assertEqual(0.0_kind_phys, rthratenlw_p) + @assertEqual(0.0_kind_phys, rthratensw_p) + + @assertEqual(0.0_kind_phys, rqvblten_p) + @assertEqual(0.0_kind_phys, rqvcuten_p) + + @assertEqual(0.0_kind_phys, rqcblten_p) + @assertEqual(0.0_kind_phys, rncblten_p) + @assertEqual(0.0_kind_phys, rqccuten_p) + + @assertEqual(0.0_kind_phys, rqiblten_p) + @assertEqual(0.0_kind_phys, rniblten_p) + @assertEqual(0.0_kind_phys, rqicuten_p) + + @assertEqual(0.0_kind_phys, rqsblten_p) + + @assertEqual(0.0_kind_phys, rozblten_p) + + @assertEqual(0.0_kind_phys, rnwfablten_p) + @assertEqual(0.0_kind_phys, rnifablten_p) + @assertEqual(0.0_kind_phys, rnbcablten_p) + + @assertEqual('', errmsg) + @assertEqual(0, errflg) + + call mmm_physics_save_tendencies_run( & + rublten_p, rucuten_p, rvblten_p, rvcuten_p, & + rthblten_p, rthcuten_p, rthratenlw_p, rthratensw_p, & + rqvblten_p, rqvcuten_p, & + rqcblten_p, rncblten_p, rqccuten_p, & + rqiblten_p, rniblten_p, rqicuten_p, & + rqsblten_p, & + rozblten_p, & + rnwfablten_p, rnifablten_p, rnbcablten_p, & + rublten, rucuten, rvblten, rvcuten, & + rthblten, rthcuten, rthratenlw, rthratensw, & + rqvblten, rqvcuten, & + rqcblten, rncblten, rqccuten, & + rqiblten, rniblten, rqicuten, & + rqsblten, & + rozblten, & + rnwfablten, rnifablten, rnbcablten, & + errmsg, errflg) + + call mmm_physics_save_tendencies_run( & + rublten_p, rucuten_p, rvblten_p, rvcuten_p, & + rthblten_p, rthcuten_p, rthratenlw_p, rthratensw_p, & + rqvblten_p, rqvcuten_p, & + rqcblten_p, rncblten_p, rqccuten_p, & + rqiblten_p, rniblten_p, rqicuten_p, & + rqsblten_p, & + rozblten_p, & + rnwfablten_p, rnifablten_p, rnbcablten_p, & + rublten, rucuten, rvblten, rvcuten, & + rthblten, rthcuten, rthratenlw, rthratensw, & + rqvblten, rqvcuten, & + rqcblten, rncblten, rqccuten, & + rqiblten, rniblten, rqicuten, & + rqsblten, & + rozblten, & + rnwfablten, rnifablten, rnbcablten, & + errmsg, errflg) + + ! Consecutive calls should be idempotent. + @assertEqual(0.2_kind_phys, rublten, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rucuten, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rvblten, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rvcuten, spacing(0.2_kind_phys)) + + @assertEqual(0.2_kind_phys, rthblten, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rthcuten, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rthratenlw, spacing(0.2_kind_phys)) + @assertEqual(0.2_kind_phys, rthratensw, spacing(0.2_kind_phys)) + + @assertEqual(0.0005_kind_phys, rqvblten, spacing(0.0005_kind_phys)) + @assertEqual(0.0005_kind_phys, rqvcuten, spacing(0.0005_kind_phys)) + + @assertEqual(0.0005_kind_phys, rqcblten, spacing(0.0005_kind_phys)) + @assertEqual(50000.0_kind_phys, rncblten, spacing(50000.0_kind_phys)) + @assertEqual(0.0005_kind_phys, rqccuten, spacing(0.0005_kind_phys)) + + @assertEqual(0.0005_kind_phys, rqiblten, spacing(0.0005_kind_phys)) + @assertEqual(500.0_kind_phys, rniblten, spacing(500.0_kind_phys)) + @assertEqual(0.0005_kind_phys, rqicuten, spacing(0.0005_kind_phys)) + + @assertEqual(0.0005_kind_phys, rqsblten, spacing(0.0005_kind_phys)) + + @assertEqual(5.0E-10_kind_phys, rozblten, spacing(5.0E-10_kind_phys)) + + @assertEqual(50000.0_kind_phys, rnwfablten, spacing(50000.0_kind_phys)) + @assertEqual(50000.0_kind_phys, rnifablten, spacing(50000.0_kind_phys)) + @assertEqual(50000.0_kind_phys, rnbcablten, spacing(50000.0_kind_phys)) + + ! Consecutive calls should be idempotent. + @assertEqual(0.0_kind_phys, rublten_p) + @assertEqual(0.0_kind_phys, rucuten_p) + @assertEqual(0.0_kind_phys, rvblten_p) + @assertEqual(0.0_kind_phys, rvcuten_p) + + @assertEqual(0.0_kind_phys, rthblten_p) + @assertEqual(0.0_kind_phys, rthcuten_p) + @assertEqual(0.0_kind_phys, rthratenlw_p) + @assertEqual(0.0_kind_phys, rthratensw_p) + + @assertEqual(0.0_kind_phys, rqvblten_p) + @assertEqual(0.0_kind_phys, rqvcuten_p) + + @assertEqual(0.0_kind_phys, rqcblten_p) + @assertEqual(0.0_kind_phys, rncblten_p) + @assertEqual(0.0_kind_phys, rqccuten_p) + + @assertEqual(0.0_kind_phys, rqiblten_p) + @assertEqual(0.0_kind_phys, rniblten_p) + @assertEqual(0.0_kind_phys, rqicuten_p) + + @assertEqual(0.0_kind_phys, rqsblten_p) + + @assertEqual(0.0_kind_phys, rozblten_p) + + @assertEqual(0.0_kind_phys, rnwfablten_p) + @assertEqual(0.0_kind_phys, rnifablten_p) + @assertEqual(0.0_kind_phys, rnbcablten_p) + + @assertEqual('', errmsg) + @assertEqual(0, errflg) +end subroutine test_mmm_physics_save_tendencies_run + @test subroutine test_mmm_physics_persist_states_init() use ccpp_kinds, only: kind_phys @@ -823,3 +1368,85 @@ subroutine test_geopotential_height_wrt_sfc_to_msl_run() @assertEqual('', errmsg) @assertEqual(0, errflg) end subroutine test_geopotential_height_wrt_sfc_to_msl_run + +@test +subroutine test_lw_heating_rate_to_air_potential_temperature_tendency_run() + use ccpp_kinds, only: kind_phys + use funit + use mmm_physics_compat, only: lw_heating_rate_to_air_potential_temperature_tendency_run + + integer, parameter :: ncol = 100, pver = 10 + real(kind_phys) :: cpairv(ncol, pver), exner(ncol, pver), lw_heating_rate(ncol, pver) + real(kind_phys) :: rthratenlw(ncol, pver) + character(100) :: errmsg + integer :: errflg + + cpairv(:, :) = 1004.0_kind_phys + exner(:, :) = 0.9_kind_phys + lw_heating_rate(:, :) = 1.8072_kind_phys + rthratenlw(:, :) = huge(0.0_kind_phys) + + call lw_heating_rate_to_air_potential_temperature_tendency_run( & + cpairv, exner, lw_heating_rate, & + rthratenlw, & + errmsg, errflg) + + ! Should compute LW heating rate as potential temperature tendency correctly. + @assertEqual(0.002_kind_phys, rthratenlw, spacing(0.002_kind_phys)) + @assertEqual('', errmsg) + @assertEqual(0, errflg) + + lw_heating_rate(:, :) = -1.8072_kind_phys + rthratenlw(:, :) = huge(0.0_kind_phys) + + call lw_heating_rate_to_air_potential_temperature_tendency_run( & + cpairv, exner, lw_heating_rate, & + rthratenlw, & + errmsg, errflg) + + ! Should compute LW heating rate as potential temperature tendency correctly. + @assertEqual(-0.002_kind_phys, rthratenlw, spacing(-0.002_kind_phys)) + @assertEqual('', errmsg) + @assertEqual(0, errflg) +end subroutine test_lw_heating_rate_to_air_potential_temperature_tendency_run + +@test +subroutine test_sw_heating_rate_to_air_potential_temperature_tendency_run() + use ccpp_kinds, only: kind_phys + use funit + use mmm_physics_compat, only: sw_heating_rate_to_air_potential_temperature_tendency_run + + integer, parameter :: ncol = 100, pver = 10 + real(kind_phys) :: cpairv(ncol, pver), exner(ncol, pver), sw_heating_rate(ncol, pver) + real(kind_phys) :: rthratensw(ncol, pver) + character(100) :: errmsg + integer :: errflg + + cpairv(:, :) = 1004.0_kind_phys + exner(:, :) = 0.9_kind_phys + sw_heating_rate(:, :) = 1.8072_kind_phys + rthratensw(:, :) = huge(0.0_kind_phys) + + call sw_heating_rate_to_air_potential_temperature_tendency_run( & + cpairv, exner, sw_heating_rate, & + rthratensw, & + errmsg, errflg) + + ! Should compute SW heating rate as potential temperature tendency correctly. + @assertEqual(0.002_kind_phys, rthratensw, spacing(0.002_kind_phys)) + @assertEqual('', errmsg) + @assertEqual(0, errflg) + + sw_heating_rate(:, :) = -1.8072_kind_phys + rthratensw(:, :) = huge(0.0_kind_phys) + + call sw_heating_rate_to_air_potential_temperature_tendency_run( & + cpairv, exner, sw_heating_rate, & + rthratensw, & + errmsg, errflg) + + ! Should compute SW heating rate as potential temperature tendency correctly. + @assertEqual(-0.002_kind_phys, rthratensw, spacing(-0.002_kind_phys)) + @assertEqual('', errmsg) + @assertEqual(0, errflg) +end subroutine test_sw_heating_rate_to_air_potential_temperature_tendency_run