Skip to content
Closed
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
31 changes: 19 additions & 12 deletions core/src/Iterator.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*!
* @author Tim Spain <timothy.spain@nersc.no>
* @author Joe Wallwork <jw2423@cam.ac.uk>
*/

#include "include/Iterator.hpp"
Expand All @@ -10,37 +11,43 @@ namespace Nextsim {

void Iterator::setStartStopStep(TimePoint startTime, TimePoint stopTime, Duration timestep)
{
this->startTime = startTime;
this->stopTime = stopTime;
this->timestep = timestep;
TimePartition& timePartition = Iterator::getTimePartition();
timePartition.startTime = startTime;
timePartition.stopTime = stopTime;
timePartition.timestep = timestep;
}

TimePoint Iterator::parseAndSet(const std::string& startTimeStr, const std::string& stopTimeStr,
const std::string& durationStr, const std::string& stepStr)
{
TimePartition& timePartition = Iterator::getTimePartition();

std::stringstream ss(startTimeStr);
ss >> startTime;
ss >> timePartition.startTime;
ss = std::stringstream(stepStr);
ss >> timestep;
ss >> timePartition.timestep;
if (!durationStr.empty()) {
ss = std::stringstream(durationStr);
Duration duration;
ss >> duration;
stopTime = startTime + duration;
timePartition.stopTime = timePartition.startTime + duration;
} else {
ss = std::stringstream(stopTimeStr);
ss >> stopTime;
ss >> timePartition.stopTime;
}

return startTime;
return timePartition.startTime;
}

void Iterator::run()
{
iterant.start(startTime);
TimePartition& timePartition = Iterator::getTimePartition();

iterant.start(timePartition.startTime);

for (auto t = startTime; t < stopTime; t += timestep) {
TimestepTime tsTime = { t, timestep };
for (auto t = timePartition.startTime; t < timePartition.stopTime;
t += timePartition.timestep) {
TimestepTime tsTime = { t, timePartition.timestep };
try {
iterant.iterate(tsTime);
} catch (const std::exception& e) {
Expand All @@ -50,7 +57,7 @@ void Iterator::run()
}
}

iterant.stop(stopTime);
iterant.stop(timePartition.stopTime);
}

} /* namespace Nextsim */
13 changes: 9 additions & 4 deletions core/src/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,8 @@ Model::Model()

Model::~Model() { }

void Model::configure()
void Model::configureTime()
{
// Configure logging
Logged::configure();

// Store the start/stop/step configuration directly in ModelConfig before
// parsing these values to the numerical time values used by the model.
ModelConfig::startTimeStr
Expand All @@ -76,6 +73,14 @@ void Model::configure()
TimePoint timeNow = iterator.parseAndSet(ModelConfig::startTimeStr, ModelConfig::stopTimeStr,
ModelConfig::durationStr, ModelConfig::stepStr);
m_etadata.setTime(timeNow);
}

void Model::configure()
{
// Configure logging
Logged::configure();

configureTime();

// Configure the missing data value
MissingData::setValue(
Expand Down
43 changes: 7 additions & 36 deletions core/src/Xios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,50 +188,21 @@ void Xios::finalize()
}

/*!
* Overrides `Configure` method from `Configured`
*
* Configure the XIOS server if XIOS is enabled in the settings.
* @brief Overrides `Configure` method from `Configured`
*
* @details Configure the XIOS server if XIOS is enabled in the settings.
*/
void Xios::configure()
{
// Check if XIOS is enabled in the nextSIM-DG configuration
istringstream(Configured::getConfiguration(keyMap.at(ENABLED_KEY), std::string()))
>> std::boolalpha >> isEnabled;

// Extract the start time from the model configuration
// TODO: Deduce from Model.iterator rather than duplicating here?
std::string startTimeStr;
istringstream(Configured::getConfiguration(keyMap.at(STARTTIME_KEY), std::string()))
>> startTimeStr;
if (startTimeStr.length() == 0) {
Logged::warning("Xios: Setting default start: 1970-01-01T00:00:00Z");
startTimeStr = "1970-01-01T00:00:00Z";
}
startTime = TimePoint(startTimeStr);

// Extract the timestep from the model configuration
// TODO: Deduce from Model.iterator rather than duplicating here?
std::string timeStepStr;
istringstream(Configured::getConfiguration(keyMap.at(TIME_STEP_KEY), std::string()))
>> timeStepStr;
if (timeStepStr.length() == 0) {
Logged::warning("Xios: Setting default time_step: P0-0T01:00:00");
timeStepStr = "P0-0T01:00:00";
}
timestep = Duration(timeStepStr);

// Extract the stop time from the model configuration
// TODO: Deduce from Model.iterator rather than duplicating here?
std::string stopTimeStr;
istringstream(Configured::getConfiguration(keyMap.at(STOPTIME_KEY), std::string()))
>> stopTimeStr;
if (stopTimeStr.length() == 0) {
Logged::warning("Xios: Setting default stop: start time plus P0-0T01:00:00");
stopTime = startTime + timestep;
} else {
stopTime = TimePoint(stopTimeStr);
}
// Extract the time partition information from the Iterator class
Iterator::TimePartition& timePartition = Iterator::getTimePartition();
startTime = timePartition.startTime;
timestep = timePartition.timestep;
stopTime = timePartition.stopTime;

if (isEnabled) {
configureServer();
Expand Down
22 changes: 17 additions & 5 deletions core/src/include/Iterator.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*!
* @author Tim Spain <timothy.spain@nersc.no>
* @author Joe Wallwork <jw2423@cam.ac.uk>
*/

#ifndef SRC_INCLUDE_ITERATOR_HPP
Expand Down Expand Up @@ -34,7 +35,7 @@ class Iterator {
* @param stopTime Stop time point.
* @param timestep Timestep length.
*/
void setStartStopStep(TimePoint startTime, TimePoint stopTime, Duration timestep);
static void setStartStopStep(TimePoint startTime, TimePoint stopTime, Duration timestep);
/*!
* @brief Sets the time parameters as a start time, run length and timestep
* length.
Expand All @@ -57,16 +58,27 @@ class Iterator {
* @param durationStr string to parse for the model run duration.
* @param stepStr string to parse for the model time step length.
*/
TimePoint parseAndSet(const std::string& startTimeStr, const std::string& stopTimeStr,
static TimePoint parseAndSet(const std::string& startTimeStr, const std::string& stopTimeStr,
const std::string& durationStr, const std::string& stepStr);
//! Run the Iterant over the specified time period.
void run();

// A struct to hold information related to the time partition.
struct TimePartition {
TimePoint startTime;
TimePoint stopTime;
Duration timestep;
};

//! Returns a reference to the static TimePartition instance.
static TimePartition& getTimePartition()
{
static TimePartition instance;
return instance;
}

private:
Iterant& iterant;
TimePoint startTime;
TimePoint stopTime;
Duration timestep;

public:
//! A base class for classes that specify what happens during one timestep.
Expand Down
2 changes: 2 additions & 0 deletions core/src/include/Model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class Model : public Configured<Model> {
#endif
~Model(); // Finalize the model. Collect data and so on.

void configureTime();

void configure() override;

enum {
Expand Down
1 change: 1 addition & 0 deletions core/src/include/Xios.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#if USE_XIOS

#include "include/Configured.hpp"
#include "include/Iterator.hpp"
#include "include/Logged.hpp"
#include "include/ModelArray.hpp"
#include "include/ModelConfig.hpp"
Expand Down
42 changes: 35 additions & 7 deletions core/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,39 +83,59 @@ if(ENABLE_MPI)
target_compile_definitions(testXiosCalendar_MPI1 PRIVATE USE_XIOS)
target_include_directories(
testXiosCalendar_MPI1
PRIVATE "${MODEL_INCLUDE_DIR}" "${XIOS_INCLUDE_LIST}" "${ModulesRoot}/StructureModule"
PRIVATE
${PHYSICS_INCLUDE_DIRS}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to add these includes to each of the XIOS tests to avoid linking errors when including Model.hpp.

"${MODEL_INCLUDE_DIR}"
"${XIOS_INCLUDE_LIST}"
"${ModulesRoot}/StructureModule"
)
target_link_libraries(testXiosCalendar_MPI1 PRIVATE nextsimlib doctest::doctest)

add_executable(testXiosAxis_MPI3 "XiosAxis_test.cpp" "MainMPI.cpp")
target_compile_definitions(testXiosAxis_MPI3 PRIVATE USE_XIOS)
target_include_directories(
testXiosAxis_MPI3
PRIVATE "${MODEL_INCLUDE_DIR}" "${XIOS_INCLUDE_LIST}" "${ModulesRoot}/StructureModule"
PRIVATE
${PHYSICS_INCLUDE_DIRS}
"${MODEL_INCLUDE_DIR}"
"${XIOS_INCLUDE_LIST}"
"${ModulesRoot}/StructureModule"
)
target_link_libraries(testXiosAxis_MPI3 PRIVATE nextsimlib doctest::doctest)

add_executable(testXiosGrid_MPI2 "XiosGrid_test.cpp" "MainMPI.cpp")
target_compile_definitions(testXiosGrid_MPI2 PRIVATE USE_XIOS)
target_include_directories(
testXiosGrid_MPI2
PRIVATE "${MODEL_INCLUDE_DIR}" "${XIOS_INCLUDE_LIST}" "${ModulesRoot}/StructureModule"
PRIVATE
${PHYSICS_INCLUDE_DIRS}
"${MODEL_INCLUDE_DIR}"
"${XIOS_INCLUDE_LIST}"
"${ModulesRoot}/StructureModule"
)
target_link_libraries(testXiosGrid_MPI2 PRIVATE nextsimlib doctest::doctest)

add_executable(testXiosField_MPI3 "XiosField_test.cpp" "MainMPI.cpp")
target_compile_definitions(testXiosField_MPI3 PRIVATE USE_XIOS)
target_include_directories(
testXiosField_MPI3
PRIVATE "${MODEL_INCLUDE_DIR}" "${XIOS_INCLUDE_LIST}" "${ModulesRoot}/StructureModule"
PRIVATE
${PHYSICS_INCLUDE_DIRS}
"${MODEL_INCLUDE_DIR}"
"${XIOS_INCLUDE_LIST}"
"${ModulesRoot}/StructureModule"
)
target_link_libraries(testXiosField_MPI3 PRIVATE nextsimlib doctest::doctest)

add_executable(testXiosFile_MPI2 "XiosFile_test.cpp" "MainMPI.cpp")
target_compile_definitions(testXiosFile_MPI2 PRIVATE USE_XIOS)
target_include_directories(
testXiosFile_MPI2
PRIVATE "${MODEL_INCLUDE_DIR}" "${XIOS_INCLUDE_LIST}" "${ModulesRoot}/StructureModule"
PRIVATE
${PHYSICS_INCLUDE_DIRS}
"${MODEL_INCLUDE_DIR}"
"${XIOS_INCLUDE_LIST}"
"${ModulesRoot}/StructureModule"
)
target_link_libraries(testXiosFile_MPI2 PRIVATE nextsimlib doctest::doctest)

Expand All @@ -127,15 +147,23 @@ if(ENABLE_MPI)
)
target_include_directories(
testXiosRead_MPI2
PRIVATE "${MODEL_INCLUDE_DIR}" "${XIOS_INCLUDE_LIST}" "${ModulesRoot}/StructureModule"
PRIVATE
${PHYSICS_INCLUDE_DIRS}
"${MODEL_INCLUDE_DIR}"
"${XIOS_INCLUDE_LIST}"
"${ModulesRoot}/StructureModule"
)
target_link_libraries(testXiosRead_MPI2 PRIVATE nextsimlib doctest::doctest)

add_executable(testXiosWrite_MPI2 "XiosWrite_test.cpp" "MainMPI.cpp")
target_compile_definitions(testXiosWrite_MPI2 PRIVATE USE_XIOS)
target_include_directories(
testXiosWrite_MPI2
PRIVATE "${MODEL_INCLUDE_DIR}" "${XIOS_INCLUDE_LIST}" "${ModulesRoot}/StructureModule"
PRIVATE
${PHYSICS_INCLUDE_DIRS}
"${MODEL_INCLUDE_DIR}"
"${XIOS_INCLUDE_LIST}"
"${ModulesRoot}/StructureModule"
)
target_link_libraries(testXiosWrite_MPI2 PRIVATE nextsimlib doctest::doctest)

Expand Down
2 changes: 1 addition & 1 deletion core/test/Iterator_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ TEST_CASE("Count iterator testing")
Duration overall(dt);
overall *= nSteps;
TimePoint stop = start + overall;
iterator.setStartStopStep(start, start + overall, dt);
Iterator::setStartStopStep(start, start + overall, dt);
iterator.run();

REQUIRE(dt.seconds() == 1);
Expand Down
15 changes: 15 additions & 0 deletions core/test/XiosAxis_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@

#include "StructureModule/include/ParametricGrid.hpp"
#include "include/Finalizer.hpp"
#include "include/Model.hpp"
#include "include/Xios.hpp"

#include <mpi.h>

namespace Nextsim {

/*!
Expand All @@ -27,7 +30,19 @@ namespace Nextsim {
*/
MPI_TEST_CASE("TestXiosAxis", 3)
{
// Enable XIOS in the 'config' and provide parameters to configure it
enableXios();
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 << "time_step = P0-0T01:00:00" << std::endl;
std::unique_ptr<std::istream> pcstream(new std::stringstream(config.str()));
Configurator::addStream(std::move(pcstream));

// Create a Model and configure it so that time partition options are parsed
Model model(MPI_COMM_WORLD);
model.configureTime();

// Get the Xios singleton instance and check it's initialized
Xios& xiosHandler = Xios::getInstance();
Expand Down
8 changes: 8 additions & 0 deletions core/test/XiosCalendar_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
#include "StructureModule/include/ParametricGrid.hpp"
#include "include/Configurator.hpp"
#include "include/Finalizer.hpp"
#include "include/Model.hpp"
#include "include/Xios.hpp"

#include <mpi.h>

namespace Nextsim {

/*!
Expand All @@ -33,10 +36,15 @@ 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 << "time_step = P0-0T01:00:00" << std::endl;
std::unique_ptr<std::istream> pcstream(new std::stringstream(config.str()));
Configurator::addStream(std::move(pcstream));

// Create a Model and configure it so that time partition options are parsed
Model model(MPI_COMM_WORLD);
model.configureTime();

// Get the Xios singleton instance and check it's initialized
Xios& xiosHandler = Xios::getInstance();
REQUIRE(xiosHandler.isInitialized());
Expand Down
Loading
Loading