Skip to content

Commit

Permalink
Create IOPForcing ATM process
Browse files Browse the repository at this point in the history
Moves IOP forcing from within HOMME interface to it's own physics
process, called directly after dynamics process. Also, changes name of
IntensiveObservationPeriod class to IOPDataManager.
  • Loading branch information
tcclevenger committed Nov 21, 2024
1 parent 28474c3 commit f1ef82b
Show file tree
Hide file tree
Showing 26 changed files with 813 additions and 757 deletions.
4 changes: 4 additions & 0 deletions components/eamxx/cime_config/namelist_defaults_scream.xml
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,9 @@ be lost if SCREAM_HACK_XML is not enabled.
<ML_correction_unit_test type="logical">false</ML_correction_unit_test>
</mlcorrection>

<!-- IOPForcing -->
<iop_forcing inherit="atm_proc_base" />

<!-- For internal testing only -->
<testOnly inherit="atm_proc_base">
<my_param type="array(integer)">1,2</my_param>
Expand Down Expand Up @@ -556,6 +559,7 @@ be lost if SCREAM_HACK_XML is not enabled.

<physics inherit="atm_proc_group">
<atm_procs_list>mac_aero_mic,rrtmgp</atm_procs_list>
<atm_procs_list COMPSET=".*DP-EAMxx">iop_forcing,mac_aero_mic,rrtmgp</atm_procs_list>
</physics>
</atmosphere_processes_defaults>

Expand Down
46 changes: 23 additions & 23 deletions components/eamxx/src/control/atmosphere_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,24 +180,24 @@ init_time_stamps (const util::TimeStamp& run_t0, const util::TimeStamp& case_t0,
}

void AtmosphereDriver::
setup_iop ()
setup_iop_data_manager ()
{
// At this point, must have comm, params, initialized timestamps created.
check_ad_status(s_comm_set | s_params_set | s_ts_inited);

// Check to make sure iop is not already initialized
EKAT_REQUIRE_MSG(not m_iop, "Error! setup_iop() is called, but IOP already set up.\n");
EKAT_REQUIRE_MSG(not m_iop_data_manager, "Error! setup_iop_data_manager() is called, but IOP already set up.\n");

// This function should only be called if we are enabling IOP
const bool enable_iop =
m_atm_params.sublist("driver_options").get("enable_iop", false);
EKAT_REQUIRE_MSG(enable_iop, "Error! setup_iop() is called, but enable_iop=false "
EKAT_REQUIRE_MSG(enable_iop, "Error! setup_iop_data_manager() is called, but enable_iop=false "
"in driver_options parameters.\n");

// Params must include iop_options sublist.
const auto iop_sublist_exists = m_atm_params.isSublist("iop_options");
EKAT_REQUIRE_MSG(iop_sublist_exists,
"Error! setup_iop() is called, but no iop_options "
"Error! setup_iop_data_manager() is called, but no iop_options "
"defined in parameters.\n");

const auto iop_params = m_atm_params.sublist("iop_options");
Expand All @@ -206,15 +206,15 @@ setup_iop ()
const auto hyam = phys_grid->get_geometry_data("hyam");
const auto hybm = phys_grid->get_geometry_data("hybm");

m_iop = std::make_shared<IntensiveObservationPeriod>(m_atm_comm,
iop_params,
m_run_t0,
nlevs,
hyam,
hybm);
m_iop_data_manager = std::make_shared<IOPDataManager>(m_atm_comm,
iop_params,
m_run_t0,
nlevs,
hyam,
hybm);

// Set IOP object in atm processes
m_atm_process_group->set_iop(m_iop);
m_atm_process_group->set_iop_data_manager(m_iop_data_manager);
}

void AtmosphereDriver::create_atm_processes()
Expand Down Expand Up @@ -295,7 +295,7 @@ void AtmosphereDriver::create_grids()
const bool enable_iop =
m_atm_params.sublist("driver_options").get("enable_iop", false);
if (enable_iop) {
setup_iop ();
setup_iop_data_manager ();
}

// Set the grids in the processes. Do this by passing the grids manager.
Expand Down Expand Up @@ -1203,7 +1203,7 @@ void AtmosphereDriver::set_initial_conditions ()
}
}

if (m_iop) {
if (m_iop_data_manager) {
// For runs with IOP, call to setup io grids and lat
// lon information needed for reading from file
// We use a single topo file for both GLL and PG2 runs. All
Expand All @@ -1213,13 +1213,13 @@ void AtmosphereDriver::set_initial_conditions ()
for (const auto& it : m_field_mgrs) {
const auto& grid_name = it.first;
if (ic_fields_names[grid_name].size() > 0 or
topography_eamxx_fields_names[grid_name].size() > 0) {
topography_eamxx_fields_names[grid_name].size() > 0) {
const auto& file_name = grid_name == "Physics GLL"
?
ic_pl.get<std::string>("Filename")
:
ic_pl.get<std::string>("topography_filename");
m_iop->setup_io_info(file_name, it.second->get_grid());
m_iop_data_manager->setup_io_info(file_name, it.second->get_grid());
}
}
}
Expand All @@ -1231,12 +1231,12 @@ void AtmosphereDriver::set_initial_conditions ()
m_atm_logger->info(" [EAMxx] IC filename: " + file_name);
for (const auto& it : m_field_mgrs) {
const auto& grid_name = it.first;
if (not m_iop) {
if (not m_iop_data_manager) {
read_fields_from_file (ic_fields_names[grid_name],it.second->get_grid(),file_name,m_current_ts);
} else {
// For IOP enabled, we load from file and copy data from the closest
// lat/lon column to every other column
m_iop->read_fields_from_file_for_iop(file_name,
m_iop_data_manager->read_fields_from_file_for_iop(file_name,
ic_fields_names[grid_name],
m_current_ts,
it.second);
Expand Down Expand Up @@ -1306,7 +1306,7 @@ void AtmosphereDriver::set_initial_conditions ()
m_atm_logger->info(" filename: " + file_name);
for (const auto& it : m_field_mgrs) {
const auto& grid_name = it.first;
if (not m_iop) {
if (not m_iop_data_manager) {
// Topography files always use "ncol_d" for the GLL grid value of ncol.
// To ensure we read in the correct value, we must change the name for that dimension
auto io_grid = it.second->get_grid();
Expand All @@ -1322,7 +1322,7 @@ void AtmosphereDriver::set_initial_conditions ()
} else {
// For IOP enabled, we load from file and copy data from the closest
// lat/lon column to every other column
m_iop->read_fields_from_file_for_iop(file_name,
m_iop_data_manager->read_fields_from_file_for_iop(file_name,
topography_file_fields_names[grid_name],
topography_eamxx_fields_names[grid_name],
m_current_ts,
Expand All @@ -1347,16 +1347,16 @@ void AtmosphereDriver::set_initial_conditions ()
m_atm_params.sublist("provenance").set<std::string>("topography_file","NONE");
}

if (m_iop) {
if (m_iop_data_manager) {
// Load IOP data file data for initial time stamp
m_iop->read_iop_file_data(m_current_ts);
m_iop_data_manager->read_iop_file_data(m_current_ts);

// Now that ICs are processed, set appropriate fields using IOP file data.
// Since ICs are loaded on GLL grid, we set those fields only and dynamics
// will take care of the rest (for PG2 case).
if (m_field_mgrs.count("Physics GLL") > 0) {
const auto& fm = m_field_mgrs.at("Physics GLL");
m_iop->set_fields_from_iop_data(fm);
m_iop_data_manager->set_fields_from_iop_data(fm);
}
}

Expand Down Expand Up @@ -1754,7 +1754,7 @@ void AtmosphereDriver::finalize ( /* inputs? */ ) {
}

// Destroy iop
m_iop = nullptr;
m_iop_data_manager = nullptr;

// Destroy the buffer manager
m_memory_buffer = nullptr;
Expand Down
8 changes: 4 additions & 4 deletions components/eamxx/src/control/atmosphere_driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#define SCREAM_ATMOSPHERE_DRIVER_HPP

#include "control/surface_coupling_utils.hpp"
#include "share/iop/intensive_observation_period.hpp"
#include "share/field/field_manager.hpp"
#include "share/grid/grids_manager.hpp"
#include "share/util/scream_time_stamp.hpp"
Expand All @@ -11,6 +10,7 @@
#include "share/io/scorpio_input.hpp"
#include "share/atm_process/ATMBufferManager.hpp"
#include "share/atm_process/SCDataManager.hpp"
#include "share/atm_process/IOPDataManager.hpp"

#include "ekat/logging/ekat_logger.hpp"
#include "ekat/mpi/ekat_comm.hpp"
Expand Down Expand Up @@ -72,8 +72,8 @@ class AtmosphereDriver
// Set AD params
void init_scorpio (const int atm_id = 0);

// Setup IntensiveObservationPeriod
void setup_iop ();
// Setup IOPDataManager
void setup_iop_data_manager ();

// Create atm processes, without initializing them
void create_atm_processes ();
Expand Down Expand Up @@ -217,7 +217,7 @@ class AtmosphereDriver
std::shared_ptr<SCDataManager> m_surface_coupling_import_data_manager;
std::shared_ptr<SCDataManager> m_surface_coupling_export_data_manager;

std::shared_ptr<IntensiveObservationPeriod> m_iop;
std::shared_ptr<IOPDataManager> m_iop_data_manager;

// This is the time stamp at the beginning of the time step.
util::TimeStamp m_current_ts;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ void SurfaceCouplingImporter::do_import(const bool called_during_initialization)
});
#endif

if (m_iop) {
if (m_iop->get_params().get<bool>("iop_srf_prop")) {
if (m_iop_data_manager) {
if (m_iop_data_manager->get_params().get<bool>("iop_srf_prop")) {
// Overwrite imports with data from IOP file
overwrite_iop_imports(called_during_initialization);
}
Expand All @@ -221,9 +221,12 @@ void SurfaceCouplingImporter::overwrite_iop_imports (const bool called_during_in
using policy_type = KokkosTypes<DefaultDevice>::RangePolicy;
using C = physics::Constants<Real>;

const auto has_lhflx = m_iop->has_iop_field("lhflx");
const auto has_shflx = m_iop->has_iop_field("shflx");
const auto has_Tg = m_iop->has_iop_field("Tg");
const auto has_lhflx = m_iop_data_manager->has_iop_field("lhflx");
const auto has_shflx = m_iop_data_manager->has_iop_field("shflx");
const auto has_Tg = m_iop_data_manager->has_iop_field("Tg");

// Read IOP file for current time step, if necessary
m_iop_data_manager->read_iop_file_data(timestamp());

static constexpr Real latvap = C::LatVap;
static constexpr Real stebol = C::stebol;
Expand All @@ -243,19 +246,19 @@ void SurfaceCouplingImporter::overwrite_iop_imports (const bool called_during_in
// Store IOP surf data into col_val
Real col_val(std::nan(""));
if (fname == "surf_evap" && has_lhflx) {
const auto f = m_iop->get_iop_field("lhflx");
const auto f = m_iop_data_manager->get_iop_field("lhflx");
f.sync_to_host();
col_val = f.get_view<Real, Host>()()/latvap;
} else if (fname == "surf_sens_flux" && has_shflx) {
const auto f = m_iop->get_iop_field("shflx");
const auto f = m_iop_data_manager->get_iop_field("shflx");
f.sync_to_host();
col_val = f.get_view<Real, Host>()();
} else if (fname == "surf_radiative_T" && has_Tg) {
const auto f = m_iop->get_iop_field("Tg");
const auto f = m_iop_data_manager->get_iop_field("Tg");
f.sync_to_host();
col_val = f.get_view<Real, Host>()();
} else if (fname == "surf_lw_flux_up" && has_Tg) {
const auto f = m_iop->get_iop_field("Tg");
const auto f = m_iop_data_manager->get_iop_field("Tg");
f.sync_to_host();
col_val = stebol*std::pow(f.get_view<Real, Host>()(), 4);
} else {
Expand Down
1 change: 0 additions & 1 deletion components/eamxx/src/dynamics/homme/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ macro (CreateDynamicsLib HOMME_TARGET NP PLEV QSIZE)
${SCREAM_DYNAMICS_SRC_DIR}/eamxx_homme_process_interface.cpp
${SCREAM_DYNAMICS_SRC_DIR}/eamxx_homme_fv_phys.cpp
${SCREAM_DYNAMICS_SRC_DIR}/eamxx_homme_rayleigh_friction.cpp
${SCREAM_DYNAMICS_SRC_DIR}/eamxx_homme_iop.cpp
${SCREAM_DYNAMICS_SRC_DIR}/physics_dynamics_remapper.cpp
${SCREAM_DYNAMICS_SRC_DIR}/homme_grids_manager.cpp
${SCREAM_DYNAMICS_SRC_DIR}/interface/homme_context_mod.F90
Expand Down
Loading

0 comments on commit f1ef82b

Please sign in to comment.