netxsimdg
Loading...
Searching...
No Matches
ConfigOutput.cpp
Go to the documentation of this file.
1
9#include "include/Logged.hpp"
11
12#include <cmath>
13#include <sstream>
14
15namespace Nextsim {
16
17const std::string ConfigOutput::all = "ALL";
18const std::string ConfigOutput::defaultLastOutput = "0-01-01T00:00:00Z";
19
20template <>
21const std::map<int, std::string> Configured<ConfigOutput>::keyMap = {
22 { ConfigOutput::PERIOD_KEY, "ConfigOutput.period" },
23 { ConfigOutput::START_KEY, "ConfigOutput.start" },
24 { ConfigOutput::FIELDNAMES_KEY, "ConfigOutput.field_names" },
25};
26
27ConfigOutput::ConfigOutput()
28 : IDiagnosticOutput()
29 , m_filePrefix()
30 , outputPeriod()
31 , firstOutput(true)
32 , everyTS(false)
33 , outputAllTheFields(false)
34 , lastOutput(defaultLastOutput)
35 , fieldsForOutput()
36 , currentFileName()
37{
38}
39
40void ConfigOutput::configure()
41{
42 std::string periodString = Configured::getConfiguration(keyMap.at(PERIOD_KEY), std::string(""));
43 if (periodString.empty()) {
44 everyTS = true;
45 } else {
46 outputPeriod.parse(periodString);
47 }
48 std::string startString = Configured::getConfiguration(keyMap.at(START_KEY), std::string(""));
49 if (startString.empty()) {
50 // If you start the model before 1st January year 0, tough.
51 lastOutput.parse(defaultLastOutput);
52 } else {
53 lastOutput.parse(startString);
54 if (!everyTS) {
55 lastOutput -= outputPeriod;
56 }
57 }
58
59 std::string outputFields
60 = Configured::getConfiguration(keyMap.at(FIELDNAMES_KEY), std::string(""));
61 if (outputFields == all || outputFields.empty()) { // Output *all* the fields?
62 outputAllTheFields = true; // Output all the fields!
63 } else {
64 std::istringstream fieldStream;
65 fieldStream.str(outputFields);
66 for (std::string line; std::getline(fieldStream, line, ',');) {
67 fieldsForOutput.insert(line);
68 }
69 // Sort through the list of fields and create lists of Shared- or ProtectedArrays that
70 // correspond to the fields.
71 for (const std::string& fieldName : fieldsForOutput) {
72 if (sharedExternalNames.count(fieldName)) {
73 sharedArraysForOutput.insert(
74 sharedArrayNames.at(sharedExternalNames.at(fieldName)));
75 } else if (protectedExternalNames.count(fieldName)) {
76 protectedArraysForOutput.insert(
77 protectedArrayNames.at(protectedExternalNames.at(fieldName)));
78 } else {
79 Logged::warning(
80 "ConfigOutput: No field with the name \"" + fieldName + "\" was found.");
81 }
82 }
83 }
84}
85
86void ConfigOutput::outputState(const ModelMetadata& meta)
87{
88 if (currentFileName == "") {
89 std::stringstream startStream;
90 startStream << meta.time();
91 currentFileName = m_filePrefix + ".nc";
92 }
93
94 ModelState state;
95 if (outputAllTheFields) {
96 for (const auto& entry : protectedArrayNames) {
98 = getProtectedArray().at(static_cast<size_t>(entry.second));
99 if (macr && macr->trueSize() > 0)
100 state.data[entry.first] = *macr;
101 }
102 for (const auto& entry : sharedArrayNames) {
103 ModelArrayReference mar = getSharedArray().at(static_cast<size_t>(entry.second));
104 if (mar && mar->trueSize() > 0)
105 state.data[entry.first] = *mar;
106 }
107 } else {
108 // Filter only the given fields to the output state
109 for (const auto& fieldExtName : fieldsForOutput) {
110 if (protectedExternalNames.count(fieldExtName)) {
111 ModelArrayConstReference macr = getProtectedArray().at(static_cast<size_t>(
112 protectedArrayNames.at(protectedExternalNames.at(fieldExtName))));
113 if (macr)
114 state.data[fieldExtName] = *macr;
115 } else if (sharedExternalNames.count(fieldExtName)) {
116 ModelArrayReference mar = getSharedArray().at(
117 static_cast<size_t>(sharedArrayNames.at(sharedExternalNames.at(fieldExtName))));
118 if (mar)
119 state.data[fieldExtName] = *mar;
120 } // else do not add any data to the state under that name
121 }
122 }
123
124 /*
125 * Produce output either:
126 * • on every timestep after the start time initially stored in lastOutput
127 * • whenever the current time is an integer number of time periods from the
128 * last output time.
129 */
130 if ((everyTS && meta.time() >= lastOutput)
131 || (std::fmod((meta.time() - lastOutput).seconds(), outputPeriod.seconds()) == 0.)) {
132 Logged::info("ConfigOutput: Outputting " + std::to_string(state.data.size()) + " fields to "
133 + currentFileName + " at " + meta.time().format() + "\n");
134 StructureFactory::fileFromState(state, meta, currentFileName, false);
135 lastOutput = meta.time();
136 }
137}
138
139std::string concatenateFields(const std::set<std::string>& strSet)
140{
141 std::string outStr = "";
142 for (auto& str : strSet) {
143 outStr += str + ",";
144 }
145 return outStr;
146}
147
148ModelState ConfigOutput::getStateRecursive(const OutputSpec& os) const
149{
150 return { {},
151 {
152 { keyMap.at(PERIOD_KEY), outputPeriod.format() },
153 { keyMap.at(START_KEY), lastOutput.format() }, // FIXME Not necessarily the start date!
154 { keyMap.at(FIELDNAMES_KEY), concatenateFields(fieldsForOutput) },
155 } };
156}
157
158} /* namespace Nextsim */
A class that holds the array data for the model.
size_t trueSize() const
Returns the size of the data array of this object.
const TimePoint & time() const
Returns the current model time.