From 18e335efe07a5ba851deb290bb5b86de894ea921 Mon Sep 17 00:00:00 2001 From: tcclevenger Date: Tue, 29 Oct 2024 15:01:35 -0600 Subject: [PATCH 1/6] Allow for not advecting tracers in shoc --- .../eamxx/src/control/atmosphere_driver.cpp | 60 +++++++++++++++++++ .../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 +- .../mam/eamxx_mam_aci_process_interface.cpp | 23 ++++--- ...eamxx_mam_constituent_fluxes_interface.cpp | 23 ++++--- ...x_mam_dry_deposition_process_interface.cpp | 18 +++--- ...mxx_mam_microphysics_process_interface.cpp | 18 +++--- .../eamxx_mam_optics_process_interface.cpp | 19 +++--- .../eamxx_mam_wetscav_process_interface.cpp | 20 ++++--- .../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 | 5 +- 19 files changed, 169 insertions(+), 85 deletions(-) diff --git a/components/eamxx/src/control/atmosphere_driver.cpp b/components/eamxx/src/control/atmosphere_driver.cpp index 0f1cb1e31ab0..c0a2599bd5d0 100644 --- a/components/eamxx/src/control/atmosphere_driver.cpp +++ b/components/eamxx/src/control/atmosphere_driver.cpp @@ -534,6 +534,66 @@ void AtmosphereDriver::create_fields() m_field_mgrs[grid->name()]->registration_begins(); } + // 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 (std::find(req.groups.begin(), + req.groups.end(), + "tracers") == req.groups.end()) return; + + std::string fname = req.fid.name(); + if (tracer_requests.find(fname) == tracer_requests.end()) { + tracer_requests[fname] = std::vector(1, req); + } else { + tracer_requests[fname].push_back(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) { + bool mismatch_found = false; + + const auto reqs = fr.second; + const bool is_first_turb_advect = + std::find(reqs.front().groups.begin(), + reqs.front().groups.end(), + "turbulence_advected_tracers") != reqs.front().groups.end(); + for (size_t i=1; iget_required_field_requests()) { m_field_mgrs.at(req.fid.get_grid_name())->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 5b5ea600a857..cd51c934ddd0 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 8b7495ffd73f..10be9f435094 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, Bundling::Required); 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 5c9b6b36dcb5..cdb1d91f0731 100644 --- a/components/eamxx/src/physics/cosp/eamxx_cosp.cpp +++ b/components/eamxx/src/physics/cosp/eamxx_cosp.cpp @@ -74,9 +74,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_aci_process_interface.cpp b/components/eamxx/src/physics/mam/eamxx_mam_aci_process_interface.cpp index 449ba4a55d89..1d23a69b237f 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_aci_process_interface.cpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_aci_process_interface.cpp @@ -82,19 +82,19 @@ void MAMAci::set_grids( // 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); // Temperature[K] at midpoints add_field("T_mid", scalar3d_mid, K, grid_name); @@ -157,15 +157,16 @@ void MAMAci::set_grids( // interstitial and cloudborne aerosol tracers of interest: mass (q) and // number (n) mixing ratios + // NOTE: + // - For interstitial aerosols, we have dynamics advect, but not turbulence. + // - For cloudborne aerosols, DO NOT advect. for(int mode = 0; mode < mam_coupling::num_aero_modes(); ++mode) { // interstitial aerosol tracers of interest: number (n) mixing ratios const char *int_nmr_field_name = mam_coupling::int_aero_nmr_field_name(mode); - add_tracer(int_nmr_field_name, grid_, n_unit); + add_tracer(int_nmr_field_name, grid_, n_unit, false); // cloudborne aerosol tracers of interest: number (n) mixing ratios - // NOTE: DO NOT add cld borne aerosols to the "tracer" group as these are - // NOT advected const char *cld_nmr_field_name = mam_coupling::cld_aero_nmr_field_name(mode); add_field(cld_nmr_field_name, scalar3d_mid, n_unit, grid_name); @@ -175,11 +176,9 @@ void MAMAci::set_grids( const char *int_mmr_field_name = mam_coupling::int_aero_mmr_field_name(mode, a); if(strlen(int_mmr_field_name) > 0) { - add_tracer(int_mmr_field_name, grid_, q_unit); + add_tracer(int_mmr_field_name, grid_, q_unit, false); } // (cloudborne) aerosol tracers of interest: mass (q) mixing ratios - // NOTE: DO NOT add cld borne aerosols to the "tracer" group as these are - // NOT advected const char *cld_mmr_field_name = mam_coupling::cld_aero_mmr_field_name(mode, a); if(strlen(cld_mmr_field_name) > 0) { @@ -190,7 +189,7 @@ void MAMAci::set_grids( 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_, q_unit); + add_tracer(gas_mmr_field_name, grid_, q_unit, true); } // end for loop num gases // ------------------------------------------------------------------------ diff --git a/components/eamxx/src/physics/mam/eamxx_mam_constituent_fluxes_interface.cpp b/components/eamxx/src/physics/mam/eamxx_mam_constituent_fluxes_interface.cpp index 2428dd5d9ea7..c7be1182b7cc 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_constituent_fluxes_interface.cpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_constituent_fluxes_interface.cpp @@ -43,19 +43,19 @@ void MAMConstituentFluxes::set_grids( // -------------------------------------------------------------------------- // ----------- Atmospheric quantities ------------- // Specific humidity [kg/kg](Require only for building DS) - add_tracer("qv", grid_, q_unit); + add_tracer("qv", grid_, q_unit, true); // Cloud liquid mass mixing ratio [kg/kg](Require only for building DS) - add_tracer("qc", grid_, q_unit); + add_tracer("qc", grid_, q_unit, true); // Cloud ice mass mixing ratio [kg/kg](Require only for building DS) - add_tracer("qi", grid_, q_unit); + add_tracer("qi", grid_, q_unit, true); // Cloud liquid number mixing ratio [1/kg](Require only for building DS) - add_tracer("nc", grid_, n_unit); + add_tracer("nc", grid_, n_unit, true); // Cloud ice number mixing ratio [1/kg](Require only for building DS) - add_tracer("ni", grid_, n_unit); + add_tracer("ni", grid_, n_unit, true); // Temperature[K] at midpoints add_field("T_mid", scalar3d_mid, K, grid_name); @@ -98,15 +98,16 @@ void MAMConstituentFluxes::set_grids( // interstitial and cloudborne aerosol tracers of interest: mass (q) and // number (n) mixing ratios + // NOTE: + // - For interstitial aerosols, we have dynamics advect, but not turbulence. + // - For cloudborne aerosols, DO NOT advect. (for now just a field) for(int mode = 0; mode < mam_coupling::num_aero_modes(); ++mode) { // 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); // cloudborne aerosol tracers of interest: number (n) mixing ratios - // NOTE: DO NOT add cld borne aerosols to the "tracer" group as these are - // NOT advected const std::string cld_nmr_field_name = mam_coupling::cld_aero_nmr_field_name(mode); add_field(cld_nmr_field_name, scalar3d_mid, n_unit, grid_name); @@ -116,11 +117,9 @@ void MAMConstituentFluxes::set_grids( 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); } // (cloudborne) aerosol tracers of interest: mass (q) mixing ratios - // NOTE: DO NOT add cld borne aerosols to the "tracer" group as these are - // NOT advected const std::string cld_mmr_field_name = mam_coupling::cld_aero_mmr_field_name(mode, a); if(not cld_mmr_field_name.empty()) { @@ -131,7 +130,7 @@ void MAMConstituentFluxes::set_grids( 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 } // set_grid diff --git a/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_process_interface.cpp b/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_process_interface.cpp index 1b4ad91d0681..a6fd56838135 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_process_interface.cpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_process_interface.cpp @@ -71,19 +71,19 @@ void MAMDryDep::set_grids( // ----------- Atmospheric quantities ------------- // Specific humidity [kg/kg](Require only for building DS) - add_tracer("qv", grid_, q_unit); + add_tracer("qv", grid_, q_unit, true); // Cloud liquid mass mixing ratio [kg/kg](Require only for building DS) - add_tracer("qc", grid_, q_unit); + add_tracer("qc", grid_, q_unit, true); // Cloud ice mass mixing ratio [kg/kg](Require only for building DS) - add_tracer("qi", grid_, q_unit); + add_tracer("qi", grid_, q_unit, true); // Cloud liquid number mixing ratio [1/kg](Require only for building DS) - add_tracer("nc", grid_, n_unit); + add_tracer("nc", grid_, n_unit, true); // Cloud ice number mixing ratio [1/kg](Require only for building DS) - add_tracer("ni", grid_, n_unit); + add_tracer("ni", grid_, n_unit, true); // Temperature[K] at midpoints add_field("T_mid", scalar3d_mid, K, grid_name); @@ -153,20 +153,22 @@ void MAMDryDep::set_grids( // (interstitial) aerosol tracers of interest: mass (q) and number (n) mixing // ratios + // NOTE: For interstitial aerosols, we have dynamics advect, but not turbulence. for(int m = 0; m < num_aero_modes; ++m) { const char *int_nmr_field_name = mam_coupling::int_aero_nmr_field_name(m); - 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) { const char *int_mmr_field_name = mam_coupling::int_aero_mmr_field_name(m, a); if(strlen(int_mmr_field_name) > 0) { - add_tracer(int_mmr_field_name, grid_, q_unit); + add_tracer(int_mmr_field_name, grid_, q_unit, false); } } } // (cloud) aerosol tracers of interest: mass (q) and number (n) mixing ratios + // NOTE: For cloudborne aerosols, DO NOT advect. for(int m = 0; m < num_aero_modes; ++m) { const char *cld_nmr_field_name = mam_coupling::cld_aero_nmr_field_name(m); @@ -184,7 +186,7 @@ void MAMDryDep::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_, q_unit); + add_tracer(gas_mmr_field_name, grid_, q_unit, true); } // ------------------------------------------------------------- diff --git a/components/eamxx/src/physics/mam/eamxx_mam_microphysics_process_interface.cpp b/components/eamxx/src/physics/mam/eamxx_mam_microphysics_process_interface.cpp index 57eaf9275483..d505db3e6dc7 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_microphysics_process_interface.cpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_microphysics_process_interface.cpp @@ -81,19 +81,19 @@ void MAMMicrophysics::set_grids( // ----------- Atmospheric quantities ------------- // Specific humidity [kg/kg](Require only for building DS) - add_tracer("qv", grid_, kg/kg); // specific humidity + add_tracer("qv", grid_, kg/kg, true); // specific humidity // Cloud liquid mass mixing ratio [kg/kg](Require only for building DS) - add_tracer("qc", grid_, kg/kg); // cloud liquid wet mixing ratio + add_tracer("qc", grid_, kg/kg, true); // cloud liquid wet mixing ratio // Cloud ice mass mixing ratio [kg/kg](Require only for building DS) - add_tracer("qi", grid_, kg/kg); // ice wet mixing ratio + add_tracer("qi", grid_, kg/kg, true); // ice wet mixing ratio // Cloud liquid number mixing ratio [1/kg](Require only for building DS) - add_tracer("nc", grid_, n_unit); // cloud liquid wet number mixing ratio + add_tracer("nc", grid_, n_unit, true); // cloud liquid wet number mixing ratio // Cloud ice number mixing ratio [1/kg](Require only for building DS) - add_tracer("ni", grid_, n_unit); // ice number mixing ratio + add_tracer("ni", grid_, n_unit, true); // ice number mixing ratio // Temperature[K] at midpoints add_field("T_mid", scalar3d_mid, K, grid_name); @@ -152,20 +152,22 @@ void MAMMicrophysics::set_grids( // (interstitial) aerosol tracers of interest: mass (q) and number (n) mixing // ratios + // NOTE: For interstitial aerosols, we have dynamics advect, but not turbulence. for(int m = 0; m < nmodes; ++m) { const char *int_nmr_field_name = mam_coupling::int_aero_nmr_field_name(m); - 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) { const char *int_mmr_field_name = mam_coupling::int_aero_mmr_field_name(m, a); if(strlen(int_mmr_field_name) > 0) { - add_tracer(int_mmr_field_name, grid_, kg/kg); + add_tracer(int_mmr_field_name, grid_, kg/kg, false); } } // for loop species } // for loop nmodes interstitial // (cloud) aerosol tracers of interest: mass (q) and number (n) mixing ratios + // NOTE: For cloudborne aerosols, DO NOT advect. for(int m = 0; m < nmodes; ++m) { const char *cld_nmr_field_name = mam_coupling::cld_aero_nmr_field_name(m); @@ -183,7 +185,7 @@ void MAMMicrophysics::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); } // Creating a Linoz reader and setting Linoz parameters involves reading data 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 68153624b635..b5a3f7a122e8 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 @@ -55,13 +55,13 @@ void MAMOptics::set_grids( add_field("p_int", scalar3d_int, Pa, grid_name); // total pressure add_field("pseudo_density", scalar3d_mid, Pa, grid_name); add_field("pseudo_density_dry", scalar3d_mid, Pa, grid_name); - add_tracer("qv", grid_, kg/kg); // specific humidity - add_tracer("qi", grid_, kg/kg); // ice wet mixing ratio - add_tracer("ni", grid_, n_unit); // ice number mixing ratio + add_tracer("qv", grid_, kg/kg, true); // specific humidity + add_tracer("qi", grid_, kg/kg, true); // ice wet mixing ratio + add_tracer("ni", grid_, n_unit, true); // ice number mixing ratio // droplet activation can alter cloud liquid and number mixing ratios - add_tracer("qc", grid_, kg/kg); // cloud liquid wet mixing ratio - add_tracer("nc", grid_, n_unit); // cloud liquid wet number mixing ratio + add_tracer("qc", grid_, kg/kg, true); // cloud liquid wet mixing ratio + add_tracer("nc", grid_, n_unit, true); // cloud liquid wet number mixing ratio add_field("phis", scalar2d, m2 / s2, grid_name); add_field("cldfrac_tot", scalar3d_mid, nondim,grid_name); // cloud fraction @@ -83,22 +83,23 @@ void MAMOptics::set_grids( // (interstitial) aerosol tracers of interest: mass (q) and number (n) mixing // ratios + // NOTE: For interstitial aerosols, we have dynamics advect, but not turbulence. for(int m = 0; m < mam_coupling::num_aero_modes(); ++m) { const char *int_nmr_field_name = mam_coupling::int_aero_nmr_field_name(m); - 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) { const char *int_mmr_field_name = mam_coupling::int_aero_mmr_field_name(m, a); if(strlen(int_mmr_field_name) > 0) { - add_tracer(int_mmr_field_name, grid_, kg/kg); + add_tracer(int_mmr_field_name, grid_, kg/kg, false); } } } // (cloud) aerosol tracers of interest: mass (q) and number (n) mixing ratios + // NOTE: For cloudborne aerosols, DO NOT advect. for(int m = 0; m < mam_coupling::num_aero_modes(); ++m) { const char *cld_nmr_field_name = mam_coupling::cld_aero_nmr_field_name(m); - add_field(cld_nmr_field_name, scalar3d_mid, n_unit, grid_name); for(int a = 0; a < mam_coupling::num_aero_species(); ++a) { const char *cld_mmr_field_name = @@ -113,7 +114,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/mam/eamxx_mam_wetscav_process_interface.cpp b/components/eamxx/src/physics/mam/eamxx_mam_wetscav_process_interface.cpp index 863da8021dd4..64d13a9b38c8 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_wetscav_process_interface.cpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_wetscav_process_interface.cpp @@ -61,19 +61,19 @@ void MAMWetscav::set_grids( // ----------- Atmospheric quantities ------------- // Specific humidity [kg/kg] - add_tracer("qv", m_grid, q_unit); + add_tracer("qv", m_grid, q_unit, true); // cloud liquid mass mixing ratio [kg/kg] - add_tracer("qc", m_grid, q_unit); + add_tracer("qc", m_grid, q_unit, true); // cloud ice mass mixing ratio [kg/kg] - add_tracer("qi", m_grid, q_unit); + add_tracer("qi", m_grid, q_unit, true); // cloud liquid number mixing ratio [1/kg] - add_tracer("nc", m_grid, n_unit); + add_tracer("nc", m_grid, n_unit, true); // cloud ice number mixing ratio [1/kg] - add_tracer("ni", m_grid, n_unit); + add_tracer("ni", m_grid, n_unit, true); // Temperature[K] at midpoints add_field("T_mid", scalar3d_mid, K, grid_name); @@ -157,11 +157,15 @@ void MAMWetscav::set_grids( // NOTE: Interstitial aerosols are updated in the interface using the // "tendencies" from the wetscavenging process + // NOTE: + // - For interstitial aerosols, we have dynamics advect, but not turbulence. + // - For cloudborne aerosols, DO NOT advect. + for(int imode = 0; imode < mam_coupling::num_aero_modes(); ++imode) { // interstitial aerosol tracers of interest: number (n) mixing ratios const char *int_nmr_field_name = mam_coupling::int_aero_nmr_field_name(imode); - add_tracer(int_nmr_field_name, m_grid, n_unit); + add_tracer(int_nmr_field_name, m_grid, n_unit, false); // cloudborne aerosol tracers of interest: number (n) mixing ratios // Note: Do *not* add cld borne aerosols to the "tracer" group as these are @@ -176,7 +180,7 @@ void MAMWetscav::set_grids( const char *int_mmr_field_name = mam_coupling::int_aero_mmr_field_name(imode, ispec); if(strlen(int_mmr_field_name) > 0) { - add_tracer(int_mmr_field_name, m_grid, q_unit); + add_tracer(int_mmr_field_name, m_grid, q_unit, false); } // (cloudborne) aerosol tracers of interest: mass (q) mixing ratios @@ -196,7 +200,7 @@ void MAMWetscav::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, m_grid, q_unit); + add_tracer(gas_mmr_field_name, m_grid, q_unit, 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 ce3b64b3dc8a..8dc9fae1faf8 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, Bundling::Required); } 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 069f4ec49150..b5af0d043e6c 100644 --- a/components/eamxx/src/physics/nudging/eamxx_nudging_process_interface.cpp +++ b/components/eamxx/src/physics/nudging/eamxx_nudging_process_interface.cpp @@ -84,7 +84,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 f6771d6bf171..7e5da808be9f 100644 --- a/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp +++ b/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp @@ -69,15 +69,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 ac620e19add5..7598571e5efa 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, Bundling::Required); + add_group("turbulence_advected_tracers", grid_name, ps, Bundling::Required); // 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 43fc35a33185..fc39882d4d42 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 311a0a6b14be..37792d790147 100644 --- a/components/eamxx/src/share/field/field_manager.cpp +++ b/components/eamxx/src/share/field/field_manager.cpp @@ -330,6 +330,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 (has_field("qv")) { auto it = ekat::find(groups_to_bundle,"tracers"); diff --git a/components/eamxx/src/share/field/field_request.hpp b/components/eamxx/src/share/field/field_request.hpp index bca9c46f4da6..ce9c766d0c88 100644 --- a/components/eamxx/src/share/field/field_request.hpp +++ b/components/eamxx/src/share/field/field_request.hpp @@ -108,7 +108,7 @@ struct GroupRequest { // 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 @@ -191,7 +191,7 @@ inline bool operator< (const GroupRequest& lhs, /* * A struct used to request a field. - * + * * The request contains at least a FieldIdentifier, but can also contain * a pack size, and a list of names of groups that the field should belong to. */ @@ -271,6 +271,7 @@ struct FieldRequest { SubviewInfo subview_info; std::string parent_name; bool incomplete = false; + std::string calling_process = ""; }; // In order to use FieldRequest in std sorted containers (like std::set), From 74c95e6937d6f3610bc802d0dceb20ac2d03d5b1 Mon Sep 17 00:00:00 2001 From: Balwinder Singh Date: Tue, 12 Nov 2024 12:06:17 -0800 Subject: [PATCH 2/6] Adds a limiter to avoid zero interstitial aerosols in ACI --- .../mam/eamxx_mam_aci_process_interface.hpp | 1 + .../eamxx/src/physics/mam/mam_coupling.hpp | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/components/eamxx/src/physics/mam/eamxx_mam_aci_process_interface.hpp b/components/eamxx/src/physics/mam/eamxx_mam_aci_process_interface.hpp index 63f87dd9f246..e4559af4ac03 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_aci_process_interface.hpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_aci_process_interface.hpp @@ -212,6 +212,7 @@ class MAMAci final : public scream::AtmosphereProcess { // for atmosphere compute_vertical_layer_heights(team, dry_atm_pre_, i); compute_updraft_velocities(team, wet_atm_pre_, dry_atm_pre_, i); + set_min_background_mmr(team, dry_aero_pre_, i); //dry_atm_pre_ is the output } // operator() // local variables for preprocess struct diff --git a/components/eamxx/src/physics/mam/mam_coupling.hpp b/components/eamxx/src/physics/mam/mam_coupling.hpp index 68f67f62c5c6..9cb7edd38a4d 100644 --- a/components/eamxx/src/physics/mam/mam_coupling.hpp +++ b/components/eamxx/src/physics/mam/mam_coupling.hpp @@ -776,6 +776,34 @@ void compute_wet_mixing_ratios(const Team& team, }); } +// Set minimum background MMR for the interstitial aerosols +KOKKOS_INLINE_FUNCTION +void set_min_background_mmr(const Team& team, + const AerosolState& dry_aero, + const int column_index) { + + EKAT_KERNEL_ASSERT_MSG(column_index == team.league_rank(), + "Given column index does not correspond to given team!"); + + //Minimum background value for the interstitial aerosols + constexpr Real INTERSTITIAL_AERO_MIN_VAL = 1e-36; + + constexpr int nlev = mam4::nlev; + const int icol = column_index; + Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev), [&] (const int klev) { + for (int imode = 0; imode < num_aero_modes(); ++imode) { + dry_aero.int_aero_nmr[imode](icol,klev) = haero::max(dry_aero.int_aero_nmr[imode](icol,klev), INTERSTITIAL_AERO_MIN_VAL); + for (int ispec = 0; ispec < num_aero_species(); ++ispec) { + if (dry_aero.int_aero_mmr[imode][ispec].data()) { + dry_aero.int_aero_mmr[imode][ispec](icol,klev) = haero::max(dry_aero.int_aero_mmr[imode][ispec](icol,klev), INTERSTITIAL_AERO_MIN_VAL); + } + }//ispec + }//imode + }); +} // set_min_background_mmr + + + // Computes the reciprocal of pseudo density for a column inline void compute_recipical_pseudo_density(haero::ThreadTeamPolicy team_policy, From 6746b673c9ca023c2fdb095f26e65163a799615a Mon Sep 17 00:00:00 2001 From: tcclevenger Date: Thu, 14 Nov 2024 14:10:35 -0700 Subject: [PATCH 3/6] Use UNKNOWN as a default for calling_process --- components/eamxx/src/share/field/field_request.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/eamxx/src/share/field/field_request.hpp b/components/eamxx/src/share/field/field_request.hpp index ce9c766d0c88..dd8fdb3902f8 100644 --- a/components/eamxx/src/share/field/field_request.hpp +++ b/components/eamxx/src/share/field/field_request.hpp @@ -271,7 +271,7 @@ struct FieldRequest { SubviewInfo subview_info; std::string parent_name; bool incomplete = false; - std::string calling_process = ""; + std::string calling_process = "UNKNOWN"; }; // In order to use FieldRequest in std sorted containers (like std::set), From 37ba46171ab5f43061c45f04d48dce8881d1275c Mon Sep 17 00:00:00 2001 From: tcclevenger Date: Thu, 14 Nov 2024 14:20:25 -0700 Subject: [PATCH 4/6] use ekat::contains --- .../eamxx/src/control/atmosphere_driver.cpp | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/components/eamxx/src/control/atmosphere_driver.cpp b/components/eamxx/src/control/atmosphere_driver.cpp index c0a2599bd5d0..b4a0bc21d251 100644 --- a/components/eamxx/src/control/atmosphere_driver.cpp +++ b/components/eamxx/src/control/atmosphere_driver.cpp @@ -539,9 +539,7 @@ void AtmosphereDriver::create_fields() // 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 (std::find(req.groups.begin(), - req.groups.end(), - "tracers") == req.groups.end()) return; + if (not ekat::contains(req.groups, "tracers")) return; std::string fname = req.fid.name(); if (tracer_requests.find(fname) == tracer_requests.end()) { @@ -563,15 +561,9 @@ void AtmosphereDriver::create_fields() bool mismatch_found = false; const auto reqs = fr.second; - const bool is_first_turb_advect = - std::find(reqs.front().groups.begin(), - reqs.front().groups.end(), - "turbulence_advected_tracers") != reqs.front().groups.end(); + const bool is_first_turb_advect = ekat::contains(reqs.front().groups, "turbulence_advected_tracers") for (size_t i=1; i Date: Thu, 14 Nov 2024 14:29:23 -0700 Subject: [PATCH 5/6] fix missing ; --- components/eamxx/src/control/atmosphere_driver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/eamxx/src/control/atmosphere_driver.cpp b/components/eamxx/src/control/atmosphere_driver.cpp index b4a0bc21d251..970cc0be3985 100644 --- a/components/eamxx/src/control/atmosphere_driver.cpp +++ b/components/eamxx/src/control/atmosphere_driver.cpp @@ -561,7 +561,7 @@ void AtmosphereDriver::create_fields() bool mismatch_found = false; const auto reqs = fr.second; - const bool is_first_turb_advect = ekat::contains(reqs.front().groups, "turbulence_advected_tracers") + const bool is_first_turb_advect = ekat::contains(reqs.front().groups, "turbulence_advected_tracers"); for (size_t i=1; i Date: Fri, 15 Nov 2024 08:26:07 -0700 Subject: [PATCH 6/6] Use calling_process in the FieldRequest::operator< Increases the number of entries in the AtmosphereProcess set m_*_field_requests, but not the number of allocations. Allows us to output all instances of field requests of the same name. --- .../eamxx/src/control/atmosphere_driver.cpp | 22 ++++++++----------- .../eamxx/src/share/field/field_request.hpp | 6 ++++- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/components/eamxx/src/control/atmosphere_driver.cpp b/components/eamxx/src/control/atmosphere_driver.cpp index 970cc0be3985..b58839e766fa 100644 --- a/components/eamxx/src/control/atmosphere_driver.cpp +++ b/components/eamxx/src/control/atmosphere_driver.cpp @@ -537,15 +537,15 @@ void AtmosphereDriver::create_fields() // 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; + 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] = std::vector(1, req); + tracer_requests[fname] = {req}; } else { - tracer_requests[fname].push_back(req); + tracer_requests[fname].emplace(req); } }; for (const auto& req : m_atm_process_group->get_required_field_requests()){ @@ -558,18 +558,14 @@ void AtmosphereDriver::create_fields() // 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) { - bool mismatch_found = false; - const auto reqs = fr.second; - const bool is_first_turb_advect = ekat::contains(reqs.front().groups, "turbulence_advected_tracers"); - for (size_t i=1; i turb_advect_types; + for (auto req : reqs) { + turb_advect_types.emplace(ekat::contains(req.groups, "turbulence_advected_tracers")); } - if (mismatch_found) { + + 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" diff --git a/components/eamxx/src/share/field/field_request.hpp b/components/eamxx/src/share/field/field_request.hpp index dd8fdb3902f8..8962ec2b4e1f 100644 --- a/components/eamxx/src/share/field/field_request.hpp +++ b/components/eamxx/src/share/field/field_request.hpp @@ -285,7 +285,11 @@ inline bool operator< (const FieldRequest& lhs, if (lhs.pack_size