8#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
9#include <doctest/doctest.h>
29const std::string filename =
"paraGrid_test.nc";
30const std::string diagFile =
"paraGrid_diag.nc";
32static const int DG = 3;
33static const int DGSTRESS = 6;
34static const int CG = 2;
40TEST_SUITE_BEGIN(
"ParaGrid");
41TEST_CASE(
"Write and read a ModelState-based ParaGrid restart file")
43 Module::setImplementation<IStructure>(
"ParametricGrid");
45 std::filesystem::remove(filename);
48 ParaGridIO* pio =
new ParaGridIO(grid);
56 size_t nxcg = CG * nx + 1;
57 size_t nycg = CG * ny + 1;
59 double yFactor = 0.01;
60 double xFactor = 0.0001;
74 HField fractional(ModelArray::Type::H);
75 DGField fractionalDG(ModelArray::Type::DG);
76 HField mask(ModelArray::Type::H);
78 fractionalDG.resize();
79 for (
size_t j = 0; j < ny; ++j) {
80 for (
size_t i = 0; i < nx; ++i) {
81 fractional(i, j) = j * yFactor + i * xFactor;
83 = (i - nx / 2) * (i - nx / 2) + (j - ny / 2) * (j - ny / 2) > (nx * ny) ? 0 : 1;
84 for (
size_t d = 0; d < DG; ++d) {
85 fractionalDG.components({ i, j })[d] = fractional(i, j) + d;
90 DGField hice = fractionalDG + 10;
91 DGField cice = fractionalDG + 20;
92 HField hsnow = fractional + 30;
93 ZField tice(ModelArray::Type::Z);
96 for (
size_t k = 0; k < nz; ++k) {
97 tice.zIndexAndLayer(i, k) = fractional[i] + 40 + k;
101 VertexField coordinates(ModelArray::Type::VERTEX);
102 coordinates.resize();
110 double x = i - 0.5 - nx / 2;
111 double y = j - 0.5 - ny / 2;
112 coordinates.components({ i, j })[0] = x * scale;
113 coordinates.components({ i, j })[1] = y * scale;
117 REQUIRE(coordinates.components({ 12, 13 })[0] - coordinates.components({ 11, 13 })[0] == scale);
118 REQUIRE(coordinates.components({ 12, 13 })[1] - coordinates.components({ 12, 12 })[1] == scale);
120 ModelState state = { {
124 { hsnowName, hsnow },
126 { coordsName, coordinates },
130 ModelMetadata metadata;
131 metadata.setTime(TimePoint(
"2000-01-01T00:00:00Z"));
133 grid.dumpModelState(state, metadata, filename,
true);
135 REQUIRE(std::filesystem::exists(std::filesystem::path(filename)));
149 ParametricGrid gridIn;
150 ParaGridIO* readIO =
new ParaGridIO(gridIn);
151 gridIn.setIO(readIO);
153 ModelState ms = gridIn.getModelState(filename);
159 REQUIRE(ms.data.size() == state.data.size());
161 ModelArray& ticeRef = ms.data.at(ticeName);
163 REQUIRE(ticeRef.getType() == ModelArray::Type::Z);
164 REQUIRE(ticeRef.nDimensions() == 3);
165 REQUIRE(ticeRef.dimensions()[0] == nx);
166 REQUIRE(ticeRef.dimensions()[1] == ny);
167 REQUIRE(ticeRef.dimensions()[2] == NZLevels::get());
169 ModelArray& hiceRef = ms.data.at(hiceName);
170 REQUIRE(hiceRef.nDimensions() == 2);
171 REQUIRE(hiceRef.dimensions()[0] == nx);
172 REQUIRE(hiceRef.dimensions()[1] == ny);
174 REQUIRE(hiceRef.nComponents() == DG);
176 REQUIRE(ticeRef(12, 14, 1) == tice(12, 14, 1));
178 ModelArray& coordRef = ms.data.at(coordsName);
179 REQUIRE(coordRef.nDimensions() == 2);
180 REQUIRE(coordRef.nComponents() == 2);
181 REQUIRE(coordRef.components({ 12, 13 })[0] - coordRef.components({ 11, 13 })[0] == scale);
182 REQUIRE(coordRef.components({ 12, 13 })[1] - coordRef.components({ 12, 12 })[1] == scale);
184 std::filesystem::remove(filename);
187TEST_CASE(
"Write a diagnostic ParaGrid file")
189 Module::setImplementation<IStructure>(
"ParametricGrid");
191 REQUIRE(Module::getImplementation<IStructure>().structureType() ==
"parametric_rectangular");
193 std::filesystem::remove(diagFile);
196 ParaGridIO* pio =
new ParaGridIO(grid);
204 size_t nxcg = CG * nx + 1;
205 size_t nycg = CG * ny + 1;
207 double yFactor = 0.01;
208 double xFactor = 0.0001;
222 HField fractional(ModelArray::Type::H);
223 DGField fractionalDG(ModelArray::Type::DG);
224 HField mask(ModelArray::Type::H);
226 fractionalDG.resize();
227 for (
size_t j = 0; j < ny; ++j) {
228 for (
size_t i = 0; i < nx; ++i) {
229 fractional(i, j) = j * yFactor + i * xFactor;
230 mask(i, j) = fractional(i, j);
232 for (
size_t d = 0; d < DG; ++d) {
233 fractionalDG.components({ i, j })[d] = fractional(i, j) + d;
238 REQUIRE(fractional(12, 12) - fractional(11, 12) == doctest::Approx(xFactor).
epsilon(prec));
239 REQUIRE(fractional(12, 12) - fractional(12, 11) == doctest::Approx(yFactor).
epsilon(prec));
241 REQUIRE(fractionalDG(12, 12) - fractionalDG(11, 12) == doctest::Approx(xFactor).
epsilon(prec));
242 REQUIRE(fractionalDG(12, 12) - fractionalDG(12, 11) == doctest::Approx(yFactor).
epsilon(prec));
245 DGField hice = fractionalDG + 10;
246 DGField cice = fractionalDG + 20;
248 VertexField coordinates(ModelArray::Type::VERTEX);
249 coordinates.resize();
257 double x = i - 0.5 - nx / 2;
258 double y = j - 0.5 - ny / 2;
259 coordinates.components({ i, j })[0] = x * scale;
260 coordinates.components({ i, j })[1] = y * scale;
264 REQUIRE(coordinates.components({ 12, 13 })[0] - coordinates.components({ 11, 13 })[0] == scale);
265 REQUIRE(coordinates.components({ 12, 13 })[1] - coordinates.components({ 12, 12 })[1] == scale);
267 ModelState state = { {
271 { coordsName, coordinates },
275 ModelMetadata metadata;
276 metadata.setTime(TimePoint(
"2000-01-01T00:00:00Z"));
278 grid.dumpModelState(state, metadata, diagFile,
false);
280 for (
int t = 1; t < 5; ++t) {
289 grid.dumpModelState(state, metadata, diagFile,
false);
291 pio->close(diagFile);
294 netCDF::NcFile ncFile(diagFile, netCDF::NcFile::read);
296 REQUIRE(ncFile.getGroups().size() == 3);
301 std::string structureType;
302 structGrp.getAtt(grid.typeNodeName()).getValues(structureType);
304 REQUIRE(structureType == grid.structureType());
309 REQUIRE(dataGrp.getVarCount() == 5);
310 netCDF::NcVar hiceVar = dataGrp.getVar(hiceName);
311 netCDF::NcVar ciceVar = dataGrp.getVar(ciceName);
312 netCDF::NcVar coordVar = dataGrp.getVar(coordsName);
313 netCDF::NcVar maskVar = dataGrp.getVar(maskName);
314 netCDF::NcVar timeVar = dataGrp.getVar(timeName);
317 REQUIRE(hiceVar.getDimCount() == 4);
321 std::filesystem::remove(diagFile);
325#define TO_STR(s) TO_STRI(s)
327#ifndef TEST_FILE_SOURCE
328#define TEST_FILE_SOURCE .
331TEST_CASE(
"Test array ordering")
333 std::string inputFilename =
"ParaGridIO_input_test.nc";
335 Module::setImplementation<IStructure>(
"ParametricGrid");
337 REQUIRE(Module::getImplementation<IStructure>().structureType() ==
"parametric_rectangular");
349 HField index2d(ModelArray::Type::H);
351 std::string fieldName =
"index2d";
352 std::set<std::string> fields = { fieldName };
355 ModelState state = ParaGridIO::readForcingTimeStatic(fields, time, TO_STR(TEST_FILE_SOURCE) + std::string(
"/") + inputFilename);
356 REQUIRE(state.data.count(fieldName) > 0);
357 index2d = state.data.at(fieldName);
358 REQUIRE(index2d(3, 5) == 35);
static const std::string dataNodeName()
Returns the name of the data node.
static const std::string structureNodeName()
The name of the group holding the definitive structure type.
static const std::string metadataNodeName()
Returns the name of the metadata node.
const MultiDim & dimensions() const
Returns a vector<size_t> of the size of each dimension of this type of ModelArray.
static void setDimension(Dimension dim, size_t length)
Sets the length of an individual dimension before propagating it to the defined array types.
size_t nComponents() const
Returns the number of discontinuous Galerkin components held in this type of ModelArray.
size_t nDimensions() const
Returns the number of dimensions of this type of ModelArray.
size_t size() const
Returns the total number of elements of this type of ModelArray.
static std::map< Dimension, DimensionSpec > definedDimensions
The name and length of each dimension that is defined.
static void setNComponents(std::map< Type, size_t > cMap)
Sets the number of components for DG & CG array types.
const double epsilon
Thermal emissivity of smooth ice [0..1].