Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow timestep to be set when XIOS handler is created #750

Merged
merged 7 commits into from
Dec 10, 2024
Merged
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
40 changes: 30 additions & 10 deletions core/src/Xios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @file Xios.cpp
* @author Tom Meltzer <tdm39@cam.ac.uk>
* @author Joe Wallwork <jw2423@cam.ac.uk>
* @date 19 Nov 2024
* @date 09 Dec 2024
* @brief XIOS interface implementation
* @details
*
Expand Down Expand Up @@ -45,13 +45,20 @@ void enableXios()
}

/*!
* Constructor
* Constructor: Configure an XIOS server
*
* Configure an XIOS server
* @param dt Timestep to use for the model
* @param contextid ID for the XIOS context
* @param starttime Datetime string for the start of the simulation
* @param calendartype Type of calendar to use
*/
Xios::Xios(const std::string contextId)
Xios::Xios(const std::string dt, const std::string contextid, const std::string starttime,
const std::string calendartype)
{
_contextId = contextId;
timestep = Duration(dt);
startTime = TimePoint(starttime);
contextId = contextid;
calendarType = calendartype;
configure();
}

Expand Down Expand Up @@ -99,7 +106,7 @@ void Xios::configure()
}

//! Configure calendar settings
void Xios::configureServer(const std::string calendarType)
void Xios::configureServer()
{
// Initialize XIOS Server process and store MPI communicator
clientId = "client";
Expand All @@ -112,14 +119,18 @@ void Xios::configureServer(const std::string calendarType)
MPI_Comm_size(clientComm, &mpi_size);

// Initialize 'nextSIM-DG' context
cxios_context_initialize(_contextId.c_str(), _contextId.length(), &clientComm_F);
cxios_context_initialize(contextId.c_str(), contextId.length(), &clientComm_F);

// Initialize calendar wrapper for 'nextSIM-DG' context
cxios_get_current_calendar_wrapper(&clientCalendar);
cxios_set_calendar_wrapper_type(clientCalendar, calendarType.c_str(), calendarType.length());
cxios_duration timestep { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 };
cxios_set_calendar_wrapper_timestep(clientCalendar, timestep);
cxios_set_calendar_wrapper_timestep(clientCalendar, convertDurationToXios(timestep));
cxios_create_calendar(clientCalendar);
cxios_update_calendar_timestep(clientCalendar);

// Set default calendar origin and start
setCalendarOrigin(TimePoint("1970-01-01T00:00:00Z")); // Unix epoch
setCalendarStart(TimePoint(startTime));
}

/*!
Expand All @@ -140,7 +151,7 @@ int Xios::getClientMPIRank() { return mpi_rank; }
bool Xios::isInitialized()
{
bool init = false;
cxios_context_is_initialized(_contextId.c_str(), _contextId.length(), &init);
cxios_context_is_initialized(contextId.c_str(), contextId.length(), &init);
return init;
}

Expand Down Expand Up @@ -279,6 +290,9 @@ std::string Xios::getCalendarType()
*/
TimePoint Xios::getCalendarOrigin()
{
if (!cxios_is_defined_calendar_wrapper_time_origin(clientCalendar)) {
throw std::runtime_error("Xios: Calendar origin has not been set");
}
cxios_date calendar_origin;
cxios_get_calendar_wrapper_date_time_origin(clientCalendar, &calendar_origin);
return TimePoint(convertXiosDatetimeToString(calendar_origin, true));
Expand All @@ -291,6 +305,9 @@ TimePoint Xios::getCalendarOrigin()
*/
TimePoint Xios::getCalendarStart()
{
if (!cxios_is_defined_calendar_wrapper_start_date(clientCalendar)) {
throw std::runtime_error("Xios: Calendar start date has not been set");
}
cxios_date calendar_start;
cxios_get_calendar_wrapper_date_start_date(clientCalendar, &calendar_start);
return TimePoint(convertXiosDatetimeToString(calendar_start, true));
Expand All @@ -303,6 +320,9 @@ TimePoint Xios::getCalendarStart()
*/
Duration Xios::getCalendarTimestep()
{
if (!cxios_is_defined_calendar_wrapper_timestep(clientCalendar)) {
throw std::runtime_error("Xios: Calendar timestep has not been set");
}
cxios_duration calendar_timestep;
cxios_get_calendar_wrapper_timestep(clientCalendar, &calendar_timestep);
return convertDurationFromXios(calendar_timestep);
Expand Down
13 changes: 9 additions & 4 deletions core/src/include/Xios.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @file Xios.hpp
* @author Tom Meltzer <tdm39@cam.ac.uk>
* @author Joe Wallwork <jw2423@cam.ac.uk>
* @date 18 Nov 2024
* @date 04 Dec 2024
* @brief XIOS interface header
* @details
*
Expand Down Expand Up @@ -31,7 +31,9 @@ void enableXios();

class Xios : public Configured<Xios> {
public:
Xios(const std::string contextId = "nextSIM-DG");
Xios(const std::string dt = "P0-0T01:00:00", const std::string contextid = "nextSIM-DG",
const std::string starttime = "1970-01-01T00:00:00Z",
const std::string calendartype = "Gregorian");
~Xios();

/* Initialization and finalization */
Expand All @@ -42,7 +44,7 @@ class Xios : public Configured<Xios> {

/* Configuration */
void configure() override;
void configureServer(const std::string calendarType = "Gregorian");
void configureServer();

/* MPI decomposition */
int getClientMPISize();
Expand Down Expand Up @@ -146,7 +148,10 @@ class Xios : public Configured<Xios> {
bool isEnabled;

std::string clientId;
std::string _contextId;
std::string calendarType;
std::string contextId;
Duration timestep;
TimePoint startTime;
MPI_Comm clientComm;
MPI_Fint clientComm_F;
MPI_Fint nullComm_F;
Expand Down
5 changes: 4 additions & 1 deletion core/src/include/xios_c_interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @file xios_c_interface.hpp
* @author Tom Meltzer <tdm39@cam.ac.uk>
* @author Joe Wallwork <jw2423@cam.ac.uk>
* @date 12 August 2024
* @date 09 Dec 2024
* @brief C interface for XIOS library
* @details
* This interface is based on an earlier version provided by Laurent as part of
Expand Down Expand Up @@ -59,13 +59,16 @@ void cxios_get_calendar_wrapper_date_time_origin(
void cxios_get_calendar_wrapper_type(
xios::CCalendarWrapper* calendarWrapper_hdl, const char* type, int type_size);
void cxios_get_current_date(cxios_date* date);
bool cxios_is_defined_calendar_wrapper_time_origin(xios::CCalendarWrapper* calendar_wrapper_hdl);
bool cxios_is_defined_calendar_wrapper_start_date(xios::CCalendarWrapper* calendar_wrapper_hdl);
void cxios_update_calendar(int step);

// timestep methods
void cxios_set_calendar_wrapper_timestep(
xios::CCalendarWrapper* calendar_wrapper_hdl, cxios_duration timestep_c);
void cxios_get_calendar_wrapper_timestep(
xios::CCalendarWrapper* calendar_wrapper_hdl, cxios_duration* timestep_c);
bool cxios_is_defined_calendar_wrapper_timestep(xios::CCalendarWrapper* calendar_wrapper_hdl);
void cxios_update_calendar_timestep(xios::CCalendarWrapper* calendarWrapper_hdl);

// axis group methods
Expand Down
5 changes: 1 addition & 4 deletions core/test/XiosAxis_test.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* @file XiosAxis_test.cpp
* @author Joe Wallwork <jw2423@cam.ac.uk>
* @date 19 Nov 2024
* @date 03 Dec 2024
* @brief Tests for XIOS axes
* @details
* This test is designed to test axis functionality of the C++ interface
Expand Down Expand Up @@ -34,9 +34,6 @@ MPI_TEST_CASE("TestXiosAxis", 2)
REQUIRE(xios_handler.isInitialized());
REQUIRE(xios_handler.getClientMPISize() == 2);

// Set timestep as a minimum
xios_handler.setCalendarTimestep(Duration("P0-0T01:00:00"));

// --- Tests for axis API
const std::string axisId = { "axis_A" };
REQUIRE_THROWS_WITH(xios_handler.getAxisSize(axisId), "Xios: Undefined axis 'axis_A'");
Expand Down
9 changes: 6 additions & 3 deletions core/test/XiosCalendar_test.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* @file XiosCalendar_test.cpp
* @author Joe Wallwork <jw2423@cam.ac.uk>
* @date 19 Nov 2024
* @date 04 Dec 2024
* @brief Tests for XIOS calandars
* @details
* This test is designed to test calendar functionality of the C++ interface
Expand Down Expand Up @@ -38,20 +38,23 @@ MPI_TEST_CASE("TestXiosInitialization", 2)
// Calendar type
REQUIRE(xios_handler.getCalendarType() == "Gregorian");
// Calendar origin
REQUIRE(xios_handler.getCalendarOrigin().format() == "1970-01-01T00:00:00Z"); // Default
TimePoint origin("2020-01-23T00:08:15Z");
xios_handler.setCalendarOrigin(origin);
REQUIRE(origin == xios_handler.getCalendarOrigin());
REQUIRE(origin.format() == "2020-01-23T00:08:15Z");
// Calendar start
REQUIRE(xios_handler.getCalendarStart().format() == "1970-01-01T00:00:00Z"); // Default
TimePoint start("2023-03-17T17:11:00Z");
xios_handler.setCalendarStart(start);
REQUIRE(start == xios_handler.getCalendarStart());
REQUIRE(start.format() == "2023-03-17T17:11:00Z");
// Timestep
REQUIRE(xios_handler.getCalendarTimestep().seconds() == 3600.0); // Default
Duration timestep("P0-0T01:30:00");
REQUIRE(timestep.seconds() == doctest::Approx(5400.0));
REQUIRE(timestep.seconds() == 5400.0);
xios_handler.setCalendarTimestep(timestep);
REQUIRE(xios_handler.getCalendarTimestep().seconds() == doctest::Approx(5400.0));
REQUIRE(xios_handler.getCalendarTimestep().seconds() == 5400.0);

xios_handler.close_context_definition();

Expand Down
5 changes: 1 addition & 4 deletions core/test/XiosDomain_test.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* @file XiosDomain_test.cpp
* @author Joe Wallwork <jw2423@cam.ac.uk>
* @date 19 Nov 2024
* @date 03 Dec 2024
* @brief Tests for XIOS domains
* @details
* This test is designed to test domain functionality of the C++ interface
Expand Down Expand Up @@ -36,9 +36,6 @@ MPI_TEST_CASE("TestXiosDomain", 2)
REQUIRE(size == 2);
const size_t rank = xios_handler.getClientMPIRank();

// Set timestep as a minimum
xios_handler.setCalendarTimestep(Duration("P0-0T01:00:00"));

// --- Tests for domain API
const std::string domainId = "domain_A";
REQUIRE_THROWS_WITH(xios_handler.getDomainType(domainId), "Xios: Undefined domain 'domain_A'");
Expand Down
8 changes: 2 additions & 6 deletions core/test/XiosField_test.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* @file XiosField_test.cpp
* @author Joe Wallwork <jw2423@cam.ac.uk>
* @date 19 Nov 2024
* @date 03 Dec 2024
* @brief Tests for XIOS axes
* @details
* This test is designed to test axis functionality of the C++ interface
Expand Down Expand Up @@ -36,10 +36,6 @@ MPI_TEST_CASE("TestXiosField", 2)
REQUIRE(size == 2);
const size_t rank = xios_handler.getClientMPIRank();

// Set timestep as a minimum
Duration timestep("P0-0T01:00:00");
xios_handler.setCalendarTimestep(timestep);

// Create an axis with two points
xios_handler.createAxis("axis_A");
xios_handler.setAxisValues("axis_A", { 0.0, 1.0 });
Expand Down Expand Up @@ -76,7 +72,7 @@ MPI_TEST_CASE("TestXiosField", 2)
xios_handler.setFieldReadAccess(fieldId, readAccess);
REQUIRE(xios_handler.getFieldReadAccess(fieldId));
// Frequency offset
Duration freqOffset = timestep;
Duration freqOffset = xios_handler.getCalendarTimestep();
xios_handler.setFieldFreqOffset(fieldId, freqOffset);
// TODO: Overload == for Duration
REQUIRE(xios_handler.getFieldFreqOffset(fieldId).seconds() == freqOffset.seconds());
Expand Down
9 changes: 3 additions & 6 deletions core/test/XiosFile_test.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* @file XiosFile_test.cpp
* @author Joe Wallwork <jw2423@cam.ac.uk>
* @date 19 Nov 2024
* @date 03 Dec 2024
* @brief Tests for XIOS axes
* @details
* This test is designed to test axis functionality of the C++ interface
Expand Down Expand Up @@ -32,16 +32,12 @@ MPI_TEST_CASE("TestXiosFile", 2)
enableXios();

// Initialize an Xios instance called xios_handler
Xios xios_handler;
Xios xios_handler("P0-0T01:30:00");
REQUIRE(xios_handler.isInitialized());
const size_t size = xios_handler.getClientMPISize();
REQUIRE(size == 2);
const size_t rank = xios_handler.getClientMPIRank();

// Set timestep as a minimum
Duration timestep("P0-0T01:30:00");
xios_handler.setCalendarTimestep(timestep);

// Create a simple axis with two points
xios_handler.createAxis("axis_A");
xios_handler.setAxisValues("axis_A", { 0.0, 1.0 });
Expand Down Expand Up @@ -73,6 +69,7 @@ MPI_TEST_CASE("TestXiosFile", 2)
// Output frequency
REQUIRE_THROWS_WITH(xios_handler.getFileOutputFreq(fileId),
"Xios: Undefined output frequency for file 'output'");
Duration timestep = xios_handler.getCalendarTimestep();
xios_handler.setFileOutputFreq(fileId, timestep);
REQUIRE(xios_handler.getFileOutputFreq(fileId).seconds() == 1.5 * 60 * 60);
// Split frequency
Expand Down
5 changes: 1 addition & 4 deletions core/test/XiosGrid_test.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* @file XiosGrid_test.cpp
* @author Joe Wallwork <jw2423@cam.ac.uk>
* @date 19 Nov 2024
* @date 03 Dec 2024
* @brief Tests for XIOS axes
* @details
* This test is designed to test axis functionality of the C++ interface
Expand Down Expand Up @@ -35,9 +35,6 @@ MPI_TEST_CASE("TestXiosGrid", 2)
REQUIRE(size == 2);
const size_t rank = xios_handler.getClientMPIRank();

// Set timestep as a minimum
xios_handler.setCalendarTimestep(Duration("P0-0T01:30:00"));

// Create a 4x2 horizontal domain with a partition halving the x-extent
xios_handler.createDomain("domain_XY");
xios_handler.setDomainType("domain_XY", "rectilinear");
Expand Down
11 changes: 3 additions & 8 deletions core/test/XiosReadWrite_test.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* @file XiosReadWrite_test.cpp
* @author Joe Wallwork <jw2423@cam.ac.uk>
* @date 19 Nov 2024
* @date 04 Dec 2024
* @brief Tests for XIOS write method
* @details
* This test is designed to test the read and write methods of the C++
Expand Down Expand Up @@ -61,18 +61,12 @@ Xios setupXiosHandler(int dim, bool read)
} else {
label = "write";
}
Xios xios_handler(formatId(label, dim));
Xios xios_handler("P0-0T01:30:00", formatId(label, dim), "2023-03-17T17:11:00Z");
REQUIRE(xios_handler.isInitialized());
const size_t size = xios_handler.getClientMPISize();
REQUIRE(size == 2);
const size_t rank = xios_handler.getClientMPIRank();

// Calendar setup
xios_handler.setCalendarOrigin(TimePoint("2020-01-23T00:08:15Z"));
xios_handler.setCalendarStart(TimePoint("2023-03-17T17:11:00Z"));
Duration timestep("P0-0T01:30:00");
xios_handler.setCalendarTimestep(timestep);

// Set ModelArray dimensions
const size_t nx_glo = 4;
const size_t ny_glo = 2;
Expand Down Expand Up @@ -111,6 +105,7 @@ Xios setupXiosHandler(int dim, bool read)
xios_handler.setFieldOperation(fieldId, "instant");
xios_handler.setFieldGridRef(fieldId, formatId("grid", dim));
xios_handler.setFieldReadAccess(fieldId, read);
Duration timestep = xios_handler.getCalendarTimestep();
xios_handler.setFieldFreqOffset(fieldId, timestep);

// Create an file for reading/writing of field data
Expand Down
Loading