diff --git a/components/eamxx/src/control/atmosphere_driver.cpp b/components/eamxx/src/control/atmosphere_driver.cpp index 9cf2b48e358..75c44579303 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 5b5ea600a85..cd51c934ddd 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 8b7495ffd73..10be9f43509 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 b41dcc1f272..6b99e8e09ac 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 5c9b6b36dcb..cdb1d91f073 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 449ba4a55d8..1d23a69b237 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 2428dd5d9ea..c7be1182b7c 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 1b4ad91d068..a6fd5683813 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 b0ab232c255..6b931c3e349 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 @@ -80,19 +80,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); @@ -151,20 +151,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); @@ -182,7 +184,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 68153624b63..b5a3f7a122e 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 863da8021dd..64d13a9b38c 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 ce3b64b3dc8..8dc9fae1faf 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 069f4ec4915..b5af0d043e6 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 a2b8ccb2e29..a46d6f29d04 100644 --- a/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp +++ b/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp @@ -71,15 +71,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 ac620e19add..7598571e5ef 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 86bd520fca9..e4ab1a86529 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 43fc35a3318..fc39882d4d4 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 311a0a6b14b..37792d79014 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 bca9c46f4da..ce9c766d0c8 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),