From af7fdb2893bcba9f51b96c146b52d1bb50c85059 Mon Sep 17 00:00:00 2001 From: tcclevenger Date: Tue, 29 Oct 2024 15:01:35 -0600 Subject: [PATCH 1/7] Allow for not advecting tracers in shoc - AtmosphereProcess::add_tracer() now takes in bool turbulence_advected which dictates if shoc advects tracer or ignores - SHOC requests group "turbulence_advected_tracers", not full "tracers" array - FieldRequest includes a "calling_process" var for error output --- .../eamxx/src/control/atmosphere_driver.cpp | 50 ++++++++++++++++++- .../atmosphere_surface_coupling_exporter.cpp | 2 +- .../homme/eamxx_homme_process_interface.cpp | 2 +- .../eamxx_cld_fraction_process_interface.cpp | 2 +- .../eamxx/src/physics/cosp/eamxx_cosp.cpp | 6 +-- .../eamxx_mam_generic_process_interface.cpp | 22 ++++---- .../eamxx_mam_optics_process_interface.cpp | 2 +- .../eamxx_ml_correction_process_interface.cpp | 2 +- .../eamxx_nudging_process_interface.cpp | 2 +- .../physics/p3/eamxx_p3_process_interface.cpp | 18 +++---- .../shoc/eamxx_shoc_process_interface.cpp | 12 ++--- .../tms/eamxx_tms_process_interface.cpp | 2 +- .../share/atm_process/atmosphere_process.hpp | 15 +++++- .../eamxx/src/share/field/field_manager.cpp | 5 ++ .../eamxx/src/share/field/field_request.hpp | 7 ++- 15 files changed, 109 insertions(+), 40 deletions(-) diff --git a/components/eamxx/src/control/atmosphere_driver.cpp b/components/eamxx/src/control/atmosphere_driver.cpp index 3339e7f5e61e..07a67f648187 100644 --- a/components/eamxx/src/control/atmosphere_driver.cpp +++ b/components/eamxx/src/control/atmosphere_driver.cpp @@ -535,8 +535,54 @@ void AtmosphereDriver::create_fields() m_field_mgr = std::make_shared(m_grids_manager); m_field_mgr->registration_begins(); - // By now, the processes should have fully built the ids of their - // required/computed fields and groups. Let them register them in the FM + // Before registering fields, check that Field Requests for tracers are compatible + { + // Create map from tracer name to a vector which contains the field requests for that tracer. + std::map> tracer_requests; + auto gather_tracer_requests = [&] (FieldRequest req) { + if (not ekat::contains(req.groups, "tracers")) return; + + std::string fname = req.fid.name(); + if (tracer_requests.find(fname) == tracer_requests.end()) { + tracer_requests[fname] = {req}; + } else { + tracer_requests[fname].emplace(req); + } + }; + for (const auto& req : m_atm_process_group->get_required_field_requests()){ + gather_tracer_requests(req); + } + for (const auto& req : m_atm_process_group->get_computed_field_requests()) { + gather_tracer_requests(req); + } + + // Go through the map entry for each tracer and check that every one + // has the same request for turbulence advection. + for (auto fr : tracer_requests) { + const auto reqs = fr.second; + + std::set turb_advect_types; + for (auto req : reqs) { + turb_advect_types.emplace(ekat::contains(req.groups, "turbulence_advected_tracers")); + } + + if (turb_advect_types.size()!=1) { + std::ostringstream ss; + ss << "Error! Incompatible tracer request. Turbulence advection requests not consistent among processes.\n" + " - Tracer name: " + fr.first + "\n" + " - Requests (process name, grid name, is tracers turbulence advected):\n"; + for (auto req : reqs) { + const auto grid_name = req.fid.get_grid_name(); + const bool turb_advect = ekat::contains(req.groups, "turbulence_advected_tracers"); + ss << " - (" + req.calling_process + ", " + grid_name + ", " + (turb_advect ? "true" : "false") + ")\n"; + } + EKAT_ERROR_MSG(ss.str()); + } + } + } + + // Register required/computed fields. By now, the processes should have + // fully built the ids of their required/computed fields and groups for (const auto& req : m_atm_process_group->get_required_field_requests()) { m_field_mgr->register_field(req); } diff --git a/components/eamxx/src/control/atmosphere_surface_coupling_exporter.cpp b/components/eamxx/src/control/atmosphere_surface_coupling_exporter.cpp index b4264dd7243c..c9aeb7d8620c 100644 --- a/components/eamxx/src/control/atmosphere_surface_coupling_exporter.cpp +++ b/components/eamxx/src/control/atmosphere_surface_coupling_exporter.cpp @@ -44,7 +44,7 @@ void SurfaceCouplingExporter::set_grids(const std::shared_ptr("phis", scalar2d_layout, m2/s2, grid_name); add_field("p_mid", scalar3d_layout_mid, Pa, grid_name, ps); add_field("T_mid", scalar3d_layout_mid, K, grid_name, ps); - add_tracer("qv", m_grid, kg/kg, ps); + add_tracer("qv", m_grid, kg/kg, true, ps); // TODO: Switch horiz_winds to using U and V, note right now there is an issue with when the subfields are created, so can't switch yet. add_field("horiz_winds", vector3d_layout, m/s, grid_name); add_field("sfc_flux_dir_nir", scalar2d_layout, W/m2, grid_name); diff --git a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp index 452a5b5fbee0..2f5842e46070 100644 --- a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp +++ b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp @@ -179,7 +179,7 @@ void HommeDynamics::set_grids (const std::shared_ptr grids_m add_field("p_dry_mid", pg_scalar3d_mid, Pa, pgn,N); add_field("omega", pg_scalar3d_mid, Pa/s, pgn,N); - add_tracer("qv", m_phys_grid, kg/kg, N); + add_tracer("qv", m_phys_grid, kg/kg, true, N); add_group("tracers",pgn,N, true); if (fv_phys_active()) { diff --git a/components/eamxx/src/physics/cld_fraction/eamxx_cld_fraction_process_interface.cpp b/components/eamxx/src/physics/cld_fraction/eamxx_cld_fraction_process_interface.cpp index b41dcc1f2720..6b99e8e09ace 100644 --- a/components/eamxx/src/physics/cld_fraction/eamxx_cld_fraction_process_interface.cpp +++ b/components/eamxx/src/physics/cld_fraction/eamxx_cld_fraction_process_interface.cpp @@ -38,7 +38,7 @@ void CldFraction::set_grids(const std::shared_ptr grids_mana // Set of fields used strictly as input constexpr int ps = Pack::n; - add_tracer("qi", m_grid, kg/kg, ps); + add_tracer("qi", m_grid, kg/kg, true, ps); add_field("cldfrac_liq", scalar3d_layout_mid, nondim, grid_name,ps); // Set of fields used strictly as output diff --git a/components/eamxx/src/physics/cosp/eamxx_cosp.cpp b/components/eamxx/src/physics/cosp/eamxx_cosp.cpp index 43228684cfed..4047518336d3 100644 --- a/components/eamxx/src/physics/cosp/eamxx_cosp.cpp +++ b/components/eamxx/src/physics/cosp/eamxx_cosp.cpp @@ -75,9 +75,9 @@ void Cosp::set_grids(const std::shared_ptr grids_manager) add_field("phis", scalar2d , m2/s2, grid_name); add_field("pseudo_density", scalar3d_mid, Pa, grid_name); add_field("cldfrac_rad", scalar3d_mid, nondim, grid_name); - add_tracer("qv", m_grid, kg/kg); - add_tracer("qc", m_grid, kg/kg); - add_tracer("qi", m_grid, kg/kg); + add_tracer("qv", m_grid, kg/kg, true); + add_tracer("qc", m_grid, kg/kg, true); + add_tracer("qi", m_grid, kg/kg, true); // Optical properties, should be computed in radiation interface add_field("dtau067", scalar3d_mid, nondim, grid_name); // 0.67 micron optical depth add_field("dtau105", scalar3d_mid, nondim, grid_name); // 10.5 micron optical depth diff --git a/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp b/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp index 4fc7390f8ebf..2a2c1ef7d22b 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp @@ -140,8 +140,10 @@ void MAMGenericInterface::add_tracers_interstitial_aerosol() { // --------------------------------------------------------------------- // These variables are "Updated" or inputs/outputs for the process // --------------------------------------------------------------------- - // NOTE: Cloud borne aerosols are not updated in this process but are included - // to create data structures. + // NOTE: + // - Cloud borne aerosols are not updated in this process but are included + // to create data structures. + // - For interstitial aerosols, we have dynamics advect, but not turbulence. // interstitial and cloudborne aerosol tracers of interest: mass (q) and // number (n) mixing ratios @@ -149,13 +151,13 @@ void MAMGenericInterface::add_tracers_interstitial_aerosol() { // interstitial aerosol tracers of interest: number (n) mixing ratios const std::string int_nmr_field_name = mam_coupling::int_aero_nmr_field_name(mode); - add_tracer(int_nmr_field_name, grid_, n_unit); + add_tracer(int_nmr_field_name, grid_, n_unit, false); for(int a = 0; a < mam_coupling::num_aero_species(); ++a) { // (interstitial) aerosol tracers of interest: mass (q) mixing ratios const std::string int_mmr_field_name = mam_coupling::int_aero_mmr_field_name(mode, a); if(not int_mmr_field_name.empty()) { - add_tracer(int_mmr_field_name, grid_, q_unit); + add_tracer(int_mmr_field_name, grid_, q_unit, false); } } // end for loop num species } // end for loop for num modes @@ -167,7 +169,7 @@ void MAMGenericInterface::add_tracers_gases() { auto q_unit = kg / kg; // units of mass mixing ratios of tracers for(int g = 0; g < mam_coupling::num_aero_gases(); ++g) { const std::string gas_mmr_field_name = mam_coupling::gas_mmr_field_name(g); - add_tracer(gas_mmr_field_name, grid_, q_unit); + add_tracer(gas_mmr_field_name, grid_, q_unit, true); } // end for loop num gases } // ================================================================ @@ -331,19 +333,19 @@ void MAMGenericInterface::add_tracers_wet_atm() { // atmospheric quantities // specific humidity [kg/kg] - add_tracer("qv", grid_, q_unit); + add_tracer("qv", grid_, q_unit, true); // cloud liquid mass mixing ratio [kg/kg] - add_tracer("qc", grid_, q_unit); + add_tracer("qc", grid_, q_unit, true); // cloud ice mass mixing ratio [kg/kg] - add_tracer("qi", grid_, q_unit); + add_tracer("qi", grid_, q_unit, true); // cloud liquid number mixing ratio [1/kg] - add_tracer("nc", grid_, n_unit); + add_tracer("nc", grid_, n_unit, true); // cloud ice number mixing ratio [1/kg] - add_tracer("ni", grid_, n_unit); + add_tracer("ni", grid_, n_unit, true); } void MAMGenericInterface::add_fields_dry_atm() { diff --git a/components/eamxx/src/physics/mam/eamxx_mam_optics_process_interface.cpp b/components/eamxx/src/physics/mam/eamxx_mam_optics_process_interface.cpp index a56c0eb3f284..68143f2cacc3 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_optics_process_interface.cpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_optics_process_interface.cpp @@ -83,7 +83,7 @@ void MAMOptics::set_grids( // aerosol-related gases: mass mixing ratios 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(gas_mmr_field_name, grid_, kg / kg); + add_tracer(gas_mmr_field_name, grid_, kg / kg, true); } } diff --git a/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp b/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp index 735b76746f6b..1c5d2e3f4030 100644 --- a/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp +++ b/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp @@ -66,7 +66,7 @@ void MLCorrection::set_grids( add_field("precip_liq_surf_mass", scalar2d, kg/m2, grid_name); add_field("precip_ice_surf_mass", scalar2d, kg/m2, grid_name); /* ----------------------- WARNING --------------------------------*/ - add_tracer("qv", m_grid, kg/kg, ps); + add_tracer("qv", m_grid, kg/kg, true, ps); add_group("tracers", grid_name, 1, true); } diff --git a/components/eamxx/src/physics/nudging/eamxx_nudging_process_interface.cpp b/components/eamxx/src/physics/nudging/eamxx_nudging_process_interface.cpp index a4b3e6256f72..7dca3d2d99ac 100644 --- a/components/eamxx/src/physics/nudging/eamxx_nudging_process_interface.cpp +++ b/components/eamxx/src/physics/nudging/eamxx_nudging_process_interface.cpp @@ -83,7 +83,7 @@ void Nudging::set_grids(const std::shared_ptr grids_manager) add_field("T_mid", scalar3d_layout_mid, K, grid_name, ps); } if (ekat::contains(m_fields_nudge,"qv")) { - add_tracer("qv", m_grid, kg/kg, ps); + add_tracer("qv", m_grid, kg/kg, true, ps); } if (ekat::contains(m_fields_nudge,"U") or ekat::contains(m_fields_nudge,"V")) { add_field("horiz_winds", horiz_wind_layout, m/s, grid_name, ps); diff --git a/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp b/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp index 462808395db1..05e14e421811 100644 --- a/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp +++ b/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp @@ -76,15 +76,15 @@ void P3Microphysics::set_grids(const std::shared_ptr grids_m add_field ("T_mid", scalar3d_layout_mid, K, grid_name, ps); // T_mid is the only one of these variables that is also updated. // Prognostic State: (all fields are both input and output) - add_tracer("qv", m_grid, kg/kg, ps); - add_tracer("qc", m_grid, kg/kg, ps); - add_tracer("qr", m_grid, kg/kg, ps); - add_tracer("qi", m_grid, kg/kg, ps); - add_tracer("qm", m_grid, kg/kg, ps); - add_tracer("nc", m_grid, 1/kg, ps); - add_tracer("nr", m_grid, 1/kg, ps); - add_tracer("ni", m_grid, 1/kg, ps); - add_tracer("bm", m_grid, 1/kg, ps); + add_tracer("qv", m_grid, kg/kg, true, ps); + add_tracer("qc", m_grid, kg/kg, true, ps); + add_tracer("qr", m_grid, kg/kg, true, ps); + add_tracer("qi", m_grid, kg/kg, true, ps); + add_tracer("qm", m_grid, kg/kg, true, ps); + add_tracer("nc", m_grid, 1/kg, true, ps); + add_tracer("nr", m_grid, 1/kg, true, ps); + add_tracer("ni", m_grid, 1/kg, true, ps); + add_tracer("bm", m_grid, 1/kg, true, ps); // Diagnostic Inputs: (only the X_prev fields are both input and output, all others are just inputs) add_field("nc_nuceat_tend", scalar3d_layout_mid, 1/(kg*s), grid_name, ps); diff --git a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp index 9fb76bd4852e..b9376e2db085 100644 --- a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp +++ b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp @@ -61,7 +61,7 @@ void SHOCMacrophysics::set_grids(const std::shared_ptr grids add_field("surf_evap", scalar2d , kg/(m2*s), grid_name); add_field ("T_mid", scalar3d_mid, K, grid_name, ps); - add_tracer("qv", m_grid, kg/kg, ps); + add_tracer("qv", m_grid, kg/kg, true, ps); // If TMS is a process, add surface drag coefficient to required fields if (m_params.get("apply_tms", false)) { @@ -79,8 +79,8 @@ void SHOCMacrophysics::set_grids(const std::shared_ptr grids add_field("sgs_buoy_flux", scalar3d_mid, K*(m/s), grid_name, ps); add_field("eddy_diff_mom", scalar3d_mid, m2/s, grid_name, ps); add_field("cldfrac_liq", scalar3d_mid, nondim, grid_name, ps); - add_tracer("tke", m_grid, m2/s2, ps); - add_tracer("qc", m_grid, kg/kg, ps); + add_tracer("tke", m_grid, m2/s2, true, ps); + add_tracer("qc", m_grid, kg/kg, true, ps); // Output variables add_field("pbl_height", scalar2d , m, grid_name); @@ -111,7 +111,7 @@ void SHOCMacrophysics::set_grids(const std::shared_ptr grids } // Extra SHOC output diagnostics // Tracer group - add_group("tracers", grid_name, ps, true); + add_group("turbulence_advected_tracers", grid_name, ps, true); // Boundary flux fields for energy and mass conservation checks if (has_column_conservation_check()) { @@ -131,7 +131,7 @@ set_computed_group_impl (const FieldGroup& group) const auto& name = group.m_info->m_group_name; - EKAT_REQUIRE_MSG(name=="tracers", + EKAT_REQUIRE_MSG(name=="turbulence_advected_tracers", "Error! We were not expecting a field group called '" << name << "\n"); EKAT_REQUIRE_MSG(group.m_info->m_bundled, @@ -269,7 +269,7 @@ void SHOCMacrophysics::initialize_impl (const RunType run_type) const auto& surf_sens_flux = get_field_in("surf_sens_flux").get_view(); const auto& surf_evap = get_field_in("surf_evap").get_view(); const auto& surf_mom_flux = get_field_in("surf_mom_flux").get_view(); - const auto& qtracers = get_group_out("tracers").m_bundle->get_view(); + const auto& qtracers = get_group_out("turbulence_advected_tracers").m_bundle->get_view(); const auto& qc = get_field_out("qc").get_view(); const auto& qv = get_field_out("qv").get_view(); const auto& tke = get_field_out("tke").get_view(); diff --git a/components/eamxx/src/physics/tms/eamxx_tms_process_interface.cpp b/components/eamxx/src/physics/tms/eamxx_tms_process_interface.cpp index 86bd520fca94..e4ab1a865297 100644 --- a/components/eamxx/src/physics/tms/eamxx_tms_process_interface.cpp +++ b/components/eamxx/src/physics/tms/eamxx_tms_process_interface.cpp @@ -52,7 +52,7 @@ void TurbulentMountainStress::set_grids(const std::shared_ptr("pseudo_density", scalar3d_mid, Pa, grid_name, ps); add_field("sgh30", scalar2d , m, grid_name); add_field("landfrac", scalar2d , nondim, grid_name); - add_tracer("qv", m_grid, kg/kg, ps); + add_tracer("qv", m_grid, kg/kg, true, ps); add_field("surf_drag_coeff_tms", scalar2d, kg/(m2*s), grid_name); add_field("wind_stress_tms", vector2d, N/m2, grid_name); diff --git a/components/eamxx/src/share/atm_process/atmosphere_process.hpp b/components/eamxx/src/share/atm_process/atmosphere_process.hpp index 2e6140fe9550..a8723c2fe084 100644 --- a/components/eamxx/src/share/atm_process/atmosphere_process.hpp +++ b/components/eamxx/src/share/atm_process/atmosphere_process.hpp @@ -352,8 +352,19 @@ class AtmosphereProcess : public ekat::enable_shared_from_this void add_tracer (const std::string& name, std::shared_ptr grid, - const ekat::units::Units& u, const int ps = 1) - { add_field(name, grid->get_3d_scalar_layout(true), u, grid->name(), "tracers", ps); } + const ekat::units::Units& u, bool turbulence_advected, + const int ps = 1) + { + std::list tracer_groups; + tracer_groups.push_back("tracers"); + if (turbulence_advected) tracer_groups.push_back("turbulence_advected_tracers"); + + FieldIdentifier fid(name, grid->get_3d_scalar_layout(true), u, grid->name()); + FieldRequest req(fid, tracer_groups, ps); + req.calling_process = this->name(); + + add_field(req); + } // Group requests template diff --git a/components/eamxx/src/share/field/field_manager.cpp b/components/eamxx/src/share/field/field_manager.cpp index 44bf29e771c5..4310e824f006 100644 --- a/components/eamxx/src/share/field/field_manager.cpp +++ b/components/eamxx/src/share/field/field_manager.cpp @@ -419,6 +419,11 @@ void FieldManager::registration_ends () // extensive changes in Homme. Instead, we hack our way around this limitatin // (for now), and rearrange groups/fields so that we can expect qv to be the // first tracer. + // Note: there are potentially two bundled groups of tracers, "tracers" (which + // homme advects) and "turbulence_advected_tracers" (which shoc advects). + // "turbulence_advected_tracers" is guarenteed to be a subset of "tracers", so + // moving qv first in "tracers" will do the same for "turbulence_advected_tracers". + // Only homme requires qv first, so we only need to move qv if "tracers" exist. bool qv_must_come_first = false; if (ekat::contains(groups_to_bundle,"tracers") and diff --git a/components/eamxx/src/share/field/field_request.hpp b/components/eamxx/src/share/field/field_request.hpp index 8a0ef0b7dbf5..957e3efe8c7d 100644 --- a/components/eamxx/src/share/field/field_request.hpp +++ b/components/eamxx/src/share/field/field_request.hpp @@ -168,6 +168,7 @@ struct FieldRequest { SubviewInfo subview_info; std::string parent_name; bool incomplete = false; + std::string calling_process = "UNKNOWN"; }; // In order to use FieldRequest in std sorted containers (like std::set), @@ -181,7 +182,11 @@ inline bool operator< (const FieldRequest& lhs, if (lhs.pack_size Date: Fri, 7 Mar 2025 14:55:31 -0500 Subject: [PATCH 2/7] Use get_strided_layout for shoc tracers --- .../src/physics/shoc/eamxx_shoc_process_interface.cpp | 2 +- .../src/physics/shoc/eamxx_shoc_process_interface.hpp | 9 +++++---- components/eamxx/src/physics/shoc/shoc_functions.hpp | 5 ++++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp index b9376e2db085..63f4198bb9a6 100644 --- a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp +++ b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp @@ -269,7 +269,7 @@ void SHOCMacrophysics::initialize_impl (const RunType run_type) const auto& surf_sens_flux = get_field_in("surf_sens_flux").get_view(); const auto& surf_evap = get_field_in("surf_evap").get_view(); const auto& surf_mom_flux = get_field_in("surf_mom_flux").get_view(); - const auto& qtracers = get_group_out("turbulence_advected_tracers").m_bundle->get_view(); + const auto& qtracers = get_group_out("turbulence_advected_tracers").m_bundle->get_strided_view(); const auto& qc = get_field_out("qc").get_view(); const auto& qv = get_field_out("qv").get_view(); const auto& tke = get_field_out("tke").get_view(); diff --git a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.hpp b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.hpp index e3fd61703bf9..b8a7e3f6b3f8 100644 --- a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.hpp +++ b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.hpp @@ -41,6 +41,7 @@ class SHOCMacrophysics : public scream::AtmosphereProcess using sview_2d_const = typename KokkosTypes::template view_2d; using view_3d = typename SHF::view_3d; using view_3d_const = typename SHF::view_3d; + using view_3d_strided = typename SHF::view_3d_strided; using WSM = ekat::WorkspaceManager; @@ -176,7 +177,7 @@ class SHOCMacrophysics : public scream::AtmosphereProcess view_1d_const surf_sens_flux; view_1d_const surf_evap; sview_2d_const surf_mom_flux; - view_3d qtracers; + view_3d_strided qtracers; view_2d qv; view_2d_const qc; view_2d qc_copy; @@ -211,7 +212,7 @@ class SHOCMacrophysics : public scream::AtmosphereProcess const view_2d_const& omega_, const view_1d_const& phis_, const view_1d_const& surf_sens_flux_, const view_1d_const& surf_evap_, const sview_2d_const& surf_mom_flux_, - const view_3d& qtracers_, + const view_3d_strided& qtracers_, const view_2d& qv_, const view_2d_const& qc_, const view_2d& qc_copy_, const view_2d& tke_, const view_2d& tke_copy_, const view_2d& z_mid_, const view_2d& z_int_, @@ -323,7 +324,7 @@ class SHOCMacrophysics : public scream::AtmosphereProcess view_2d_const rrho; view_2d qv, qc, tke; view_2d_const tke_copy, qc_copy, qw; - view_3d qtracers; + view_3d_strided qtracers; view_2d_const qc2; view_2d cldfrac_liq; view_2d inv_qc_relvar; @@ -342,7 +343,7 @@ class SHOCMacrophysics : public scream::AtmosphereProcess void set_variables(const int ncol_, const int nlev_, const int num_qtracers_, const view_2d_const& rrho_, const view_2d& qv_, const view_2d_const& qw_, const view_2d& qc_, const view_2d_const& qc_copy_, - const view_2d& tke_, const view_2d_const& tke_copy_, const view_3d& qtracers_, const view_2d_const& qc2_, + const view_2d& tke_, const view_2d_const& tke_copy_, const view_3d_strided& qtracers_, const view_2d_const& qc2_, const view_2d& cldfrac_liq_, const view_2d& inv_qc_relvar_, const view_2d& T_mid_, const view_2d_const& dse_, const view_2d_const& z_mid_, const view_1d_const phis_) { diff --git a/components/eamxx/src/physics/shoc/shoc_functions.hpp b/components/eamxx/src/physics/shoc/shoc_functions.hpp index 5dceedbdd5d8..22a9032a55d2 100644 --- a/components/eamxx/src/physics/shoc/shoc_functions.hpp +++ b/components/eamxx/src/physics/shoc/shoc_functions.hpp @@ -55,6 +55,9 @@ struct Functions template using view_3d = typename KT::template view_3d; + template + using view_3d_strided = typename KT::template sview; + template using view_1d_ptr_array = typename KT::template view_1d_ptr_carray; @@ -144,7 +147,7 @@ struct Functions // buoyancy flux [K m/s] view_2d wthv_sec; // tracers [varies] - view_3d qtracers; + view_3d_strided qtracers; // eddy coefficient for momentum [m2/s] view_2d tk; // Cloud fraction [-] From b1acce2a72cadf18d8d79e6ca2a8f4a142b01d62 Mon Sep 17 00:00:00 2001 From: tcclevenger Date: Fri, 7 Mar 2025 15:37:32 -0500 Subject: [PATCH 3/7] Store FieldGroups to avoid recomputing --- .../eamxx/src/share/field/field_manager.cpp | 77 ++++++++++--------- .../eamxx/src/share/field/field_manager.hpp | 8 +- 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/components/eamxx/src/share/field/field_manager.cpp b/components/eamxx/src/share/field/field_manager.cpp index 4310e824f006..be48c9ade51b 100644 --- a/components/eamxx/src/share/field/field_manager.cpp +++ b/components/eamxx/src/share/field/field_manager.cpp @@ -20,6 +20,7 @@ FieldManager (const std::shared_ptr& gm) // For each grid, initialize maps for (auto gname : m_grids_mgr->get_grid_names()) { m_fields[gname] = std::map>(); + m_field_groups[gname] = std::map>(); m_group_requests[gname] = std::map>(); } @@ -83,7 +84,7 @@ void FieldManager::register_field (const FieldRequest& req) // that each field belongs to. for (const auto& group_name : req.groups) { // Get group (and init ptr, if necessary) - auto& group_info = m_field_groups[group_name]; + auto& group_info = m_field_group_info[group_name]; if (not group_info) { group_info = std::make_shared(group_name); } @@ -98,7 +99,7 @@ void FieldManager::register_field (const FieldRequest& req) group_info->m_grid_registered[id.name()].push_back(grid_name); } - // Ensure that each group in m_field_groups also appears in the m_group_requests map by + // Ensure that each group in m_field_group_info also appears in the m_group_requests map by // adding a "trivial" GroupRequest for this group, meaning no bundling and pack size 1. register_group(GroupRequest(group_name, grid_name)); } @@ -116,7 +117,7 @@ void FieldManager::register_group (const GroupRequest& req) // and create an empty group info (if it does not already exist) m_group_requests[req.grid][req.name].insert(req); - auto& group_info = m_field_groups[req.name]; + auto& group_info = m_field_group_info[req.name]; if (not group_info) { group_info = std::make_shared(req.name); group_info->m_bundled = (req.bundled); @@ -134,7 +135,7 @@ add_to_group (const std::string& field_name, const std::string& grid_name, const { EKAT_REQUIRE_MSG (m_repo_state==RepoState::Closed, "Error! You cannot call 'add_to_group' until after 'registration_ends' has been called.\n"); - auto& group = m_field_groups[group_name]; + auto& group = m_field_group_info[group_name]; if (not group) { group = std::make_shared(group_name); } @@ -169,8 +170,8 @@ bool FieldManager:: has_group (const std::string& group_name, const std::string& grid_name) const { // Return true if there exists a group "name" and group // "name" has at least one field registered on "grid_name" - if (m_field_groups.count(group_name)>0) { - auto& group_info = m_field_groups.at(group_name); + if (m_field_group_info.count(group_name)>0) { + auto& group_info = m_field_group_info.at(group_name); for (auto& fname : group_info->m_fields_names) { if (ekat::contains(group_info->m_grid_registered.at(fname), grid_name)) { return true; @@ -207,7 +208,7 @@ get_group_info (const std::string& group_name, const std::string& grid_name) con EKAT_REQUIRE_MSG (has_group(group_name, grid_name), "Error! Field group '" + group_name + "' on grid '" + grid_name + "' not found.\n"); - auto info = *m_field_groups.at(group_name); + auto info = *m_field_group_info.at(group_name); if (info.m_bundled) { // All fields in a bundled group should exist on any grid in that group @@ -240,7 +241,7 @@ get_group_info (const std::string& group_name, const std::string& grid_name) con } FieldGroup FieldManager:: -get_field_group (const std::string& group_name, const std::string& grid_name) const +get_field_group (const std::string& group_name, const std::string& grid_name) { // Sanity checks EKAT_REQUIRE_MSG(m_repo_state==RepoState::Closed, @@ -248,21 +249,27 @@ get_field_group (const std::string& group_name, const std::string& grid_name) co EKAT_REQUIRE_MSG (has_group(group_name, grid_name), "Error! Field group '" + group_name + "' on grid '" + grid_name + "' not found.\n"); - // Create an empty group - FieldGroup group(group_name); + // If FieldGroup has already been built, return that + if (m_field_groups.at(grid_name).find(group_name) != m_field_groups.at(grid_name).end()) { + return *m_field_groups.at(grid_name).at(group_name); + } + + // FieldGroup does not yet exist, create entry in m_field_groups + auto& group = m_field_groups[grid_name][group_name]; + group = std::make_shared(group_name); // Set the info in the group - group.m_info = std::make_shared(get_group_info(group_name, grid_name)); + group->m_info = std::make_shared(get_group_info(group_name, grid_name)); // Find all the fields registered on given grid and set them in the group - for (const auto& fname : group.m_info->m_fields_names) { - group.m_fields[fname] = m_fields.at(grid_name).at(fname); + for (const auto& fname : group->m_info->m_fields_names) { + group->m_fields[fname] = m_fields.at(grid_name).at(fname); } // Fetch the bundle field (if bundled) - if (group.m_info->m_bundled) { + if (group->m_info->m_bundled) { // All fields in a group have the same parent, get the parent from the 1st one - const auto& parent_header = group.m_fields.begin()->second->get_header().get_parent(); + const auto& parent_header = group->m_fields.begin()->second->get_header().get_parent(); EKAT_REQUIRE_MSG(parent_header!=nullptr, "Error! A field belonging to a bundled field group is missing its 'parent'.\n"); @@ -282,7 +289,7 @@ get_field_group (const std::string& group_name, const std::string& grid_name) co bool all_children_in_group = true; for (auto child : parent_header->get_children()) { bool in_group = false; - for (auto f : group.m_fields) { + for (auto f : group->m_fields) { if (child.lock()->get_identifier() == f.second->get_header().get_identifier()) { in_group = true; break; @@ -298,14 +305,14 @@ get_field_group (const std::string& group_name, const std::string& grid_name) co if (all_children_in_group) { // If all children are in the group, this is the parent group and // we can just query the bundle and set here - group.m_bundle = parent_field; + group->m_bundle = parent_field; } else { // If children exist that aren't in this group, we need to get a // subfield of the parent group containing indices of group fields std::vector ordered_subview_indices; - for (auto fn : group.m_info->m_fields_names) { + for (auto fn : group->m_info->m_fields_names) { const auto parent_child_index = - m_field_groups.at(parent_field->name())->m_subview_idx.at(fn); + m_field_group_info.at(parent_field->name())->m_subview_idx.at(fn); ordered_subview_indices.push_back(parent_child_index); } std::sort(ordered_subview_indices.begin(),ordered_subview_indices.end()); @@ -315,16 +322,16 @@ get_field_group (const std::string& group_name, const std::string& grid_name) co EKAT_REQUIRE_MSG (ordered_subview_indices.size()==span, "Error! Non-contiguous subview indices found in group \""+group_name+"\"\n"); - group.m_bundle = std::make_shared( + group->m_bundle = std::make_shared( parent_field->subfield( group_name, parent_header->get_identifier().get_units(), - group.m_info->m_subview_dim, + group->m_info->m_subview_dim, ordered_subview_indices.front(), ordered_subview_indices.back()+1)); } } - return group; + return *group; } void FieldManager:: @@ -368,7 +375,7 @@ void FieldManager::registration_ends () // all the requests: // 1) ensure all bundled groups contain the desired members. This means that we need to // loop over GroupRequest (GR), and make sure there are fields registered in those - // groups (querying m_field_groups info structs). + // groups (querying m_field_group_info info structs). // 2) Focus only on GR that require a bundled group, discarding others. // All the remaining group can simply "grab" individual fields later (and they // can even grab some "individual" fields, and some fields that are slices of @@ -427,7 +434,7 @@ void FieldManager::registration_ends () bool qv_must_come_first = false; if (ekat::contains(groups_to_bundle,"tracers") and - ekat::contains(m_field_groups["tracers"]->m_fields_names, "qv")) { + ekat::contains(m_field_group_info["tracers"]->m_fields_names, "qv")) { // Bring tracers to the front, so it will be processed first auto it = ekat::find(groups_to_bundle,"tracers"); std::swap(*it,groups_to_bundle.front()); @@ -437,8 +444,8 @@ void FieldManager::registration_ends () // with a real group name. Later, after having found an global ordering for the tracers fields, // we will remove this group. groups_to_bundle.push_front("__qv__"); - m_field_groups.emplace("__qv__",std::make_shared("__qv__")); - m_field_groups.at("__qv__")->m_fields_names.push_back("qv"); + m_field_group_info.emplace("__qv__",std::make_shared("__qv__")); + m_field_group_info.at("__qv__")->m_fields_names.push_back("qv"); qv_must_come_first = true; } @@ -475,9 +482,9 @@ void FieldManager::registration_ends () } // Get the fields of this group - const auto& fnames = m_field_groups.at(gn)->m_fields_names; + const auto& fnames = m_field_group_info.at(gn)->m_fields_names; for (const auto& c_gn : c) { - const auto& c_fnames = m_field_groups.at(c_gn)->m_fields_names; + const auto& c_fnames = m_field_group_info.at(c_gn)->m_fields_names; if (intersect(fnames,c_fnames)) { // Ok, group gn intersects the cluser in at least one group (c_gn). // We add gn to the cluster, then break @@ -498,7 +505,7 @@ void FieldManager::registration_ends () LOL_t groups_fields; for (const auto& gn : cluster) { - groups_fields.push_back(m_field_groups.at(gn)->m_fields_names); + groups_fields.push_back(m_field_group_info.at(gn)->m_fields_names); ::scream::sort(groups_fields.back()); } @@ -562,7 +569,7 @@ void FieldManager::registration_ends () cluster_name += " | " + gn; } - const auto& fnames = m_field_groups.at(gn)->m_fields_names; + const auto& fnames = m_field_group_info.at(gn)->m_fields_names; if (fnames.size()==cluster_ordered_fields.size()) { // Found a group in the cluster that contains all fields. cluster_name = gn; @@ -669,13 +676,13 @@ void FieldManager::registration_ends () if (ekat::contains(cluster,"__qv__")) { // Erase the 'fake group' we added (to guarantee qv would be first/last in the tracers) - m_field_groups.erase(m_field_groups.find("__qv__")); + m_field_group_info.erase(m_field_group_info.find("__qv__")); cluster.erase(ekat::find(cluster,"__qv__")); } // Now, update the group info of all the field groups in the cluster for (const auto& gn : cluster) { - auto& info = *m_field_groups.at(gn); + auto& info = *m_field_group_info.at(gn); const auto n = info.size(); // Find the first field of this group in the ordered cluster names. @@ -731,7 +738,7 @@ void FieldManager::registration_ends () it.second->allocate_view(); } - for (const auto& it : m_field_groups) { + for (const auto& it : m_field_group_info) { if (m_group_requests.at(grid_name).find(it.first)!=m_group_requests.at(grid_name).end()) { // Get fields in this group auto group_info = it.second; @@ -753,7 +760,7 @@ void FieldManager::clean_up() { m_fields.clear(); // Clean group info - m_field_groups.clear(); + m_field_group_info.clear(); // Reset repo state m_repo_state = RepoState::Clean; @@ -802,7 +809,7 @@ void FieldManager::add_field (const Field& f) { void FieldManager::pre_process_bundled_group_requests () { // For each bundled group, loop over all fields in the group and register // on to each grid the group is requested on (if necessary) - for (auto [group_name, group_info] : m_field_groups) { + for (auto [group_name, group_info] : m_field_group_info) { if (not group_info->m_bundled) continue; // Gather all grids in this bundled group. We need to check // both grids that already exist in the group and grids that diff --git a/components/eamxx/src/share/field/field_manager.hpp b/components/eamxx/src/share/field/field_manager.hpp index 59eb1a8a90d6..392b0bf4f479 100644 --- a/components/eamxx/src/share/field/field_manager.hpp +++ b/components/eamxx/src/share/field/field_manager.hpp @@ -39,6 +39,7 @@ class FieldManager { using identifier_type = typename Field::identifier_type; using ci_string = typename identifier_type::ci_string; using repo_type = std::map>>; + using field_group_type = std::map>>; using group_info_map = std::map>; // Constructor(s) @@ -120,7 +121,7 @@ class FieldManager { } FieldGroupInfo get_group_info (const std::string& group_name, const std::string& grid_name) const; - FieldGroup get_field_group (const std::string& name, const std::string& grid_name) const; + FieldGroup get_field_group (const std::string& name, const std::string& grid_name); const std::map>& get_repo () const { @@ -162,8 +163,11 @@ class FieldManager { // The actual repo. repo_type m_fields; + // Preprocessed field groups + field_group_type m_field_groups; + // The map group_name -> FieldGroupInfo - group_info_map m_field_groups; + group_info_map m_field_group_info; // Groups need to be created after all fields have been registered, // since we may need to rearrange fields inside them. Also, we From 6bd2c91da44cbf28e116902e573d283a6b3170f4 Mon Sep 17 00:00:00 2001 From: tcclevenger Date: Wed, 12 Mar 2025 15:17:14 -0400 Subject: [PATCH 4/7] Change turbulence_advected->no_turbulence_advection, and give a default value (false) --- .../atmosphere_surface_coupling_exporter.cpp | 2 +- .../homme/eamxx_homme_process_interface.cpp | 2 +- .../eamxx_cld_fraction_process_interface.cpp | 2 +- .../eamxx/src/physics/cosp/eamxx_cosp.cpp | 6 +++--- .../eamxx_mam_generic_process_interface.cpp | 16 +++++++-------- .../eamxx_mam_optics_process_interface.cpp | 2 +- .../eamxx_ml_correction_process_interface.cpp | 2 +- .../eamxx_nudging_process_interface.cpp | 2 +- .../physics/p3/eamxx_p3_process_interface.cpp | 20 +++++++++---------- .../shoc/eamxx_shoc_process_interface.cpp | 6 +++--- .../tms/eamxx_tms_process_interface.cpp | 2 +- .../share/atm_process/atmosphere_process.hpp | 6 +++--- 12 files changed, 34 insertions(+), 34 deletions(-) diff --git a/components/eamxx/src/control/atmosphere_surface_coupling_exporter.cpp b/components/eamxx/src/control/atmosphere_surface_coupling_exporter.cpp index c9aeb7d8620c..b4264dd7243c 100644 --- a/components/eamxx/src/control/atmosphere_surface_coupling_exporter.cpp +++ b/components/eamxx/src/control/atmosphere_surface_coupling_exporter.cpp @@ -44,7 +44,7 @@ void SurfaceCouplingExporter::set_grids(const std::shared_ptr("phis", scalar2d_layout, m2/s2, grid_name); add_field("p_mid", scalar3d_layout_mid, Pa, grid_name, ps); add_field("T_mid", scalar3d_layout_mid, K, grid_name, ps); - add_tracer("qv", m_grid, kg/kg, true, ps); + add_tracer("qv", m_grid, kg/kg, ps); // TODO: Switch horiz_winds to using U and V, note right now there is an issue with when the subfields are created, so can't switch yet. add_field("horiz_winds", vector3d_layout, m/s, grid_name); add_field("sfc_flux_dir_nir", scalar2d_layout, W/m2, grid_name); diff --git a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp index 2f5842e46070..452a5b5fbee0 100644 --- a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp +++ b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp @@ -179,7 +179,7 @@ void HommeDynamics::set_grids (const std::shared_ptr grids_m add_field("p_dry_mid", pg_scalar3d_mid, Pa, pgn,N); add_field("omega", pg_scalar3d_mid, Pa/s, pgn,N); - add_tracer("qv", m_phys_grid, kg/kg, true, N); + add_tracer("qv", m_phys_grid, kg/kg, N); add_group("tracers",pgn,N, true); if (fv_phys_active()) { diff --git a/components/eamxx/src/physics/cld_fraction/eamxx_cld_fraction_process_interface.cpp b/components/eamxx/src/physics/cld_fraction/eamxx_cld_fraction_process_interface.cpp index 6b99e8e09ace..b41dcc1f2720 100644 --- a/components/eamxx/src/physics/cld_fraction/eamxx_cld_fraction_process_interface.cpp +++ b/components/eamxx/src/physics/cld_fraction/eamxx_cld_fraction_process_interface.cpp @@ -38,7 +38,7 @@ void CldFraction::set_grids(const std::shared_ptr grids_mana // Set of fields used strictly as input constexpr int ps = Pack::n; - add_tracer("qi", m_grid, kg/kg, true, ps); + add_tracer("qi", m_grid, kg/kg, ps); add_field("cldfrac_liq", scalar3d_layout_mid, nondim, grid_name,ps); // Set of fields used strictly as output diff --git a/components/eamxx/src/physics/cosp/eamxx_cosp.cpp b/components/eamxx/src/physics/cosp/eamxx_cosp.cpp index 4047518336d3..43228684cfed 100644 --- a/components/eamxx/src/physics/cosp/eamxx_cosp.cpp +++ b/components/eamxx/src/physics/cosp/eamxx_cosp.cpp @@ -75,9 +75,9 @@ void Cosp::set_grids(const std::shared_ptr grids_manager) add_field("phis", scalar2d , m2/s2, grid_name); add_field("pseudo_density", scalar3d_mid, Pa, grid_name); add_field("cldfrac_rad", scalar3d_mid, nondim, grid_name); - add_tracer("qv", m_grid, kg/kg, true); - add_tracer("qc", m_grid, kg/kg, true); - add_tracer("qi", m_grid, kg/kg, true); + add_tracer("qv", m_grid, kg/kg); + add_tracer("qc", m_grid, kg/kg); + add_tracer("qi", m_grid, kg/kg); // Optical properties, should be computed in radiation interface add_field("dtau067", scalar3d_mid, nondim, grid_name); // 0.67 micron optical depth add_field("dtau105", scalar3d_mid, nondim, grid_name); // 10.5 micron optical depth diff --git a/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp b/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp index 2a2c1ef7d22b..2f56a75b3f1e 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp @@ -151,13 +151,13 @@ void MAMGenericInterface::add_tracers_interstitial_aerosol() { // interstitial aerosol tracers of interest: number (n) mixing ratios const std::string int_nmr_field_name = mam_coupling::int_aero_nmr_field_name(mode); - add_tracer(int_nmr_field_name, grid_, n_unit, false); + add_tracer(int_nmr_field_name, grid_, n_unit, 1, true); for(int a = 0; a < mam_coupling::num_aero_species(); ++a) { // (interstitial) aerosol tracers of interest: mass (q) mixing ratios const std::string int_mmr_field_name = mam_coupling::int_aero_mmr_field_name(mode, a); if(not int_mmr_field_name.empty()) { - add_tracer(int_mmr_field_name, grid_, q_unit, false); + add_tracer(int_mmr_field_name, grid_, q_unit, 1, true); } } // end for loop num species } // end for loop for num modes @@ -169,7 +169,7 @@ void MAMGenericInterface::add_tracers_gases() { auto q_unit = kg / kg; // units of mass mixing ratios of tracers for(int g = 0; g < mam_coupling::num_aero_gases(); ++g) { const std::string gas_mmr_field_name = mam_coupling::gas_mmr_field_name(g); - add_tracer(gas_mmr_field_name, grid_, q_unit, true); + add_tracer(gas_mmr_field_name, grid_, q_unit); } // end for loop num gases } // ================================================================ @@ -333,19 +333,19 @@ void MAMGenericInterface::add_tracers_wet_atm() { // atmospheric quantities // specific humidity [kg/kg] - add_tracer("qv", grid_, q_unit, true); + add_tracer("qv", grid_, q_unit); // cloud liquid mass mixing ratio [kg/kg] - add_tracer("qc", grid_, q_unit, true); + add_tracer("qc", grid_, q_unit); // cloud ice mass mixing ratio [kg/kg] - add_tracer("qi", grid_, q_unit, true); + add_tracer("qi", grid_, q_unit); // cloud liquid number mixing ratio [1/kg] - add_tracer("nc", grid_, n_unit, true); + add_tracer("nc", grid_, n_unit); // cloud ice number mixing ratio [1/kg] - add_tracer("ni", grid_, n_unit, true); + add_tracer("ni", grid_, n_unit); } void MAMGenericInterface::add_fields_dry_atm() { diff --git a/components/eamxx/src/physics/mam/eamxx_mam_optics_process_interface.cpp b/components/eamxx/src/physics/mam/eamxx_mam_optics_process_interface.cpp index 68143f2cacc3..a56c0eb3f284 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_optics_process_interface.cpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_optics_process_interface.cpp @@ -83,7 +83,7 @@ void MAMOptics::set_grids( // aerosol-related gases: mass mixing ratios 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(gas_mmr_field_name, grid_, kg / kg, true); + add_tracer(gas_mmr_field_name, grid_, kg / kg); } } diff --git a/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp b/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp index 1c5d2e3f4030..735b76746f6b 100644 --- a/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp +++ b/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp @@ -66,7 +66,7 @@ void MLCorrection::set_grids( add_field("precip_liq_surf_mass", scalar2d, kg/m2, grid_name); add_field("precip_ice_surf_mass", scalar2d, kg/m2, grid_name); /* ----------------------- WARNING --------------------------------*/ - add_tracer("qv", m_grid, kg/kg, true, ps); + add_tracer("qv", m_grid, kg/kg, ps); add_group("tracers", grid_name, 1, true); } diff --git a/components/eamxx/src/physics/nudging/eamxx_nudging_process_interface.cpp b/components/eamxx/src/physics/nudging/eamxx_nudging_process_interface.cpp index 7dca3d2d99ac..a4b3e6256f72 100644 --- a/components/eamxx/src/physics/nudging/eamxx_nudging_process_interface.cpp +++ b/components/eamxx/src/physics/nudging/eamxx_nudging_process_interface.cpp @@ -83,7 +83,7 @@ void Nudging::set_grids(const std::shared_ptr grids_manager) add_field("T_mid", scalar3d_layout_mid, K, grid_name, ps); } if (ekat::contains(m_fields_nudge,"qv")) { - add_tracer("qv", m_grid, kg/kg, true, ps); + add_tracer("qv", m_grid, kg/kg, ps); } if (ekat::contains(m_fields_nudge,"U") or ekat::contains(m_fields_nudge,"V")) { add_field("horiz_winds", horiz_wind_layout, m/s, grid_name, ps); diff --git a/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp b/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp index 05e14e421811..386512dfb825 100644 --- a/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp +++ b/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp @@ -76,15 +76,15 @@ void P3Microphysics::set_grids(const std::shared_ptr grids_m add_field ("T_mid", scalar3d_layout_mid, K, grid_name, ps); // T_mid is the only one of these variables that is also updated. // Prognostic State: (all fields are both input and output) - add_tracer("qv", m_grid, kg/kg, true, ps); - add_tracer("qc", m_grid, kg/kg, true, ps); - add_tracer("qr", m_grid, kg/kg, true, ps); - add_tracer("qi", m_grid, kg/kg, true, ps); - add_tracer("qm", m_grid, kg/kg, true, ps); - add_tracer("nc", m_grid, 1/kg, true, ps); - add_tracer("nr", m_grid, 1/kg, true, ps); - add_tracer("ni", m_grid, 1/kg, true, ps); - add_tracer("bm", m_grid, 1/kg, true, ps); + add_tracer("qv", m_grid, kg/kg, ps); + add_tracer("qc", m_grid, kg/kg, ps); + add_tracer("qr", m_grid, kg/kg, ps); + add_tracer("qi", m_grid, kg/kg, ps); + add_tracer("qm", m_grid, kg/kg, ps); + add_tracer("nc", m_grid, 1/kg, ps); + add_tracer("nr", m_grid, 1/kg, ps); + add_tracer("ni", m_grid, 1/kg, ps); + add_tracer("bm", m_grid, 1/kg, ps); // Diagnostic Inputs: (only the X_prev fields are both input and output, all others are just inputs) add_field("nc_nuceat_tend", scalar3d_layout_mid, 1/(kg*s), grid_name, ps); @@ -346,7 +346,7 @@ void P3Microphysics::initialize_impl (const RunType /* run_type */) diag_inputs.cld_frac_r = p3_preproc.cld_frac_r; diag_inputs.dz = p3_preproc.dz; diag_inputs.inv_exner = p3_preproc.inv_exner; - + // Inputs for the heteogeneous freezing if (runtime_options.use_hetfrz_classnuc){ diag_inputs.hetfrz_immersion_nucleation_tend = get_field_in("hetfrz_immersion_nucleation_tend").get_view(); diff --git a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp index 63f4198bb9a6..8894552f7db8 100644 --- a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp +++ b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp @@ -61,7 +61,7 @@ void SHOCMacrophysics::set_grids(const std::shared_ptr grids add_field("surf_evap", scalar2d , kg/(m2*s), grid_name); add_field ("T_mid", scalar3d_mid, K, grid_name, ps); - add_tracer("qv", m_grid, kg/kg, true, ps); + add_tracer("qv", m_grid, kg/kg, ps); // If TMS is a process, add surface drag coefficient to required fields if (m_params.get("apply_tms", false)) { @@ -79,8 +79,8 @@ void SHOCMacrophysics::set_grids(const std::shared_ptr grids add_field("sgs_buoy_flux", scalar3d_mid, K*(m/s), grid_name, ps); add_field("eddy_diff_mom", scalar3d_mid, m2/s, grid_name, ps); add_field("cldfrac_liq", scalar3d_mid, nondim, grid_name, ps); - add_tracer("tke", m_grid, m2/s2, true, ps); - add_tracer("qc", m_grid, kg/kg, true, ps); + add_tracer("tke", m_grid, m2/s2, ps); + add_tracer("qc", m_grid, kg/kg, ps); // Output variables add_field("pbl_height", scalar2d , m, grid_name); diff --git a/components/eamxx/src/physics/tms/eamxx_tms_process_interface.cpp b/components/eamxx/src/physics/tms/eamxx_tms_process_interface.cpp index e4ab1a865297..86bd520fca94 100644 --- a/components/eamxx/src/physics/tms/eamxx_tms_process_interface.cpp +++ b/components/eamxx/src/physics/tms/eamxx_tms_process_interface.cpp @@ -52,7 +52,7 @@ void TurbulentMountainStress::set_grids(const std::shared_ptr("pseudo_density", scalar3d_mid, Pa, grid_name, ps); add_field("sgh30", scalar2d , m, grid_name); add_field("landfrac", scalar2d , nondim, grid_name); - add_tracer("qv", m_grid, kg/kg, true, ps); + add_tracer("qv", m_grid, kg/kg, ps); add_field("surf_drag_coeff_tms", scalar2d, kg/(m2*s), grid_name); add_field("wind_stress_tms", vector2d, N/m2, grid_name); diff --git a/components/eamxx/src/share/atm_process/atmosphere_process.hpp b/components/eamxx/src/share/atm_process/atmosphere_process.hpp index a8723c2fe084..c3962dcc96fa 100644 --- a/components/eamxx/src/share/atm_process/atmosphere_process.hpp +++ b/components/eamxx/src/share/atm_process/atmosphere_process.hpp @@ -352,12 +352,12 @@ class AtmosphereProcess : public ekat::enable_shared_from_this void add_tracer (const std::string& name, std::shared_ptr grid, - const ekat::units::Units& u, bool turbulence_advected, - const int ps = 1) + const ekat::units::Units& u, + const int ps = 1, const bool no_turbulence_advection = false) { std::list tracer_groups; tracer_groups.push_back("tracers"); - if (turbulence_advected) tracer_groups.push_back("turbulence_advected_tracers"); + if (not no_turbulence_advection) tracer_groups.push_back("turbulence_advected_tracers"); FieldIdentifier fid(name, grid->get_3d_scalar_layout(true), u, grid->name()); FieldRequest req(fid, tracer_groups, ps); From f957603104c0115213f85783679d8cc40f10e37d Mon Sep 17 00:00:00 2001 From: tcclevenger Date: Thu, 13 Mar 2025 10:15:07 -0400 Subject: [PATCH 5/7] Revert "Convert bundling to bool" This reverts commit 6237c87ea41be76032c6a360d714829bbf7cbcc9. Adds back the enum for bundling --- .../homme/eamxx_homme_process_interface.cpp | 4 +-- .../eamxx_iop_forcing_process_interface.cpp | 2 +- .../eamxx_ml_correction_process_interface.cpp | 2 +- .../shoc/eamxx_shoc_process_interface.cpp | 2 +- .../share/atm_process/atmosphere_process.hpp | 8 +++--- .../eamxx/src/share/field/field_manager.cpp | 6 ++--- .../eamxx/src/share/field/field_request.hpp | 26 ++++++++++++------- .../eamxx/src/share/tests/field_tests.cpp | 7 ++--- 8 files changed, 32 insertions(+), 25 deletions(-) diff --git a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp index 452a5b5fbee0..94b2a0d8c1f2 100644 --- a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp +++ b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp @@ -180,7 +180,7 @@ void HommeDynamics::set_grids (const std::shared_ptr grids_m add_field("omega", pg_scalar3d_mid, Pa/s, pgn,N); add_tracer("qv", m_phys_grid, kg/kg, N); - add_group("tracers",pgn,N, true); + add_group("tracers",pgn,N, Bundling::Required); if (fv_phys_active()) { // [CGLL ICs in pg2] Read CGLL IC data even though our in/out format is @@ -196,7 +196,7 @@ void HommeDynamics::set_grids (const std::shared_ptr grids_m add_field("T_mid", rg_scalar3d_mid,K, rgn,N); add_field("ps", rg_scalar2d ,Pa, rgn); add_field("phis", rg_scalar2d ,m2/s2, rgn); - add_group("tracers",rgn,N, true); + add_group("tracers",rgn,N, Bundling::Required); fv_phys_rrtmgp_active_gases_init(grids_manager); // This is needed for the dp_ref init in initialize_homme_state. add_field("pseudo_density",rg_scalar3d_mid,Pa, rgn,N); diff --git a/components/eamxx/src/physics/iop_forcing/eamxx_iop_forcing_process_interface.cpp b/components/eamxx/src/physics/iop_forcing/eamxx_iop_forcing_process_interface.cpp index 150dbbb12c58..c9a3714e1dce 100644 --- a/components/eamxx/src/physics/iop_forcing/eamxx_iop_forcing_process_interface.cpp +++ b/components/eamxx/src/physics/iop_forcing/eamxx_iop_forcing_process_interface.cpp @@ -29,7 +29,7 @@ void IOPForcing::set_grids(const std::shared_ptr grids_manag add_field("T_mid", scalar3d_mid, K, grid_name, pack_size); add_tracer("qv", m_grid, kg/kg, pack_size); - add_group("tracers", grid_name, pack_size, true); + add_group("tracers", grid_name, pack_size, Bundling::Required); // Sanity check that iop data manager is setup by driver EKAT_REQUIRE_MSG(m_iop_data_manager, diff --git a/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp b/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp index 735b76746f6b..ce3b64b3dc8a 100644 --- a/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp +++ b/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp @@ -67,7 +67,7 @@ void MLCorrection::set_grids( add_field("precip_ice_surf_mass", scalar2d, kg/m2, grid_name); /* ----------------------- WARNING --------------------------------*/ add_tracer("qv", m_grid, kg/kg, ps); - add_group("tracers", grid_name, 1, true); + add_group("tracers", grid_name, 1, Bundling::Required); } // ========================================================================================= diff --git a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp index 8894552f7db8..5d63e233fdec 100644 --- a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp +++ b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp @@ -111,7 +111,7 @@ void SHOCMacrophysics::set_grids(const std::shared_ptr grids } // Extra SHOC output diagnostics // Tracer group - add_group("turbulence_advected_tracers", grid_name, ps, true); + add_group("turbulence_advected_tracers", grid_name, ps, Bundling::Required); // Boundary flux fields for energy and mass conservation checks if (has_column_conservation_check()) { diff --git a/components/eamxx/src/share/atm_process/atmosphere_process.hpp b/components/eamxx/src/share/atm_process/atmosphere_process.hpp index c3962dcc96fa..ec652dd08bc8 100644 --- a/components/eamxx/src/share/atm_process/atmosphere_process.hpp +++ b/components/eamxx/src/share/atm_process/atmosphere_process.hpp @@ -369,13 +369,13 @@ class AtmosphereProcess : public ekat::enable_shared_from_this void add_group (const std::string& name, const std::string& grid_name, - const bool bundled = false) - { add_group (GroupRequest(name,grid_name,bundled)); } + const Bundling b = Bundling::NotNeeded) + { add_group (GroupRequest(name,grid_name,b)); } template void add_group (const std::string& name, const std::string& grid_name, - const int pack_size, const bool bundled = false) - { add_group (GroupRequest(name,grid_name,pack_size,bundled)); } + const int pack_size, const Bundling b = Bundling::NotNeeded) + { add_group (GroupRequest(name,grid_name,pack_size,b)); } template void add_field (const FieldRequest& req) diff --git a/components/eamxx/src/share/field/field_manager.cpp b/components/eamxx/src/share/field/field_manager.cpp index be48c9ade51b..e7c70fbe829e 100644 --- a/components/eamxx/src/share/field/field_manager.cpp +++ b/components/eamxx/src/share/field/field_manager.cpp @@ -120,9 +120,9 @@ void FieldManager::register_group (const GroupRequest& req) auto& group_info = m_field_group_info[req.name]; if (not group_info) { group_info = std::make_shared(req.name); - group_info->m_bundled = (req.bundled); + group_info->m_bundled = (req.bundling==Bundling::Required); } else if (not group_info->m_bundled) { - group_info->m_bundled = (req.bundled); + group_info->m_bundled = (req.bundling==Bundling::Required); } if (not ekat::contains(group_info->m_requested_grids, req.grid)) { @@ -409,7 +409,7 @@ void FieldManager::registration_ends () for (auto& grid_it : m_grids_mgr->get_repo()) { for (const auto& greqs : m_group_requests.at(grid_it.second->name())) { for (const auto& r : greqs.second) { - if (r.bundled) { + if (r.bundling==Bundling::Required) { // There's at least one request for this group to be bundled. groups_to_bundle.push_back(greqs.first); break; diff --git a/components/eamxx/src/share/field/field_request.hpp b/components/eamxx/src/share/field/field_request.hpp index 957e3efe8c7d..3bd9914f0163 100644 --- a/components/eamxx/src/share/field/field_request.hpp +++ b/components/eamxx/src/share/field/field_request.hpp @@ -13,6 +13,12 @@ enum RequestType { Updated // For convenience, triggers Required+Computed }; +// Whether the bundling of a field group (see below) is needed, optional, or not needed. +enum class Bundling : int { + Required, + NotNeeded +}; + /* * A struct used to request a group of fields. * @@ -34,26 +40,26 @@ struct GroupRequest { // - grid: the grid where the group is requested // - ps: the pack size that the allocation of the fields in the group // (and the bundled field, if any) should accommodate (see field_alloc_prop.hpp) - // - bundled: whether the group should be bundled (see field_group.hpp) - GroupRequest (const std::string& name_, const std::string& grid_, const int ps, const bool bundled_ = false) - : name(name_), grid(grid_), pack_size(ps), bundled(bundled_) + // - bundling: whether the group should be bundled (see field_group.hpp) + GroupRequest (const std::string& name_, const std::string& grid_, const int ps, const Bundling b = Bundling::NotNeeded) + : name(name_), grid(grid_), pack_size(ps), bundling(b) { EKAT_REQUIRE_MSG(pack_size>=1, "Error! Invalid pack size request.\n"); } GroupRequest (const std::string& name_, const std::string& grid_, - const bool bundled = false) - : GroupRequest(name_,grid_,1,bundled) + const Bundling b = Bundling::NotNeeded) + : GroupRequest(name_,grid_,1,b) { /* Nothing to do here */ } // Default copy ctor is perfectly fine GroupRequest (const GroupRequest&) = default; // Main parts of a group request - std::string name; // Group name - std::string grid; // Grid name - int pack_size; // Request an allocation that can accomodate Pack - bool bundled; // Whether the group should be allocated as a single n+1 dimensional field + std::string name; // Group name + std::string grid; // Grid name + int pack_size; // Request an allocation that can accomodate Pack + Bundling bundling; // Whether the group should be allocated as a single n+1 dimensional field }; // In order to use GroupRequest in std sorted containers (like std::set), @@ -83,7 +89,7 @@ inline bool operator< (const GroupRequest& lhs, } // Same pack size, order by bundling - return lhs.bundled Date: Thu, 13 Mar 2025 10:42:37 -0400 Subject: [PATCH 6/7] Use enum for advecting decidion --- .../physics/mam/eamxx_mam_generic_process_interface.cpp | 4 ++-- .../eamxx/src/share/atm_process/atmosphere_process.hpp | 9 ++++++--- components/eamxx/src/share/field/field_request.hpp | 7 +++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp b/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp index 2f56a75b3f1e..696e95f4c3f8 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_generic_process_interface.cpp @@ -151,13 +151,13 @@ void MAMGenericInterface::add_tracers_interstitial_aerosol() { // interstitial aerosol tracers of interest: number (n) mixing ratios const std::string int_nmr_field_name = mam_coupling::int_aero_nmr_field_name(mode); - add_tracer(int_nmr_field_name, grid_, n_unit, 1, true); + add_tracer(int_nmr_field_name, grid_, n_unit, 1, TracerAdvection::DynamicsOnly); for(int a = 0; a < mam_coupling::num_aero_species(); ++a) { // (interstitial) aerosol tracers of interest: mass (q) mixing ratios const std::string int_mmr_field_name = mam_coupling::int_aero_mmr_field_name(mode, a); if(not int_mmr_field_name.empty()) { - add_tracer(int_mmr_field_name, grid_, q_unit, 1, true); + add_tracer(int_mmr_field_name, grid_, q_unit, 1, TracerAdvection::DynamicsOnly); } } // end for loop num species } // end for loop for num modes diff --git a/components/eamxx/src/share/atm_process/atmosphere_process.hpp b/components/eamxx/src/share/atm_process/atmosphere_process.hpp index ec652dd08bc8..ac45b9ceb956 100644 --- a/components/eamxx/src/share/atm_process/atmosphere_process.hpp +++ b/components/eamxx/src/share/atm_process/atmosphere_process.hpp @@ -352,12 +352,15 @@ class AtmosphereProcess : public ekat::enable_shared_from_this void add_tracer (const std::string& name, std::shared_ptr grid, - const ekat::units::Units& u, - const int ps = 1, const bool no_turbulence_advection = false) + const ekat::units::Units& u, + const int ps = 1, + const TracerAdvection tracer_advection = TracerAdvection::DynamicsAndTurbulence) { std::list tracer_groups; tracer_groups.push_back("tracers"); - if (not no_turbulence_advection) tracer_groups.push_back("turbulence_advected_tracers"); + if (tracer_advection==TracerAdvection::DynamicsAndTurbulence) { + tracer_groups.push_back("turbulence_advected_tracers"); + } FieldIdentifier fid(name, grid->get_3d_scalar_layout(true), u, grid->name()); FieldRequest req(fid, tracer_groups, ps); diff --git a/components/eamxx/src/share/field/field_request.hpp b/components/eamxx/src/share/field/field_request.hpp index 3bd9914f0163..09a037d224e2 100644 --- a/components/eamxx/src/share/field/field_request.hpp +++ b/components/eamxx/src/share/field/field_request.hpp @@ -13,6 +13,13 @@ enum RequestType { Updated // For convenience, triggers Required+Computed }; +// Whether a tracer should be advected by both Dynamics +// and Turbulance, or only by Dynamics +enum TracerAdvection { + DynamicsAndTurbulence, // Default use case + DynamicsOnly, +}; + // Whether the bundling of a field group (see below) is needed, optional, or not needed. enum class Bundling : int { Required, From c3fb462ee88042fe366c16ff00d05aa5350f17ad Mon Sep 17 00:00:00 2001 From: tcclevenger Date: Thu, 13 Mar 2025 21:00:13 -0400 Subject: [PATCH 7/7] Several renames wrt bundling - Bundling enum -> MonolithicAlloc - m_bundle field -> m_monolithic_field - m_fields (in field group) -> m_individual_fields - All comments updated --- .../eamxx/src/control/atmosphere_driver.cpp | 36 +++-- .../src/control/tests/dummy_atm_proc.hpp | 10 +- .../dynamics/homme/eamxx_homme_fv_phys.cpp | 12 +- .../homme/eamxx_homme_process_interface.cpp | 16 +- .../eamxx_iop_forcing_process_interface.cpp | 8 +- .../eamxx_ml_correction_process_interface.cpp | 2 +- .../shoc/eamxx_shoc_process_interface.cpp | 8 +- .../shoc/eamxx_shoc_process_interface.hpp | 10 +- .../src/share/atm_process/IOPDataManager.cpp | 2 +- .../share/atm_process/atmosphere_process.cpp | 24 +-- .../share/atm_process/atmosphere_process.hpp | 6 +- .../atm_process/atmosphere_process_dag.cpp | 30 ++-- .../atm_process/atmosphere_process_group.cpp | 4 +- .../atm_process/atmosphere_process_hash.cpp | 6 +- .../eamxx/src/share/field/field_group.cpp | 22 +-- .../eamxx/src/share/field/field_group.hpp | 14 +- .../src/share/field/field_group_info.hpp | 32 ++-- .../eamxx/src/share/field/field_manager.cpp | 143 +++++++++--------- .../eamxx/src/share/field/field_manager.hpp | 4 +- .../eamxx/src/share/field/field_request.hpp | 31 ++-- .../eamxx/src/share/tests/field_tests.cpp | 70 ++++----- 21 files changed, 244 insertions(+), 246 deletions(-) diff --git a/components/eamxx/src/control/atmosphere_driver.cpp b/components/eamxx/src/control/atmosphere_driver.cpp index 07a67f648187..caa3876b30a4 100644 --- a/components/eamxx/src/control/atmosphere_driver.cpp +++ b/components/eamxx/src/control/atmosphere_driver.cpp @@ -58,9 +58,7 @@ namespace control { * Note: at this stage, atm procs that act on non-ref grid(s) should be able to create their * remappers. The AD will *not* take care of remapping inputs/outputs of the process. * 4) Register all fields and all groups from all atm procs inside the field managers, and proceed - * to allocate fields. Each field manager (there is one FM per grid) will take care of - * accommodating all requests for packing as well as (if possible) bundling of groups. - * For more details, see the documentation in the share/field/field_request.hpp header. + * to allocate fields. For more details, see the documentation in the share/field/field_request.hpp header. * 5) Set all the fields into the atm procs. Before this point, all the atm procs had were the * FieldIdentifiers for their input/output fields and FieldGroupInfo for their input/output * field groups. Now, we pass actual Field and FieldGroup objects to them, where both the @@ -405,7 +403,7 @@ void AtmosphereDriver::reset_accumulated_fields () } auto accum_group = m_field_mgr->get_field_group("ACCUMULATED", grid_name); - for (auto f_it : accum_group.m_fields) { + for (auto f_it : accum_group.m_individual_fields) { auto& track = f_it.second->get_header().get_tracking(); f_it.second->deep_copy(zero); track.set_accum_start_time(m_current_ts); @@ -645,8 +643,8 @@ void AtmosphereDriver::create_fields() m_field_mgr->add_to_group(fid, "RESTART"); } for (const auto& g : m_atm_process_group->get_groups_in()) { - if (g.m_bundle) { - m_field_mgr->add_to_group(g.m_bundle->get_header().get_identifier(), "RESTART"); + if (g.m_monolithic_field) { + m_field_mgr->add_to_group(g.m_monolithic_field->get_header().get_identifier(), "RESTART"); } else { for (const auto& fn : g.m_info->m_fields_names) { m_field_mgr->add_to_group(fn, g.grid_name(), "RESTART"); @@ -1174,19 +1172,19 @@ void AtmosphereDriver::set_initial_conditions () // ...then the input groups m_atm_logger->debug(" [EAMxx] Processing input groups ..."); for (const auto& g : m_atm_process_group->get_groups_in()) { - if (g.m_bundle) { - process_ic_field(*g.m_bundle); + if (g.m_monolithic_field) { + process_ic_field(*g.m_monolithic_field); } - for (auto it : g.m_fields) { + for (auto it : g.m_individual_fields) { process_ic_field(*it.second); } } m_atm_logger->debug(" [EAMxx] Processing input groups ... done!"); - // Some fields might be the subfield of a group's bundled field. In that case, - // we only need to init one: either the bundled field, or all the individual subfields. + // Some fields might be the subfield of a group's monolithic field. In that case, + // we only need to init one: either the monolithic field, or all the individual subfields. // So loop over the fields that appear to require loading from file, and remove - // them from the list if they are the subfield of a bundled field already inited + // them from the list if they are the subfield of a groups monolithic field already inited // (perhaps via initialize_constant_field, or copied from another field). for (auto& it1 : ic_fields_names) { const auto& grid_name = it1.first; @@ -1290,17 +1288,17 @@ void AtmosphereDriver::set_initial_conditions () } m_atm_logger->debug(" [EAMxx] Processing fields to copy ... done!"); - // It is possible to have a bundled group G1=(f1,f2,f3), + // It is possible to have a monolithically allocated group G1=(f1,f2,f3), // where the IC are read from file for f1, f2, and f3. In that case, - // the time stamp for the bundled G1 has not be inited, but the data + // the time stamp for the monolithic field of G1 has not be inited, but the data // is valid (all entries have been inited). Let's fix that. m_atm_logger->debug(" [EAMxx] Processing subfields ..."); for (const auto& g : m_atm_process_group->get_groups_in()) { - if (g.m_bundle) { - auto& track = g.m_bundle->get_header().get_tracking(); + if (g.m_monolithic_field) { + auto& track = g.m_monolithic_field->get_header().get_tracking(); if (not track.get_time_stamp().is_valid()) { - // The bundled field has not been inited. Check if all the subfields - // have been inited. If so, init the timestamp of the bundled field too. + // The groups monolithic field has not been inited. Check if all the subfields + // have been inited. If so, init the timestamp of the monlithic field too. const auto& children = track.get_children(); bool all_inited = children.size()>0; // If no children, then something is off, so mark as not good for (auto wp : children) { @@ -1678,7 +1676,7 @@ void AtmosphereDriver::run (const int dt) { } auto rescale_group = m_field_mgr->get_field_group("DIVIDE_BY_DT", gname); - for (auto f_it : rescale_group.m_fields) { + for (auto f_it : rescale_group.m_individual_fields) { f_it.second->scale(Real(1) / dt); } } diff --git a/components/eamxx/src/control/tests/dummy_atm_proc.hpp b/components/eamxx/src/control/tests/dummy_atm_proc.hpp index 0c27346cd6b5..4aec7db664d3 100644 --- a/components/eamxx/src/control/tests/dummy_atm_proc.hpp +++ b/components/eamxx/src/control/tests/dummy_atm_proc.hpp @@ -93,8 +93,8 @@ class DummyProcess : public scream::AtmosphereProcess { }); } else if (m_name=="Group to Group") { const auto& g = get_group_out("The Group"); - const auto view_B = g.m_fields.at("B")->get_view(); - const auto view_C = g.m_fields.at("C")->get_view(); + const auto view_B = g.m_individual_fields.at("B")->get_view(); + const auto view_C = g.m_individual_fields.at("C")->get_view(); Kokkos::parallel_for(policy,KOKKOS_LAMBDA(const int idx) { const int icol = idx / nlevs; @@ -105,8 +105,8 @@ class DummyProcess : public scream::AtmosphereProcess { }); } else { const auto& g = get_group_in("The Group"); - const auto view_B = g.m_fields.at("B")->get_view(); - const auto view_C = g.m_fields.at("C")->get_view(); + const auto view_B = g.m_individual_fields.at("B")->get_view(); + const auto view_C = g.m_individual_fields.at("C")->get_view(); const auto view_A = get_field_out("A").get_view(); Kokkos::parallel_for(policy,KOKKOS_LAMBDA(const int idx) { @@ -128,7 +128,7 @@ class DummyProcess : public scream::AtmosphereProcess { std::string m_name; - DummyType m_dummy_type; + DummyType m_dummy_type; }; } // namespace scream diff --git a/components/eamxx/src/dynamics/homme/eamxx_homme_fv_phys.cpp b/components/eamxx/src/dynamics/homme/eamxx_homme_fv_phys.cpp index 8d84a038a025..662b046ce421 100644 --- a/components/eamxx/src/dynamics/homme/eamxx_homme_fv_phys.cpp +++ b/components/eamxx/src/dynamics/homme/eamxx_homme_fv_phys.cpp @@ -111,7 +111,7 @@ void HommeDynamics::fv_phys_dyn_to_fv_phys (const bool restart) { t.T_mid = Homme::ExecView("T_mid_tmp", nelem, npg, npacks*N); t.horiz_winds = Homme::ExecView("horiz_winds_tmp", nelem, npg, 2, npacks*N); // Really need just the first tracer. - const auto qsize = get_group_out("tracers", pgn).m_bundle->get_view().extent_int(1); + const auto qsize = get_group_out("tracers", pgn).m_monolithic_field->get_view().extent_int(1); t.tracers = Homme::ExecView("tracers_tmp", nelem, npg, qsize, npacks*N); remap_dyn_to_fv_phys(&t); assert(ncols == nelem*npg); @@ -138,7 +138,7 @@ void HommeDynamics::fv_phys_dyn_to_fv_phys (const bool restart) { auto f = get_field_out(n,pgn); f.get_header().get_tracking().update_time_stamp(timestamp()); } - auto Q = get_group_out("tracers",pgn).m_bundle; + auto Q = get_group_out("tracers",pgn).m_monolithic_field; Q->get_header().get_tracking().update_time_stamp(timestamp()); } update_pressure(m_phys_grid); @@ -169,7 +169,7 @@ void HommeDynamics::remap_dyn_to_fv_phys (GllFvRemapTmp* t) const { const auto npg = m_phys_grid_pgN*m_phys_grid_pgN; const auto& gn = m_phys_grid->name(); const auto nlev = get_field_out("T_mid", gn).get_view().extent_int(1); - const auto nq = get_group_out("tracers").m_bundle->get_view().extent_int(1); + const auto nq = get_group_out("tracers").m_monolithic_field->get_view().extent_int(1); assert(get_field_out("T_mid", gn).get_view().extent_int(0) == nelem*npg); assert(get_field_out("horiz_winds", gn).get_view().extent_int(1) == 2); @@ -189,7 +189,7 @@ void HommeDynamics::remap_dyn_to_fv_phys (GllFvRemapTmp* t) const { t ? t->horiz_winds.data() : get_field_out("horiz_winds", gn).get_view().data(), nelem, npg, 2, nlev); const auto q = Homme::GllFvRemap::Phys3T( - t ? t->tracers.data() : get_group_out("tracers", gn).m_bundle->get_view().data(), + t ? t->tracers.data() : get_group_out("tracers", gn).m_monolithic_field->get_view().data(), nelem, npg, nq, nlev); const auto dp = Homme::GllFvRemap::Phys2T( get_field_out("pseudo_density", gn).get_view().data(), @@ -209,7 +209,7 @@ void HommeDynamics::remap_fv_phys_to_dyn () const { const auto npg = m_phys_grid_pgN*m_phys_grid_pgN; const auto& gn = m_phys_grid->name(); const auto nlev = m_helper_fields.at("FT_phys").get_view().extent_int(1); - const auto nq = get_group_in("tracers", gn).m_bundle->get_view().extent_int(1); + const auto nq = get_group_in("tracers", gn).m_monolithic_field->get_view().extent_int(1); assert(m_helper_fields.at("FT_phys").get_view().extent_int(0) == nelem*npg); const auto uv_ndim = m_helper_fields.at("FM_phys").get_view().extent_int(1); @@ -222,7 +222,7 @@ void HommeDynamics::remap_fv_phys_to_dyn () const { m_helper_fields.at("FM_phys").get_view().data(), nelem, npg, uv_ndim, nlev); const auto q = Homme::GllFvRemap::CPhys3T( - get_group_in("tracers", gn).m_bundle->get_view().data(), + get_group_in("tracers", gn).m_monolithic_field->get_view().data(), nelem, npg, nq, nlev); gfr.run_fv_phys_to_dyn(time_idx, T, uv, q); diff --git a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp index 94b2a0d8c1f2..f64c780d61e2 100644 --- a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp +++ b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp @@ -180,7 +180,7 @@ void HommeDynamics::set_grids (const std::shared_ptr grids_m add_field("omega", pg_scalar3d_mid, Pa/s, pgn,N); add_tracer("qv", m_phys_grid, kg/kg, N); - add_group("tracers",pgn,N, Bundling::Required); + add_group("tracers",pgn,N, MonolithicAlloc::Required); if (fv_phys_active()) { // [CGLL ICs in pg2] Read CGLL IC data even though our in/out format is @@ -196,7 +196,7 @@ void HommeDynamics::set_grids (const std::shared_ptr grids_m add_field("T_mid", rg_scalar3d_mid,K, rgn,N); add_field("ps", rg_scalar2d ,Pa, rgn); add_field("phis", rg_scalar2d ,m2/s2, rgn); - add_group("tracers",rgn,N, Bundling::Required); + add_group("tracers",rgn,N, MonolithicAlloc::Required); fv_phys_rrtmgp_active_gases_init(grids_manager); // This is needed for the dp_ref init in initialize_homme_state. add_field("pseudo_density",rg_scalar3d_mid,Pa, rgn,N); @@ -397,7 +397,7 @@ void HommeDynamics::initialize_impl (const RunType run_type) // ftype!=FORCING_0: // 1) remap Q_pgn->FQ_dyn // Remap Q directly into FQ, tendency computed in pre_process step - m_p2d_remapper->register_field(*get_group_out("Q",pgn).m_bundle,m_helper_fields.at("FQ_dyn")); + m_p2d_remapper->register_field(*get_group_out("Q",pgn).m_monolithic_field,m_helper_fields.at("FQ_dyn")); m_p2d_remapper->register_field(m_helper_fields.at("FT_phys"),m_helper_fields.at("FT_dyn")); // FM has 3 components on dyn grid, but only 2 on phys grid @@ -412,7 +412,7 @@ void HommeDynamics::initialize_impl (const RunType run_type) m_d2p_remapper->register_field(get_internal_field("v_dyn"),get_field_out("horiz_winds")); m_d2p_remapper->register_field(get_internal_field("dp3d_dyn"), get_field_out("pseudo_density")); m_d2p_remapper->register_field(get_internal_field("ps_dyn"), get_field_out("ps")); - m_d2p_remapper->register_field(m_helper_fields.at("Q_dyn"),*get_group_out("Q",pgn).m_bundle); + m_d2p_remapper->register_field(m_helper_fields.at("Q_dyn"),*get_group_out("Q",pgn).m_monolithic_field); m_d2p_remapper->register_field(m_helper_fields.at("omega_dyn"), get_field_out("omega")); m_p2d_remapper->registration_ends(); @@ -463,7 +463,7 @@ void HommeDynamics::initialize_impl (const RunType run_type) using Interval = FieldWithinIntervalCheck; using LowerBound = FieldLowerBoundCheck; - add_postcondition_check(*get_group_out("Q",pgn).m_bundle,m_phys_grid,0,true); + add_postcondition_check(*get_group_out("Q",pgn).m_monolithic_field,m_phys_grid,0,true); add_postcondition_check(get_field_out("T_mid",pgn),m_phys_grid,100.0, 500.0,false); add_postcondition_check(get_field_out("horiz_winds",pgn),m_phys_grid,-400.0, 400.0,false); add_postcondition_check(get_field_out("ps"),m_phys_grid,30000.0, 120000.0,false); @@ -686,7 +686,7 @@ void HommeDynamics::homme_post_process (const double dt) { const auto dp_dry_view = get_field_out("pseudo_density_dry").get_view(); const auto p_dry_int_view = get_field_out("p_dry_int").get_view(); const auto p_dry_mid_view = get_field_out("p_dry_mid").get_view(); - const auto Q_view = get_group_out("Q",pgn).m_bundle->get_view(); + const auto Q_view = get_group_out("Q",pgn).m_monolithic_field->get_view(); const auto T_view = get_field_out("T_mid").get_view(); const auto T_prev_view = m_helper_fields.at("FT_phys").get_view(); @@ -1003,7 +1003,7 @@ void HommeDynamics::restart_homme_state () { auto qv_prev_ref = std::make_shared(); auto Q_dyn = m_helper_fields.at("Q_dyn"); if (params.ftype==Homme::ForcingAlg::FORCING_2) { - auto Q_old = *get_group_in("Q",pgn).m_bundle; + auto Q_old = *get_group_in("Q",pgn).m_monolithic_field; m_ic_remapper->register_field(Q_old,Q_dyn); // Grab qv_ref_old from Q_old @@ -1106,7 +1106,7 @@ void HommeDynamics::initialize_homme_state () { m_ic_remapper->register_field(get_field_in("ps",rgn),get_internal_field("ps_dyn")); m_ic_remapper->register_field(get_field_in("phis",rgn),m_helper_fields.at("phis_dyn")); m_ic_remapper->register_field(get_field_in("T_mid",rgn),get_internal_field("vtheta_dp_dyn")); - m_ic_remapper->register_field(*get_group_in("tracers",rgn).m_bundle,m_helper_fields.at("Q_dyn")); + m_ic_remapper->register_field(*get_group_in("tracers",rgn).m_monolithic_field,m_helper_fields.at("Q_dyn")); m_ic_remapper->registration_ends(); m_ic_remapper->remap_fwd(); diff --git a/components/eamxx/src/physics/iop_forcing/eamxx_iop_forcing_process_interface.cpp b/components/eamxx/src/physics/iop_forcing/eamxx_iop_forcing_process_interface.cpp index c9a3714e1dce..5eb6d6e9b9f1 100644 --- a/components/eamxx/src/physics/iop_forcing/eamxx_iop_forcing_process_interface.cpp +++ b/components/eamxx/src/physics/iop_forcing/eamxx_iop_forcing_process_interface.cpp @@ -29,7 +29,7 @@ void IOPForcing::set_grids(const std::shared_ptr grids_manag add_field("T_mid", scalar3d_mid, K, grid_name, pack_size); add_tracer("qv", m_grid, kg/kg, pack_size); - add_group("tracers", grid_name, pack_size, Bundling::Required); + add_group("tracers", grid_name, pack_size, MonolithicAlloc::Required); // Sanity check that iop data manager is setup by driver EKAT_REQUIRE_MSG(m_iop_data_manager, @@ -64,8 +64,8 @@ set_computed_group_impl (const FieldGroup& group) EKAT_REQUIRE_MSG(name=="tracers", "Error! IOPForcing was not expecting a field group called '" << name << "\n"); - EKAT_REQUIRE_MSG(group.m_info->m_bundled, - "Error! IOPForcing expects bundled fields for tracers.\n"); + EKAT_REQUIRE_MSG(group.m_info->m_monolithic_allocation, + "Error! IOPForcing expects a monolithic allocation for tracers.\n"); m_num_tracers = group.m_info->size(); } @@ -343,7 +343,7 @@ void IOPForcing::run_impl (const double dt) const auto horiz_winds = get_field_out("horiz_winds").get_view(); const auto T_mid = get_field_out("T_mid").get_view(); const auto qv = get_field_out("qv").get_view(); - const auto Q = get_group_out("tracers").m_bundle->get_view(); + const auto Q = get_group_out("tracers").m_monolithic_field->get_view(); // Load data from IOP files, if necessary m_iop_data_manager->read_iop_file_data(timestamp()); diff --git a/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp b/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp index ce3b64b3dc8a..bfa01ed4b8ef 100644 --- a/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp +++ b/components/eamxx/src/physics/ml_correction/eamxx_ml_correction_process_interface.cpp @@ -67,7 +67,7 @@ void MLCorrection::set_grids( add_field("precip_ice_surf_mass", scalar2d, kg/m2, grid_name); /* ----------------------- WARNING --------------------------------*/ add_tracer("qv", m_grid, kg/kg, ps); - add_group("tracers", grid_name, 1, Bundling::Required); + add_group("tracers", grid_name, 1, MonolithicAlloc::Required); } // ========================================================================================= diff --git a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp index 5d63e233fdec..8e9eb52a5703 100644 --- a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp +++ b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.cpp @@ -111,7 +111,7 @@ void SHOCMacrophysics::set_grids(const std::shared_ptr grids } // Extra SHOC output diagnostics // Tracer group - add_group("turbulence_advected_tracers", grid_name, ps, Bundling::Required); + add_group("turbulence_advected_tracers", grid_name, ps, MonolithicAlloc::Required); // Boundary flux fields for energy and mass conservation checks if (has_column_conservation_check()) { @@ -134,8 +134,8 @@ set_computed_group_impl (const FieldGroup& group) EKAT_REQUIRE_MSG(name=="turbulence_advected_tracers", "Error! We were not expecting a field group called '" << name << "\n"); - EKAT_REQUIRE_MSG(group.m_info->m_bundled, - "Error! Shoc expects bundled fields for tracers.\n"); + EKAT_REQUIRE_MSG(group.m_info->m_monolithic_allocation, + "Error! Shoc expects a monolithic allocation for tracers.\n"); // Calculate number of advected tracers m_num_tracers = group.m_info->size(); @@ -269,7 +269,7 @@ void SHOCMacrophysics::initialize_impl (const RunType run_type) const auto& surf_sens_flux = get_field_in("surf_sens_flux").get_view(); const auto& surf_evap = get_field_in("surf_evap").get_view(); const auto& surf_mom_flux = get_field_in("surf_mom_flux").get_view(); - const auto& qtracers = get_group_out("turbulence_advected_tracers").m_bundle->get_strided_view(); + const auto& qtracers = get_group_out("turbulence_advected_tracers").m_monolithic_field->get_strided_view(); const auto& qc = get_field_out("qc").get_view(); const auto& qv = get_field_out("qv").get_view(); const auto& tke = get_field_out("tke").get_view(); diff --git a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.hpp b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.hpp index b8a7e3f6b3f8..48126bbc302a 100644 --- a/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.hpp +++ b/components/eamxx/src/physics/shoc/eamxx_shoc_process_interface.hpp @@ -86,7 +86,7 @@ class SHOCMacrophysics : public scream::AtmosphereProcess Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev_packs), [&] (const Int& k) { - + cldfrac_liq_prev(i,k)=cldfrac_liq(i,k); // Inverse of Exner. In non-rel builds, assert that exner != 0 when in range before computing. @@ -98,10 +98,10 @@ class SHOCMacrophysics : public scream::AtmosphereProcess tke(i,k) = ekat::max(mintke, tke(i,k)); // Tracers are updated as a group. The tracers tke and qc act as separate inputs to shoc_main() - // and are therefore updated differently to the bundled tracers. Here, we make a copy if each - // of these tracers and pass to shoc_main() so that changes to the tracer group does not alter - // tke or qc values. Then during post processing, we copy back correct values of tke and qc - // to tracer group in postprocessing. + // and are therefore updated differently to the tracers group's monolithic field. Here, we make + // a copy if each of these tracers and pass to shoc_main() so that changes to the tracer group + // does not alter tke or qc values. Then during post processing, we copy back correct values of + // tke and qc to tracer group in postprocessing. // TODO: remove *_copy views once SHOC can request a subset of tracers. tke_copy(i,k) = tke(i,k); qc_copy(i,k) = qc(i,k); diff --git a/components/eamxx/src/share/atm_process/IOPDataManager.cpp b/components/eamxx/src/share/atm_process/IOPDataManager.cpp index e88d3bf93afd..3316bd3f9091 100644 --- a/components/eamxx/src/share/atm_process/IOPDataManager.cpp +++ b/components/eamxx/src/share/atm_process/IOPDataManager.cpp @@ -617,7 +617,7 @@ set_fields_from_iop_data(const field_mgr_ptr field_mgr, const std::string& grid_ { if (m_params.get("zero_non_iop_tracers") && field_mgr->has_group("tracers", grid_name)) { // Zero out all tracers before setting iop tracers (if requested) - field_mgr->get_field_group("tracers", grid_name).m_bundle->deep_copy(0); + field_mgr->get_field_group("tracers", grid_name).m_monolithic_field->deep_copy(0); } EKAT_REQUIRE_MSG(grid_name == "Physics GLL", diff --git a/components/eamxx/src/share/atm_process/atmosphere_process.cpp b/components/eamxx/src/share/atm_process/atmosphere_process.cpp index 3ebe02e777ac..dc2f1c5de3f1 100644 --- a/components/eamxx/src/share/atm_process/atmosphere_process.cpp +++ b/components/eamxx/src/share/atm_process/atmosphere_process.cpp @@ -322,10 +322,10 @@ void AtmosphereProcess::set_required_group (const FieldGroup& group) { // AtmosphereProcessGroup is just a "container" of *real* atm processes, // so don't add me as customer if I'm an atm proc group. if (this->type()!=AtmosphereProcessType::Group) { - if (group.m_bundle) { - add_me_as_customer(*group.m_bundle); + if (group.m_monolithic_field) { + add_me_as_customer(*group.m_monolithic_field); } else { - for (auto& it : group.m_fields) { + for (auto& it : group.m_individual_fields) { add_me_as_customer(*it.second); } } @@ -349,10 +349,10 @@ void AtmosphereProcess::set_computed_group (const FieldGroup& group) { // AtmosphereProcessGroup is just a "container" of *real* atm processes, // so don't add me as provider if I'm an atm proc group. if (this->type()!=AtmosphereProcessType::Group) { - if (group.m_bundle) { - add_me_as_provider(*group.m_bundle); + if (group.m_monolithic_field) { + add_me_as_provider(*group.m_monolithic_field); } else { - for (auto& it : group.m_fields) { + for (auto& it : group.m_individual_fields) { add_me_as_provider(*it.second); } } @@ -429,7 +429,7 @@ void AtmosphereProcess::run_property_check (const prop_check_ptr& property } } for (const auto& g : m_groups_in) { - for (const auto& f : g.m_fields) { + for (const auto& f : g.m_individual_fields) { if (f.second->get_header().get_identifier().get_layout().has_tags(tags)) { print_field_hyperslab (*f.second,tags,idx,ss); ss << " -----------------------------------------------------------------------\n"; @@ -444,7 +444,7 @@ void AtmosphereProcess::run_property_check (const prop_check_ptr& property } } for (const auto& g : m_groups_out) { - for (const auto& f : g.m_fields) { + for (const auto& f : g.m_individual_fields) { if (f.second->get_header().get_identifier().get_layout().has_tags(tags)) { print_field_hyperslab (*f.second,tags,idx,ss); ss << " -----------------------------------------------------------------------\n"; @@ -588,10 +588,10 @@ void AtmosphereProcess::update_time_stamps () { f.get_header().get_tracking().update_time_stamp(t); } for (auto& g : m_groups_out) { - if (g.m_bundle) { - g.m_bundle->get_header().get_tracking().update_time_stamp(t); + if (g.m_monolithic_field) { + g.m_monolithic_field->get_header().get_tracking().update_time_stamp(t); } else { - for (auto& f : g.m_fields) { + for (auto& f : g.m_individual_fields) { f.second->get_header().get_tracking().update_time_stamp(t); } } @@ -1111,7 +1111,7 @@ ::remove_group (const std::string& group_name, const std::string& grid_name) { if (it->m_info->m_group_name == group_name and it->grid_name() == grid_name) { rm_its.push_back(it); ptrs[group_name][grid_name] = nullptr; - for (auto& kv : it->m_fields) + for (auto& kv : it->m_individual_fields) remove_field(kv.first, grid_name); } } diff --git a/components/eamxx/src/share/atm_process/atmosphere_process.hpp b/components/eamxx/src/share/atm_process/atmosphere_process.hpp index ac45b9ceb956..bb018f436a2b 100644 --- a/components/eamxx/src/share/atm_process/atmosphere_process.hpp +++ b/components/eamxx/src/share/atm_process/atmosphere_process.hpp @@ -183,7 +183,7 @@ class AtmosphereProcess : public ekat::enable_shared_from_this& get_fields_in () const { return m_fields_in; } const std::list& get_fields_out () const { return m_fields_out; } @@ -372,12 +372,12 @@ class AtmosphereProcess : public ekat::enable_shared_from_this void add_group (const std::string& name, const std::string& grid_name, - const Bundling b = Bundling::NotNeeded) + const MonolithicAlloc b = MonolithicAlloc::NotRequired) { add_group (GroupRequest(name,grid_name,b)); } template void add_group (const std::string& name, const std::string& grid_name, - const int pack_size, const Bundling b = Bundling::NotNeeded) + const int pack_size, const MonolithicAlloc b = MonolithicAlloc::NotRequired) { add_group (GroupRequest(name,grid_name,pack_size,b)); } template diff --git a/components/eamxx/src/share/atm_process/atmosphere_process_dag.cpp b/components/eamxx/src/share/atm_process/atmosphere_process_dag.cpp index d7d09e3af913..a934a549a804 100644 --- a/components/eamxx/src/share/atm_process/atmosphere_process_dag.cpp +++ b/components/eamxx/src/share/atm_process/atmosphere_process_dag.cpp @@ -286,7 +286,7 @@ void AtmProcDAG::write_dag (const std::string& fname, const int verbosity) const if (verbosity>2) { ofile << " Members:"; const auto& group = m_gr_fid_to_group.at(m_fids[gr_fid]); - const auto& members = group.m_fields; + const auto& members = group.m_individual_fields; const auto& members_names = group.m_info->m_fields_names; const size_t max_len = 40; size_t len = 0; @@ -336,7 +336,7 @@ void AtmProcDAG::write_dag (const std::string& fname, const int verbosity) const if (verbosity>2) { ofile << " Members:"; const auto& group = m_gr_fid_to_group.at(m_fids[gr_fid]); - const auto& members = group.m_fields; + const auto& members = group.m_individual_fields; const auto& members_names = group.m_info->m_fields_names; const size_t max_len = 40; size_t len = 0; @@ -473,17 +473,17 @@ add_nodes (const group_type& atm_procs) // Input groups for (const auto& group : proc->get_groups_in()) { - if (!group.m_info->m_bundled) { - // Group is not bundled: process fields individually - for (const auto& it_f : group.m_fields) { + if (!group.m_info->m_monolithic_allocation) { + // Group does not allocate a monolithic field: process fields individually + for (const auto& it_f : group.m_individual_fields) { const auto& fid = it_f.second->get_header().get_identifier(); const int fid_id = add_fid(fid); node.computed.insert(fid_id); m_fid_to_last_provider[fid_id] = id; } } else { - // Group is bundled: process the bundled field - const auto& gr_fid = group.m_bundle->get_header().get_identifier(); + // Group allocates a monolithic field: process the monolithic field + const auto& gr_fid = group.m_monolithic_field->get_header().get_identifier(); const int gr_fid_id = add_fid(gr_fid); node.gr_required.insert(gr_fid_id); m_gr_fid_to_group.emplace(gr_fid,group); @@ -492,17 +492,17 @@ add_nodes (const group_type& atm_procs) // Output groups for (const auto& group : proc->get_groups_out()) { - if (!group.m_info->m_bundled) { - // Group is not bundled: process fields in the group individually - for (const auto& it_f : group.m_fields) { + if (!group.m_info->m_monolithic_allocation) { + // Group does not allocate a monolithic field: process fields in the group individually + for (const auto& it_f : group.m_individual_fields) { const auto& fid = it_f.second->get_header().get_identifier(); const int fid_id = add_fid(fid); node.computed.insert(fid_id); m_fid_to_last_provider[fid_id] = id; } } else { - // Group is bundled: process the bundled field - const auto& gr_fid = group.m_bundle->get_header().get_identifier(); + // Group allocates a monolithic field: process the monolithic field + const auto& gr_fid = group.m_monolithic_field->get_header().get_identifier(); const int gr_fid_id = add_fid(gr_fid); node.gr_computed.insert(gr_fid_id); m_fid_to_last_provider[gr_fid_id] = id; @@ -510,7 +510,7 @@ add_nodes (const group_type& atm_procs) // Additionally, each field in the group is implicitly 'computed' // by this node, so update their last provider - for (auto it_f : group.m_fields) { + for (auto it_f : group.m_individual_fields) { const auto& fid = it_f.second->get_header().get_identifier(); const int fid_id = add_fid(fid); m_fid_to_last_provider[fid_id] = id; @@ -536,7 +536,7 @@ void AtmProcDAG::add_edges () { m_unmet_deps[node.id].insert(id); } } - // Then process groups, looking at both the bundled field and individual fields. + // Then process groups, looking at both the monolithic field and individual fields. // NOTE: we don't know if the group as a whole is the last to be updated // OR if each group member is updated after the last "group-update". // So get the id of the last node that updates each field and the group, @@ -557,7 +557,7 @@ void AtmProcDAG::add_edges () { } // Then check when each group member was last updated int i=0; - for (auto f_it : group.m_fields) { + for (auto f_it : group.m_individual_fields) { const auto& fid = f_it.second->get_header().get_identifier(); auto fid_id = std::find(m_fids.begin(),m_fids.end(),fid) - m_fids.begin(); it = m_fid_to_last_provider.find(fid_id); diff --git a/components/eamxx/src/share/atm_process/atmosphere_process_group.cpp b/components/eamxx/src/share/atm_process/atmosphere_process_group.cpp index 9d5ff4889295..17da387332c3 100644 --- a/components/eamxx/src/share/atm_process/atmosphere_process_group.cpp +++ b/components/eamxx/src/share/atm_process/atmosphere_process_group.cpp @@ -336,7 +336,7 @@ void AtmosphereProcessGroup::add_postcondition_nan_checks () const { for (const auto& g : proc->get_groups_out()) { const auto& grid = m_grids_mgr->get_grid(g.grid_name()); - for (const auto& f : g.m_fields) { + for (const auto& f : g.m_individual_fields) { auto nan_check = std::make_shared(*f.second,grid); proc->add_postcondition_check(nan_check, CheckFailHandling::Fatal); } @@ -523,7 +523,7 @@ set_required_group (const FieldGroup& group) { // NOTE: we still check also the groups computed by the previous procs, // in case they contain some of the fields in this group. std::set computed; - for (const auto& it : group.m_fields) { + for (const auto& it : group.m_individual_fields) { const auto& fn = it.first; const auto& fid = it.second->get_header().get_identifier(); for (int iproc=0; iproc& v, bfbhash::hash(v(idx), accum); }, bfbhash::HashReducer<>(accum)); Kokkos::fence(); - bfbhash::hash(accum, accum_out); + bfbhash::hash(accum, accum_out); } void hash (const Field::view_dev_t& v, @@ -97,7 +97,7 @@ void hash (const Field& f, HashType& accum) { case 4: hash(f.get_view(), lo, accum); break; case 5: hash(f.get_view(), lo, accum); break; default: break; - } + } } void hash (const std::list& fs, HashType& accum) { @@ -107,7 +107,7 @@ void hash (const std::list& fs, HashType& accum) { void hash (const std::list& fgs, HashType& accum) { for (const auto& g : fgs) - for (const auto& e : g.m_fields) + for (const auto& e : g.m_individual_fields) hash(*e.second, accum); } diff --git a/components/eamxx/src/share/field/field_group.cpp b/components/eamxx/src/share/field/field_group.cpp index c993342afc8d..523d6862d08a 100644 --- a/components/eamxx/src/share/field/field_group.cpp +++ b/components/eamxx/src/share/field/field_group.cpp @@ -18,32 +18,32 @@ FieldGroup (const FieldGroupInfo& info) FieldGroup FieldGroup::get_const () const { FieldGroup gr(*m_info); - if (m_info->m_bundled) { - gr.m_bundle = std::make_shared(m_bundle->get_const()); + if (m_info->m_monolithic_allocation) { + gr.m_monolithic_field = std::make_shared(m_monolithic_field->get_const()); } - for (const auto& it : m_fields) { - gr.m_fields[it.first] = std::make_shared(it.second->get_const()); + for (const auto& it : m_individual_fields) { + gr.m_individual_fields[it.first] = std::make_shared(it.second->get_const()); } return gr; } const std::string& FieldGroup::grid_name () const { - EKAT_REQUIRE_MSG(m_fields.size()>0 || m_bundle, + EKAT_REQUIRE_MSG(m_individual_fields.size()>0 || m_monolithic_field, "Error! Cannot establish the group grid name until fields have been added.\n"); - if (m_bundle) { - const auto& id = m_bundle->get_header().get_identifier(); + if (m_monolithic_field) { + const auto& id = m_monolithic_field->get_header().get_identifier(); return id.get_grid_name(); } else { - const auto& id = m_fields.begin()->second->get_header().get_identifier(); + const auto& id = m_individual_fields.begin()->second->get_header().get_identifier(); return id.get_grid_name(); } } void FieldGroup::copy_fields (const FieldGroup& src) { - m_bundle = src.m_bundle; - for (auto it : src.m_fields) { - m_fields[it.first] = it.second; + m_monolithic_field = src.m_monolithic_field; + for (auto it : src.m_individual_fields) { + m_individual_fields[it.first] = it.second; } } diff --git a/components/eamxx/src/share/field/field_group.hpp b/components/eamxx/src/share/field/field_group.hpp index 3dcbfbd6d06e..bb27665029d5 100644 --- a/components/eamxx/src/share/field/field_group.hpp +++ b/components/eamxx/src/share/field/field_group.hpp @@ -23,14 +23,14 @@ namespace scream { * The same FieldGroupInfo can be recycled for several FieldGroup's, each living * on a different grid. * - * Notice that, if the allocation was bundled, the big bundle is allocated + * Notice that, if the group has a monolithic allocation, the monolithic field is allocated * with layout given by grid->get_Xd_vector_layout(), where grid is the * grid object where the fields are defined on, and X=2 or 3. * Each field is then subviewed at entry k (different for each field) - * along dimension I (same for all field) of the big bundle field. + * along dimension I (same for all field) of the monolithic field. * * E.g., say we have 3d scalar fields F1,F2,F3,F4 belonging to group MyGroup, - * which is then allocated as a bundled field F. F will have layout + * which is then allocated as a monolithic field F. F will have layout * given by grid->get_3d_vector_layout(). Say this layout is (COL,CMP,LEV). * Each field is subviewed along m_subview_dim=1, at entry 0,1,2,3 respectively. * Note: as of 02/2021 m_subview_dim is *always* 1, but we store this bit @@ -57,11 +57,11 @@ struct FieldGroup { const std::string& grid_name () const; // The fields in this group - std::map> m_fields; + std::map> m_individual_fields; - // If m_info->m_bundled is true, this is the field that all fields - // in m_fields are a subview of. - std::shared_ptr m_bundle; + // If m_info->m_monolithic_alloc is true, this is the field + // that all fields in m_individual_fields are a subview of. + std::shared_ptr m_monolithic_field; // The info of this group. std::shared_ptr m_info; diff --git a/components/eamxx/src/share/field/field_group_info.hpp b/components/eamxx/src/share/field/field_group_info.hpp index ba83565a1a68..b8631a21692c 100644 --- a/components/eamxx/src/share/field/field_group_info.hpp +++ b/components/eamxx/src/share/field/field_group_info.hpp @@ -18,10 +18,10 @@ namespace scream { * A FieldGroupInfo stores: * * - a list of the field names associated to this group; - * - whether the field were allocated as a single "bundled" field, - * with each field extracted as a "subview" of the bundled one; - * - if the allocation was "bundled", also store for each field - * the index that was used to extract the corresponding subview. + * - whether the field were allocated as a single monolithic field, + * with each field extracted as a "subview" of the monolithic one; + * - if the group allocated a monolithic field, also store for each + * subfield the index that was used to extract the corresponding subview. */ struct FieldGroupInfo @@ -32,7 +32,7 @@ struct FieldGroupInfo FieldGroupInfo (const ci_string& group_name) : m_group_name (group_name) , m_fields_names{} - , m_bundled (false) + , m_monolithic_allocation (false) , m_subview_dim(-1) , m_subview_idx{} { @@ -55,21 +55,21 @@ struct FieldGroupInfo std::map> m_grid_registered; // Store any grid that is requested for a group. - // This is useful in the bundled case where - // we can add a grid that may not have any - // registered fields, but that we want the - // bundled group to exist. + // This is useful in the case where we allocate + // a monolithic field, we can add a grid that may + // not have any registered fields, but that we want + // the group to exist. std::list m_requested_grids; - // Whether the group was allocated as a bundle - bool m_bundled; + // Whether the group allocated a monolithic field + bool m_monolithic_allocation; - // If bundled, each field is subviewed along a different entry - // along the same dimension. + // If we allocate a monolithic field, each field is subviewed + // along a different entry along the same dimension. int m_subview_dim; - // If bundled, for each field name, store the idx used - // to subview each field from the bundle. + // If we allocate a monolithic field, for each field name, + // store the idx used to subview each individual field. std::map m_subview_idx; }; @@ -78,7 +78,7 @@ inline bool operator== (const FieldGroupInfo& lhs, { return lhs.m_group_name==rhs.m_group_name && lhs.m_fields_names==rhs.m_fields_names && - lhs.m_bundled==rhs.m_bundled && + lhs.m_monolithic_allocation==rhs.m_monolithic_allocation && lhs.m_subview_dim==rhs.m_subview_dim && lhs.m_subview_idx==rhs.m_subview_idx; } diff --git a/components/eamxx/src/share/field/field_manager.cpp b/components/eamxx/src/share/field/field_manager.cpp index e7c70fbe829e..cd25fb374be2 100644 --- a/components/eamxx/src/share/field/field_manager.cpp +++ b/components/eamxx/src/share/field/field_manager.cpp @@ -100,7 +100,7 @@ void FieldManager::register_field (const FieldRequest& req) } // Ensure that each group in m_field_group_info also appears in the m_group_requests map by - // adding a "trivial" GroupRequest for this group, meaning no bundling and pack size 1. + // adding a "trivial" GroupRequest for this group, meaning no monolithic allocation and pack size 1. register_group(GroupRequest(group_name, grid_name)); } } @@ -120,9 +120,9 @@ void FieldManager::register_group (const GroupRequest& req) auto& group_info = m_field_group_info[req.name]; if (not group_info) { group_info = std::make_shared(req.name); - group_info->m_bundled = (req.bundling==Bundling::Required); - } else if (not group_info->m_bundled) { - group_info->m_bundled = (req.bundling==Bundling::Required); + group_info->m_monolithic_allocation = (req.monolithic_alloc==MonolithicAlloc::Required); + } else if (not group_info->m_monolithic_allocation) { + group_info->m_monolithic_allocation = (req.monolithic_alloc==MonolithicAlloc::Required); } if (not ekat::contains(group_info->m_requested_grids, req.grid)) { @@ -139,8 +139,8 @@ add_to_group (const std::string& field_name, const std::string& grid_name, const if (not group) { group = std::make_shared(group_name); } - EKAT_REQUIRE_MSG (not group->m_bundled, - "Error! Cannot add fields to a group that is bundled.\n" + EKAT_REQUIRE_MSG (not group->m_monolithic_allocation, + "Error! Cannot add fields to a group that has a monolithic allocation.\n" " field name: " + field_name + "\n" " group name: " + group_name + "\n"); @@ -210,11 +210,11 @@ get_group_info (const std::string& group_name, const std::string& grid_name) con auto info = *m_field_group_info.at(group_name); - if (info.m_bundled) { - // All fields in a bundled group should exist on any grid in that group + if (info.m_monolithic_allocation) { + // All fields in a group with a monolithic allocation should exist on any grid in that group for (const auto& fname : info.m_fields_names) { EKAT_REQUIRE_MSG(has_field(fname, grid_name), - "Internal FieldManager Error! Bundled groups must contain all " + "Internal FieldManager Error! Groups with monolithic allocation must contain all " "fields in m_fields_names on any grid from m_grids_in_group.\n" "The following field should, but does not, exist:\n" " - Group: " + group_name + "\n" @@ -222,7 +222,7 @@ get_group_info (const std::string& group_name, const std::string& grid_name) con " - Grid: " + grid_name + "\n"); } } else { - // For non-bundled groups, remove fields in the group + // For all other groups, remove fields in the group // that do not exist on the requested grid std::list remove_fnames; for (const auto& fname : info.m_fields_names) { @@ -263,21 +263,21 @@ get_field_group (const std::string& group_name, const std::string& grid_name) // Find all the fields registered on given grid and set them in the group for (const auto& fname : group->m_info->m_fields_names) { - group->m_fields[fname] = m_fields.at(grid_name).at(fname); + group->m_individual_fields[fname] = m_fields.at(grid_name).at(fname); } - // Fetch the bundle field (if bundled) - if (group->m_info->m_bundled) { + // Fetch the monolithic field (if applicable) + if (group->m_info->m_monolithic_allocation) { // All fields in a group have the same parent, get the parent from the 1st one - const auto& parent_header = group->m_fields.begin()->second->get_header().get_parent(); + const auto& parent_header = group->m_individual_fields.begin()->second->get_header().get_parent(); EKAT_REQUIRE_MSG(parent_header!=nullptr, - "Error! A field belonging to a bundled field group is missing its 'parent'.\n"); + "Error! A field belonging to a field group with monolithic allocation is missing its 'parent'.\n"); const auto& parent_id = parent_header->get_identifier(); EKAT_REQUIRE_MSG(has_field(parent_id.name(), grid_name), - "Internal FieldManager Error! Bundled field must exist in the FieldManager:\n" + "Internal FieldManager Error! Parent field must exist in the FieldManager:\n" " - Group: " + group_name + "\n" " - Bundeled field: " + parent_id.name() + "\n" " - Grid: " + grid_name + "\n"); @@ -289,7 +289,7 @@ get_field_group (const std::string& group_name, const std::string& grid_name) bool all_children_in_group = true; for (auto child : parent_header->get_children()) { bool in_group = false; - for (auto f : group->m_fields) { + for (auto f : group->m_individual_fields) { if (child.lock()->get_identifier() == f.second->get_header().get_identifier()) { in_group = true; break; @@ -301,11 +301,11 @@ get_field_group (const std::string& group_name, const std::string& grid_name) } } - // Set m_bundle field + // Set m_monolithic_field field if (all_children_in_group) { // If all children are in the group, this is the parent group and - // we can just query the bundle and set here - group->m_bundle = parent_field; + // we can just query the monolithic field and set here + group->m_monolithic_field = parent_field; } else { // If children exist that aren't in this group, we need to get a // subfield of the parent group containing indices of group fields @@ -322,7 +322,7 @@ get_field_group (const std::string& group_name, const std::string& grid_name) EKAT_REQUIRE_MSG (ordered_subview_indices.size()==span, "Error! Non-contiguous subview indices found in group \""+group_name+"\"\n"); - group->m_bundle = std::make_shared( + group->m_monolithic_field = std::make_shared( parent_field->subfield( group_name, parent_header->get_identifier().get_units(), group->m_info->m_subview_dim, @@ -356,8 +356,8 @@ void FieldManager::registration_begins () void FieldManager::registration_ends () { // This method is responsible of allocating the fields in the repo. The most delicate part is - // the allocation of fields group, in the case where bundling is required. If we are not able - // to honor requests for bundling, we will error out. An example of a scenario where we can't + // the allocation of fields group, in the case where a monolithic allocation is required. If we + // are not able to honor requests, we will error out. An example of a scenario where we can't // honor all requests is given by the three groups G1=(A,B), G2=(B,C), and G3=(A,C). Clearly, // only two of these groups can have contiguous allocation. @@ -373,10 +373,10 @@ void FieldManager::registration_ends () // This is the sequence of operations that allows us to establish if (and how) we can honor // all the requests: - // 1) ensure all bundled groups contain the desired members. This means that we need to - // loop over GroupRequest (GR), and make sure there are fields registered in those + // 1) ensure all groups with a monolithic allocation contain the desired members. This means that + // we need to loop over GroupRequest (GR), and make sure there are fields registered in those // groups (querying m_field_group_info info structs). - // 2) Focus only on GR that require a bundled group, discarding others. + // 2) Focus only on GR that require a monolithic allocation, discarding others. // All the remaining group can simply "grab" individual fields later (and they // can even grab some "individual" fields, and some fields that are slices of // another group). @@ -389,68 +389,67 @@ void FieldManager::registration_ends () // Note: to build a cluster, take any group not yet in a cluster. Then iteratively // add any group that intersects the cluster, until no intersections are found. // 4) If there is no group in the cluster that contains all the fields of the cluster, - // create the cluster group C. In order to accommodate all requests for bundled groups, - // we must be able to allocate C bundled. + // create the cluster group C. In order to accommodate all requests for groups, + // we must be able to allocate C contiguously. // 5) For each cluster, call the function contiguous_superset from eamxx_utils.hpp // (see that file for details). If the fcn fails to find an ordering of the cluster's - // field that accommodate all bundled requests, it will return an empty list. + // field that accommodate all requests, it will return an empty list. // Otherwise it will return the ordering of all fields in the cluster that allows all // groups of the cluster to be a contiguous subset of C. - // Note: this can be done independent of grid since each grid will contain that same fields - // in a bundled group. + // Note: this can be done independent of grid since each grid will contain the same fields // Start by processing group request. This function checks that all group fields are properly // registered on the appropriate grid and the FieldGroupInfo is up to date. If group G is // requested, we make sure to register the union of all fields in group G on any grids they appear. - pre_process_bundled_group_requests(); + pre_process_monolithic_group_requests(); - // Gather a list of groups to be bundled - std::list groups_to_bundle; + // Gather a list of groups whose fields require monolithic allocation + std::list groups_with_monolithic_allocation; for (auto& grid_it : m_grids_mgr->get_repo()) { for (const auto& greqs : m_group_requests.at(grid_it.second->name())) { for (const auto& r : greqs.second) { - if (r.bundling==Bundling::Required) { - // There's at least one request for this group to be bundled. - groups_to_bundle.push_back(greqs.first); + if (r.monolithic_alloc==MonolithicAlloc::Required) { + // There's at least one request for this group to be allocated. + groups_with_monolithic_allocation.push_back(greqs.first); break; } } } } // TODO: Is this still needed? Probably no. - ::scream::sort(groups_to_bundle); - groups_to_bundle.unique(); + ::scream::sort(groups_with_monolithic_allocation); + groups_with_monolithic_allocation.unique(); // Homme currently wants qv to be the first tracer. We should be able to // modify Homme, to use something like qv_idx. However, that requires // extensive changes in Homme. Instead, we hack our way around this limitatin // (for now), and rearrange groups/fields so that we can expect qv to be the // first tracer. - // Note: there are potentially two bundled groups of tracers, "tracers" (which + // Note: there are potentially two groups of tracers, "tracers" (which // homme advects) and "turbulence_advected_tracers" (which shoc advects). // "turbulence_advected_tracers" is guarenteed to be a subset of "tracers", so // moving qv first in "tracers" will do the same for "turbulence_advected_tracers". // Only homme requires qv first, so we only need to move qv if "tracers" exist. bool qv_must_come_first = false; - if (ekat::contains(groups_to_bundle,"tracers") + if (ekat::contains(groups_with_monolithic_allocation,"tracers") and ekat::contains(m_field_group_info["tracers"]->m_fields_names, "qv")) { // Bring tracers to the front, so it will be processed first - auto it = ekat::find(groups_to_bundle,"tracers"); - std::swap(*it,groups_to_bundle.front()); + auto it = ekat::find(groups_with_monolithic_allocation,"tracers"); + std::swap(*it,groups_with_monolithic_allocation.front()); - // Adding the 'fake' group G=(qv) at the front of groups_to_bundle ensures qv won't be put + // Adding the 'fake' group G=(qv) at the front of groups_with_monolithic_allocation ensures qv won't be put // in the middle of the tracers group. We use a highly unlikely group name, to avoid clashing // with a real group name. Later, after having found an global ordering for the tracers fields, // we will remove this group. - groups_to_bundle.push_front("__qv__"); + groups_with_monolithic_allocation.push_front("__qv__"); m_field_group_info.emplace("__qv__",std::make_shared("__qv__")); m_field_group_info.at("__qv__")->m_fields_names.push_back("qv"); qv_must_come_first = true; } - // Do all the bundling stuff only if there are groups do bundle at all. - if (groups_to_bundle.size()>0) { + // Do all the monolithic allocation stuff only if there are groups which require it. + if (groups_with_monolithic_allocation.size()>0) { using namespace ShortFieldTagsNames; // A cluster is a list of names of groups in the cluster @@ -469,13 +468,13 @@ void FieldManager::registration_ends () std::list clusters; std::list added_to_a_cluster; - while (added_to_a_cluster.size()get_3d_vector_layout(f_layout.tags().back()==LEV,cluster_ordered_fields.size()); } - // The units for the bundled field are nondimensional, cause checking whether - // all fields in the bundle have the same units so we can use those is too long and pointless. + // The units for the monolithic field are nondimensional, cause checking whether + // all fields in the group have the same units so we can use those is too long and pointless. auto nondim = ekat::units::Units::nondimensional(); // Allocate cluster field @@ -702,15 +701,15 @@ void FieldManager::registration_ends () "Error! Something went wrong while looking for fields of this group in the ordered cluster.\n" " Group name: " + gn + "\n"); - // Update the list of fields in the group info, mark it as bundled, - // and update the subfield indices too. + // Update the list of fields in the group info, mark it as monolithically + // allocated, and update the subfield indices too. info.m_fields_names.clear(); for (auto it=first; it!=last; ++it) { info.m_fields_names.push_back(*it); info.m_subview_dim = 1; // Assumption is checked above info.m_subview_idx [*it] = std::distance(cluster_ordered_fields.begin(),it); } - info.m_bundled = true; + info.m_monolithic_allocation = true; // The subview indices will need to be corrected in the case of this group being // itself a subfile of the cluster field. We are guarenteed that the indices @@ -806,27 +805,27 @@ void FieldManager::add_field (const Field& f) { if (m_repo_state==RepoState::Clean) m_repo_state = RepoState::Closed; } -void FieldManager::pre_process_bundled_group_requests () { - // For each bundled group, loop over all fields in the group and register +void FieldManager::pre_process_monolithic_group_requests () { + // For each group, loop over all fields in the group and register // on to each grid the group is requested on (if necessary) for (auto [group_name, group_info] : m_field_group_info) { - if (not group_info->m_bundled) continue; - // Gather all grids in this bundled group. We need to check + if (not group_info->m_monolithic_allocation) continue; + // Gather all grids in this group. We need to check // both grids that already exist in the group and grids that // at one point were requested by the group. - std::list grids_in_bundle; + std::list grids_in_group; for (auto field_name : group_info->m_fields_names) { for (auto grid_name : group_info->m_grid_registered.at(field_name)) { - if (not ekat::contains(grids_in_bundle, grid_name)) grids_in_bundle.push_back(grid_name); + if (not ekat::contains(grids_in_group, grid_name)) grids_in_group.push_back(grid_name); } } for (auto grid_name : group_info->m_requested_grids) { - if (not ekat::contains(grids_in_bundle, grid_name)) grids_in_bundle.push_back(grid_name); + if (not ekat::contains(grids_in_group, grid_name)) grids_in_group.push_back(grid_name); } - // Register fields on all grids in bundle + // Register fields on all grids for (auto field_name : group_info->m_fields_names) { - for (auto grid_name : grids_in_bundle) { + for (auto grid_name : grids_in_group) { // Field already registered on grid, nothing to do if (has_field(field_name, grid_name)) continue; diff --git a/components/eamxx/src/share/field/field_manager.hpp b/components/eamxx/src/share/field/field_manager.hpp index 392b0bf4f479..7aa8518575dc 100644 --- a/components/eamxx/src/share/field/field_manager.hpp +++ b/components/eamxx/src/share/field/field_manager.hpp @@ -69,7 +69,7 @@ class FieldManager { void add_field (const Field& f); // Adds $field_name on $grid_name to group $group_name (creating the group, if necessary). - // NOTE: if $group_name is allocated as a bundled field, this throws. + // NOTE: if $group_name is allocated as a monolithic field, this throws. // NOTE: must be called after registration ends void add_to_group (const std::string& field_name, const std::string& grid_name, const std::string& group_name); void add_to_group (const identifier_type& id, const std::string& group_name) { add_to_group(id.name(), id.get_grid_name(), group_name); } @@ -155,7 +155,7 @@ class FieldManager { protected: - void pre_process_bundled_group_requests (); + void pre_process_monolithic_group_requests (); // The state of the repository RepoState m_repo_state; diff --git a/components/eamxx/src/share/field/field_request.hpp b/components/eamxx/src/share/field/field_request.hpp index 09a037d224e2..e48b7e6017c0 100644 --- a/components/eamxx/src/share/field/field_request.hpp +++ b/components/eamxx/src/share/field/field_request.hpp @@ -20,10 +20,10 @@ enum TracerAdvection { DynamicsOnly, }; -// Whether the bundling of a field group (see below) is needed, optional, or not needed. -enum class Bundling : int { +// Whether the field group should be allocated as a monolithic field +enum class MonolithicAlloc : int { Required, - NotNeeded + NotRequired }; /* @@ -46,27 +46,28 @@ struct GroupRequest { // - name: the name of the group // - grid: the grid where the group is requested // - ps: the pack size that the allocation of the fields in the group - // (and the bundled field, if any) should accommodate (see field_alloc_prop.hpp) - // - bundling: whether the group should be bundled (see field_group.hpp) - GroupRequest (const std::string& name_, const std::string& grid_, const int ps, const Bundling b = Bundling::NotNeeded) - : name(name_), grid(grid_), pack_size(ps), bundling(b) + // (and the monolithic field, if any) should accommodate (see field_alloc_prop.hpp) + // - monolithic_alloc: whether the group should be allocated as a monolithic group (see field_group.hpp) + GroupRequest (const std::string& name_, const std::string& grid_, const int ps, + const MonolithicAlloc monolithic_alloc_ = MonolithicAlloc::NotRequired) + : name(name_), grid(grid_), pack_size(ps), monolithic_alloc(monolithic_alloc_) { EKAT_REQUIRE_MSG(pack_size>=1, "Error! Invalid pack size request.\n"); } GroupRequest (const std::string& name_, const std::string& grid_, - const Bundling b = Bundling::NotNeeded) - : GroupRequest(name_,grid_,1,b) + const MonolithicAlloc monolithic_alloc_ = MonolithicAlloc::NotRequired) + : GroupRequest(name_,grid_,1,monolithic_alloc_) { /* Nothing to do here */ } // Default copy ctor is perfectly fine GroupRequest (const GroupRequest&) = default; // Main parts of a group request - std::string name; // Group name - std::string grid; // Grid name - int pack_size; // Request an allocation that can accomodate Pack - Bundling bundling; // Whether the group should be allocated as a single n+1 dimensional field + std::string name; // Group name + std::string grid; // Grid name + int pack_size; // Request an allocation that can accomodate Pack + MonolithicAlloc monolithic_alloc; // Whether the group should be allocated as a single n+1 dimensional field }; // In order to use GroupRequest in std sorted containers (like std::set), @@ -95,8 +96,8 @@ inline bool operator< (const GroupRequest& lhs, return false; } - // Same pack size, order by bundling - return etoi(lhs.bundling) f_i; for (int i=0; i(f); + g.m_monolithic_field = std::make_shared(f); for (int i=0; i(f_i[i]); + g.m_individual_fields["G_"+std::to_string(i)] = std::make_shared(f_i[i]); } // Check const cloning auto cg= g.get_const(); - REQUIRE (cg.m_bundle->is_read_only()); - REQUIRE (cg.m_fields.size()==g.m_fields.size()); + REQUIRE (cg.m_monolithic_field->is_read_only()); + REQUIRE (cg.m_individual_fields.size()==g.m_individual_fields.size()); REQUIRE (*cg.m_info==*g.m_info); - REQUIRE (cg.m_bundle->get_internal_view_data()== - g.m_bundle->get_internal_view_data()); + REQUIRE (cg.m_monolithic_field->get_internal_view_data()== + g.m_monolithic_field->get_internal_view_data()); for (int i=0; i()== cf.get_internal_view_data()); } @@ -558,7 +558,7 @@ TEST_CASE("field_mgr", "") { REQUIRE_THROWS (field_mgr.add_field(f2_1_sf)); // Cannot have duplicates } -TEST_CASE("tracers_bundle", "") { +TEST_CASE("tracers_group", "") { using namespace scream; using namespace ekat::units; using namespace ShortFieldTagsNames; @@ -596,10 +596,10 @@ TEST_CASE("tracers_bundle", "") { field_mgr.register_field(FR{b_id,los{"tracers", "subtracers"}}); field_mgr.register_field(FR{c_id,los{"tracers", "subtracers"}}); - field_mgr.register_group(GroupRequest("tracers",gn1,Bundling::Required)); - field_mgr.register_group(GroupRequest("tracers",gn2,Bundling::Required)); - field_mgr.register_group(GroupRequest("subtracers",gn1,Bundling::Required)); - //field_mgr.register_group(GroupRequest("subtracers",gn2,Bundling::Required)); + field_mgr.register_group(GroupRequest("tracers",gn1,MonolithicAlloc::Required)); + field_mgr.register_group(GroupRequest("tracers",gn2,MonolithicAlloc::Required)); + field_mgr.register_group(GroupRequest("subtracers",gn1,MonolithicAlloc::Required)); + //field_mgr.register_group(GroupRequest("subtracers",gn2,MonolithicAlloc::Required)); field_mgr.registration_ends(); @@ -619,17 +619,17 @@ TEST_CASE("tracers_bundle", "") { REQUIRE_THROWS (field_mgr.get_field("subtracers", gn1)); REQUIRE_THROWS (field_mgr.get_field("subtracers", gn2)); - // The field_mgr should have allocated the group bundled + // The field_mgr should have allocated the group as a monolith auto tracers1 = field_mgr.get_field_group("tracers", gn1); auto tracers2 = field_mgr.get_field_group("tracers", gn2); auto subtracers = field_mgr.get_field_group("subtracers", gn1); - REQUIRE (tracers1.m_info->m_bundled); - REQUIRE (tracers2.m_info->m_bundled); - REQUIRE (subtracers.m_info->m_bundled); + REQUIRE (tracers1.m_info->m_monolithic_allocation); + REQUIRE (tracers2.m_info->m_monolithic_allocation); + REQUIRE (subtracers.m_info->m_monolithic_allocation); - // The bundled field in the tracers group should match the field we get from the field_mgr - REQUIRE (T1.is_aliasing(*tracers1.m_bundle)); - REQUIRE (T2.is_aliasing(*tracers2.m_bundle)); + // The monolithic field in the tracers group should match the field we get from the field_mgr + REQUIRE (T1.is_aliasing(*tracers1.m_monolithic_field)); + REQUIRE (T2.is_aliasing(*tracers2.m_monolithic_field)); // Require that the parent of each field is the "tracers" group auto qv1_p = qv1.get_header().get_parent(); @@ -650,10 +650,10 @@ TEST_CASE("tracers_bundle", "") { REQUIRE ((b2_p!=nullptr && b2_p.get()==&T2.get_header())); REQUIRE ((c2_p!=nullptr && c2_p.get()==&T2.get_header())); - // Require subtracers bundle is subfield of tracers + // Require subtracers monolith is subfield of tracers REQUIRE (( - subtracers.m_bundle->get_header().get_parent() != nullptr && - subtracers.m_bundle->get_header().get_parent().get() == &T1.get_header())); + subtracers.m_monolithic_field->get_header().get_parent() != nullptr && + subtracers.m_monolithic_field->get_header().get_parent().get() == &T1.get_header())); const auto idx_qv1 = tracers1.m_info->m_subview_idx.at("qv"); const auto idx_a1 = tracers1.m_info->m_subview_idx.at("a"); @@ -726,7 +726,7 @@ TEST_CASE("tracers_bundle", "") { // Check that changing sub tracers change tracers group and individual tracers T1.deep_copy(0.0); - auto& sub_T1 = subtracers.m_bundle; + auto& sub_T1 = subtracers.m_monolithic_field; randomize(*sub_T1,engine,pdf); sub_T1->sync_to_host(); auto sub_T1_h = sub_T1->get_strided_view(); @@ -739,28 +739,28 @@ TEST_CASE("tracers_bundle", "") { } // Check that the field ptrs stored in the group are the same as the fields - auto qv1_ptr = tracers1.m_fields.at("qv"); - auto a1_ptr = tracers1.m_fields.at("a"); - auto b1_ptr = tracers1.m_fields.at("b"); - auto c1_ptr = tracers1.m_fields.at("c"); + auto qv1_ptr = tracers1.m_individual_fields.at("qv"); + auto a1_ptr = tracers1.m_individual_fields.at("a"); + auto b1_ptr = tracers1.m_individual_fields.at("b"); + auto c1_ptr = tracers1.m_individual_fields.at("c"); REQUIRE (qv1_ptr->is_aliasing(qv1)); REQUIRE (a1_ptr->is_aliasing(a1)); REQUIRE (b1_ptr->is_aliasing(b1)); REQUIRE (c1_ptr->is_aliasing(c1)); - auto qv2_ptr = tracers2.m_fields.at("qv"); - auto a2_ptr = tracers2.m_fields.at("a"); - auto b2_ptr = tracers2.m_fields.at("b"); - auto c2_ptr = tracers2.m_fields.at("c"); + auto qv2_ptr = tracers2.m_individual_fields.at("qv"); + auto a2_ptr = tracers2.m_individual_fields.at("a"); + auto b2_ptr = tracers2.m_individual_fields.at("b"); + auto c2_ptr = tracers2.m_individual_fields.at("c"); REQUIRE (qv2_ptr->is_aliasing(qv2)); REQUIRE (a2_ptr->is_aliasing(a2)); REQUIRE (b2_ptr->is_aliasing(b2)); REQUIRE (c2_ptr->is_aliasing(c2)); - b1_ptr = subtracers.m_fields.at("b"); - c1_ptr = subtracers.m_fields.at("c"); + b1_ptr = subtracers.m_individual_fields.at("b"); + c1_ptr = subtracers.m_individual_fields.at("c"); REQUIRE (b1_ptr->is_aliasing(b1)); REQUIRE (c1_ptr->is_aliasing(c1)); }