Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
8858a3e
Reorder read and write tests
joewallwork Oct 21, 2025
f99b583
Drop unnecessary MPI helper functions
joewallwork Oct 21, 2025
fc7911c
No need to set time
joewallwork Oct 24, 2025
d050acf
Drop axisValues getter and setter as not needed
joewallwork Oct 24, 2025
c77a972
Separate out parseInputFile and call during setup
joewallwork Oct 24, 2025
0266a42
Separate out setup<Axes,Domains,Grids> and call in ParaGridIO constru…
joewallwork Oct 24, 2025
5d93f0d
Inline enableXios in Model.configureTime
joewallwork Oct 24, 2025
678f7df
Xios read member function should be private
joewallwork Oct 24, 2025
40eac3f
Inline isInitialized, raising error if not
joewallwork Oct 24, 2025
b527f82
Drop getCalendarTimestep
joewallwork Oct 24, 2025
dc9425c
Drop getCalendarType
joewallwork Oct 24, 2025
a3a5280
Automate setting nCoords for VERTEX
joewallwork Oct 21, 2025
12567b5
Automate setting nComponents for DGSTRESS and DG
joewallwork Oct 21, 2025
282247e
Default DGCOMP to 6 for consistency with CMakeLists.txt
joewallwork Oct 24, 2025
8d764a0
Mention enabling XIOS in docs
joewallwork Oct 24, 2025
4192b3f
Merge branch 'issue917_xios-write-diag-time' into issue850_xios-pruning
joewallwork Nov 3, 2025
2647c46
Merge branch 'issue911_xios-cg-dgs' into issue850_xios-pruning
joewallwork Nov 3, 2025
746de39
Merge branch 'issue911_xios-cg-dgs' into issue850_xios-pruning
joewallwork Nov 4, 2025
19ad630
Merge branch 'issue911_xios-cg-dgs' into issue850_xios-pruning
joewallwork Nov 4, 2025
698975e
Post-merge fixes
joewallwork Nov 4, 2025
79c6eec
Clearer note on singleton creation in XIOS tests
joewallwork Nov 10, 2025
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
7 changes: 7 additions & 0 deletions core/src/Model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ void Model::configureTime()
{
ModelMetadata& metadata = ModelMetadata::getInstance();

#ifdef USE_XIOS
// Enable XIOS in the config
std::stringstream config;
config << "[xios]" << std::endl << "enable = true" << std::endl;
Configurator::addStream(std::unique_ptr<std::istream>(new std::stringstream(config.str())));
#endif

// Start/stop times. Run length will override stop time, if present.
std::string startTimeStr
= Configured::getConfiguration(keyMap.at(STARTTIME_KEY), std::string());
Expand Down
6 changes: 0 additions & 6 deletions core/src/ModelMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,6 @@ void ModelMetadata::setTime(const TimePoint& time)
m_time = time;
#ifdef USE_XIOS
Xios& xiosHandler = Xios::getInstance();
if (!xiosHandler.isInitialized()) {
throw std::runtime_error("ModelMetadata: Xios handler has not been initialized");
}
xiosHandler.setCalendarStart(time);
#endif
}
Expand All @@ -226,9 +223,6 @@ void ModelMetadata::incrementTime(const Duration& step)
m_time += step;
#ifdef USE_XIOS
Xios& xiosHandler = Xios::getInstance();
if (!xiosHandler.isInitialized()) {
throw std::runtime_error("ModelMetadata: Xios handler has not been initialized");
}
xiosHandler.incrementCalendar();
#endif
}
Expand Down
9 changes: 3 additions & 6 deletions core/src/ParaGridIO_Xios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,9 @@ ParaGridIO::ParaGridIO(ParametricGrid& grid)
: IParaGridIO(grid)
{
Xios& xiosHandler = Xios::getInstance();
// NOTE: getInstance will call the constructor for the Xios handler class the first time it is
// called. This will automatically:
// * Create XIOS input and output files if the XiosInput.filename and XiosOutput.filename
// entries are set in the config.
// * Create all fields found in the config based off the field names found in the
// XiosInput.field_names and XiosOutput.field_names entries in the config.
xiosHandler.setupDomains();
xiosHandler.setupAxes();
xiosHandler.setupGrids();
}

ParaGridIO::~ParaGridIO() = default;
Expand Down
173 changes: 69 additions & 104 deletions core/src/Xios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@
#include <regex>
#include <string>

#ifndef DGCOMP
#define DGCOMP 6 // Define to prevent errors from static analysis tools
#error "Number of DG components (DGCOMP) not defined" // But throw an error anyway
#endif

#ifndef DGSTRESSCOMP
#define DGSTRESSCOMP 8 // Define to prevent errors from static analysis tools
#error "Number of DG stress components (DGSTRESSCOMP) not defined" // But throw an error anyway
#endif

#ifndef CGDEGREE
#define CGDEGREE 2 // Define to prevent errors from static analysis tools
#error "CG degree (CGDEGREE) not defined" // But throw an error anyway
#endif

namespace Nextsim {

static const std::string xOutputPfx = "XiosOutput";
Expand Down Expand Up @@ -106,6 +121,15 @@ Xios::Xios(const std::string contextid, const std::string calendartype)
}
}
}

// Verify the XIOS context has been initialized properly
bool init;
cxios_context_is_initialized(contextId.c_str(), contextId.length(), &init);
if (!init) {
throw std::runtime_error("Xios: context '" + contextId + "' not initialized");
}

parseInputFiles();
}
firstTime = false;
}
Expand Down Expand Up @@ -237,6 +261,9 @@ void Xios::configureServer()
clientCalendar, convertDurationToXios(metadata.stepLength()));
cxios_create_calendar(clientCalendar);
cxios_update_calendar_timestep(clientCalendar);
if (!cxios_is_defined_calendar_wrapper_timestep(clientCalendar)) {
throw std::runtime_error("Xios: Calendar timestep has not been set");
}

// Set default calendar origin
setCalendarOrigin(TimePoint("1970-01-01T00:00:00Z")); // Unix epoch
Expand All @@ -245,28 +272,6 @@ void Xios::configureServer()
setCalendarStart(metadata.startTime());
}

/*!
* @return size of the client MPI communicator
*/
int Xios::getClientMPISize() { return mpi_size; }

/*!
* @return rank of the client MPI communicator
*/
int Xios::getClientMPIRank() { return mpi_rank; }

/*!
* Verify XIOS server is initialized
*
* @return true when XIOS server is initialized
*/
bool Xios::isInitialized()
{
bool init = false;
cxios_context_is_initialized(contextId.c_str(), contextId.length(), &init);
return init;
}

/*!
* Return datetime as std::string using ISO 8601 format (default).
*
Expand Down Expand Up @@ -384,18 +389,6 @@ void Xios::setCalendarStep(const int stepNumber) { cxios_update_calendar(stepNum
*/
void Xios::incrementCalendar() { setCalendarStep(getCalendarStep() + 1); }

/*!
* Get calendar type
*
* @return calendar type
*/
std::string Xios::getCalendarType()
{
char cStr[cStrLen];
cxios_get_calendar_wrapper_type(clientCalendar, cStr, cStrLen);
return convertCStrToCppStr(cStr, cStrLen);
}

/*!
* Get calendar origin
*
Expand Down Expand Up @@ -426,21 +419,6 @@ TimePoint Xios::getCalendarStart()
return TimePoint(convertXiosDatetimeToString(calendar_start, true));
}

/*!
* Get calendar timestep
*
* @return calendar timestep
*/
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);
}

/*!
* Get calendar step
*
Expand Down Expand Up @@ -538,31 +516,6 @@ void Xios::setAxisSize(const std::string axisId, const size_t size)
}
}

/*!
* Set the values associated with a given axis
*
* @param the axis ID
* @param the values to set
*/
void Xios::setAxisValues(const std::string axisId, std::vector<double> values)
{
xios::CAxis* axis = getAxis(axisId);
if (cxios_is_defined_axis_value(axis)) {
Logged::warning("Xios: Values already set for axis '" + axisId + "'");
}
if (!cxios_is_defined_axis_n_glo(axis)) {
setAxisSize(axisId, values.size());
}
int size = getAxisSize(axisId);
if (size != values.size()) {
throw std::runtime_error("Xios: Size incompatible with values for axis '" + axisId + "'");
}
cxios_set_axis_value(axis, values.data(), &size);
if (!cxios_is_defined_axis_value(axis)) {
throw std::runtime_error("Xios: Failed to set values for axis '" + axisId + "'");
}
}

/*!
* Get the size of a given axis (the number of global points)
*
Expand All @@ -580,26 +533,6 @@ size_t Xios::getAxisSize(const std::string axisId)
return (size_t)size;
}

/*!
* Get the values associated with a given axis
*
* @param the axis ID
* @return the corresponding values
*/
std::vector<double> Xios::getAxisValues(const std::string axisId)
{
xios::CAxis* axis = getAxis(axisId);
if (!cxios_is_defined_axis_value(axis)) {
throw std::runtime_error("Xios: Undefined values for axis '" + axisId + "'");
}
int size = getAxisSize(axisId);
double* values = new double[size];
cxios_get_axis_value(axis, values, &size);
std::vector<double> vec(values, values + size);
delete[] values;
return vec;
}

/*!
* Get the domain_definition group
*
Expand Down Expand Up @@ -637,11 +570,16 @@ xios::CDomain* Xios::getDomain(const std::string domainId)
}

/*!
* Create axes, domains, and grids based off the provided metadata.
* @brief Do an initial read of input files to deduce field dimensions.
*
* @details This function will read the dimension information from any NetCDF input files (restarts
* and/or forcings) and set dimensions appropriately. It will then set the field type of
* each input field.
*/
void Xios::affixModelMetadata()
void Xios::parseInputFiles()
{
auto& metadata = ModelMetadata::getInstance();

// Initial read of the NetCDF file to deduce the dimensions
for (std::string filename : { inputFilename, forcingFilename }) {
if (filename.length() == 0) {
Expand Down Expand Up @@ -752,8 +690,21 @@ void Xios::affixModelMetadata()
throw std::runtime_error(ncWhat);
}
}
}

// Create XIOS domains associated with each ModelArray type
/*!
* @brief Create XIOS domains associated with each ModelArray type
*
* @details This function sets up the XIOS domains for each field type based on the configuration
* in the domainIds map and in the ModelMetadata class.
*/
void Xios::setupDomains()
{
auto& metadata = ModelMetadata::getInstance();

ModelArray::setNComponents(ModelArray::Type::VERTEX, ModelArray::nCoords);
ModelArray::setNComponents(ModelArray::Type::DG, DGCOMP);
ModelArray::setNComponents(ModelArray::Type::DGSTRESS, DGSTRESSCOMP);
for (auto entry : domainIds) {
ModelArray::Type type = entry.first;
const std::string domainId = entry.second;
Expand Down Expand Up @@ -875,15 +826,20 @@ void Xios::affixModelMetadata()
counter++;
}
}
}

// Create XIOS axes for each ModelArray type
for (auto entry : ModelArray::componentMap) {
/*!
* @brief Create XIOS axes for each ModelArray type
*
* @details This function sets up the XIOS axes for each field type based on the configuration
* in the axisIds map and in the ModelArray class.
*/
void Xios::setupAxes()
{
for (auto entry : axisIds) {
ModelArray::Type type = entry.first;
ModelArray::Dimension dim = entry.second;
if (axisIds.count(type) == 0) {
continue;
}
const std::string axisId = axisIds[type];
const std::string axisId = entry.second;
ModelArray::Dimension dim = ModelArray::componentMap.at(type);
createAxis(axisId);
setAxisSize(axisId, ModelArray::size(dim));
xios::CAxis* axis = getAxis(axisId);
Expand All @@ -893,7 +849,16 @@ void Xios::affixModelMetadata()
throw std::runtime_error("Xios: Failed to set name for axis '" + axisId + "'");
}
}
}

/*!
* @brief Create XIOS grids for each ModelArray type
*
* @details This function sets up the XIOS grids for each field type based on the configuration
* in the gridIds, axisIds, and domainIds maps.
*/
void Xios::setupGrids()
{
// Create XIOS grid associated with domain and possibly axis
for (auto entry : gridIds) {
ModelArray::Type type = entry.first;
Expand Down
2 changes: 1 addition & 1 deletion core/src/discontinuousgalerkin/ModelArrayDetails.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "include/ModelArray.hpp"

#ifndef DGCOMP
#define DGCOMP 3
#define DGCOMP 6
#endif

#ifndef DGSTRESSCOMP
Expand Down
Loading
Loading