Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EAMxx: abstract MAMGenericInterface and check intervals in MAM4xx fields. #7054

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions components/eamxx/cime_config/namelist_defaults_eamxx.xml
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ be lost if SCREAM_HACK_XML is not enabled.
<enable_aero_vertical_mix type="logical" doc="Enable vertical mixing of interstitial aerosols and liquid number during activation">true</enable_aero_vertical_mix>
<top_level_mam4xx type="integer" doc="Level corresponding to the top of troposphere clouds" nlev="72" >6</top_level_mam4xx>
<top_level_mam4xx type="integer" doc="level corresponding to the top of troposphere clouds" nlev="128" >0</top_level_mam4xx>
<create_fields_interval_checks type="logical" doc="Create field interval checks for all fields that are computed and requested in mam4xx." >false</create_fields_interval_checks>
</mam4_aci>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since you introduced the generic process, it might be worthwhile adding an equivalent to it here as well and then you can house shared options in the generic process and all other inheritors will inherit those options. This will help with less code duplication (e.g., you're repeating create_fields_interval_checks for each process, but you can just store in the generic one)


<!-- MAM4xx-Dry Deposition -->
Expand All @@ -268,6 +269,7 @@ be lost if SCREAM_HACK_XML is not enabled.
<drydep_remap_file hgrid="ne256np4.pg2">${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne256pg2_20231201.nc</drydep_remap_file>
<drydep_remap_file hgrid="ne512np4.pg2">${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne512pg2_20231201.nc</drydep_remap_file>
<drydep_remap_file hgrid="ne1024np4.pg2">${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne1024pg2_20231201.nc</drydep_remap_file>
<create_fields_interval_checks type="logical" doc="Create field interval checks for all fields that are computed and requested in mam4xx." >false</create_fields_interval_checks>
</mam4_drydep>

<!-- CLD fraction -->
Expand Down Expand Up @@ -331,7 +333,7 @@ be lost if SCREAM_HACK_XML is not enabled.
<aero_microphys_remap_file hgrid="ne256np4.pg2">${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne256pg2_20231201.nc</aero_microphys_remap_file>
<aero_microphys_remap_file hgrid="ne512np4.pg2">${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne512pg2_20231201.nc</aero_microphys_remap_file>
<aero_microphys_remap_file hgrid="ne1024np4.pg2">${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne1024pg2_20231201.nc</aero_microphys_remap_file>

<create_fields_interval_checks type="logical" doc="Create field interval checks for all fields that are computed and requested in mam4xx." >false</create_fields_interval_checks>
</mam4_aero_microphys>

<!-- MAM4xx-Optics -->
Expand All @@ -348,10 +350,13 @@ be lost if SCREAM_HACK_XML is not enabled.
<mam4_pom_physical_properties_file type="file" doc="File containing optical properties for primary organic aerosol">${DIN_LOC_ROOT}/atm/scream/mam4xx/physprops/ocpho_rrtmg_c20240206.nc</mam4_pom_physical_properties_file>
<mam4_bc_physical_properties_file type="file" doc="File containing optical properties for black carbon">${DIN_LOC_ROOT}/atm/scream/mam4xx/physprops/bcpho_rrtmg_c20240206.nc</mam4_bc_physical_properties_file>
<mam4_mom_physical_properties_file type="file" doc="File containing optical properties for marine organic aerosol">${DIN_LOC_ROOT}/atm/scream/mam4xx/physprops/poly_rrtmg_c20240206.nc</mam4_mom_physical_properties_file>
<create_fields_interval_checks type="logical" doc="Create field interval checks for all fields that are computed and requested in mam4xx." >false</create_fields_interval_checks>
</mam4_optics>

<!-- MAM4xx-Wetscav -->
<mam4_wetscav inherit="atm_proc_base" />
<mam4_wetscav inherit="atm_proc_base" >
<create_fields_interval_checks type="logical" doc="Create field interval checks for all fields that are computed and requested in mam4xx." >false</create_fields_interval_checks>
</mam4_wetscav>

<!-- MAM4xx-Surface-Emissions -->
<mam4_srf_online_emiss inherit="atm_proc_base">
Expand Down Expand Up @@ -390,10 +395,13 @@ be lost if SCREAM_HACK_XML is not enabled.
<srf_remap_file hgrid="ne256np4.pg2">${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne256pg2_20231201.nc</srf_remap_file>
<srf_remap_file hgrid="ne512np4.pg2">${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne512pg2_20231201.nc</srf_remap_file>
<srf_remap_file hgrid="ne1024np4.pg2">${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne1024pg2_20231201.nc</srf_remap_file>
<create_fields_interval_checks type="logical" doc="Create field interval checks for all fields that are computed and requested in mam4xx." >false</create_fields_interval_checks>
</mam4_srf_online_emiss>

<!-- MAM4xx-constituent fluxes -->
<mam4_constituent_fluxes inherit="atm_proc_base" />
<mam4_constituent_fluxes inherit="atm_proc_base" >
<create_fields_interval_checks type="logical" doc="Create field interval checks for all fields that are computed and requested in mam4xx." >false</create_fields_interval_checks>
</mam4_constituent_fluxes>

<!-- nudging -->
<nudging inherit="atm_proc_base">
Expand Down
1 change: 1 addition & 0 deletions components/eamxx/src/physics/mam/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ add_subdirectory(${EXTERNALS_SOURCE_DIR}/mam4xx ${CMAKE_BINARY_DIR}/externals/ma

# EAMxx mam4xx-based atmospheric processes
add_library(mam
eamxx_mam_generic_process_interface.cpp
eamxx_mam_microphysics_process_interface.cpp
${SCREAM_BASE_DIR}/src/physics/rrtmgp/shr_orb_mod_c2f.F90
eamxx_mam_optics_process_interface.cpp
Expand Down
173 changes: 11 additions & 162 deletions components/eamxx/src/physics/mam/eamxx_mam_aci_process_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

// For EKAT units package
#include "ekat/util/ekat_units.hpp"

#include <physics/mam/physical_limits.hpp>
/*
-----------------------------------------------------------------
NOTES:
Expand Down Expand Up @@ -36,7 +36,7 @@ directly

namespace scream {
MAMAci::MAMAci(const ekat::Comm &comm, const ekat::ParameterList &params)
: AtmosphereProcess(comm, params) {
: MAMGenericInterface(comm, params) {
// Asserts for the runtime or namelist options
EKAT_REQUIRE_MSG(m_params.isParameter("wsubmin"),
"ERROR: wsubmin is missing from mam_aci parameter list.");
Expand All @@ -46,6 +46,8 @@ MAMAci::MAMAci(const ekat::Comm &comm, const ekat::ParameterList &params)
EKAT_REQUIRE_MSG(
m_params.isParameter("top_level_mam4xx"),
"ERROR: top_level_mam4xx is missing from mam_aci parameter list.");
check_fields_intervals_ = m_params.get<bool>("create_fields_interval_checks", false);

}

// ================================================================
Expand All @@ -72,53 +74,13 @@ void MAMAci::set_grids(
// Layout for 3D (2d horiz X 1d vertical) variable defined at mid-level and
// interfaces
const FieldLayout scalar3d_mid = grid_->get_3d_scalar_layout(true);
const FieldLayout scalar3d_int = grid_->get_3d_scalar_layout(false);

// layout for 2D (1d horiz X 1d vertical) variable
FieldLayout scalar2d_layout_col{{COL}, {ncol_}};

using namespace ekat::units;
constexpr auto q_unit = kg / kg; // units of mass mixing ratios of tracers
constexpr auto n_unit = 1 / kg; // units of number mixing ratios of tracers

constexpr auto nondim = ekat::units::Units::nondimensional();

// atmospheric quantities
// specific humidity [kg/kg]
add_tracer<Required>("qv", grid_, q_unit);

// cloud liquid mass mixing ratio [kg/kg]
add_tracer<Required>("qc", grid_, q_unit);

// cloud ice mass mixing ratio [kg/kg]
add_tracer<Required>("qi", grid_, q_unit);

// cloud liquid number mixing ratio [1/kg]
add_tracer<Required>("nc", grid_, n_unit);

// cloud ice number mixing ratio [1/kg]
add_tracer<Required>("ni", grid_, n_unit);

// Temperature[K] at midpoints
add_field<Required>("T_mid", scalar3d_mid, K, grid_name);

// Vertical pressure velocity [Pa/s] at midpoints
add_field<Required>("omega", scalar3d_mid, Pa / s, grid_name);

// Total pressure [Pa] at midpoints
add_field<Required>("p_mid", scalar3d_mid, Pa, grid_name);

// Total pressure [Pa] at interfaces
add_field<Required>("p_int", scalar3d_int, Pa, grid_name);

// Layer thickness(pdel) [Pa] at midpoints
add_field<Required>("pseudo_density", scalar3d_mid, Pa, grid_name);

// planetary boundary layer height
add_field<Required>("pbl_height", scalar2d_layout_col, m, grid_name);

// cloud fraction [nondimensional] computed by eamxx_cld_fraction_process
add_field<Required>("cldfrac_tot", scalar3d_mid, nondim, grid_name);
add_tracers_wet_and_dry_atm();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these are all "wet" tracers, can we change the name of this function to "add_fields_and_wet_atm_tracers"?
We should keep in mind that we may need to revisit this when we further prune these to match what we actually need in a process. Currently, we need all these to build the data structures that MAM4xx expects.


constexpr auto m2 = pow(m, 2);
constexpr auto s2 = pow(s, 2);
Expand Down Expand Up @@ -160,41 +122,7 @@ void MAMAci::set_grids(

// interstitial and cloudborne aerosol tracers of interest: mass (q) and
// number (n) mixing ratios
for(int mode = 0; mode < mam_coupling::num_aero_modes(); ++mode) {
// interstitial aerosol tracers of interest: number (n) mixing ratios
const char *int_nmr_field_name =
mam_coupling::int_aero_nmr_field_name(mode);
add_tracer<Updated>(int_nmr_field_name, grid_, n_unit);

// cloudborne aerosol tracers of interest: number (n) mixing ratios
// NOTE: DO NOT add cld borne aerosols to the "tracer" group as these are
// NOT advected
const char *cld_nmr_field_name =
mam_coupling::cld_aero_nmr_field_name(mode);
add_field<Updated>(cld_nmr_field_name, scalar3d_mid, n_unit, grid_name);

for(int a = 0; a < mam_coupling::num_aero_species(); ++a) {
// (interstitial) aerosol tracers of interest: mass (q) mixing ratios
const char *int_mmr_field_name =
mam_coupling::int_aero_mmr_field_name(mode, a);
if(strlen(int_mmr_field_name) > 0) {
add_tracer<Updated>(int_mmr_field_name, grid_, q_unit);
}
// (cloudborne) aerosol tracers of interest: mass (q) mixing ratios
// NOTE: DO NOT add cld borne aerosols to the "tracer" group as these are
// NOT advected
const char *cld_mmr_field_name =
mam_coupling::cld_aero_mmr_field_name(mode, a);
if(strlen(cld_mmr_field_name) > 0) {
add_field<Updated>(cld_mmr_field_name, scalar3d_mid, q_unit, grid_name);
}
} // end for loop num species
} // end for loop for num modes

for(int g = 0; g < mam_coupling::num_aero_gases(); ++g) {
const char *gas_mmr_field_name = mam_coupling::gas_mmr_field_name(g);
add_tracer<Updated>(gas_mmr_field_name, grid_, q_unit);
} // end for loop num gases
add_tracers_aerosol_and_gases();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed, we should split this into 3 functions (interstitial, cloud-borne, and gasses), as some interfaces may only need two of these.


// ------------------------------------------------------------------------
// Output from ice nucleation process
Expand Down Expand Up @@ -273,7 +201,8 @@ void MAMAci::initialize_impl(const RunType run_type) {
// ------------------------------------------------------------------------
// ## Runtime options
// ------------------------------------------------------------------------

// Check pre/post condition interval values for all fields employed by this interface
add_interval_checks();
wsubmin_ = m_params.get<double>("wsubmin");
enable_aero_vertical_mix_ = m_params.get<bool>("enable_aero_vertical_mix");
top_lev_ = m_params.get<int>("top_level_mam4xx");
Expand All @@ -287,45 +216,7 @@ void MAMAci::initialize_impl(const RunType run_type) {
liqcldf_prev_ = get_field_in("cldfrac_liq_prev").get_view<const Real **>();
kvh_mid_ = get_field_in("eddy_diff_heat").get_view<const Real **>();

// store fields only to be converted to dry mmrs in wet_atm_
wet_atm_.qv = get_field_in("qv").get_view<const Real **>();
wet_atm_.qc = get_field_in("qc").get_view<const Real **>();
wet_atm_.nc = get_field_in("nc").get_view<const Real **>();
wet_atm_.qi = get_field_in("qi").get_view<const Real **>();
wet_atm_.ni = get_field_in("ni").get_view<const Real **>();

// store rest fo the atm fields in dry_atm_in
dry_atm_.z_surf = 0;
dry_atm_.T_mid = get_field_in("T_mid").get_view<const Real **>();
dry_atm_.p_mid = get_field_in("p_mid").get_view<const Real **>();
dry_atm_.p_int = get_field_in("p_int").get_view<const Real **>();
dry_atm_.p_del = get_field_in("pseudo_density").get_view<const Real **>();
dry_atm_.omega = get_field_in("omega").get_view<const Real **>();

// store fields converted to dry mmr from wet mmr in dry_atm_
dry_atm_.qv = buffer_.qv_dry;
dry_atm_.qc = buffer_.qc_dry;
dry_atm_.nc = buffer_.nc_dry;
dry_atm_.qi = buffer_.qi_dry;
dry_atm_.ni = buffer_.ni_dry;

// pbl_height
dry_atm_.pblh = get_field_in("pbl_height").get_view<const Real *>();

// geometric thickness of layers (m)
dry_atm_.dz = buffer_.dz;

// geopotential height above surface at interface levels (m)
dry_atm_.z_iface = buffer_.z_iface;

// geopotential height above surface at mid levels (m)
dry_atm_.z_mid = buffer_.z_mid;

// total cloud fraction
dry_atm_.cldfrac = get_field_in("cldfrac_tot").get_view<const Real **>();

// computed updraft velocity
dry_atm_.w_updraft = buffer_.w_updraft;
populate_wet_and_dry_atm();

// ------------------------------------------------------------------------
// Output fields to be used by other processes
Expand All @@ -338,46 +229,7 @@ void MAMAci::initialize_impl(const RunType run_type) {

// interstitial and cloudborne aerosol tracers of interest: mass (q) and
// number (n) mixing ratios
for(int m = 0; m < mam_coupling::num_aero_modes(); ++m) {
// interstitial aerosol tracers of interest: number (n) mixing ratios
const char *int_nmr_field_name = mam_coupling::int_aero_nmr_field_name(m);
wet_aero_.int_aero_nmr[m] =
get_field_out(int_nmr_field_name).get_view<Real **>();
dry_aero_.int_aero_nmr[m] = buffer_.dry_int_aero_nmr[m];

// cloudborne aerosol tracers of interest: number (n) mixing ratios
const char *cld_nmr_field_name = mam_coupling::cld_aero_nmr_field_name(m);
wet_aero_.cld_aero_nmr[m] =
get_field_out(cld_nmr_field_name).get_view<Real **>();
dry_aero_.cld_aero_nmr[m] = buffer_.dry_cld_aero_nmr[m];

for(int a = 0; a < mam_coupling::num_aero_species(); ++a) {
// (interstitial) aerosol tracers of interest: mass (q) mixing ratios
const char *int_mmr_field_name =
mam_coupling::int_aero_mmr_field_name(m, a);

if(strlen(int_mmr_field_name) > 0) {
wet_aero_.int_aero_mmr[m][a] =
get_field_out(int_mmr_field_name).get_view<Real **>();
dry_aero_.int_aero_mmr[m][a] = buffer_.dry_int_aero_mmr[m][a];
}

// (cloudborne) aerosol tracers of interest: mass (q) mixing ratios
const char *cld_mmr_field_name =
mam_coupling::cld_aero_mmr_field_name(m, a);
if(strlen(cld_mmr_field_name) > 0) {
wet_aero_.cld_aero_mmr[m][a] =
get_field_out(cld_mmr_field_name).get_view<Real **>();
dry_aero_.cld_aero_mmr[m][a] = buffer_.dry_cld_aero_mmr[m][a];
}
}
}
for(int g = 0; g < mam_coupling::num_aero_gases(); ++g) {
const char *gas_mmr_field_name = mam_coupling::gas_mmr_field_name(g);
wet_aero_.gas_mmr[g] =
get_field_out(gas_mmr_field_name).get_view<Real **>();
dry_aero_.gas_mmr[g] = buffer_.dry_gas_mmr[g];
}
populate_wet_and_dry_aero();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please split this function into three: interstitial, cloud-borne and gasses.


// hetrozenous freezing outputs
hetfrz_immersion_nucleation_tend_ =
Expand Down Expand Up @@ -531,9 +383,6 @@ void MAMAci::initialize_impl(const RunType run_type) {
preprocess_.initialize(ncol_, nlev_, wet_atm_, wet_aero_, dry_atm_,
dry_aero_);

postprocess_.initialize(ncol_, nlev_, wet_atm_, wet_aero_, dry_atm_,
dry_aero_);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for removing the repeated code!

} // end function initialize_impl

// ================================================================
Expand Down Expand Up @@ -657,7 +506,7 @@ void MAMAci::run_impl(const double dt) {
dry_aero_);

// call post processing to convert dry mixing ratios to wet mixing ratios
Kokkos::parallel_for("postprocess", scan_policy, postprocess_);
post_process();
Kokkos::fence(); // wait before returning to calling function
}

Expand Down
Loading
Loading