diff --git a/components/eamxx/cime_config/namelist_defaults_scream.xml b/components/eamxx/cime_config/namelist_defaults_scream.xml index 1b84aef2273..c392615e7db 100644 --- a/components/eamxx/cime_config/namelist_defaults_scream.xml +++ b/components/eamxx/cime_config/namelist_defaults_scream.xml @@ -37,6 +37,8 @@ be lost if SCREAM_HACK_XML is not enabled. + + @@ -250,7 +252,17 @@ be lost if SCREAM_HACK_XML is not enabled. - + + ${DIN_LOC_ROOT}/atm/scream/mam4xx/drydep/ne30pg2/atmsrf_ne30pg2_c20241017.nc + ${DIN_LOC_ROOT}/atm/scream/mam4xx/drydep/ne4pg2/atmsrf_ne4pg2_c20241017.nc + + + + ${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne120pg2_20231201.nc + ${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne256pg2_20231201.nc + ${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne512pg2_20231201.nc + ${DIN_LOC_ROOT}/atm/scream/maps/map_ne30pg2_to_ne1024pg2_20231201.nc + @@ -278,15 +290,6 @@ be lost if SCREAM_HACK_XML is not enabled. - ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/DMSflux.2010.ne4pg2_conserv.POPmonthlyClimFromACES4BGC_c20240814.nc - ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_so2_surf_ne4pg2_2010_clim_c20240815.nc - ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_bc_a4_surf_ne4pg2_2010_clim_c20240815.nc - ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_num_a1_surf_ne4pg2_2010_clim_c20240815.nc - ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_num_a2_surf_ne4pg2_2010_clim_c20240815.nc - ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_num_a4_surf_ne4pg2_2010_clim_c20240815.nc - ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_pom_a4_surf_ne4pg2_2010_clim_c20240815.nc - ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_so4_a1_surf_ne4pg2_2010_clim_c20240815.nc - ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_so4_a2_surf_ne4pg2_2010_clim_c20240815.nc ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne30pg2/surface/DMSflux.2010.ne30pg2_conserv.POPmonthlyClimFromACES4BGC_c20240816.nc ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne30pg2/surface/cmip6_mam4_so2_surf_ne30pg2_2010_clim_c20240816.nc @@ -297,6 +300,18 @@ be lost if SCREAM_HACK_XML is not enabled. ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne30pg2/surface/cmip6_mam4_pom_a4_surf_ne30pg2_2010_clim_c20240816.nc ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne30pg2/surface/cmip6_mam4_so4_a1_surf_ne30pg2_2010_clim_c20240816.nc ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne30pg2/surface/cmip6_mam4_so4_a2_surf_ne30pg2_2010_clim_c20240816.nc + + + ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/DMSflux.2010.ne4pg2_conserv.POPmonthlyClimFromACES4BGC_c20240814.nc + ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_so2_surf_ne4pg2_2010_clim_c20240815.nc + ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_bc_a4_surf_ne4pg2_2010_clim_c20240815.nc + ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_num_a1_surf_ne4pg2_2010_clim_c20240815.nc + ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_num_a2_surf_ne4pg2_2010_clim_c20240815.nc + ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_num_a4_surf_ne4pg2_2010_clim_c20240815.nc + ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_pom_a4_surf_ne4pg2_2010_clim_c20240815.nc + ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_so4_a1_surf_ne4pg2_2010_clim_c20240815.nc + ${DIN_LOC_ROOT}/atm/scream/mam4xx/emissions/ne4pg2/surface/cmip6_mam4_so4_a2_surf_ne4pg2_2010_clim_c20240815.nc + @@ -490,9 +505,11 @@ be lost if SCREAM_HACK_XML is not enabled. UNSET ${DIN_LOC_ROOT}/atm/scream/init/screami_ne4np4L72_20220823.nc + ${DIN_LOC_ROOT}/atm/scream/init/screami_mam4xx_ne4np4L72_c20240208.nc ${DIN_LOC_ROOT}/atm/scream/init/screami_ne4np4L128_20241022.nc ${DIN_LOC_ROOT}/atm/scream/init/screami_ne30np4L72_20220823.nc ${DIN_LOC_ROOT}/atm/scream/init/screami_ne30np4L128_20221004.nc + ${DIN_LOC_ROOT}/atm/scream/init/screami_mam_ne30np4L72_c20240623.nc ${DIN_LOC_ROOT}/atm/scream/init/screami_ne120np4L72_20220823.nc ${DIN_LOC_ROOT}/atm/scream/init/screami_ne120np4L128_20230215.nc ${DIN_LOC_ROOT}/atm/scream/init/screami_ne256np4L128_ifs-20200120_20220914.nc diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/aci/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/aci/shell_commands index 658c94a3cf6..492bda019fc 100644 --- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/aci/shell_commands +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/aci/shell_commands @@ -5,9 +5,6 @@ #------------------------------------------------------ $CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh -#modify initial condition file to get aerosol species ICs -$CIMEROOT/../components/eamxx/scripts/atmchange initial_conditions::Filename='$DIN_LOC_ROOT/atm/scream/init/screami_mam4xx_ne4np4L72_c20240208.nc' -b - # Add spa as RRTMG needs spa $CIMEROOT/../components/eamxx/scripts/atmchange physics::atm_procs_list="mac_aero_mic,spa,rrtmgp" -b diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/drydep/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/drydep/shell_commands index c5acf055a88..ea2d56ab53f 100644 --- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/drydep/shell_commands +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/drydep/shell_commands @@ -8,9 +8,8 @@ $CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh -b #------------------------------------------------------ -#Update IC file and add drydep process +# Add drydep process #------------------------------------------------------ -$CIMEROOT/../components/eamxx/scripts/atmchange initial_conditions::Filename='$DIN_LOC_ROOT/atm/scream/init/screami_mam4xx_ne4np4L72_c20240208.nc' -b $CIMEROOT/../components/eamxx/scripts/atmchange physics::atm_procs_list="mac_aero_mic,rrtmgp,mam4_drydep" -b diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/optics/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/optics/shell_commands index 224c1658610..9bbcfaea898 100644 --- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/optics/shell_commands +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/optics/shell_commands @@ -4,7 +4,6 @@ #------------------------------------------------------ $CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh -$CIMEROOT/../components/eamxx/scripts/atmchange initial_conditions::Filename='$DIN_LOC_ROOT/atm/scream/init/screami_mam4xx_ne4np4L72_c20240208.nc' -b $CIMEROOT/../components/eamxx/scripts/atmchange physics::atm_procs_list="mac_aero_mic,mam4_optics,rrtmgp" -b diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/srf_online_emiss_constituent_fluxes/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/srf_online_emiss_constituent_fluxes/shell_commands index f47a1729ed7..500d0bf660a 100644 --- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/srf_online_emiss_constituent_fluxes/shell_commands +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/srf_online_emiss_constituent_fluxes/shell_commands @@ -8,9 +8,8 @@ $CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh -b #------------------------------------------------------ -#Update IC file and add the processes +# Add the processes #------------------------------------------------------ -$CIMEROOT/../components/eamxx/scripts/atmchange initial_conditions::Filename='$DIN_LOC_ROOT/atm/scream/init/screami_mam4xx_ne4np4L72_c20240208.nc' -b $CIMEROOT/../components/eamxx/scripts/atmchange physics::atm_procs_list="mam4_constituent_fluxes,mac_aero_mic,rrtmgp,mam4_srf_online_emiss" -b diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/wetscav/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/wetscav/shell_commands index 7b5b9a87650..2cdf303a582 100644 --- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/wetscav/shell_commands +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/wetscav/shell_commands @@ -7,7 +7,6 @@ $CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh -b #------------------------------------------------------ -#Update IC file and add wetscav process +# Add wetscav process #------------------------------------------------------ -$CIMEROOT/../components/eamxx/scripts/atmchange initial_conditions::Filename='$DIN_LOC_ROOT/atm/scream/init/screami_mam4xx_ne4np4L72_c20240208.nc' -b $CIMEROOT/../components/eamxx/scripts/atmchange physics::atm_procs_list="mac_aero_mic,mam4_wetscav,rrtmgp" -b diff --git a/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_functions.hpp b/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_functions.hpp index f5423e8eb1c..93c085c8c1f 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_functions.hpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_functions.hpp @@ -19,7 +19,7 @@ void compute_tendencies( const MAMDryDep::const_view_1d ocnfrac, const MAMDryDep::const_view_1d friction_velocity, const MAMDryDep::const_view_1d aerodynamical_resistance, - MAMDryDep::view_3d qtracers, MAMDryDep::view_2d fraction_landuse_, + const MAMDryDep::const_view_2d fraction_landuse_, const MAMDryDep::const_view_3d dgncur_awet_, const MAMDryDep::const_view_3d wet_dens_, const mam_coupling::DryAtmosphere dry_atm, @@ -35,7 +35,7 @@ void compute_tendencies( // work arrays MAMDryDep::view_2d rho_, MAMDryDep::view_4d vlc_dry_, MAMDryDep::view_3d vlc_trb_, MAMDryDep::view_4d vlc_grv_, - MAMDryDep::view_3d dqdt_tmp_) { + MAMDryDep::view_3d dqdt_tmp_, MAMDryDep::view_3d qtracers) { static constexpr int num_aero_modes = mam_coupling::num_aero_modes(); const auto policy = ekat::ExeSpaceUtils::get_default_team_policy( @@ -86,7 +86,7 @@ void compute_tendencies( static constexpr int n_land_type = MAMDryDep::n_land_type; Real fraction_landuse[n_land_type]; for(int i = 0; i < n_land_type; ++i) { - fraction_landuse[i] = fraction_landuse_(i, icol); + fraction_landuse[i] = fraction_landuse_(icol, i); } static constexpr int nmodes = mam4::AeroConfig::num_modes(); @@ -181,24 +181,6 @@ void update_cloudborne_mmrs(const MAMDryDep::view_3d qqcw, const double dt, } } // Update cloud borne aerosols ends -// FIXME: remove the following function after implementing file read for landuse -void populated_fraction_landuse(MAMDryDep::view_2d flu, const int ncol) { - Kokkos::parallel_for( - "populated_fraction_landuse", 1, KOKKOS_LAMBDA(int) { - static constexpr int n_land_type = MAMDryDep::n_land_type; - const Real temp[n_land_type] = { - 0.28044346587077795E-003, 0.26634987180780171E-001, - 0.16803558403621365E-001, 0.18076055155371872E-001, - 0.00000000000000000E+000, 0.00000000000000000E+000, - 0.91803784897907303E+000, 0.17186036997038400E-002, - 0.00000000000000000E+000, 0.00000000000000000E+000, - 0.18448503115578840E-001}; - for(int i = 0; i < n_land_type; ++i) - for(int j = 0; j < ncol; ++j) flu(i, j) = temp[i]; - }); - Kokkos::fence(); -} - } // namespace } // namespace scream 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 55bdf2d7158..1b4ad91d068 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 @@ -3,16 +3,13 @@ // Drydep functions are stored in the following hpp file #include -/* ------------------------------------------------------------------ -NOTES: -1. Add a CIME test and multi-process tests -2. Ensure that the submodule for MAM4xx is the main branch -3. Read file for fractional landuse ------------------------------------------------------------------ -*/ +// For reading fractional land use file +#include + namespace scream { +using FracLandUseFunc = frac_landuse::fracLandUseFunctions; + MAMDryDep::MAMDryDep(const ekat::Comm &comm, const ekat::ParameterList ¶ms) : AtmosphereProcess(comm, params) { /* Anything that can be initialized without grid information can be @@ -56,7 +53,8 @@ void MAMDryDep::set_grids( // Layout for 4D (2d horiz X 1d vertical x number of modes) variables // at mid points const int num_aero_modes = mam_coupling::num_aero_modes(); - const FieldLayout vector3d_mid = grid_->get_3d_vector_layout(true, num_aero_modes, "num_modes"); + const FieldLayout vector3d_mid = + grid_->get_3d_vector_layout(true, num_aero_modes, "num_modes"); using namespace ekat::units; @@ -199,6 +197,27 @@ void MAMDryDep::set_grids( // surface deposition flux of interstitial aerosols, [kg/m2/s] or [1/m2/s] add_field("deposition_flux_of_interstitial_aerosols", vector2d_pcnst, 1 / m2 / s, grid_name); + + // ------------------------------------------------------------- + // setup to enable reading fractional land use file + // ------------------------------------------------------------- + + const auto mapping_file = m_params.get("drydep_remap_file", ""); + const std::string frac_landuse_data_file = + m_params.get("fractional_land_use_file"); + + // Field to be read from file + const std::string field_name = "fraction_landuse"; + + // Dimensions of the filed + const std::string dim_name1 = "ncol"; + const std::string dim_name2 = "class"; + + // initialize the file read + FracLandUseFunc::init_frac_landuse_file_read( + ncol_, field_name, dim_name1, dim_name2, grid_, frac_landuse_data_file, + mapping_file, horizInterp_, dataReader_); // output + } // set_grids // ================================================================ @@ -345,10 +364,14 @@ void MAMDryDep::initialize_impl(const RunType run_type) { // Work array to hold tendency for 1 species [kg/kg/s] or [1/kg/s] dqdt_tmp_ = view_3d("dqdt_tmp_", pcnst, ncol_, nlev_); - static constexpr int n_land_type = mam4::DryDeposition::n_land_type; - // FIXME: This should come from a file reading - // The fraction of land use for the column. [non-dimentional] - fraction_landuse_ = view_2d("fraction_landuse_", n_land_type, ncol_); + //----------------------------------------------------------------- + // Read fractional land use data + //----------------------------------------------------------------- + // This data is time-independent, we read all data here for the + // entire simulation + FracLandUseFunc::update_frac_land_use_data_from_file( + dataReader_, *horizInterp_, + frac_landuse_); // output //----------------------------------------------------------------- // Setup preprocessing and post processing @@ -403,21 +426,20 @@ void MAMDryDep::run_impl(const double dt) { auto aerdepdryis_ = get_field_out("deposition_flux_of_interstitial_aerosols") .get_view(); - // FIXME: remove it if it read from a file - populated_fraction_landuse(fraction_landuse_, ncol_); - + //-------------------------------------------------------------------- // Call drydeposition and get tendencies + //-------------------------------------------------------------------- compute_tendencies(ncol_, nlev_, dt, obukhov_length_, surface_friction_velocty_, land_fraction_, ice_fraction_, ocean_fraction_, friction_velocity_, - aerodynamical_resistance_, qtracers_, fraction_landuse_, - dgncur_awet_, wet_dens_, dry_atm_, dry_aero_, + aerodynamical_resistance_, frac_landuse_, dgncur_awet_, + wet_dens_, dry_atm_, dry_aero_, // Inouts-outputs qqcw_, // Outputs ptend_q_, aerdepdrycw_, aerdepdryis_, // work arrays - rho_, vlc_dry_, vlc_trb_, vlc_grv_, dqdt_tmp_); + rho_, vlc_dry_, vlc_trb_, vlc_grv_, dqdt_tmp_, qtracers_); Kokkos::fence(); // Update the interstitial aerosols using ptend. diff --git a/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_process_interface.hpp b/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_process_interface.hpp index e39090cecde..55ab5b15b95 100644 --- a/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_process_interface.hpp +++ b/components/eamxx/src/physics/mam/eamxx_mam_dry_deposition_process_interface.hpp @@ -7,6 +7,9 @@ // For MAM4 aerosol configuration #include +// For AtmosphereInput +#include "share/io/scorpio_input.hpp" + // For component name #include @@ -26,6 +29,7 @@ class MAMDryDep final : public scream::AtmosphereProcess { using view_3d = Field::view_dev_t; using view_4d = Field::view_dev_t; using const_view_1d = Field::view_dev_t; + using const_view_2d = Field::view_dev_t; using const_view_3d = Field::view_dev_t; private: @@ -45,7 +49,6 @@ class MAMDryDep final : public scream::AtmosphereProcess { // physics grid for column information std::shared_ptr grid_; - /* Note on mam4::DryDeposition::aerosol_categories = 4 used in deposition velocity dimension defined below. These correspond to the two attachment states and two moments: @@ -64,14 +67,13 @@ class MAMDryDep final : public scream::AtmosphereProcess { // Dimensions // [num_modes, aerosol_categories_, num columns, num levels] view_4d vlc_grv_; - + // Output deposition velocity, [m/s] - // fraction landuse weighted sum of vlc_grv and vlc_trb + // fraction landuse weighted sum of vlc_grv and vlc_trb // Dimensions // [num_modes, aerosol_categories_, num columns, num levels] view_4d vlc_dry_; - // Output of the the mixing ratio tendencies [kg/kg/s or 1/kg/s] // Dimensions // [num columns, num levels, mam4::aero_model::pcnst] @@ -81,25 +83,18 @@ class MAMDryDep final : public scream::AtmosphereProcess { // Work array to hold the mixing ratios [kg/kg or 1/kg] // Dimensions // [num columns, num levels, mam4::aero_model::pcnst] - // Packs AerosolState::int_aero_nmr + // Packs AerosolState::int_aero_nmr // and AerosolState::int_aero_nmr // into one array, hence is mixed kg/kg and 1/kg. view_3d qtracers_; - // Work array to hold the fraction [non-dimentional] - // of land use for column. - // Dimensions - // [MAMDryDep::n_land_type, num columns] - // Values should sum to 1. - view_2d fraction_landuse_; - // Work array to hold the air density [kg/m3] // Dimensions // [num columns, num levels] // Calculated from air pressure at layer midpoint, // Constants::r_gas_dry_air and air temperture. view_2d rho_; - + // Work array to hold tendency for 1 species [kg/kg/s] or [1/kg/s] // Dimensions // [mam4::aero_model::pcnst, num column, num level] @@ -111,6 +106,11 @@ class MAMDryDep final : public scream::AtmosphereProcess { // Filled with Prognostics::n_mode_c and Prognostics::q_aero_c view_3d qqcw_; + // For reading fractional land use file + std::shared_ptr horizInterp_; + std::shared_ptr dataReader_; + const_view_2d frac_landuse_; + public: using KT = ekat::KokkosTypes; diff --git a/components/eamxx/src/physics/mam/readfiles/fractional_land_use.hpp b/components/eamxx/src/physics/mam/readfiles/fractional_land_use.hpp new file mode 100644 index 00000000000..1dba53c38ed --- /dev/null +++ b/components/eamxx/src/physics/mam/readfiles/fractional_land_use.hpp @@ -0,0 +1,59 @@ +#ifndef FRACTIONAL_LANDUSE_HPP +#define FRACTIONAL_LANDUSE_HPP + +// For AtmosphereInput +#include "share/io/scorpio_input.hpp" + +namespace scream { +namespace frac_landuse { + +template +struct fracLandUseFunctions { + using Device = DeviceType; + + using KT = KokkosTypes; + using const_view_2d = typename KT::template view_2d; + + // ------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------- + + // Fractional land use routines + static std::shared_ptr create_horiz_remapper( + const std::shared_ptr &model_grid, + const std::string &fracLandUse_data_file, const std::string &map_file, + const std::string &field_name, const std::string &dim_name1, + const std::string &dim_name2); + + // ------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------- + + static std::shared_ptr create_data_reader( + const std::shared_ptr &horiz_remapper, + const std::string &data_file); + + // ------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------- + + static void update_frac_land_use_data_from_file( + std::shared_ptr &scorpio_reader, + AbstractRemapper &horiz_interp, const_view_2d &input); + + // ------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------- + + static void init_frac_landuse_file_read( + const int ncol, const std::string field_name, const std::string dim_name1, + const std::string dim_name2, + const std::shared_ptr &grid, + const std::string &data_file, const std::string &mapping_file, + // output + std::shared_ptr &FracLandUseHorizInterp, + std::shared_ptr &FracLandUseDataReader); + +}; // struct fracLandUseFunctions + +} // namespace frac_landuse +} // namespace scream +#endif // FRACTIONAL_LANDUSE_HPP + +#include "fractional_land_use_impl.hpp" \ No newline at end of file diff --git a/components/eamxx/src/physics/mam/readfiles/fractional_land_use_impl.hpp b/components/eamxx/src/physics/mam/readfiles/fractional_land_use_impl.hpp new file mode 100644 index 00000000000..8bddd390e19 --- /dev/null +++ b/components/eamxx/src/physics/mam/readfiles/fractional_land_use_impl.hpp @@ -0,0 +1,148 @@ +#ifndef FRACTIONAL_LANDUSE_IMPL_HPP +#define FRACTIONAL_LANDUSE_IMPL_HPP + +#include "share/grid/remap/identity_remapper.hpp" +#include "share/grid/remap/refining_remapper_p2p.hpp" +#include "share/io/scream_scorpio_interface.hpp" +#include "share/util/scream_timing.hpp" + +namespace scream { +namespace frac_landuse { + +template +std::shared_ptr +fracLandUseFunctions::create_horiz_remapper( + const std::shared_ptr &model_grid, + const std::string &data_file, const std::string &map_file, + const std::string &field_name, const std::string &dim_name1, + const std::string &dim_name2) { + using namespace ShortFieldTagsNames; + + scorpio::register_file(data_file, scorpio::Read); + const int ncols_data = scorpio::get_dimlen(data_file, dim_name1); + const int nclass_data = scorpio::get_dimlen(data_file, dim_name2); + + scorpio::release_file(data_file); + + // We could use model_grid directly if using same num levels, + // but since shallow clones are cheap, we may as well do it (less lines of + // code) + auto horiz_interp_tgt_grid = + model_grid->clone("frac_land_use_horiz_interp_tgt_grid", true); + + const int ncols_model = model_grid->get_num_global_dofs(); + std::shared_ptr remapper; + if(ncols_data == ncols_model) { + remapper = std::make_shared( + horiz_interp_tgt_grid, IdentityRemapper::SrcAliasTgt); + } else { + EKAT_REQUIRE_MSG(ncols_data <= ncols_model, + "Error! We do not allow to coarsen fractional land use " + "data to fit the model. We only allow\n" + " fractional land use data to be at the same or " + "coarser resolution as the model.\n"); + // We must have a valid map file + EKAT_REQUIRE_MSG(map_file != "", + "ERROR: fractional land use data is on a different grid " + "than the model one,\n" + " but remap file is missing from fractional " + "land use parameter list."); + + remapper = + std::make_shared(horiz_interp_tgt_grid, map_file); + } + + remapper->registration_begins(); + + const auto tgt_grid = remapper->get_tgt_grid(); + + const auto layout_2d = tgt_grid->get_2d_vector_layout(nclass_data, "class"); + const auto nondim = ekat::units::Units::nondimensional(); + + Field fractional_land_use( + FieldIdentifier(field_name, layout_2d, nondim, tgt_grid->name())); + fractional_land_use.allocate_view(); + + remapper->register_field_from_tgt(fractional_land_use); + + remapper->registration_ends(); + + return remapper; +} // create_horiz_remapper + +// ------------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------- + +template +std::shared_ptr fracLandUseFunctions::create_data_reader( + const std::shared_ptr &horiz_remapper, + const std::string &data_file) { + std::vector io_fields; + for(int i = 0; i < horiz_remapper->get_num_fields(); ++i) { + io_fields.push_back(horiz_remapper->get_src_field(i)); + } + const auto io_grid = horiz_remapper->get_src_grid(); + return std::make_shared(data_file, io_grid, io_fields, true); +} // create_data_reader + +// ------------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------- + +template +void fracLandUseFunctions::update_frac_land_use_data_from_file( + std::shared_ptr &scorpio_reader, + AbstractRemapper &horiz_interp, const_view_2d &input) { + start_timer("EAMxx::FracLandUse::update_frac_land_use_data_from_file"); + + // 1. Read from file + start_timer( + "EAMxx::FracLandUse::update_frac_land_use_data_from_file::read_data"); + scorpio_reader->read_variables(); + stop_timer( + "EAMxx::FracLandUse::update_frac_land_use_data_from_file::read_data"); + + // 2. Run the horiz remapper (it is a do-nothing op if FracLandUse data is on + // same grid as model) + start_timer( + "EAMxx::FracLandUse::update_frac_land_use_data_from_file::horiz_remap"); + horiz_interp.remap(/*forward = */ true); + stop_timer( + "EAMxx::FracLandUse::update_frac_land_use_data_from_file::horiz_remap"); + + // 3. Get the tgt field of the remapper + start_timer( + "EAMxx::FracLandUse::update_frac_land_use_data_from_file::get_field"); + // Recall, the fields are registered in the order: + // Read the field from the file + input = horiz_interp.get_tgt_field(0).get_view(); + stop_timer( + "EAMxx::FracLandUse::update_frac_land_use_data_from_file::get_field"); + + stop_timer("EAMxx::FracLandUse::update_frac_land_use_data_from_file"); + +} // END update_frac_landuse_data_from_file + +// ------------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------- + +template +void fracLandUseFunctions::init_frac_landuse_file_read( + const int ncol, const std::string field_name, const std::string dim_name1, + const std::string dim_name2, + const std::shared_ptr &grid, + const std::string &data_file, const std::string &mapping_file, + // output + std::shared_ptr &FracLandUseHorizInterp, + std::shared_ptr &FracLandUseDataReader) { + // Init horizontal remap + FracLandUseHorizInterp = create_horiz_remapper( + grid, data_file, mapping_file, field_name, dim_name1, dim_name2); + + // Create reader (an AtmosphereInput object) + FracLandUseDataReader = create_data_reader(FracLandUseHorizInterp, data_file); +} // init_frac_landuse_file_read + +} // namespace frac_landuse +} // namespace scream + +#endif // FRACTIONAL_LANDUSE_IMPL_HPP diff --git a/components/eamxx/tests/multi-process/dynamics_physics/mam/homme_shoc_cld_mam_aci_p3_mam_optics_rrtmgp_mam_drydep/CMakeLists.txt b/components/eamxx/tests/multi-process/dynamics_physics/mam/homme_shoc_cld_mam_aci_p3_mam_optics_rrtmgp_mam_drydep/CMakeLists.txt index e3c562cfcd1..43ec03b0cd6 100644 --- a/components/eamxx/tests/multi-process/dynamics_physics/mam/homme_shoc_cld_mam_aci_p3_mam_optics_rrtmgp_mam_drydep/CMakeLists.txt +++ b/components/eamxx/tests/multi-process/dynamics_physics/mam/homme_shoc_cld_mam_aci_p3_mam_optics_rrtmgp_mam_drydep/CMakeLists.txt @@ -79,6 +79,7 @@ set (TEST_INPUT_FILES scream/mam4xx/physprops/ocpho_rrtmg_c20240206.nc scream/mam4xx/physprops/bcpho_rrtmg_c20240206.nc scream/mam4xx/physprops/poly_rrtmg_c20240206.nc + scream/mam4xx/drydep/ne2np4/atmsrf_ne2np4_c20241017.nc ) foreach (file IN ITEMS ${TEST_INPUT_FILES}) diff --git a/components/eamxx/tests/multi-process/dynamics_physics/mam/homme_shoc_cld_mam_aci_p3_mam_optics_rrtmgp_mam_drydep/input.yaml b/components/eamxx/tests/multi-process/dynamics_physics/mam/homme_shoc_cld_mam_aci_p3_mam_optics_rrtmgp_mam_drydep/input.yaml index 1857bc534dd..3dbd99682fd 100644 --- a/components/eamxx/tests/multi-process/dynamics_physics/mam/homme_shoc_cld_mam_aci_p3_mam_optics_rrtmgp_mam_drydep/input.yaml +++ b/components/eamxx/tests/multi-process/dynamics_physics/mam/homme_shoc_cld_mam_aci_p3_mam_optics_rrtmgp_mam_drydep/input.yaml @@ -96,6 +96,10 @@ atmosphere_processes: rrtmgp_cloud_optics_file_sw: ${SCREAM_DATA_DIR}/init/rrtmgp-cloud-optics-coeffs-sw.nc rrtmgp_cloud_optics_file_lw: ${SCREAM_DATA_DIR}/init/rrtmgp-cloud-optics-coeffs-lw.nc enable_column_conservation_checks: true + mam4_drydep: + # Fractional land use file + drydep_remap_file: "" + fractional_land_use_file: ${SCREAM_DATA_DIR}/mam4xx/drydep/ne2np4/atmsrf_ne2np4_c20241017.nc grids_manager: Type: Homme diff --git a/components/eamxx/tests/multi-process/physics_only/mam/shoc_mam4_drydep/CMakeLists.txt b/components/eamxx/tests/multi-process/physics_only/mam/shoc_mam4_drydep/CMakeLists.txt index 9f6fb8733c2..d64cc7eebaf 100644 --- a/components/eamxx/tests/multi-process/physics_only/mam/shoc_mam4_drydep/CMakeLists.txt +++ b/components/eamxx/tests/multi-process/physics_only/mam/shoc_mam4_drydep/CMakeLists.txt @@ -21,6 +21,13 @@ set (SHOC_MAX_DT 300) math (EXPR MAC_MIC_SUBCYCLES "(${ATM_TIME_STEP} + ${SHOC_MAX_DT} - 1) / ${SHOC_MAX_DT}") # Ensure test input files are present in the data dir +set (TEST_INPUT_FILES + scream/mam4xx/drydep/ne2np4/atmsrf_ne2np4_c20241017.nc +) +foreach (file IN ITEMS ${TEST_INPUT_FILES}) + GetInputFile(${file}) +endforeach() + GetInputFile(scream/init/${EAMxx_tests_IC_FILE_MAM4xx_72lev}) GetInputFile(cam/topo/${EAMxx_tests_TOPO_FILE}) diff --git a/components/eamxx/tests/multi-process/physics_only/mam/shoc_mam4_drydep/input.yaml b/components/eamxx/tests/multi-process/physics_only/mam/shoc_mam4_drydep/input.yaml index c451008adc7..24f610f041c 100644 --- a/components/eamxx/tests/multi-process/physics_only/mam/shoc_mam4_drydep/input.yaml +++ b/components/eamxx/tests/multi-process/physics_only/mam/shoc_mam4_drydep/input.yaml @@ -29,6 +29,10 @@ atmosphere_processes: c_diag_3rd_mom: 7.0 Ckh: 0.1 Ckm: 0.1 + mam4_drydep: + # Fractional land use file + drydep_remap_file: "" + fractional_land_use_file: ${SCREAM_DATA_DIR}/mam4xx/drydep/ne2np4/atmsrf_ne2np4_c20241017.nc grids_manager: Type: Mesh Free diff --git a/components/eamxx/tests/single-process/mam/drydep/CMakeLists.txt b/components/eamxx/tests/single-process/mam/drydep/CMakeLists.txt index d05e6823642..413e6be630c 100644 --- a/components/eamxx/tests/single-process/mam/drydep/CMakeLists.txt +++ b/components/eamxx/tests/single-process/mam/drydep/CMakeLists.txt @@ -23,6 +23,13 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/output.yaml ${CMAKE_CURRENT_BINARY_DIR}/output.yaml) # Ensure test input files are present in the data dir +set (TEST_INPUT_FILES + scream/mam4xx/drydep/ne2np4/atmsrf_ne2np4_c20241017.nc +) +foreach (file IN ITEMS ${TEST_INPUT_FILES}) + GetInputFile(${file}) +endforeach() + GetInputFile(scream/init/${EAMxx_tests_IC_FILE_MAM4xx_72lev}) GetInputFile(cam/topo/${EAMxx_tests_TOPO_FILE}) diff --git a/components/eamxx/tests/single-process/mam/drydep/input.yaml b/components/eamxx/tests/single-process/mam/drydep/input.yaml index 86c6dd8766a..4ae00b20297 100644 --- a/components/eamxx/tests/single-process/mam/drydep/input.yaml +++ b/components/eamxx/tests/single-process/mam/drydep/input.yaml @@ -10,6 +10,10 @@ time_stepping: atmosphere_processes: atm_procs_list: [mam4_drydep] + mam4_drydep: + # Fractional land use file + drydep_remap_file: "" + fractional_land_use_file: ${SCREAM_DATA_DIR}/mam4xx/drydep/ne2np4/atmsrf_ne2np4_c20241017.nc grids_manager: Type: Mesh Free diff --git a/components/homme/src/theta-l/share/prim_state_mod.F90 b/components/homme/src/theta-l/share/prim_state_mod.F90 index 75c6089f62a..835dfd2ddf3 100644 --- a/components/homme/src/theta-l/share/prim_state_mod.F90 +++ b/components/homme/src/theta-l/share/prim_state_mod.F90 @@ -793,7 +793,7 @@ subroutine prim_printstate(elem, tl,hybrid,hvcoord,nets,nete) write(iulog,100) "(E-E0)/E0 ",(TOTE(2)-TOTE0)/TOTE0 do q=1,qsize if(Qmass0(q)>0.0D0) then - write(iulog,'(a,E23.15,a,i1)') "(Q-Q0)/Q0 ",(Qmass(q,2)-Qmass0(q))/Qmass0(q)," Q",q + write(iulog,'(a,E23.15,a,i2)') "(Q-Q0)/Q0 ",(Qmass(q,2)-Qmass0(q))/Qmass0(q)," Q",q end if enddo endif