Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions core/src/ModelMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,25 @@ ModelState& ModelMetadata::affixCoordinates(ModelState& state) const
return state;
}

// Helper function for checking that the model start and timestep align with midnight and the hour.
void checkStartStep(const std::string start_str, double step)
{
if (start_str != "T00:00:00Z") {
throw std::runtime_error("ModelMetadata::setTimes: model.start must be at midnight.");
}
if (step < 3600) {
if (std::fmod(3600, step) != 0.) {
throw std::runtime_error(
"ModelMetadata::setTimes: model.time_step must be aligned with the hour.");
}
}
}

void ModelMetadata::setTimes(const TimePoint& start, const TimePoint& stop, const Duration& step)
{
#ifdef USE_XIOS
checkStartStep(start.format(TimePoint::hmsFormat), step.seconds());
#endif
this->start = start;
this->stop = stop;
this->step = step;
Expand All @@ -377,6 +394,9 @@ void ModelMetadata::setTimes(const TimePoint& start, const TimePoint& stop, cons

void ModelMetadata::setTimes(const TimePoint& start, const Duration& runLen, const Duration& step)
{
#ifdef USE_XIOS
checkStartStep(start.format(TimePoint::hmsFormat), step.seconds());
#endif
this->start = start;
this->stop = start + runLen;
this->step = step;
Expand Down
4 changes: 2 additions & 2 deletions core/test/XiosAxis_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ MPI_TEST_CASE("TestXiosAxis", 3)
{
std::stringstream config;
config << "[model]" << std::endl;
config << "start = 2023-03-17T17:11:00Z" << std::endl;
config << "stop = 2023-03-17T18:11:00Z" << std::endl;
config << "start = 2023-03-17T00:00:00Z" << std::endl;
config << "stop = 2023-03-17T00:00:00Z" << std::endl;
config << "time_step = P0-0T01:00:00" << std::endl;
config << "partition_file = xios_test_partition_metadata_3.nc" << std::endl;
std::unique_ptr<std::istream> pcstream(new std::stringstream(config.str()));
Expand Down
14 changes: 7 additions & 7 deletions core/test/XiosCalendar_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ MPI_TEST_CASE("TestXiosCalendar", 1)
{
std::stringstream config;
config << "[model]" << std::endl;
config << "start = 2023-03-17T17:11:00Z" << std::endl;
config << "stop = 2023-03-17T18:11:00Z" << std::endl;
config << "start = 2023-03-17T00:00:00Z" << std::endl;
config << "stop = 2023-03-17T00:00:00Z" << std::endl;
config << "time_step = P0-0T01:00:00" << std::endl;
config << "partition_file = xios_test_partition_metadata_1.nc" << std::endl;
std::unique_ptr<std::istream> pcstream(new std::stringstream(config.str()));
Expand All @@ -53,11 +53,11 @@ MPI_TEST_CASE("TestXiosCalendar", 1)

// --- Tests for calendar API
// Calendar start
REQUIRE(xiosHandler.getCalendarStart().format() == "2023-03-17T17:11:00Z"); // Set in config
TimePoint start("2023-03-17T20:11:00Z");
REQUIRE(xiosHandler.getCalendarStart().format() == "2023-03-17T00:00:00Z"); // Set in config
TimePoint start("2023-03-18T00:00:00Z");
xiosHandler.setCalendarStart(start);
REQUIRE(start == xiosHandler.getCalendarStart());
REQUIRE(start.format() == "2023-03-17T20:11:00Z");
REQUIRE(start.format() == "2023-03-18T00:00:00Z");
// Timestep
ModelMetadata& metadata = ModelMetadata::getInstance();
REQUIRE(metadata.stepLength().seconds() == 3600.0); // Read from config
Expand All @@ -67,12 +67,12 @@ MPI_TEST_CASE("TestXiosCalendar", 1)

// --- Tests for getCurrentDate method
REQUIRE(xiosHandler.getCalendarStep() == 0);
REQUIRE(xiosHandler.getCurrentDate().format() == "2023-03-17T20:11:00Z");
REQUIRE(xiosHandler.getCurrentDate().format() == "2023-03-18T00:00:00Z");

// -- Tests that the timestep is set up correctly
xiosHandler.setCalendarStep(1);
REQUIRE(xiosHandler.getCalendarStep() == 1);
REQUIRE(xiosHandler.getCurrentDate().format() == "2023-03-17T21:11:00Z");
REQUIRE(xiosHandler.getCurrentDate().format() == "2023-03-18T01:00:00Z");

xiosHandler.context_finalize();
Finalizer::finalize();
Expand Down
10 changes: 5 additions & 5 deletions core/test/XiosReadDiagnostic_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

const std::string testFilesDir = TEST_FILES_DIR;
const std::string diagnosticFilename
= testFilesDir + "/diagnostic_2023-03-17T17:11:00Z-2023-03-17T20:10:59Z.nc";
= testFilesDir + "/diagnostic_2023-03-17T00:00:00Z-2023-03-17T02:59:59Z.nc";

static const int DGCOMP = 6;
static const int DGSTRESSCOMP = 8;
Expand All @@ -37,8 +37,8 @@ MPI_TEST_CASE("TestXiosReadDiagnostic", 3)
{
std::stringstream config;
config << "[model]" << std::endl;
config << "start = 2023-03-17T17:11:00Z" << std::endl;
config << "stop = 2023-03-17T23:11:00Z" << std::endl;
config << "start = 2023-03-17T00:00:00Z" << std::endl;
config << "stop = 2023-03-17T00:00:00Z" << std::endl;
config << "time_step = P0-0T01:30:00" << std::endl;
config << "init_file = " << diagnosticFilename << std::endl;
config << "restart_period = P0-0T03:00:00" << std::endl;
Expand Down Expand Up @@ -91,8 +91,8 @@ MPI_TEST_CASE("TestXiosReadDiagnostic", 3)
int rank;
MPI_Comm_rank(test_comm, &rank);
if (rank == 0) {
std::filesystem::remove("diagnostic_2023-03-17T17:11:00Z-2023-03-17T20:10:59Z.nc");
std::filesystem::remove("diagnostic_2023-03-17T20:11:00Z-2023-03-17T23:10:59Z.nc");
std::filesystem::remove("diagnostic_2023-03-17T00:00:00Z-2023-03-17T02:59:59Z.nc");
std::filesystem::remove("diagnostic_2023-03-17T03:00:00Z-2023-03-17T05:59:59Z.nc");
}

xiosHandler.context_finalize();
Expand Down
12 changes: 6 additions & 6 deletions core/test/XiosReadRestart_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

const std::string testFilesDir = TEST_FILES_DIR;
const std::string restartFilename
= testFilesDir + "/restart_2023-03-17T17:11:00Z-2023-03-17T20:10:59Z.nc";
= testFilesDir + "/restart_2023-03-17T00:00:00Z-2023-03-17T02:59:59Z.nc";

static const int DGCOMP = 6;
static const int DGSTRESSCOMP = 8;
Expand All @@ -35,8 +35,8 @@ MPI_TEST_CASE("TestXiosReadRestart", 2)
{
std::stringstream config;
config << "[model]" << std::endl;
config << "start = 2023-03-17T17:11:00Z" << std::endl;
config << "stop = 2023-03-17T23:11:00Z" << std::endl;
config << "start = 2023-03-17T00:00:00Z" << std::endl;
config << "stop = 2023-03-17T00:00:00Z" << std::endl;
config << "time_step = P0-0T01:30:00" << std::endl;
config << "init_file = " << restartFilename << std::endl;
config << "restart_period = P0-0T03:00:00" << std::endl;
Expand Down Expand Up @@ -79,7 +79,7 @@ MPI_TEST_CASE("TestXiosReadRestart", 2)
// StructureFactory::stateFromFile()
int rank;
MPI_Comm_rank(test_comm, &rank);
float ts = 2; // Corresponds to 2023-03-17T20:10:59Z
float ts = 2; // Corresponds to 2023-03-17T02:59:59Z
ModelState modelstate = StructureFactory::stateFromFile(restartFilename);
ModelArray& mask = modelstate.data.at(maskName);
for (size_t j = 0; j < ny; ++j) {
Expand Down Expand Up @@ -172,8 +172,8 @@ MPI_TEST_CASE("TestXiosReadRestart", 2)

// Remove the restart files
if (rank == 0) {
std::filesystem::remove("restart_2023-03-17T17:11:00Z-2023-03-17T20:10:59Z.nc");
std::filesystem::remove("restart_2023-03-17T20:11:00Z-2023-03-17T23:10:59Z.nc");
std::filesystem::remove("restart_2023-03-17T00:00:00Z-2023-03-17T02:59:59Z.nc");
std::filesystem::remove("restart_2023-03-17T03:00:00Z-2023-03-17T05:59:59Z.nc");
}

xiosHandler.context_finalize();
Expand Down
12 changes: 6 additions & 6 deletions core/test/XiosReadWriteRestart_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ MPI_TEST_CASE("TestXiosReadWriteRestart", 2)
{
std::stringstream config;
config << "[model]" << std::endl;
config << "start = 2023-03-17T17:11:00Z" << std::endl;
config << "stop = 2023-03-17T23:11:00Z" << std::endl;
config << "start = 2023-03-17T00:00:00Z" << std::endl;
config << "stop = 2023-03-17T00:00:00Z" << std::endl;
config << "time_step = P0-0T01:30:00" << std::endl;
config << "init_file = " << inputFilename << std::endl;
config << "restart_file = " << outputFilename << std::endl;
Expand Down Expand Up @@ -95,11 +95,11 @@ MPI_TEST_CASE("TestXiosReadWriteRestart", 2)
}

// Check the files have indeed been created then remove them
REQUIRE(std::filesystem::exists("readwrite_2023-03-17T17:11:00Z-2023-03-17T20:10:59Z.nc"));
REQUIRE(std::filesystem::exists("readwrite_2023-03-17T20:11:00Z-2023-03-17T23:10:59Z.nc"));
REQUIRE(std::filesystem::exists("readwrite_2023-03-17T00:00:00Z-2023-03-17T02:59:59Z.nc"));
REQUIRE(std::filesystem::exists("readwrite_2023-03-17T03:00:00Z-2023-03-17T05:59:59Z.nc"));
if (rank == 0) {
std::filesystem::remove("readwrite_2023-03-17T17:11:00Z-2023-03-17T20:10:59Z.nc");
std::filesystem::remove("readwrite_2023-03-17T20:11:00Z-2023-03-17T23:10:59Z.nc");
std::filesystem::remove("readwrite_2023-03-17T00:00:00Z-2023-03-17T02:59:59Z.nc");
std::filesystem::remove("readwrite_2023-03-17T03:00:00Z-2023-03-17T05:59:59Z.nc");
}

xiosHandler.context_finalize();
Expand Down
8 changes: 4 additions & 4 deletions core/test/XiosWriteDiagnostic_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ MPI_TEST_CASE("TestXiosWriteDiagnostic", 2)
{
std::stringstream config;
config << "[model]" << std::endl;
config << "start = 2023-03-17T17:11:00Z" << std::endl;
config << "stop = 2023-03-17T23:11:00Z" << std::endl;
config << "start = 2023-03-17T00:00:00Z" << std::endl;
config << "stop = 2023-03-17T06:00:00Z" << std::endl;
config << "time_step = P0-0T01:30:00" << std::endl;
config << "init_file = " << inputFilename << std::endl;
config << "partition_file = xios_test_partition_metadata_2.nc" << std::endl;
Expand Down Expand Up @@ -118,8 +118,8 @@ MPI_TEST_CASE("TestXiosWriteDiagnostic", 2)
// Check the files have indeed been created
// NOTE: Don't remove them because their contents are checked in
// XiosReadxios_test_diagnostic_test
REQUIRE(std::filesystem::exists("diagnostic_2023-03-17T17:11:00Z-2023-03-17T20:10:59Z.nc"));
REQUIRE(std::filesystem::exists("diagnostic_2023-03-17T20:11:00Z-2023-03-17T23:10:59Z.nc"));
REQUIRE(std::filesystem::exists("diagnostic_2023-03-17T00:00:00Z-2023-03-17T02:59:59Z.nc"));
REQUIRE(std::filesystem::exists("diagnostic_2023-03-17T03:00:00Z-2023-03-17T05:59:59Z.nc"));

xiosHandler.context_finalize();
Finalizer::finalize();
Expand Down
8 changes: 4 additions & 4 deletions core/test/XiosWriteRestart_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ MPI_TEST_CASE("TestXiosWriteRestart", 2)
{
std::stringstream config;
config << "[model]" << std::endl;
config << "start = 2023-03-17T17:11:00Z" << std::endl;
config << "stop = 2023-03-17T23:11:00Z" << std::endl;
config << "start = 2023-03-17T00:00:00Z" << std::endl;
config << "stop = 2023-03-17T00:00:00Z" << std::endl;
config << "time_step = P0-0T01:30:00" << std::endl;
config << "init_file = " << inputFilename << std::endl;
config << "restart_file = " << outputFilename << std::endl;
Expand Down Expand Up @@ -248,8 +248,8 @@ MPI_TEST_CASE("TestXiosWriteRestart", 2)

// Check the files have indeed been created
// NOTE: Don't remove them because their contents are checked in XiosReadRestart_test
REQUIRE(std::filesystem::exists("restart_2023-03-17T17:11:00Z-2023-03-17T20:10:59Z.nc"));
REQUIRE(std::filesystem::exists("restart_2023-03-17T20:11:00Z-2023-03-17T23:10:59Z.nc"));
REQUIRE(std::filesystem::exists("restart_2023-03-17T00:00:00Z-2023-03-17T02:59:59Z.nc"));
REQUIRE(std::filesystem::exists("restart_2023-03-17T03:00:00Z-2023-03-17T05:59:59Z.nc"));

xiosHandler.context_finalize();
Finalizer::finalize();
Expand Down
9 changes: 9 additions & 0 deletions docs/xios.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ used to configure the calendar used by XIOS. For example,
stop = 1970-01-01T01:00:00Z
time_step = P0-0T01:00:00

.. note::

The XIOS I/O implementation makes two assumptions:

1. The simulation starts at midnight.
2. The timestep aligns with the hour.

If these conditions aren't met then an error will be thrown.

The filename and period for restart files is configured in the same way as when
building without XIOS. That is, the ``model`` section should include
``init_file``, ``restart_file`` and ``restart_period`` entries:
Expand Down
21 changes: 12 additions & 9 deletions physics/src/modules/AtmosphereBoundaryModule/ERA5Atmosphere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,18 @@ void ERA5Atmosphere::update(const TimestepTime& tst)
std::set<std::string> forcings
= { "tair", "dew2m", "pair", "sw_in", "lw_in", "wind_speed", "u", "v" };

ModelState state = ParaGridIO::readForcingTimeStatic(forcings, tst.start, filePath);
tair = state.data.at("tair");
tdew = state.data.at("dew2m");
pair = state.data.at("pair");
sw_in = state.data.at("sw_in");
lw_in = state.data.at("lw_in");
wind = state.data.at("wind_speed");
uwind = state.data.at("u");
vwind = state.data.at("v");
// Read ERA5 forcings at the top of the hour
if (std::fmod((tst.start - TimePoint()).seconds(), 3600.) == 0.) {
forcingState = ParaGridIO::readForcingTimeStatic(forcings, tst.start, filePath);
}
tair = forcingState.data.at("tair");
tdew = forcingState.data.at("dew2m");
pair = forcingState.data.at("pair");
sw_in = forcingState.data.at("sw_in");
lw_in = forcingState.data.at("lw_in");
wind = forcingState.data.at("wind_speed");
uwind = forcingState.data.at("u");
vwind = forcingState.data.at("v");
snow = 0; // FIXME get snow data
rain = 0; // FIXME get rain data

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class ERA5Atmosphere : public IAtmosphereBoundary, public Configured<ERA5Atmosph
// be static.
static std::string filePath;

ModelState forcingState;

HField tair;
HField tdew;
HField pair;
Expand Down
19 changes: 11 additions & 8 deletions physics/src/modules/OceanBoundaryModule/TOPAZOcean.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,17 @@ void TOPAZOcean::updateBefore(const TimestepTime& tst)
{
std::set<std::string> forcings = { sstName, sssName, mldName, uName, vName, sshName };

ModelState state = ParaGridIO::readForcingTimeStatic(forcings, tst.start, filePath);
sstExt = state.data.at(sstName);
sssExt = state.data.at(sssName);
mld = state.data.at(mldName);
u = state.data.at(uName);
v = state.data.at(vName);
if (state.data.count(sshName)) {
ssh = state.data.at(sshName);
// Read TOPAZ forcings at midnight
if (std::fmod((tst.start - TimePoint()).seconds(), 86400.) == 0.) {
forcingState = ParaGridIO::readForcingTimeStatic(forcings, tst.start, filePath);
}
sstExt = forcingState.data.at(sstName);
sssExt = forcingState.data.at(sssName);
mld = forcingState.data.at(mldName);
u = forcingState.data.at(uName);
v = forcingState.data.at(vName);
if (forcingState.data.count(sshName)) {
ssh = forcingState.data.at(sshName);
} else {
ssh = 0.;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class TOPAZOcean : public IOceanBoundary, public Configured<TOPAZOcean> {
// be static.
static std::string filePath;

ModelState forcingState;

HField sstExt;
HField sssExt;

Expand Down
Loading