Skip to content

Commit 22b3f9c

Browse files
authored
Merge branch 'overfelt/eamxx/diagnostics_AQ_and_GS' (PR #7459)
The "mam4_microphysics_tendency_gas_phase_chemistry" and "mam4_microphysics_tendency_aqueous_chemistry" diagnostics are added. This PR also: - Adds a namelist flag to control diagnostic output (default: false) - Adds a REP CIME test where the namelist flag is turned to true [BFB]
2 parents 62d19a3 + a5ee2dd commit 22b3f9c

File tree

6 files changed

+68
-25
lines changed

6 files changed

+68
-25
lines changed

cime_config/tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,7 @@
811811
"REP_Ln5.ne4pg2_oQU480.F2010-EAMxx-MAM4xx.eamxx-mam4xx-drydep",
812812
"REP_Ln5.ne4pg2_oQU480.F2010-EAMxx-MAM4xx.eamxx-mam4xx-aero_microphysics",
813813
"REP_Ln5.ne30pg2_oECv3.F2010-EAMxx-MAM4xx.eamxx-mam4xx-remap_emiss_ne4_ne30",
814+
"REP_Ln5.ne4pg2_oQU480.F2010-EAMxx-MAM4xx.eamxx-mam4xx-compute_mam4xx_diags",
814815
"REP_Ln5.ne4pg2_oQU480.F2010-EAMxx-MAM4xx",
815816
"ERS.ne4pg2_oQU480.F2010-EAMxx-MAM4xx.eamxx-mam4xx-optics",
816817
"ERS.ne4pg2_oQU480.F2010-EAMxx-MAM4xx.eamxx-mam4xx-aci",

components/eamxx/cime_config/namelist_defaults_eamxx.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ be lost if SCREAM_HACK_XML is not enabled.
297297
<!-- MAM4xx-Aerosol-Microphysics -->
298298
<mam4_aero_microphys inherit="mam4_atm_proc_base">
299299
<!--Aerosol Microphysics processes on/off switches -->
300+
<extra_mam4_aero_microphys_diags type="logical" doc="Extra MAM4xx aerosol microphysics diagnostics">false</extra_mam4_aero_microphys_diags>
300301
<mam4_do_cond type="logical" doc="Switch to enable aerosol microphysics condensation process">true</mam4_do_cond>
301302
<mam4_do_newnuc type="logical" doc="Switch to enable aerosol microphysics nucleation process">true</mam4_do_newnuc>
302303
<mam4_do_coag type="logical" doc="Switch to enable aerosol microphysics coagulation process">true</mam4_do_coag>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
alias ATMCHANGE='$CIMEROOT/../components/eamxx/scripts/atmchange'
2+
3+
#------------------------------------------------------
4+
# Turn on extra diagnostics for aerosol microphysics
5+
#------------------------------------------------------
6+
ATMCHANGE extra_mam4_aero_microphys_diags="true" -b

components/eamxx/src/physics/mam/eamxx_mam_microphysics_process_interface.cpp

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -128,17 +128,17 @@ void MAMMicrophysics::set_grids(
128128
constexpr int nmodes = mam4::AeroConfig::num_modes();
129129

130130
// layout for 3D (ncol, nmodes, nlevs)
131-
FieldLayout scalar3d_mid_nmodes = grid_->get_3d_vector_layout(
131+
FieldLayout vector3d_mid_nmodes = grid_->get_3d_vector_layout(
132132
true, nmodes, mam_coupling::num_modes_tag_name());
133133

134134
// Geometric mean dry diameter for number distribution [m]
135-
add_field<Required>("dgnum", scalar3d_mid_nmodes, m, grid_name);
135+
add_field<Required>("dgnum", vector3d_mid_nmodes, m, grid_name);
136136
// Geometric mean wet diameter for number distribution [m]
137-
add_field<Required>("dgnumwet", scalar3d_mid_nmodes, m, grid_name);
137+
add_field<Required>("dgnumwet", vector3d_mid_nmodes, m, grid_name);
138138

139139
constexpr auto m3 = pow(m, 3);
140140
// Wet density of interstitial aerosol [kg/m3]
141-
add_field<Required>("wetdens", scalar3d_mid_nmodes, kg / m3, grid_name);
141+
add_field<Required>("wetdens", vector3d_mid_nmodes, kg / m3, grid_name);
142142

143143
// For fractional land use
144144
const FieldLayout vector2d_class =
@@ -161,12 +161,6 @@ void MAMMicrophysics::set_grids(
161161
// Downwelling solar flux at the surface [w/m2]
162162
add_field<Required>("SW_flux_dn", scalar3d_int, W / m2, grid_name);
163163

164-
// Diagnostic fluxes
165-
const FieldLayout vector2d_nmodes =
166-
grid_->get_2d_vector_layout(nmodes, "nmodes");
167-
add_field<Computed>("dqdt_so4_aqueous_chemistry", vector2d_nmodes, kg/m2/s, grid_name);
168-
add_field<Computed>("dqdt_h2so4_uptake", vector2d_nmodes, kg/m2/s, grid_name);
169-
170164
// ---------------------------------------------------------------------
171165
// These variables are "updated" or inputs/outputs for the process
172166
// ---------------------------------------------------------------------
@@ -181,21 +175,43 @@ void MAMMicrophysics::set_grids(
181175
add_fields_cloudborne_aerosol();
182176
//----------- Updated variables from other mam4xx processes ------------
183177
// layout for Constituent fluxes
184-
FieldLayout scalar2d_pcnst =
178+
FieldLayout vector2d_pcnst =
185179
grid_->get_2d_vector_layout(mam4::pcnst, "num_phys_constituents");
186-
187180
// Constituent fluxes of species in [kg/m2/s]
188-
add_field<Updated>("constituent_fluxes", scalar2d_pcnst, kg / m2 / s,
181+
add_field<Updated>("constituent_fluxes", vector2d_pcnst, kg / m2 / s,
189182
grid_name);
190183

184+
// ---------------------------------------------------------------------
185+
// These variables are "computed" or outputs for the process
186+
// ---------------------------------------------------------------------
191187
// Number of externally forced chemical species
192188
constexpr int extcnt = mam4::gas_chemistry::extcnt;
193189

194-
FieldLayout scalar3d_extcnt = grid_->get_3d_vector_layout(true, extcnt, "ext_cnt");
190+
FieldLayout vector3d_extcnt = grid_->get_3d_vector_layout(true, extcnt, "ext_cnt");
195191

196192
// Register computed fields for external forcing
197193
// - extfrc: 3D instantaneous forcing rate [kg/m³/s]
198-
add_field<Computed>("mam4_external_forcing", scalar3d_extcnt, kg / m3 / s, grid_name);
194+
add_field<Computed>("mam4_external_forcing", vector3d_extcnt, kg / m3 / s, grid_name);
195+
196+
// Diagnostic fluxes
197+
const FieldLayout vector2d_nmodes =
198+
grid_->get_2d_vector_layout(nmodes, "nmodes");
199+
200+
// Register computed diagnostic fields
201+
add_field<Computed>("dqdt_so4_aqueous_chemistry", vector2d_nmodes, kg/m2/s, grid_name);
202+
add_field<Computed>("dqdt_h2so4_uptake", vector2d_nmodes, kg/m2/s, grid_name);
203+
204+
// Diagnostic fields for aerosol microphysics
205+
extra_mam4_aero_microphys_diags_ = m_params.get<bool>("extra_mam4_aero_microphys_diags", false);
206+
if (extra_mam4_aero_microphys_diags_) {
207+
const FieldLayout vector3d_num_gas_aerosol_constituents =
208+
grid_->get_3d_vector_layout(true, mam_coupling::gas_pcnst(), "num_gas_aerosol_constituents");
209+
210+
// Fields for tendencies due to gas phase chemistry
211+
// - dvmr/dt: Tendencies for mixing ratios [kg/kg/s]
212+
add_field<Computed>("mam4_microphysics_tendency_gas_phase_chemistry", vector3d_num_gas_aerosol_constituents, kg / kg / s, grid_name);
213+
add_field<Computed>("mam4_microphysics_tendency_aqueous_chemistry", vector3d_num_gas_aerosol_constituents, kg / kg / s, grid_name);
214+
}
199215

200216
// Creating a Linoz reader and setting Linoz parameters involves reading data
201217
// from a file and configuring the necessary parameters for the Linoz model.
@@ -637,6 +653,13 @@ void MAMMicrophysics::run_impl(const double dt) {
637653
view_2d aqso4_flx = get_field_out("dqdt_so4_aqueous_chemistry").get_view<Real **>();
638654
view_2d aqh2so4_flx = get_field_out("dqdt_h2so4_uptake").get_view<Real **>();
639655

656+
// - dvmr/dt: Tendencies for mixing ratios [kg/kg/s]
657+
view_3d gas_phase_chemistry_dvmrdt, aqueous_chemistry_dvmrdt;
658+
if (extra_mam4_aero_microphys_diags_) {
659+
gas_phase_chemistry_dvmrdt = get_field_out("mam4_microphysics_tendency_gas_phase_chemistry").get_view<Real ***>();
660+
aqueous_chemistry_dvmrdt = get_field_out("mam4_microphysics_tendency_aqueous_chemistry").get_view<Real ***>();
661+
}
662+
640663
// climatology data for linear stratospheric chemistry
641664
// ozone (climatology) [vmr]
642665
auto linoz_o3_clim = buffer_.scratch[0];
@@ -774,18 +797,18 @@ void MAMMicrophysics::run_impl(const double dt) {
774797
Kokkos::deep_copy(acos_cosine_zenith_, acos_cosine_zenith_host_);
775798
}
776799
const auto zenith_angle = acos_cosine_zenith_;
777-
constexpr int gas_pcnst = mam_coupling::gas_pcnst();
800+
constexpr int num_gas_aerosol_constituents = mam_coupling::gas_pcnst();
778801

779802
const auto &extfrc = extfrc_;
780803
const auto &forcings = forcings_;
781804
constexpr int extcnt = mam4::gas_chemistry::extcnt;
782805

783806
const int offset_aerosol = mam4::utils::gasses_start_ind();
784-
Real adv_mass_kg_per_moles[gas_pcnst];
807+
Real adv_mass_kg_per_moles[num_gas_aerosol_constituents];
785808
// NOTE: Making copies of clsmap_4 and permute_4 to fix undefined arrays on
786809
// the device.
787-
int clsmap_4[gas_pcnst], permute_4[gas_pcnst];
788-
for(int i = 0; i < gas_pcnst; ++i) {
810+
int clsmap_4[num_gas_aerosol_constituents], permute_4[num_gas_aerosol_constituents];
811+
for(int i = 0; i < num_gas_aerosol_constituents; ++i) {
789812
// NOTE: state_q is kg/kg-dry-air; adv_mass is in g/mole.
790813
// Convert adv_mass to kg/mole as vmr_from_mmr function uses
791814
// molec_weight_dry_air with kg/mole units
@@ -802,6 +825,8 @@ void MAMMicrophysics::run_impl(const double dt) {
802825
const int surface_lev = nlev - 1; // Surface level
803826
const auto &index_season_lai = index_season_lai_;
804827
const int pcnst = mam4::pcnst;
828+
const bool extra_mam4_aero_microphys_diags = extra_mam4_aero_microphys_diags_;
829+
805830
//NOTE: we need to initialize photo_rates_
806831
Kokkos::deep_copy(photo_rates_,0.0);
807832
// loop over atmosphere columns and compute aerosol microphyscs
@@ -874,6 +899,12 @@ void MAMMicrophysics::run_impl(const double dt) {
874899
const auto prain_icol = ekat::subview(prain, icol);
875900
const auto work_set_het_icol = ekat::subview(work_set_het, icol);
876901

902+
mam4::MicrophysDiagnosticArrays diag_arrays;
903+
if (extra_mam4_aero_microphys_diags) {
904+
diag_arrays.gas_phase_chemistry_dvmrdt = ekat::subview(gas_phase_chemistry_dvmrdt, icol);
905+
diag_arrays.aqueous_chemistry_dvmrdt = ekat::subview(aqueous_chemistry_dvmrdt, icol);
906+
}
907+
877908
// Wind speed at the surface
878909
const Real wind_speed =
879910
haero::sqrt(u_wind(icol, surface_lev) * u_wind(icol, surface_lev) +
@@ -918,8 +949,8 @@ void MAMMicrophysics::run_impl(const double dt) {
918949
// These output values need to be put somewhere:
919950
const auto aqso4_flx_col = ekat::subview(aqso4_flx, icol); // deposition flux of so4 [mole/mole/s]
920951
const auto aqh2so4_flx_col = ekat::subview(aqh2so4_flx, icol); // deposition flux of h2so4 [mole/mole/s]
921-
Real dflx_col[gas_pcnst] = {}; // deposition velocity [1/cm/s]
922-
Real dvel_col[gas_pcnst] = {}; // deposition flux [1/cm^2/s]
952+
Real dflx_col[num_gas_aerosol_constituents] = {}; // deposition velocity [1/cm/s]
953+
Real dvel_col[num_gas_aerosol_constituents] = {}; // deposition flux [1/cm^2/s]
923954
// Output: values are dvel, dflx
924955
// Input/Output: progs::stateq, progs::qqcw
925956
team.team_barrier();
@@ -937,7 +968,8 @@ void MAMMicrophysics::run_impl(const double dt) {
937968
offset_aerosol, config.linoz.o3_sfc, config.linoz.o3_tau,
938969
config.linoz.o3_lbl, dry_diameter_icol, wet_diameter_icol,
939970
wetdens_icol, dry_atm.phis(icol), cmfdqr, prain_icol, nevapr_icol,
940-
work_set_het_icol, drydep_data, aqso4_flx_col, aqh2so4_flx_col, dvel_col, dflx_col, progs);
971+
work_set_het_icol, drydep_data, aqso4_flx_col, aqh2so4_flx_col, diag_arrays,
972+
dvel_col, dflx_col, progs);
941973

942974
team.team_barrier();
943975
// Update constituent fluxes with gas drydep fluxes (dflx)
@@ -958,8 +990,8 @@ void MAMMicrophysics::run_impl(const double dt) {
958990
// NOTE: These indices should match the species in extfrc_lst
959991
// TODO: getting rid of hard-coded indices
960992
Kokkos::Array<int, extcnt> extfrc_pcnst_index = {3, 6, 14, 27, 28, 13, 18, 30, 5};
961-
Kokkos::Array<Real, gas_pcnst> molar_mass_g_per_mol_tmp;
962-
for (int i = 0; i < gas_pcnst; ++i) {
993+
Kokkos::Array<Real, num_gas_aerosol_constituents> molar_mass_g_per_mol_tmp;
994+
for (int i = 0; i < num_gas_aerosol_constituents; ++i) {
963995
molar_mass_g_per_mol_tmp[i] = mam4::gas_chemistry::adv_mass[i]; // host-only access
964996
}
965997

components/eamxx/src/physics/mam/eamxx_mam_microphysics_process_interface.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ class MAMMicrophysics final : public MAMGenericInterface {
6161
void finalize_impl(){/*Do nothing*/};
6262

6363
private:
64+
// Output extra mam4xx diagnostics.
65+
bool extra_mam4_aero_microphys_diags_ = false;
66+
6467
// The orbital year, used for zenith angle calculations:
6568
// If > 0, use constant orbital year for duration of simulation
6669
// If < 0, use year from timestamp for orbital parameters

0 commit comments

Comments
 (0)