Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
4 changes: 4 additions & 0 deletions core/src/ParaGridIO_Xios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ ModelState ParaGridIO::getModelState(const std::string& filePath)
DGSField field(ModelArray::Type::DGSTRESS);
field.resize();
state.merge(ModelState { { { fieldId, field } }, {} });
} else if (type == ModelArray::Type::CG) {
CGField field(ModelArray::Type::CG);
field.resize();
state.merge(ModelState { { { fieldId, field } }, {} });
} else {
throw std::runtime_error("ParaGridIO::getModelState: field type for field " + fieldId
+ " is not supported.");
Expand Down
55 changes: 39 additions & 16 deletions core/src/Xios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ void Xios::affixModelMetadata()
}
auto dimName = dim.getName();
size_t localLength;
size_t start = 0;
size_t start;
if (dimType == ModelArray::Dimension::X) {
localLength = metadata.getLocalExtentX();
start = metadata.getLocalCornerX();
Expand All @@ -695,8 +695,15 @@ void Xios::affixModelMetadata()
} else if (dimType == ModelArray::Dimension::YVERTEX) {
localLength = metadata.getLocalExtentY() + 1;
start = metadata.getLocalCornerY();
} else if (dimType == ModelArray::Dimension::XCG) {
localLength = CGDEGREE * metadata.getLocalExtentX() + 1;
start = CGDEGREE * metadata.getLocalCornerX();
} else if (dimType == ModelArray::Dimension::YCG) {
localLength = CGDEGREE * metadata.getLocalExtentY() + 1;
start = CGDEGREE * metadata.getLocalCornerY();
Comment on lines +692 to +697
Copy link
Contributor

Choose a reason for hiding this comment

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

FWIW this is also how I am currently determining the CG dims.... but I would like to hear Tim's comments on PR #969 first. I am worried we might end up in a situation where CG dims is set in several different places. I don't think you need to change this, just raising it as an FYI.

} else {
localLength = dim.getSize();
start = 0;
}

if (ModelArray::definedDimensions.at(dimType)
Expand All @@ -706,15 +713,21 @@ void Xios::affixModelMetadata()
} else {
// Otherwise, check that an attempt to modify them isn't being made
if (dim.getSize() != ModelArray::definedDimensions.at(dimType).globalLength) {
throw std::runtime_error(
"Xios: inconsistent global dimensions for " + dimName);
throw std::runtime_error("Xios: inconsistent global dimensions for "
+ dimName + ": " + std::to_string(dim.getSize()) + " vs. "
+ std::to_string(
ModelArray::definedDimensions.at(dimType).globalLength));
}
if (localLength != ModelArray::size(dimType)) {
throw std::runtime_error(
"Xios: inconsistent local dimensions for " + dimName);
if (localLength != ModelArray::definedDimensions.at(dimType).localLength) {
throw std::runtime_error("Xios: inconsistent local dimensions for "
+ dimName + ": " + std::to_string(localLength) + " vs. "
+ std::to_string(
ModelArray::definedDimensions.at(dimType).localLength));
}
if (start != ModelArray::definedDimensions.at(dimType).start) {
throw std::runtime_error("Xios: inconsistent start index for " + dimName);
throw std::runtime_error("Xios: inconsistent start index for " + dimName
+ ": " + std::to_string(start) + " vs. "
+ std::to_string(ModelArray::definedDimensions.at(dimType).start));
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this alleviates my prev. concern about different sizes for CG dims in the code. However, I might need to understand how this works a bit better. Where will this be called in NextSim? Is it only called once?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My subsequent PR #968 will make it a bit clearer, but it's only called once yeah. In that follow-up PR I have it happening when the Model gets configured, which in turn calls ModelMetadata.setTime.

}
}
}
Expand All @@ -727,7 +740,7 @@ void Xios::affixModelMetadata()
{ "ydimxdimdg_comp", ModelArray::Type::DG },
{ "yxdgstress_comp", ModelArray::Type::DGSTRESS },
{ "ydimxdimdgstress_comp", ModelArray::Type::DGSTRESS },
{ "ycgxcg", ModelArray::Type::CG },
{ "y_cgx_cg", ModelArray::Type::CG },
{ "yvertexxvertexncoords", ModelArray::Type::VERTEX },
};

Expand Down Expand Up @@ -809,9 +822,15 @@ void Xios::affixModelMetadata()
if (dim == ModelArray::Dimension::X) {
cxios_set_domain_ni_glo(domain, metadata.getGlobalExtentX());
cxios_set_domain_ni(domain, metadata.getLocalExtentX());
cxios_set_domain_ibegin(domain, metadata.getLocalCornerX());
} else if (dim == ModelArray::Dimension::XVERTEX) {
cxios_set_domain_ni_glo(domain, metadata.getGlobalExtentX() + 1);
cxios_set_domain_ni(domain, metadata.getLocalExtentX() + 1);
cxios_set_domain_ibegin(domain, metadata.getLocalCornerX());
} else if (dim == ModelArray::Dimension::XCG) {
cxios_set_domain_ni_glo(domain, CGDEGREE * metadata.getGlobalExtentX() + 1);
cxios_set_domain_ni(domain, CGDEGREE * metadata.getLocalExtentX() + 1);
cxios_set_domain_ibegin(domain, CGDEGREE * metadata.getLocalCornerX());
} else {
throw std::runtime_error(
"Xios: Could not set domain extents based on dimension '"
Expand All @@ -825,7 +844,6 @@ void Xios::affixModelMetadata()
throw std::runtime_error(
"Xios: Failed to set local x-size for domain '" + domainId + "'");
}
cxios_set_domain_ibegin(domain, metadata.getLocalCornerX());
if (!cxios_is_defined_domain_ibegin(domain)) {
throw std::runtime_error(
"Xios: Failed to set local starting x-index for domain '" + domainId + "'");
Expand All @@ -844,9 +862,15 @@ void Xios::affixModelMetadata()
if (dim == ModelArray::Dimension::Y) {
cxios_set_domain_nj_glo(domain, metadata.getGlobalExtentY());
cxios_set_domain_nj(domain, metadata.getLocalExtentY());
cxios_set_domain_jbegin(domain, metadata.getLocalCornerY());
} else if (dim == ModelArray::Dimension::YVERTEX) {
cxios_set_domain_nj_glo(domain, metadata.getGlobalExtentY() + 1);
cxios_set_domain_nj(domain, metadata.getLocalExtentY() + 1);
cxios_set_domain_jbegin(domain, metadata.getLocalCornerY());
} else if (dim == ModelArray::Dimension::YCG) {
cxios_set_domain_nj_glo(domain, CGDEGREE * metadata.getGlobalExtentY() + 1);
cxios_set_domain_nj(domain, CGDEGREE * metadata.getLocalExtentY() + 1);
cxios_set_domain_jbegin(domain, CGDEGREE * metadata.getLocalCornerY());
} else {
throw std::runtime_error(
"Xios: Could not set domain extents based on dimension '"
Expand All @@ -860,7 +884,6 @@ void Xios::affixModelMetadata()
throw std::runtime_error(
"Xios: Failed to set local y-size for domain '" + domainId + "'");
}
cxios_set_domain_jbegin(domain, metadata.getLocalCornerY());
if (!cxios_is_defined_domain_jbegin(domain)) {
throw std::runtime_error(
"Xios: Failed to set local starting y-index for domain '" + domainId + "'");
Expand Down Expand Up @@ -1675,14 +1698,14 @@ void Xios::write(const std::string fieldId, ModelArray& modelarray)
std::set<std::string> fieldNames = configGetFieldNames(readAccess);
if (fieldNames.find(fieldId) == fieldNames.end()) {
throw std::runtime_error(
"Xios::write: field " + fieldId + " has not been configured for writing with XIOS.");
"Xios::write: field '" + fieldId + "' has not been configured for writing with XIOS.");
}
if (modelarray.nDimensions() != 2) {
throw std::invalid_argument("Only ModelArrays of dimension 2 are supported");
}
auto dims = modelarray.dimensions();
auto type = modelarray.getType();
if (type == ModelArray::Type::H) {
if ((type == ModelArray::Type::H) || (type == ModelArray::Type::CG)) {
cxios_write_data_k82(
fieldId.c_str(), fieldId.length(), modelarray.getData(), dims[0], dims[1], -1);
} else if (type == ModelArray::Type::VERTEX) {
Expand All @@ -1696,7 +1719,7 @@ void Xios::write(const std::string fieldId, ModelArray& modelarray)
dims[1], ModelArray::size(ModelArray::Dimension::DGSTRESS), -1);
} else {
throw std::invalid_argument(
"Only HFields, VertexFields, DGFields, and DGStressFields are supported");
"Only HFields, VertexFields, DGFields, DGStressFields, and CGFields are supported");
}
}

Expand All @@ -1712,14 +1735,14 @@ void Xios::read(const std::string fieldId, ModelArray& modelarray)
std::set<std::string> fieldNames = configGetFieldNames(readAccess);
if (fieldNames.find(fieldId) == fieldNames.end()) {
throw std::runtime_error(
"Xios::read: field " + fieldId + " has not been configured for reading with XIOS.");
"Xios::read: field '" + fieldId + "' has not been configured for reading with XIOS.");
}
if (modelarray.nDimensions() != 2) {
throw std::invalid_argument("Only ModelArrays of dimension 2 are supported");
}
auto dims = modelarray.dimensions();
auto type = modelarray.getType();
if (type == ModelArray::Type::H) {
if ((type == ModelArray::Type::H) || (type == ModelArray::Type::CG)) {
cxios_read_data_k82(
fieldId.c_str(), fieldId.length(), modelarray.getData(), dims[0], dims[1]);
} else if (type == ModelArray::Type::VERTEX) {
Expand All @@ -1733,7 +1756,7 @@ void Xios::read(const std::string fieldId, ModelArray& modelarray)
dims[1], ModelArray::size(ModelArray::Dimension::DGSTRESS));
} else {
throw std::invalid_argument(
"Only HFields, VertexFields, DGFields, and DGStressFields are supported");
"Only HFields, VertexFields, DGFields, DGStressFields, and CGFields are supported");
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions core/src/include/Xios.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ class Xios : public Configured<Xios> {
{ ModelArray::Type::VERTEX, "VertexDomain" },
{ ModelArray::Type::DG, "HDomain" },
{ ModelArray::Type::DGSTRESS, "HDomain" },
{ ModelArray::Type::CG, "CGDomain" },
};
xios::CDomainGroup* getDomainGroup();
xios::CDomain* getDomain(std::string domainId);
Expand All @@ -224,6 +225,7 @@ class Xios : public Configured<Xios> {
{ ModelArray::Type::VERTEX, "VertexGrid" },
{ ModelArray::Type::DG, "DGGrid" },
{ ModelArray::Type::DGSTRESS, "DGSGrid" },
{ ModelArray::Type::CG, "CGGrid" },
};

/* File */
Expand Down
44 changes: 36 additions & 8 deletions core/test/XiosRead_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const std::string forcingFilename = testFilesDir + "/xios_test_forcing.nc";

static const int DG = 3;
static const int DGSTRESSCOMP = 8;
static const int CGDEGREE = 2;

namespace Nextsim {

Expand All @@ -47,7 +48,7 @@ MPI_TEST_CASE("TestXiosRead", 2)
config << "restart_period = P0-0T01:30:00" << std::endl;
config << "[XiosInput]" << std::endl;
config << "field_names = " << maskName << "," << coordsName << "," << hiceName << ","
<< ticeName << std::endl;
<< ticeName << "," << ciceName << std::endl;
config << "[XiosForcing]" << std::endl;
config << "filename = " << forcingFilename << std::endl;
config << "field_names = " << uName << std::endl;
Expand Down Expand Up @@ -107,26 +108,53 @@ MPI_TEST_CASE("TestXiosRead", 2)
metadata.setTime(xiosHandler.getCalendarStart());
REQUIRE(xiosHandler.getCalendarStep() == 0);
ModelState restarts = grid.getModelState(restartFilename);
const int rank = xiosHandler.getClientMPIRank();
for (auto& entry : restarts.data) {
for (size_t j = 0; j < ny; ++j) {
for (size_t i = 0; i < nx; ++i) {
if (entry.first == maskName) {
if (entry.first == maskName) {
for (size_t j = 0; j < ny; ++j) {
for (size_t i = 0; i < nx; ++i) {
REQUIRE(entry.second(i, j) == doctest::Approx(j >= 1 ? 1.0 : 0.0));
} else if (entry.first == coordsName) {
REQUIRE(entry.second.components({ i, j })[0] == doctest::Approx(i));
}
}
} else if (entry.first == coordsName) {
for (size_t j = 0; j < ny + 1; ++j) {
for (size_t i = 0; i < nx + 1; ++i) {
if (rank == 0) {
REQUIRE(entry.second.components({ i, j })[0] == doctest::Approx(i));
} else {
REQUIRE(entry.second.components({ i, j })[0] == doctest::Approx(i + 2));
}
REQUIRE(entry.second.components({ i, j })[1] == doctest::Approx(j));
} else if (entry.first == hiceName) {
}
}
} else if (entry.first == hiceName) {
for (size_t j = 0; j < ny; ++j) {
for (size_t i = 0; i < nx; ++i) {
for (size_t d = 0; d < DG; ++d) {
float expected = 1.0 * (d + DG * (i + nx * j));
REQUIRE(entry.second.components({ i, j })[d] == doctest::Approx(expected));
}
} else if (entry.first == ticeName) {
}
}
} else if (entry.first == ticeName) {
for (size_t j = 0; j < ny; ++j) {
for (size_t i = 0; i < nx; ++i) {
for (size_t d = 0; d < DGSTRESSCOMP; ++d) {
REQUIRE(entry.second.components({ i, j })[d]
== doctest::Approx(2.0 * (d + DGSTRESSCOMP * (i + nx * j))));
}
}
}
} else if (entry.first == ciceName) {
for (size_t j = 0; j < CGDEGREE * ny + 1; ++j) {
for (size_t i = 0; i < CGDEGREE * nx + 1; ++i) {
if (rank == 0) {
REQUIRE(entry.second(i, j) == doctest::Approx((i + 1) * (j + 1)));
} else {
REQUIRE(entry.second(i, j) == doctest::Approx((i + 5) * (j + 1)));
}
}
}
}
}

Expand Down
48 changes: 40 additions & 8 deletions core/test/XiosWrite_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const std::string diagnosticFilename = testFilesDir + "/xios_test_diagnostic.nc"

static const int DG = 3;
static const int DGSTRESSCOMP = 8;
static const int CGDEGREE = 2;

namespace Nextsim {

Expand All @@ -47,7 +48,8 @@ MPI_TEST_CASE("TestXiosWrite", 2)
config << "restart_period = P0-0T01:30:00" << std::endl;
config << "[XiosOutput]" << std::endl;
config << "field_names = " << maskName << "," << coordsName << "," << hiceName << ","
<< ticeName << std::endl;
<< ticeName << "," << ciceName << std::endl;
config << "period = P0-0T01:30:00" << std::endl;
config << "[XiosDiagnostic]" << std::endl;
config << "filename = " << diagnosticFilename << std::endl;
config << "field_names = " << uName << std::endl;
Expand Down Expand Up @@ -79,10 +81,22 @@ MPI_TEST_CASE("TestXiosWrite", 2)
const size_t ny_glo = 2;
const size_t nx = 2;
const size_t ny = 2;
ModelArray::setDimension(ModelArray::Dimension::X, nx_glo, nx, 0);
ModelArray::setDimension(ModelArray::Dimension::Y, ny_glo, ny, 0);
ModelArray::setDimension(ModelArray::Dimension::XVERTEX, nx_glo + 1, nx + 1, 0);
ModelArray::setDimension(ModelArray::Dimension::YVERTEX, ny_glo + 1, ny + 1, 0);
size_t nx_start;
const size_t ny_start = 0;
const int rank = xiosHandler.getClientMPIRank();
if (rank == 0) {
nx_start = 0;
} else {
nx_start = nx_glo - nx;
}
ModelArray::setDimension(ModelArray::Dimension::X, nx_glo, nx, nx_start);
ModelArray::setDimension(ModelArray::Dimension::XVERTEX, nx_glo + 1, nx + 1, nx_start);
ModelArray::setDimension(
ModelArray::Dimension::XCG, CGDEGREE * nx_glo + 1, CGDEGREE * nx + 1, CGDEGREE * nx_start);
ModelArray::setDimension(ModelArray::Dimension::Y, ny_glo, ny, ny_start);
ModelArray::setDimension(ModelArray::Dimension::YVERTEX, ny_glo + 1, ny + 1, ny_start);
ModelArray::setDimension(
ModelArray::Dimension::YCG, CGDEGREE * ny_glo + 1, CGDEGREE * ny + 1, ny_start);
ModelArray::setNComponents(ModelArray::Type::DG, DG);
ModelArray::setNComponents(ModelArray::Type::DGSTRESS, DGSTRESSCOMP);
ModelArray::setNComponents(ModelArray::Type::VERTEX, ModelArray::nCoords);
Expand All @@ -99,6 +113,7 @@ MPI_TEST_CASE("TestXiosWrite", 2)
xiosHandler.setFieldType(coordsName, ModelArray::Type::VERTEX);
xiosHandler.setFieldType(hiceName, ModelArray::Type::DG);
xiosHandler.setFieldType(ticeName, ModelArray::Type::DGSTRESS);
xiosHandler.setFieldType(ciceName, ModelArray::Type::CG);
xiosHandler.setFieldType(uName, ModelArray::Type::H);

// Set file split frequency for restarts (but not diagnostics)
Expand All @@ -120,8 +135,13 @@ MPI_TEST_CASE("TestXiosWrite", 2)
coordinates.resize();
for (size_t j = 0; j < ny + 1; ++j) {
for (size_t i = 0; i < nx + 1; ++i) {
coordinates.components({ i, j })[0] = (double)i;
coordinates.components({ i, j })[1] = (double)j;
if (rank == 0) {
coordinates.components({ i, j })[0] = (double)i;
coordinates.components({ i, j })[1] = (double)j;
} else {
coordinates.components({ i, j })[0] = (double)(i + 2);
coordinates.components({ i, j })[1] = (double)j;
}
}
}
DGField hice(ModelArray::Type::DG);
Expand All @@ -142,6 +162,17 @@ MPI_TEST_CASE("TestXiosWrite", 2)
}
}
}
CGField cice(ModelArray::Type::CG);
cice.resize();
for (size_t j = 0; j < CGDEGREE * ny + 1; ++j) {
for (size_t i = 0; i < CGDEGREE * nx + 1; ++i) {
if (rank == 0) {
cice(i, j) = (double)((i + 1) * (j + 1));
} else {
cice(i, j) = (double)((i + 5) * (j + 1));
}
}
}
HField u(ModelArray::Type::H);
u.resize();

Expand Down Expand Up @@ -172,6 +203,7 @@ MPI_TEST_CASE("TestXiosWrite", 2)
{ coordsName, coordinates },
{ hiceName, hice },
{ ticeName, tice },
{ ciceName, cice },
},
{} };
ModelState diagnostics = { {
Expand All @@ -188,7 +220,7 @@ MPI_TEST_CASE("TestXiosWrite", 2)
REQUIRE(std::filesystem::exists("xios_test_output_20230317171100-20230317201059.nc"));
REQUIRE(std::filesystem::exists("xios_test_output_20230317201100-20230317231059.nc"));
REQUIRE(std::filesystem::exists("xios_test_diagnostic.nc"));
if (xiosHandler.getClientMPIRank() == 0) {
if (rank == 0) {
std::filesystem::remove("xios_test_output_20230317171100-20230317201059.nc");
std::filesystem::remove("xios_test_output_20230317201100-20230317231059.nc");
std::filesystem::remove("xios_test_diagnostic.nc");
Expand Down
4 changes: 2 additions & 2 deletions core/test/xios_test_forcing.cdl
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ dimensions:
y = 2 ;
xvertex = 5 ;
yvertex = 3 ;
x_cg = 2 ;
y_cg = 2 ;
x_cg = 9 ;
y_cg = 5 ;
dg_comp = 3 ;
dgstress_comp = 8 ;
ncoords = 2 ;
Expand Down
Loading
Loading