Skip to content

Commit 03cadd9

Browse files
committed
Merge branch 'bartgol/eamxx/iop-remapper' into next (PR #6914)
2 parents 1fdb38e + a3925a8 commit 03cadd9

23 files changed

+637
-539
lines changed

components/eamxx/src/control/atmosphere_driver.cpp

Lines changed: 34 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,11 +1001,14 @@ void AtmosphereDriver::restart_model ()
10011001
continue;
10021002
}
10031003
const auto& restart_group = it.second->get_groups_info().at("RESTART");
1004-
std::vector<std::string> fnames;
1004+
std::vector<Field> fields;
10051005
for (const auto& fn : restart_group->m_fields_names) {
1006-
fnames.push_back(fn);
1006+
fields.push_back(it.second->get_field(fn));
1007+
}
1008+
read_fields_from_file (fields,it.second->get_grid(),filename);
1009+
for (auto& f : fields) {
1010+
f.get_header().get_tracking().update_time_stamp(m_current_ts);
10071011
}
1008-
read_fields_from_file (fnames,it.second->get_grid(),filename,m_current_ts);
10091012
}
10101013

10111014
// Restart the num steps counter in the atm time stamp
@@ -1267,17 +1270,20 @@ void AtmosphereDriver::set_initial_conditions ()
12671270
// Now loop over all grids, and load from file the needed fields on each grid (if any).
12681271
const auto& file_name = ic_pl.get<std::string>("Filename");
12691272
m_atm_logger->info(" [EAMxx] IC filename: " + file_name);
1270-
for (const auto& it : m_field_mgrs) {
1271-
const auto& grid_name = it.first;
1273+
for (const auto& [grid_name,fm] : m_field_mgrs) {
1274+
std::vector<Field> ic_fields;
1275+
for (const auto& fn : ic_fields_names[grid_name]) {
1276+
ic_fields.push_back(fm->get_field(fn));
1277+
}
12721278
if (not m_iop_data_manager) {
1273-
read_fields_from_file (ic_fields_names[grid_name],it.second->get_grid(),file_name,m_current_ts);
1279+
read_fields_from_file (ic_fields,fm->get_grid(),file_name);
12741280
} else {
12751281
// For IOP enabled, we load from file and copy data from the closest
12761282
// lat/lon column to every other column
1277-
m_iop_data_manager->read_fields_from_file_for_iop(file_name,
1278-
ic_fields_names[grid_name],
1279-
m_current_ts,
1280-
it.second);
1283+
m_iop_data_manager->read_fields_from_file_for_iop(file_name,ic_fields,fm->get_grid());
1284+
}
1285+
for (auto& f : ic_fields) {
1286+
f.get_header().get_tracking().update_time_stamp(m_current_ts);
12811287
}
12821288
}
12831289
}
@@ -1342,29 +1348,33 @@ void AtmosphereDriver::set_initial_conditions ()
13421348
m_atm_logger->info(" [EAMxx] Reading topography from file ...");
13431349
const auto& file_name = ic_pl.get<std::string>("topography_filename");
13441350
m_atm_logger->info(" filename: " + file_name);
1345-
for (const auto& it : m_field_mgrs) {
1346-
const auto& grid_name = it.first;
1351+
for (const auto& [grid_name,fm] : m_field_mgrs) {
1352+
std::vector<Field> topo_fields;
1353+
int nfields = topography_eamxx_fields_names[grid_name].size();
1354+
for (int i=0; i<nfields; ++i) {
1355+
auto eamxx_fname = topography_eamxx_fields_names[grid_name][i];
1356+
auto file_fname = topography_file_fields_names[grid_name][i];
1357+
topo_fields.push_back(fm->get_field(eamxx_fname).alias(file_fname));
1358+
}
1359+
13471360
if (not m_iop_data_manager) {
13481361
// Topography files always use "ncol_d" for the GLL grid value of ncol.
13491362
// To ensure we read in the correct value, we must change the name for that dimension
1350-
auto io_grid = it.second->get_grid();
1363+
auto io_grid = fm->get_grid();
13511364
if (grid_name=="Physics GLL") {
13521365
using namespace ShortFieldTagsNames;
13531366
auto grid = io_grid->clone(io_grid->name(),true);
13541367
grid->reset_field_tag_name(COL,"ncol_d");
13551368
io_grid = grid;
13561369
}
1357-
read_fields_from_file (topography_file_fields_names[grid_name],
1358-
topography_eamxx_fields_names[grid_name],
1359-
io_grid,file_name,m_current_ts);
1370+
read_fields_from_file (topo_fields,io_grid,file_name);
13601371
} else {
13611372
// For IOP enabled, we load from file and copy data from the closest
13621373
// lat/lon column to every other column
1363-
m_iop_data_manager->read_fields_from_file_for_iop(file_name,
1364-
topography_file_fields_names[grid_name],
1365-
topography_eamxx_fields_names[grid_name],
1366-
m_current_ts,
1367-
it.second);
1374+
m_iop_data_manager->read_fields_from_file_for_iop(file_name,topo_fields,fm->get_grid());
1375+
}
1376+
for (auto& f : topo_fields) {
1377+
f.get_header().get_tracking().update_time_stamp(m_current_ts);
13681378
}
13691379
}
13701380
// Store in provenance list, for later usage in output file metadata
@@ -1469,83 +1479,17 @@ void AtmosphereDriver::set_initial_conditions ()
14691479
}
14701480

14711481
void AtmosphereDriver::
1472-
read_fields_from_file (const std::vector<std::string>& field_names_nc,
1473-
const std::vector<std::string>& field_names_eamxx,
1474-
const std::shared_ptr<const AbstractGrid>& grid,
1475-
const std::string& file_name,
1476-
const util::TimeStamp& t0)
1477-
{
1478-
EKAT_REQUIRE_MSG(field_names_nc.size()==field_names_eamxx.size(),
1479-
"Error! Field name arrays must have same size.\n");
1480-
1481-
if (field_names_nc.size()==0) {
1482-
return;
1483-
}
1484-
1485-
// NOTE: we cannot pass the field_mgr and m_grids_mgr, since the input
1486-
// grid may not be in the grids_manager and may not be the grid
1487-
// of the field mgr. This sounds weird, but there is a precise
1488-
// use case: when grid is a shallow clone of the fm grid, where
1489-
// we changed the name of some field tags (e.g., we set the name
1490-
// of COL to ncol_d). This is used when reading the topography,
1491-
// since the topo file *always* uses ncol_d for GLL points data,
1492-
// while a non-PG2 run would have the tag name be "ncol".
1493-
const auto& field_mgr = m_field_mgrs.at(grid->name());
1494-
std::vector<Field> fields;
1495-
for (size_t i=0; i<field_names_nc.size(); ++i) {
1496-
const auto& eamxx_name = field_names_eamxx[i];
1497-
const auto& nc_name = field_names_nc[i];
1498-
fields.push_back(field_mgr->get_field(eamxx_name).alias(nc_name));
1499-
}
1500-
1501-
AtmosphereInput ic_reader(file_name,grid,fields);
1502-
ic_reader.set_logger(m_atm_logger);
1503-
ic_reader.read_variables();
1504-
ic_reader.finalize();
1505-
1506-
for (auto& f : fields) {
1507-
// Set the initial time stamp
1508-
// NOTE: f is an alias of the field from field_mgr, so it shares all
1509-
// pointers to the metadata (except for the FieldIdentifier),
1510-
// so changing its timestamp will also change the timestamp
1511-
// of the field in field_mgr
1512-
f.get_header().get_tracking().update_time_stamp(t0);
1513-
}
1514-
}
1515-
1516-
void AtmosphereDriver::
1517-
read_fields_from_file (const std::vector<std::string>& field_names,
1482+
read_fields_from_file (const std::vector<Field>& fields,
15181483
const std::shared_ptr<const AbstractGrid>& grid,
1519-
const std::string& file_name,
1520-
const util::TimeStamp& t0)
1484+
const std::string& file_name)
15211485
{
1522-
if (field_names.size()==0) {
1486+
if (fields.size()==0) {
15231487
return;
15241488
}
15251489

1526-
// NOTE: we cannot pass the field_mgr and m_grids_mgr, since the input
1527-
// grid may not be in the grids_manager and may not be the grid
1528-
// of the field mgr. This sounds weird, but there is a precise
1529-
// use case: when grid is a shallow clone of the fm grid, where
1530-
// we changed the name of some field tags (e.g., we set the name
1531-
// of COL to ncol_d). This is used when reading the topography,
1532-
// since the topo file *always* uses ncol_d for GLL points data,
1533-
// while a non-PG2 run would have the tag name be "ncol".
1534-
const auto& field_mgr = m_field_mgrs.at(grid->name());
1535-
std::vector<Field> fields;
1536-
for (const auto& fn : field_names) {
1537-
fields.push_back(field_mgr->get_field(fn));
1538-
}
1539-
15401490
AtmosphereInput ic_reader(file_name,grid,fields);
15411491
ic_reader.set_logger(m_atm_logger);
15421492
ic_reader.read_variables();
1543-
ic_reader.finalize();
1544-
1545-
for (auto& f : fields) {
1546-
// Set the initial time stamp
1547-
f.get_header().get_tracking().update_time_stamp(t0);
1548-
}
15491493
}
15501494

15511495
void AtmosphereDriver::

components/eamxx/src/control/atmosphere_driver.hpp

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -185,21 +185,10 @@ class AtmosphereDriver
185185
void set_initial_conditions ();
186186
void restart_model ();
187187

188-
// Read fields from a file when the names of the fields in
189-
// EAMxx do not match exactly with the .nc file. Example is
190-
// for topography data files, where GLL and PG2 grid have
191-
// different naming conventions for phis.
192-
void read_fields_from_file (const std::vector<std::string>& field_names_nc,
193-
const std::vector<std::string>& field_names_eamxx,
188+
// Read fields from a file
189+
void read_fields_from_file (const std::vector<Field>& fields,
194190
const std::shared_ptr<const AbstractGrid>& grid,
195-
const std::string& file_name,
196-
const util::TimeStamp& t0);
197-
// Read fields from a file when the names of the fields in
198-
// EAMxx match with the .nc file.
199-
void read_fields_from_file (const std::vector<std::string>& field_names,
200-
const std::shared_ptr<const AbstractGrid>& grid,
201-
const std::string& file_name,
202-
const util::TimeStamp& t0);
191+
const std::string& file_name);
203192
void register_groups ();
204193

205194
std::map<std::string,field_mgr_ptr> m_field_mgrs;

components/eamxx/src/physics/spa/eamxx_spa_process_interface.cpp

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,12 @@ void SPA::set_grids(const std::shared_ptr<const GridsManager> grids_manager)
6060
auto spa_data_file = m_params.get<std::string>("spa_data_file");
6161
auto spa_map_file = m_params.get<std::string>("spa_remap_file","");
6262

63-
// IOP cases cannot have a remap file. IOP file reader is itself a remaper,
64-
// where a single column of data corresponding to the closest lat/lon pair to
65-
// the IOP lat/lon parameters is read from file, and that column data is mapped
66-
// to all columns of the IdentityRemapper source fields.
63+
// IOP cases cannot have a remap file. We will create a IOPRemapper as the horiz remapper
6764
EKAT_REQUIRE_MSG(spa_map_file == "" or spa_map_file == "None" or not m_iop_data_manager,
6865
"Error! Cannot define spa_remap_file for cases with an Intensive Observation Period defined. "
6966
"The IOP class defines it's own remap from file data -> model data.\n");
7067

71-
SPAHorizInterp = SPAFunc::create_horiz_remapper (m_grid,spa_data_file,spa_map_file, m_iop_data_manager!=nullptr);
68+
SPAHorizInterp = SPAFunc::create_horiz_remapper (m_grid,spa_data_file,spa_map_file, m_iop_data_manager);
7269

7370
// Grab a sw and lw field from the horiz interp, and check sw/lw dim against what we hardcoded in this class
7471
auto nswbands_data = SPAHorizInterp->get_src_field(4).get_header().get_identifier().get_layout().dim("swband");
@@ -124,15 +121,8 @@ void SPA::set_grids(const std::shared_ptr<const GridsManager> grids_manager)
124121
Kokkos::deep_copy(spa_hybm,spa_hybm_h);
125122
}
126123

127-
// 4. Create reader for spa data. The reader is either an
128-
// AtmosphereInput object (for reading into standard
129-
// grids) or a SpaFunctions::IOPReader (for reading into
130-
// an IOP grid).
131-
if (m_iop_data_manager) {
132-
SPAIOPDataReader = SPAFunc::create_spa_data_reader(m_iop_data_manager,SPAHorizInterp,spa_data_file);
133-
} else {
134-
SPADataReader = SPAFunc::create_spa_data_reader(SPAHorizInterp,spa_data_file);
135-
}
124+
// 4. Create reader for spa data.
125+
SPADataReader = SPAFunc::create_spa_data_reader(SPAHorizInterp,spa_data_file);
136126
}
137127

138128
// =========================================================================================
@@ -224,7 +214,7 @@ void SPA::initialize_impl (const RunType /* run_type */)
224214
// Note: At the first time step, the data will be moved into spa_beg,
225215
// and spa_end will be reloaded from file with the new month.
226216
const int curr_month = timestamp().get_month()-1; // 0-based
227-
SPAFunc::update_spa_data_from_file(SPADataReader,SPAIOPDataReader,timestamp(),curr_month,*SPAHorizInterp,SPAData_end);
217+
SPAFunc::update_spa_data_from_file(*SPADataReader,curr_month,*SPAHorizInterp,SPAData_end);
228218

229219
// 6. Set property checks for fields in this process
230220
using Interval = FieldWithinIntervalCheck;
@@ -246,7 +236,7 @@ void SPA::run_impl (const double dt)
246236
/* Update the SPATimeState to reflect the current time, note the addition of dt */
247237
SPATimeState.t_now = ts.frac_of_year_in_days();
248238
/* Update time state and if the month has changed, update the data.*/
249-
SPAFunc::update_spa_timestate(SPADataReader,SPAIOPDataReader,ts,*SPAHorizInterp,SPATimeState,SPAData_start,SPAData_end);
239+
SPAFunc::update_spa_timestate(*SPADataReader,ts,*SPAHorizInterp,SPATimeState,SPAData_start,SPAData_end);
250240

251241
// Call the main SPA routine to get interpolated aerosol forcings.
252242
const auto& pmid_tgt = get_field_in("p_mid").get_view<const Spack**>();

components/eamxx/src/physics/spa/eamxx_spa_process_interface.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ class SPA : public AtmosphereProcess
7979

8080
// IO structure to read in data for standard grids (keep it around to avoid re-creating PIO decomps)
8181
std::shared_ptr<AtmosphereInput> SPADataReader;
82-
// Similar to above, but stores info to read data for IOP grid
83-
std::shared_ptr<SPAFunc::IOPReader> SPAIOPDataReader;
8482

8583
// Structures to store the data used for interpolation
8684
std::shared_ptr<AbstractRemapper> SPAHorizInterp;

components/eamxx/src/physics/spa/spa_functions.hpp

Lines changed: 11 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ struct SPAFunctions
3030

3131
using gid_type = AbstractGrid::gid_type;
3232

33-
using iop_data_ptr_type = std::shared_ptr<control::IOPDataManager>;
34-
3533
template <typename S>
3634
using view_1d = typename KT::template view_1d<S>;
3735
template <typename S>
@@ -127,33 +125,6 @@ struct SPAFunctions
127125
SPAData data; // All spa fields
128126
}; // SPAInput
129127

130-
struct IOPReader {
131-
IOPReader (iop_data_ptr_type& iop_,
132-
const std::string file_name_,
133-
const std::vector<Field>& io_fields_,
134-
const std::shared_ptr<const AbstractGrid>& io_grid_)
135-
: iop_data_manager(iop_), file_name(file_name_)
136-
{
137-
field_mgr = std::make_shared<FieldManager>(io_grid_);
138-
for (auto& f : io_fields_) {
139-
field_mgr->add_field(f);
140-
field_names.push_back(f.name());
141-
}
142-
143-
// Set IO info for this grid and file in IOP object
144-
iop_data_manager->setup_io_info(file_name, io_grid_);
145-
}
146-
147-
void read_variables(const int time_index, const util::TimeStamp& ts) {
148-
iop_data_manager->read_fields_from_file_for_iop(file_name, field_names, ts, field_mgr, time_index);
149-
}
150-
151-
iop_data_ptr_type iop_data_manager;
152-
std::string file_name;
153-
std::vector<std::string> field_names;
154-
std::shared_ptr<FieldManager> field_mgr;
155-
};
156-
157128
// The output is really just SPAData, but for clarity it might
158129
// help to see a SPAOutput along a SPAInput in functions signatures
159130
using SPAOutput = SPAData;
@@ -166,19 +137,13 @@ struct SPAFunctions
166137
const std::shared_ptr<const AbstractGrid>& model_grid,
167138
const std::string& spa_data_file,
168139
const std::string& map_file,
169-
const bool use_iop = false);
140+
const std::shared_ptr<control::IOPDataManager>& iop_data_mgr = nullptr);
170141

171142
static std::shared_ptr<AtmosphereInput>
172143
create_spa_data_reader (
173144
const std::shared_ptr<AbstractRemapper>& horiz_remapper,
174145
const std::string& spa_data_file);
175146

176-
static std::shared_ptr<IOPReader>
177-
create_spa_data_reader (
178-
iop_data_ptr_type& iop_data_manager,
179-
const std::shared_ptr<AbstractRemapper>& horiz_remapper,
180-
const std::string& spa_data_file);
181-
182147
static void spa_main(
183148
const SPATimeState& time_state,
184149
const view_2d<const Spack>& p_tgt,
@@ -189,21 +154,18 @@ struct SPAFunctions
189154
const SPAOutput& data_out);
190155

191156
static void update_spa_data_from_file(
192-
std::shared_ptr<AtmosphereInput>& scorpio_reader,
193-
std::shared_ptr<IOPReader>& iop_reader,
194-
const util::TimeStamp& ts,
195-
const int time_index, // zero-based
196-
AbstractRemapper& spa_horiz_interp,
197-
SPAInput& spa_input);
157+
AtmosphereInput& scorpio_reader,
158+
const int time_index, // zero-based
159+
AbstractRemapper& spa_horiz_interp,
160+
SPAInput& spa_input);
198161

199162
static void update_spa_timestate(
200-
std::shared_ptr<AtmosphereInput>& scorpio_reader,
201-
std::shared_ptr<IOPReader>& iop_reader,
202-
const util::TimeStamp& ts,
203-
AbstractRemapper& spa_horiz_interp,
204-
SPATimeState& time_state,
205-
SPAInput& spa_beg,
206-
SPAInput& spa_end);
163+
AtmosphereInput& scorpio_reader,
164+
const util::TimeStamp& ts,
165+
AbstractRemapper& spa_horiz_interp,
166+
SPATimeState& time_state,
167+
SPAInput& spa_beg,
168+
SPAInput& spa_end);
207169

208170
// The following three are called during spa_main
209171
static void perform_time_interpolation (

0 commit comments

Comments
 (0)