netxsimdg
Loading...
Searching...
No Matches
DevGridIO.cpp
Go to the documentation of this file.
1
9
11#include "include/DevGrid.hpp"
14#include "include/ModelArray.hpp"
15#include "include/NZLevels.hpp"
16
17#include <cstddef>
18#include <ncDim.h>
19#include <ncDouble.h>
20#include <ncFile.h>
21#include <ncVar.h>
22
23#include <map>
24#include <string>
25#include <vector>
26
27namespace Nextsim {
28
29// Forward declarations
30enum class StringName {
31 METADATA_NODE,
32 DATA_NODE,
33 STRUCTURE,
34 X_DIM,
35 Y_DIM,
36 Z_DIM,
37};
38
39static std::string hiceName = "hice";
40static std::string ciceName = "cice";
41static std::string hsnowName = "hsnow";
42static std::string ticeName = "tice";
43
44typedef std::map<StringName, std::string> NameMap;
45
46static const std::string metaName = "meta";
47static const std::string dataName = "data";
48static const std::string mdiName = "missing_value";
49
50// Metadata initialization
51static void initModelMetaData(const netCDF::NcGroup& metaGroup) { }
52
53static ModelState initModelData(const netCDF::NcGroup& dataGroup)
54{
55 // Get the number of array sizes from the dimension data of the ice temperature array
56 size_t nDims = 3;
57 std::vector<size_t> dim3(nDims);
58 std::vector<size_t> dim2(nDims - 1);
59
60 for (int iDim = 0; iDim < nDims; ++iDim) {
61 dim3[iDim] = dataGroup.getVar(ticeName).getDim(iDim).getSize();
62 }
63 dim2[0] = dim3[0];
64 dim2[1] = dim3[1];
65 size_t fileZLevels = dim3[2];
66 dim3[2] = NZLevels::get();
67
68 ModelArray::setDimensions(ModelArray::Type::H, dim2);
69 ModelArray::setDimensions(ModelArray::Type::U, dim2);
70 ModelArray::setDimensions(ModelArray::Type::V, dim2);
71 ModelArray::setDimensions(ModelArray::Type::Z, dim3);
72
73 // Loop over all data fields, add their name and contents to the ModelState
74 std::multimap<std::string, netCDF::NcVar> varMap = dataGroup.getVars();
75 ModelState state;
76 for (const auto var : varMap) {
77 // Get the dimensions and read into an intermediate buffer
78 int nDims = var.second.getDimCount();
79 std::vector<netCDF::NcDim> dims = var.second.getDims();
80 size_t totalSz = 1;
81 for (const auto dim : dims) {
82 totalSz *= dim.getSize();
83 }
84
85 std::string varName = var.first;
86 std::vector<double> buffer(totalSz);
87 var.second.getVar(buffer.data());
88 if (nDims == 2) {
89 HField data = ModelArray::HField();
90 data.setData(buffer.data());
91 auto [i, y] = state.data.insert({ varName, data });
92 } else if (nDims == 3) {
93 ZField data = ModelArray::ZField();
94 // Transform from the number of z levels in the data file to the
95 // number required by the ice thermodynamics.
96 // Reset the size of the buffer (and we know we have three dimensions)
97 totalSz = dim3[0] * dim3[1] * dim3[2];
98 buffer.resize(totalSz);
99 std::vector<size_t> startVector = { 0, 0, 0 };
100 var.second.getVar(startVector, dim3, buffer.data());
101 data.setData(buffer.data());
102 state.data[varName] = data;
103 }
104 }
105
106 return state;
107}
108
109ModelState DevGridIO::getModelState(const std::string& filePath) const
110{
111
112 netCDF::NcFile ncFile(filePath, netCDF::NcFile::read);
113
114 netCDF::NcGroup metaGroup(ncFile.getGroup(metaName));
115 netCDF::NcGroup dataGroup(ncFile.getGroup(dataName));
116 initModelMetaData(metaGroup);
117 ModelState ms = initModelData(dataGroup);
118
119 ncFile.close();
120 return ms;
121}
122
123void dumpModelMeta(const ModelMetadata& metadata, netCDF::NcGroup& metaGroup)
124{
126}
127
128void dumpModelData(const ModelState& state, netCDF::NcGroup& dataGroup)
129{
130 int nx = DevGrid::nx;
131 // Create the dimension data, since it has to be in the same group as the
132 // data or the parent group
133 netCDF::NcDim xDim = dataGroup.addDim(DevGrid::xDimName, nx);
134 netCDF::NcDim yDim = dataGroup.addDim(DevGrid::yDimName, nx);
135 std::vector<netCDF::NcDim> dims2 = { xDim, yDim };
136 int nLayers = 1;
137 netCDF::NcDim zDim = dataGroup.addDim(DevGrid::nIceLayersName, nLayers);
138 std::vector<netCDF::NcDim> dims3 = { xDim, yDim, zDim };
139
140 for (const auto entry : state.data) {
141 const std::string& name = entry.first;
142 if (entry.second.getType() == ModelArray::Type::H) {
143 netCDF::NcVar var(dataGroup.addVar(name, netCDF::ncDouble, dims2));
144 var.putAtt(mdiName, netCDF::ncDouble, MissingData::value);
145 var.putVar(entry.second.getData());
146 } else if (entry.second.getType() == ModelArray::Type::Z) {
147 netCDF::NcVar var(dataGroup.addVar(name, netCDF::ncDouble, dims3));
148 var.putAtt(mdiName, netCDF::ncDouble, MissingData::value);
149 var.putVar(entry.second.getData());
150 }
151 }
152}
153
154void DevGridIO::dumpModelState(const ModelState& state, const ModelMetadata& metadata,
155 const std::string& filePath, bool isRestart) const
156{
157 netCDF::NcFile ncFile(filePath, netCDF::NcFile::replace);
158 netCDF::NcGroup metaGroup = ncFile.addGroup(metaName);
159 netCDF::NcGroup dataGroup = ncFile.addGroup(dataName);
161 dumpModelMeta(metadata, metaGroup);
162 dumpModelData(state, dataGroup);
163 ncFile.close();
164}
165
166} /* namespace Nextsim */
static netCDF::NcGroup & writeRestartMetadata(netCDF::NcGroup &metaGroup, const ModelMetadata &metadata)
Writes the standard restart file metadata to a metadata node.
static netCDF::NcGroup & writeStructureType(netCDF::NcFile &rootGroup, const ModelMetadata &metadata)
Writes the structure type to the root of the restart file for future retrieval.
ModelState getModelState(const std::string &filePath) const override
Generates the ModelState based on the data in the given file.
void dumpModelState(const ModelState &state, const ModelMetadata &metadata, const std::string &filePath, bool isRestart) const override
Dumps the given ModelState to the given file path.
static void setDimensions(Type, const MultiDim &)
Sets the number and size of the dimensions of a specified type of ModelArray.