27const std::map<std::string, ModelArray::Type> ParaGridIO::dimensionKeys = {
28 {
"yx", ModelArray::Type::H },
29 {
"zyx", ModelArray::Type::Z },
30 {
"yxdg_comp", ModelArray::Type::DG },
31 {
"yxdgstress_comp", ModelArray::Type::DGSTRESS },
32 {
"ycgxcg", ModelArray::Type::CG },
33 {
"yvertexxvertexncoords", ModelArray::Type::VERTEX },
37const std::map<ModelArray::Dimension, bool> ParaGridIO::isDG = {
39 { ModelArray::Dimension::X,
false },
40 { ModelArray::Dimension::Y,
false },
41 { ModelArray::Dimension::Z,
false },
42 { ModelArray::Dimension::XCG,
true },
43 { ModelArray::Dimension::YCG,
true },
44 { ModelArray::Dimension::DG,
true },
45 { ModelArray::Dimension::DGSTRESS,
true },
47 { ModelArray::Dimension::NCOORDS,
false },
51std::map<ModelArray::Dimension, ModelArray::Type> ParaGridIO::dimCompMap;
52std::map<std::string, netCDF::NcFile> ParaGridIO::openFiles;
53std::map<std::string, size_t> ParaGridIO::timeIndexByFile;
55void ParaGridIO::makeDimCompMap()
58 { ModelArray::componentMap.at(ModelArray::Type::DG), ModelArray::Type::DG },
59 { ModelArray::componentMap.at(ModelArray::Type::DGSTRESS), ModelArray::Type::DGSTRESS },
60 { ModelArray::componentMap.at(ModelArray::Type::VERTEX), ModelArray::Type::VERTEX },
65 std::atexit(closeAllFiles);
68ParaGridIO::~ParaGridIO() =
default;
72 netCDF::NcFile ncFile(filePath, netCDF::NcFile::read);
77 std::multimap<std::string, netCDF::NcDim> dimMap = dataGroup.getDims();
79 if (dimCompMap.count(entry.first) > 0)
84 netCDF::NcDim dim = dataGroup.getDim(dimensionSpec.name);
85 if (entry.first == ModelArray::Dimension::Z) {
98 for (
auto entry : dataGroup.getVars()) {
99 const std::string& varName = entry.first;
100 netCDF::NcVar& var = entry.second;
102 std::vector<netCDF::NcDim> varDims = var.getDims();
103 std::string dimKey =
"";
104 for (netCDF::NcDim& dim : varDims) {
105 dimKey += dim.getName();
107 if (!dimensionKeys.count(dimKey)) {
108 throw std::out_of_range(
109 std::string(
"No ModelArray::Type corresponds to the dimensional key ") + dimKey);
111 ModelArray::Type newType = dimensionKeys.at(dimKey);
116 if (newType == ModelArray::Type::Z) {
121 std::reverse(extentVector.begin(), extentVector.end());
122 var.getVar(startVector, extentVector, &data[0]);
124 var.getVar(&data[0]);
132 const std::set<std::string>& forcings,
const TimePoint& time,
const std::string& filePath)
134 netCDF::NcFile ncFile(filePath, netCDF::NcFile::read);
141 netCDF::NcDim timeDim = dataGroup.getDim(timeName);
143 netCDF::NcVar timeVar = dataGroup.getVar(timeName);
147 std::vector<double> timeVec(timeDim.getSize());
148 timeVar.getVar(timeVec.data());
150 targetTIndex = std::find_if(begin(timeVec), end(timeVec), [time](
double t) {
152 }) - timeVec.begin();
155 if (targetTIndex > 0)
159 std::vector<size_t> indexArray = { targetTIndex };
160 std::vector<size_t> extentArray = { 1 };
163 const std::vector<ModelArray::Dimension>& dimensions
165 for (
auto riter = dimensions.rbegin(); riter != dimensions.rend(); ++riter) {
166 indexArray.push_back(0);
170 for (
const std::string& varName : forcings) {
171 netCDF::NcVar var = dataGroup.getVar(varName);
172 state.data[varName] = ModelArray(ModelArray::Type::H);
173 ModelArray& data = state.data.at(varName);
176 var.getVar(indexArray, extentArray, &data[0]);
185 netCDF::NcFile ncFile(filePath, netCDF::NcFile::replace);
193 std::map<ModelArray::Dimension, netCDF::NcDim> ncFromMAMap;
195 ModelArray::Dimension dim = entry.first;
197 : dimSz = entry.second.length;
198 ncFromMAMap[dim] = dataGroup.addDim(entry.second.name, dimSz);
203 std::map<ModelArray::Type, std::vector<netCDF::NcDim>> dimMap;
205 ModelArray::Type type = entry.first;
206 std::vector<netCDF::NcDim> ncDims;
207 for (
auto iter = entry.second.rbegin(); iter != entry.second.rend(); ++iter) {
208 ModelArray::Dimension& maDim = *iter;
209 ncDims.push_back(ncFromMAMap.at(maDim));
211 dimMap[type] = ncDims;
216 for (
auto entry : dimCompMap) {
217 dimMap.at(entry.second).push_back(ncFromMAMap.at(entry.first));
220 std::set<std::string> restartFields = { hiceName, ciceName, hsnowName, ticeName, sstName,
221 sssName, maskName, coordsName };
223 for (
auto entry : state.data) {
224 if (restartFields.count(entry.first)) {
226 ModelArray::Type type = entry.second.getType();
227 std::vector<netCDF::NcDim>& ncDims = dimMap.at(type);
228 netCDF::NcVar var(dataGroup.addVar(entry.first, netCDF::ncDouble, ncDims));
229 var.putAtt(mdiName, netCDF::ncDouble, MissingData::value);
230 var.putVar(entry.second.getData());
240 bool isNew = openFiles.count(filePath) <= 0;
241 size_t nt = (isNew) ? 0 : ++timeIndexByFile.at(filePath);
244 openFiles.try_emplace(filePath, filePath, netCDF::NcFile::replace);
246 timeIndexByFile[filePath] = nt;
249 netCDF::NcFile& ncFile = openFiles.at(filePath);
263 netCDF::NcDim timeDim = (isNew) ? dataGroup.addDim(timeName) : dataGroup.getDim(timeName);
266 std::map<ModelArray::Dimension, netCDF::NcDim> ncFromMAMap;
268 ModelArray::Dimension dim = entry.first;
270 : dimSz = entry.second.length;
271 ncFromMAMap[dim] = (isNew) ? dataGroup.addDim(entry.second.name, dimSz)
272 : dataGroup.getDim(entry.second.name);
276 std::map<ModelArray::Type, std::vector<netCDF::NcDim>> dimMap;
279 std::map<ModelArray::Type, std::vector<size_t>> indexArrays;
280 std::map<ModelArray::Type, std::vector<size_t>> extentArrays;
282 ModelArray::Type type = entry.first;
283 std::vector<netCDF::NcDim> ncDims;
284 std::vector<size_t> indexArray;
285 std::vector<size_t> extentArray;
289 if (type != ModelArray::Type::VERTEX) {
290 ncDims.push_back(timeDim);
291 indexArray.push_back(nt);
292 extentArray.push_back(1UL);
297 for (
auto iter = entry.second.rbegin(); iter != entry.second.rend(); ++iter) {
298 ModelArray::Dimension& maDim = *iter;
299 ncDims.push_back(ncFromMAMap.at(maDim));
300 indexArray.push_back(0);
303 dimMap[type] = ncDims;
304 indexArrays[type] = indexArray;
305 extentArrays[type] = extentArray;
308 for (
auto entry : dimCompMap) {
310 if (entry.second == ModelArray::Type::VERTEX && !isNew)
312 dimMap.at(entry.second).push_back(ncFromMAMap.at(entry.first));
313 indexArrays.at(entry.second).push_back(0);
318 std::vector<netCDF::NcDim> maskDims;
319 std::vector<size_t> maskIndexes;
320 std::vector<size_t> maskExtents;
323 maskDims.push_back(ncFromMAMap.at(maDim));
325 maskIndexes = { 0, 0 };
334 std::vector<netCDF::NcDim> timeDimVec = { timeDim };
335 netCDF::NcVar timeVar((isNew) ? dataGroup.addVar(timeName, netCDF::ncDouble, timeDimVec)
336 : dataGroup.getVar(timeName));
337 double secondsSinceEpoch = (meta.
time() -
TimePoint()).seconds();
338 timeVar.putVar({ nt }, { 1 }, &secondsSinceEpoch);
341 for (
auto entry : state.data) {
342 ModelArray::Type type = entry.second.getType();
344 if (!isNew && (entry.first == maskName || type == ModelArray::Type::VERTEX))
346 if (entry.first == maskName) {
348 netCDF::NcVar var(dataGroup.addVar(maskName, netCDF::ncDouble, maskDims));
350 var.putVar(maskIndexes, maskExtents, entry.second.getData());
353 std::vector<netCDF::NcDim>& ncDims = dimMap.at(type);
355 netCDF::NcVar var((isNew) ? dataGroup.addVar(entry.first, netCDF::ncDouble, ncDims)
356 : dataGroup.getVar(entry.first));
358 var.putAtt(mdiName, netCDF::ncDouble, MissingData::value);
360 var.putVar(indexArrays.at(type), extentArrays.at(type), entry.second.getData());
367 if (openFiles.count(filePath) > 0) {
368 openFiles.at(filePath).close();
369 openFiles.erase(openFiles.find(filePath));
370 timeIndexByFile.erase(timeIndexByFile.find(filePath));
374void ParaGridIO::closeAllFiles()
376 size_t closedFiles = 0;
377 for (
const auto& [name, handle] : openFiles) {
378 if (!handle.isNull()) {
385 if (closedFiles >= openFiles.size())
static const std::string dataNodeName()
Returns the name of the data node.
static const std::string metadataNodeName()
Returns the name of the metadata node.
A class that holds the array data for the model.
static TypeDimensions typeDimensions
The dimensions that make up each defined type. Defined in ModelArrayDetails.cpp.
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.
static std::map< Dimension, DimensionSpec > definedDimensions
The name and length of each dimension that is defined.
void writeDiagnosticTime(const ModelState &state, const ModelMetadata &meta, const std::string &filePath) override
Writes diagnostic data to a file.
void dumpModelState(const ModelState &state, const ModelMetadata &meta, const std::string &filePath) override
Writes the ModelState to a given file location from the provided model data and metadata.
ModelState getModelState(const std::string &filePath) override
static void close(const std::string &filePath)