Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <algorithm>
50 : #include <cassert>
51 : #include <cmath>
52 : #include <map>
53 : #include <ostream>
54 : #include <string>
55 : #include <vector>
56 :
57 : #include <fmt/format.h>
58 : #include <milo/dtoa.h>
59 :
60 : // ObjexxFCL Headers
61 : #include <ObjexxFCL/Array.functions.hh>
62 : #include <ObjexxFCL/Array1D.hh>
63 : #include <ObjexxFCL/Reference.fwd.hh>
64 : #include <ObjexxFCL/string.functions.hh>
65 :
66 : // EnergyPlus Headers
67 : #include <EnergyPlus/Data/EnergyPlusData.hh>
68 : #include <EnergyPlus/DataStringGlobals.hh>
69 : #include <EnergyPlus/GlobalNames.hh>
70 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
71 : #include <EnergyPlus/ResultsFramework.hh>
72 : #include <EnergyPlus/UtilityRoutines.hh>
73 :
74 : namespace EnergyPlus {
75 :
76 : namespace ResultsFramework {
77 :
78 : using namespace OutputProcessor;
79 : using OutputProcessor::RealVariables;
80 : using OutputProcessor::RealVariableType;
81 :
82 : // trim string
83 39925 : std::string trim(std::string_view const s)
84 : {
85 39925 : if (s.empty()) {
86 2645 : return std::string{};
87 : }
88 37280 : auto const first = s.find_first_not_of(' ');
89 37280 : auto const last = s.find_last_not_of(' ');
90 37280 : if ((first == std::string::npos) || (last == std::string::npos)) {
91 0 : return std::string{};
92 : } else {
93 37280 : return std::string{s.substr(first, last - first + 1)};
94 : }
95 : }
96 :
97 : // Class SimInfo
98 771 : void SimInfo::setProgramVersion(const std::string &programVersion)
99 : {
100 771 : ProgramVersion = programVersion;
101 771 : }
102 :
103 0 : std::string SimInfo::getProgramVersion() const
104 : {
105 0 : return ProgramVersion;
106 : }
107 :
108 0 : void SimInfo::setSimulationEnvironment(const std::string &simulationEnvironment)
109 : {
110 0 : SimulationEnvironment = simulationEnvironment;
111 0 : }
112 :
113 0 : void SimInfo::setInputModelURI(const std::string &inputModelURI)
114 : {
115 0 : InputModelURI = inputModelURI;
116 0 : }
117 :
118 771 : void SimInfo::setStartDateTimeStamp(const std::string &startDateTimeStamp)
119 : {
120 771 : StartDateTimeStamp = startDateTimeStamp;
121 771 : }
122 :
123 771 : void SimInfo::setRunTime(const std::string &elapsedTime)
124 : {
125 771 : RunTime = elapsedTime;
126 771 : }
127 :
128 771 : void SimInfo::setNumErrorsWarmup(const std::string &numWarningsDuringWarmup, const std::string &numSevereDuringWarmup)
129 : {
130 771 : NumWarningsDuringWarmup = numWarningsDuringWarmup;
131 771 : NumSevereDuringWarmup = numSevereDuringWarmup;
132 771 : }
133 :
134 771 : void SimInfo::setNumErrorsSizing(const std::string &numWarningsDuringSizing, const std::string &numSevereDuringSizing)
135 : {
136 771 : NumWarningsDuringSizing = numWarningsDuringSizing;
137 771 : NumSevereDuringSizing = numSevereDuringSizing;
138 771 : }
139 :
140 771 : void SimInfo::setNumErrorsSummary(const std::string &numWarnings, const std::string &numSevere)
141 : {
142 771 : NumWarnings = numWarnings;
143 771 : NumSevere = numSevere;
144 771 : }
145 :
146 2 : json SimInfo::getJSON() const
147 : {
148 : json root = {{"ProgramVersion", ProgramVersion},
149 : {"SimulationEnvironment", SimulationEnvironment},
150 : {"InputModelURI", InputModelURI},
151 : {"StartDateTimeStamp", StartDateTimeStamp},
152 : {"RunTime", RunTime},
153 : {"ErrorSummary", {{"NumWarnings", NumWarnings}, {"NumSevere", NumSevere}}},
154 : {"ErrorSummaryWarmup", {{"NumWarnings", NumWarningsDuringWarmup}, {"NumSevere", NumSevereDuringWarmup}}},
155 2 : {"ErrorSummarySizing", {{"NumWarnings", NumWarningsDuringSizing}, {"NumSevere", NumSevereDuringSizing}}}};
156 2 : return root;
157 : }
158 :
159 : // Class Variable
160 8137 : Variable::Variable(const std::string &VarName,
161 : const OutputProcessor::ReportingFrequency reportFrequency,
162 : const OutputProcessor::TimeStepType timeStepType,
163 : const int ReportID,
164 8137 : const OutputProcessor::Unit units)
165 8137 : : varName(VarName), m_timeStepType(timeStepType), rptID(ReportID), Units(units)
166 : {
167 8137 : setReportFrequency(reportFrequency);
168 8137 : }
169 :
170 5 : Variable::Variable(const std::string &VarName,
171 : const OutputProcessor::ReportingFrequency reportFrequency,
172 : const OutputProcessor::TimeStepType timeStepType,
173 : const int ReportID,
174 : const OutputProcessor::Unit units,
175 5 : const std::string &customUnits)
176 5 : : varName(VarName), m_timeStepType(timeStepType), rptID(ReportID), Units(units), m_customUnits(customUnits)
177 : {
178 5 : setReportFrequency(reportFrequency);
179 5 : }
180 :
181 497 : std::string Variable::variableName() const
182 : {
183 497 : return varName;
184 : }
185 :
186 0 : void Variable::setVariableName(const std::string &VarName)
187 : {
188 0 : varName = VarName;
189 0 : }
190 :
191 0 : std::string Variable::sReportFrequency() const
192 : {
193 0 : return sReportFreq;
194 : }
195 :
196 0 : OutputProcessor::ReportingFrequency Variable::iReportFrequency() const
197 : {
198 0 : return iReportFreq;
199 : }
200 :
201 8142 : void Variable::setReportFrequency(const OutputProcessor::ReportingFrequency reportFrequency)
202 : {
203 8142 : iReportFreq = reportFrequency;
204 8142 : switch (iReportFreq) {
205 58 : case OutputProcessor::ReportingFrequency::EachCall: // each time UpdatedataandReport is called
206 58 : if (m_timeStepType == OutputProcessor::TimeStepType::Zone) sReportFreq = "Detailed - Zone";
207 58 : if (m_timeStepType == OutputProcessor::TimeStepType::System) sReportFreq = "Detailed - HVAC";
208 58 : break;
209 50 : case OutputProcessor::ReportingFrequency::TimeStep: // at 'EndTimeStepFlag'
210 50 : sReportFreq = "TimeStep";
211 50 : break;
212 1049 : case OutputProcessor::ReportingFrequency::Hourly: // at 'EndHourFlag'
213 1049 : sReportFreq = "Hourly";
214 1049 : break;
215 71 : case OutputProcessor::ReportingFrequency::Daily: // at 'EndDayFlag'
216 71 : sReportFreq = "Daily";
217 71 : break;
218 4090 : case OutputProcessor::ReportingFrequency::Monthly: // at end of month
219 4090 : sReportFreq = "Monthly";
220 4090 : break;
221 2824 : case OutputProcessor::ReportingFrequency::Simulation: // once per environment 'EndEnvrnFlag'
222 2824 : sReportFreq = "RunPeriod";
223 2824 : break;
224 0 : case OutputProcessor::ReportingFrequency::Yearly: // once per environment 'EndEnvrnFlag'
225 0 : sReportFreq = "Yearly";
226 0 : break;
227 0 : default:
228 0 : assert(false);
229 : }
230 8142 : }
231 :
232 0 : OutputProcessor::TimeStepType Variable::timeStepType() const
233 : {
234 0 : return m_timeStepType;
235 : }
236 :
237 0 : void Variable::setTimeStepType(const OutputProcessor::TimeStepType timeStepType)
238 : {
239 0 : m_timeStepType = timeStepType;
240 0 : }
241 :
242 8113 : int Variable::reportID() const
243 : {
244 8113 : return rptID;
245 : }
246 :
247 0 : void Variable::setReportID(int Id)
248 : {
249 0 : rptID = Id;
250 0 : }
251 :
252 494 : OutputProcessor::Unit Variable::units() const
253 : {
254 494 : return Units;
255 : }
256 :
257 0 : void Variable::setUnits(const OutputProcessor::Unit units)
258 : {
259 0 : Units = units;
260 0 : }
261 :
262 382 : std::string Variable::customUnits() const
263 : {
264 382 : return m_customUnits;
265 : }
266 :
267 0 : void Variable::setCustomUnits(const std::string &customUnits)
268 : {
269 0 : m_customUnits = customUnits;
270 0 : }
271 :
272 105975 : void Variable::pushValue(const double val)
273 : {
274 105975 : Values.push_back(val);
275 105975 : }
276 :
277 25733 : double Variable::value(size_t index) const
278 : {
279 25733 : return Values.at(index);
280 : }
281 :
282 26825 : size_t Variable::numValues() const
283 : {
284 26825 : return Values.size();
285 : }
286 :
287 96 : json Variable::getJSON() const
288 : {
289 96 : json root;
290 96 : if (m_customUnits.empty()) {
291 96 : root = {{"Name", varName}, {"Units", unitEnumToString(Units)}, {"Frequency", sReportFreq}};
292 : } else {
293 0 : root = {{"Name", varName}, {"Units", m_customUnits}, {"Frequency", sReportFreq}};
294 : }
295 96 : return root;
296 : }
297 :
298 : // Class OutputVariable
299 30 : OutputVariable::OutputVariable(const std::string &VarName,
300 : const OutputProcessor::ReportingFrequency reportFrequency,
301 : const OutputProcessor::TimeStepType timeStepType,
302 : const int ReportID,
303 30 : const OutputProcessor::Unit units)
304 30 : : Variable(VarName, reportFrequency, timeStepType, ReportID, units)
305 : {
306 30 : }
307 :
308 0 : OutputVariable::OutputVariable(const std::string &VarName,
309 : const OutputProcessor::ReportingFrequency reportFrequency,
310 : const OutputProcessor::TimeStepType timeStepType,
311 : const int ReportID,
312 : const OutputProcessor::Unit units,
313 0 : const std::string &customUnits)
314 0 : : Variable(VarName, reportFrequency, timeStepType, ReportID, units, customUnits)
315 : {
316 0 : }
317 :
318 : // Class MeterVariable
319 7734 : MeterVariable::MeterVariable(const std::string &VarName,
320 : const OutputProcessor::ReportingFrequency reportFrequency,
321 : const int ReportID,
322 : const OutputProcessor::Unit units,
323 : const bool MeterOnly,
324 7734 : const bool Accumulative)
325 7734 : : Variable(VarName, reportFrequency, OutputProcessor::TimeStepType::Zone, ReportID, units)
326 : {
327 7734 : acc = Accumulative;
328 7734 : meter_only = MeterOnly;
329 7734 : }
330 :
331 0 : bool MeterVariable::accumulative() const
332 : {
333 0 : return acc;
334 : }
335 :
336 0 : void MeterVariable::setAccumulative(bool state)
337 : {
338 0 : acc = state;
339 0 : }
340 :
341 518 : bool MeterVariable::meterOnly() const
342 : {
343 518 : return meter_only;
344 : }
345 :
346 0 : void MeterVariable::setMeterOnly(bool state)
347 : {
348 0 : meter_only = state;
349 0 : }
350 :
351 0 : json MeterVariable::getJSON() const
352 : {
353 0 : json root = Variable::getJSON();
354 0 : if (acc) {
355 0 : root["Cumulative"] = true;
356 : }
357 : // if (meter_only) {
358 : // root["MeterOnly"] = true;
359 : // }
360 0 : return root;
361 : }
362 :
363 : // class DataFrame
364 10794 : DataFrame::DataFrame(const std::string &ReportFreq)
365 : {
366 10794 : ReportFrequency = ReportFreq;
367 10794 : }
368 :
369 379 : void DataFrame::addVariable(Variable const &var)
370 : {
371 379 : lastVarID = var.reportID();
372 379 : variableMap.emplace(lastVarID, var);
373 379 : }
374 :
375 0 : Variable &DataFrame::lastVariable()
376 : {
377 0 : return variableMap.at(lastVarID);
378 : }
379 :
380 22061 : void DataFrame::newRow(const int month, const int dayOfMonth, int hourOfDay, int curMin)
381 : {
382 22061 : if (curMin > 0) {
383 11340 : hourOfDay -= 1;
384 : }
385 22061 : if (curMin == 60) {
386 1584 : curMin = 0;
387 1584 : hourOfDay += 1;
388 : }
389 :
390 : // future start of ISO 8601 datetime output
391 : // fmt::format("YYYY-{:02d}/{:02d}T{:02d}:{:02d}:00", month, dayOfMonth, hourOfDay, curMin);
392 44122 : TS.emplace_back(fmt::format("{:02d}/{:02d} {:02d}:{:02d}:00", month, dayOfMonth, hourOfDay, curMin));
393 22061 : }
394 :
395 : // void DataFrame::newRow(const std::string &ts)
396 : // {
397 : // TS.emplace_back(ts);
398 : // }
399 :
400 8086 : void DataFrame::setRDataFrameEnabled(bool state)
401 : {
402 8086 : RDataFrameEnabled = state;
403 8086 : }
404 :
405 27 : void DataFrame::setIDataFrameEnabled(bool state)
406 : {
407 27 : IDataFrameEnabled = state;
408 27 : }
409 :
410 372901 : bool DataFrame::rDataFrameEnabled() const
411 : {
412 372901 : return RDataFrameEnabled;
413 : }
414 :
415 78 : bool DataFrame::iDataFrameEnabled() const
416 : {
417 78 : return IDataFrameEnabled;
418 : }
419 345784 : void DataFrame::setRVariablesScanned(bool state)
420 : {
421 345784 : RVariablesScanned = state;
422 345784 : }
423 :
424 49 : void DataFrame::setIVariablesScanned(bool state)
425 : {
426 49 : IVariablesScanned = state;
427 49 : }
428 :
429 11873 : bool DataFrame::rVariablesScanned() const
430 : {
431 11873 : return RVariablesScanned;
432 : }
433 :
434 6150 : bool DataFrame::iVariablesScanned() const
435 : {
436 6150 : return IVariablesScanned;
437 : }
438 :
439 24255 : void DataFrame::pushVariableValue(const int reportID, double value)
440 : {
441 24255 : variableMap[reportID].pushValue(value);
442 24255 : }
443 :
444 7 : json DataFrame::getVariablesJSON()
445 : {
446 7 : json arr = json::array();
447 103 : for (auto const &varMap : variableMap) {
448 96 : arr.push_back(varMap.second.getJSON());
449 : }
450 7 : return arr;
451 : }
452 :
453 12 : json DataFrame::getJSON() const
454 : {
455 12 : json root;
456 24 : json cols = json::array();
457 24 : json rows = json::array();
458 :
459 391 : for (auto const &varMap : variableMap) {
460 379 : if (varMap.second.customUnits().empty()) {
461 376 : cols.push_back({{"Variable", varMap.second.variableName()}, {"Units", unitEnumToString(varMap.second.units())}});
462 : } else {
463 3 : cols.push_back({{"Variable", varMap.second.variableName()}, {"Units", varMap.second.customUnits()}});
464 : }
465 : }
466 :
467 24 : json vals = json::array();
468 :
469 2627 : for (size_t row = 0; row < TS.size(); ++row) {
470 2615 : vals.clear();
471 :
472 27962 : for (auto const &varMap : variableMap) {
473 25347 : if (row < varMap.second.numValues()) {
474 24255 : vals.push_back(varMap.second.value(row));
475 : } else {
476 1092 : vals.push_back(nullptr);
477 : }
478 : }
479 2615 : rows.push_back({{TS.at(row), vals}});
480 : }
481 12 : root = {{"ReportFrequency", ReportFrequency}, {"Cols", cols}, {"Rows", rows}};
482 24 : return root;
483 : }
484 :
485 7734 : void MeterDataFrame::addVariable(MeterVariable const &var)
486 : {
487 7734 : lastVarID = var.reportID();
488 7734 : meterMap.emplace(lastVarID, var);
489 7734 : }
490 :
491 81720 : void MeterDataFrame::pushVariableValue(const int reportID, double value)
492 : {
493 81720 : meterMap[reportID].pushValue(value);
494 81720 : }
495 :
496 16 : json MeterDataFrame::getJSON(bool meterOnlyCheck) const
497 : {
498 16 : json root;
499 32 : json cols = json::array();
500 32 : json rows = json::array();
501 :
502 154 : for (auto const &varMap : meterMap) {
503 138 : if (!(meterOnlyCheck && varMap.second.meterOnly())) {
504 118 : cols.push_back({{"Variable", varMap.second.variableName()}, {"Units", unitEnumToString(varMap.second.units())}});
505 : }
506 : }
507 :
508 16 : if (cols.empty()) return root;
509 :
510 24 : json vals = json::array();
511 :
512 174 : for (size_t row = 0; row < TS.size(); ++row) {
513 162 : vals.clear();
514 :
515 1640 : for (auto const &varMap : meterMap) {
516 1478 : if (!(meterOnlyCheck && varMap.second.meterOnly())) {
517 1478 : if (row < varMap.second.numValues()) {
518 1478 : vals.push_back(varMap.second.value(row));
519 : } else {
520 0 : vals.push_back(nullptr);
521 : }
522 : }
523 : }
524 162 : rows.push_back({{TS.at(row), vals}});
525 : }
526 12 : root = {{"ReportFrequency", ReportFrequency}, {"Cols", cols}, {"Rows", rows}};
527 12 : return root;
528 : }
529 :
530 4 : void DataFrame::writeReport(JsonOutputFilePaths &jsonOutputFilePaths, bool outputJSON, bool outputCBOR, bool outputMsgPack)
531 : {
532 :
533 8 : json root = getJSON();
534 4 : if (ReportFrequency == "Detailed-HVAC") {
535 1 : if (outputJSON) {
536 1 : FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputTSHvacJsonFilePath, root);
537 : }
538 1 : if (outputCBOR) {
539 1 : FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputTSHvacCborFilePath, root);
540 : }
541 1 : if (outputMsgPack) {
542 1 : FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputTSHvacMsgPackFilePath, root);
543 : }
544 3 : } else if (ReportFrequency == "Detailed-Zone") {
545 0 : if (outputJSON) {
546 0 : FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputTSZoneJsonFilePath, root);
547 : }
548 0 : if (outputCBOR) {
549 0 : FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputTSZoneCborFilePath, root);
550 : }
551 0 : if (outputMsgPack) {
552 0 : FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputTSZoneMsgPackFilePath, root);
553 : }
554 3 : } else if (ReportFrequency == "TimeStep") {
555 0 : if (outputJSON) {
556 0 : FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputTSJsonFilePath, root);
557 : }
558 0 : if (outputCBOR) {
559 0 : FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputTSCborFilePath, root);
560 : }
561 0 : if (outputMsgPack) {
562 0 : FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputTSMsgPackFilePath, root);
563 : }
564 3 : } else if (ReportFrequency == "Daily") {
565 0 : if (outputJSON) {
566 0 : FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputDYJsonFilePath, root);
567 : }
568 0 : if (outputCBOR) {
569 0 : FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputDYCborFilePath, root);
570 : }
571 0 : if (outputMsgPack) {
572 0 : FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputDYMsgPackFilePath, root);
573 : }
574 3 : } else if (ReportFrequency == "Hourly") {
575 3 : if (outputJSON) {
576 3 : FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputHRJsonFilePath, root);
577 : }
578 3 : if (outputCBOR) {
579 1 : FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputHRCborFilePath, root);
580 : }
581 3 : if (outputMsgPack) {
582 1 : FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputHRMsgPackFilePath, root);
583 : }
584 0 : } else if (ReportFrequency == "Monthly") {
585 0 : if (outputJSON) {
586 0 : FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputMNJsonFilePath, root);
587 : }
588 0 : if (outputCBOR) {
589 0 : FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputMNCborFilePath, root);
590 : }
591 0 : if (outputMsgPack) {
592 0 : FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputMNMsgPackFilePath, root);
593 : }
594 0 : } else if (ReportFrequency == "RunPeriod") {
595 0 : if (outputJSON) {
596 0 : FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputSMJsonFilePath, root);
597 : }
598 0 : if (outputCBOR) {
599 0 : FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputSMCborFilePath, root);
600 : }
601 0 : if (outputMsgPack) {
602 0 : FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputSMMsgPackFilePath, root);
603 : }
604 0 : } else if (ReportFrequency == "Yearly") {
605 0 : if (outputJSON) {
606 0 : FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputYRJsonFilePath, root);
607 : }
608 0 : if (outputCBOR) {
609 0 : FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputYRCborFilePath, root);
610 : }
611 0 : if (outputMsgPack) {
612 0 : FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputYRMsgPackFilePath, root);
613 : }
614 : }
615 4 : }
616 : // class Table
617 :
618 676 : Table::Table(Array2D_string const &body,
619 : Array1D_string const &rowLabels,
620 : Array1D_string const &columnLabels,
621 : std::string const &tableName,
622 676 : std::string const &footnoteText)
623 : {
624 :
625 676 : size_t sizeColumnLabels = columnLabels.size();
626 676 : size_t sizeRowLabels = rowLabels.size();
627 676 : TableName = tableName;
628 676 : FootnoteText = footnoteText;
629 :
630 5562 : for (size_t iCol = 0, k = body.index(1, 1); iCol < sizeColumnLabels; ++iCol) {
631 4886 : ColHeaders.push_back(columnLabels[iCol]);
632 9772 : std::vector<std::string> col;
633 44811 : for (size_t iRow = 0; iRow < sizeRowLabels; ++iRow) {
634 39925 : if (iCol == 0) {
635 : // do this once only
636 4431 : RowHeaders.push_back(rowLabels[iRow]);
637 : }
638 39925 : col.push_back(trim(body[k]));
639 39925 : ++k;
640 : }
641 4886 : Data.push_back(col);
642 : }
643 676 : }
644 :
645 260 : json Table::getJSON() const
646 : {
647 260 : json root;
648 520 : json cols = json::array();
649 520 : json rows;
650 :
651 2091 : for (size_t col = 0; col < ColHeaders.size(); ++col) {
652 1831 : cols.push_back(ColHeaders[col]);
653 : }
654 :
655 1917 : for (size_t row = 0; row < RowHeaders.size(); ++row) {
656 3314 : json rowvec = json::array();
657 14833 : for (size_t col = 0; col < ColHeaders.size(); ++col) {
658 13176 : rowvec.push_back(Data[col][row]);
659 : }
660 1657 : rows[RowHeaders[row]] = rowvec;
661 : }
662 :
663 260 : root = {{"TableName", TableName}, {"Cols", cols}, {"Rows", rows}};
664 :
665 260 : if (!FootnoteText.empty()) root["Footnote"] = FootnoteText;
666 520 : return root;
667 : }
668 :
669 : // class Report
670 :
671 35 : json Report::getJSON() const
672 : {
673 :
674 35 : json root = {{"ReportName", ReportName}, {"For", ReportForString}};
675 :
676 70 : json cols = json::array();
677 :
678 295 : for (auto const &table : Tables) {
679 260 : cols.push_back(table.getJSON());
680 : }
681 :
682 35 : root["Tables"] = cols;
683 70 : return root;
684 : }
685 :
686 : // class ReportsCollection
687 771 : ReportsCollection::ReportsCollection()
688 : {
689 771 : }
690 :
691 620 : void ReportsCollection::addReportTable(Array2D_string const &body,
692 : Array1D_string const &rowLabels,
693 : Array1D_string const &columnLabels,
694 : std::string const &reportName,
695 : std::string const &reportForString,
696 : std::string const &tableName)
697 : {
698 620 : addReportTable(body, rowLabels, columnLabels, reportName, reportForString, tableName, "");
699 620 : }
700 :
701 676 : void ReportsCollection::addReportTable(Array2D_string const &body,
702 : Array1D_string const &rowLabels,
703 : Array1D_string const &columnLabels,
704 : std::string const &reportName,
705 : std::string const &reportForString,
706 : std::string const &tableName,
707 : std::string const &footnoteText)
708 : {
709 1352 : std::string const key = reportName + reportForString;
710 : // Report *r;
711 1352 : Table tbl(body, rowLabels, columnLabels, tableName, footnoteText);
712 :
713 1352 : auto search = reportsMap.find(key);
714 676 : if (search != reportsMap.end()) {
715 : // r = search->second;
716 563 : search->second.Tables.push_back(tbl);
717 : } else {
718 : // r = new Report();
719 226 : Report r;
720 113 : r.ReportName = reportName;
721 113 : r.ReportForString = reportForString;
722 113 : r.Tables.push_back(tbl);
723 113 : reportsMap.emplace(key, r);
724 : }
725 :
726 : // Table *tbl = new Table( body, rowLabels, columnLabels, tableName, footnoteText );
727 : // r->Tables.push_back( tbl );
728 676 : }
729 :
730 2 : json ReportsCollection::getJSON() const
731 : {
732 2 : json root = json::array();
733 :
734 37 : for (auto const &iter : reportsMap) {
735 35 : root.push_back(iter.second.getJSON());
736 : }
737 2 : return root;
738 : }
739 :
740 20 : void CSVWriter::parseTSOutputs(EnergyPlusData &state,
741 : json const &data,
742 : std::vector<std::string> const &outputVariables,
743 : OutputProcessor::ReportingFrequency reportingFrequency)
744 : {
745 20 : if (data.empty()) return;
746 16 : updateReportingFrequency(reportingFrequency);
747 32 : std::vector<int> indices;
748 32 : std::unordered_set<std::string> seen;
749 32 : std::string search_string;
750 :
751 32 : std::string reportFrequency = data.at("ReportFrequency").get<std::string>();
752 16 : if (reportFrequency == "Detailed-HVAC" || reportFrequency == "Detailed-Zone") {
753 6 : reportFrequency = "Each Call";
754 : }
755 16 : auto const &columns = data.at("Cols");
756 168 : for (auto const &column : columns) {
757 152 : search_string =
758 304 : fmt::format("{0} [{1}]({2})", column.at("Variable").get<std::string>(), column.at("Units").get<std::string>(), reportFrequency);
759 304 : auto found = std::find(outputVariables.begin(), outputVariables.end(), search_string);
760 152 : if (found == outputVariables.end()) {
761 0 : search_string =
762 0 : fmt::format("{0} [{1}]({2})", column.at("Variable").get<std::string>(), column.at("Units").get<std::string>(), "Each Call");
763 0 : found = std::find(outputVariables.begin(), outputVariables.end(), search_string);
764 : }
765 152 : if (found == outputVariables.end()) {
766 0 : ShowFatalError(state, fmt::format("Output variable ({0}) not found output variable list", search_string));
767 : }
768 152 : outputVariableIndices[std::distance(outputVariables.begin(), found)] = true;
769 152 : indices.emplace_back(std::distance(outputVariables.begin(), found));
770 : }
771 :
772 16 : auto const &rows = data.at("Rows");
773 1968 : for (auto const &row : rows) {
774 3904 : for (auto &el : row.items()) {
775 3904 : auto found_key = outputs.find(el.key());
776 1952 : if (found_key == outputs.end()) {
777 2832 : std::vector<std::string> output(outputVariables.size());
778 1416 : int i = 0;
779 10659 : for (auto const &col : el.value()) {
780 9243 : if (col.is_null()) {
781 0 : output[indices[i]] = "";
782 : } else {
783 9243 : dtoa(col.get<double>(), s);
784 9243 : output[indices[i]] = s;
785 : }
786 9243 : ++i;
787 : }
788 1416 : outputs[el.key()] = output;
789 : } else {
790 536 : int i = 0;
791 1918 : for (auto const &col : el.value()) {
792 1382 : if (col.is_null()) {
793 0 : found_key->second[indices[i]] = "";
794 : } else {
795 1382 : dtoa(col.get<double>(), s);
796 1382 : found_key->second[indices[i]] = s;
797 : }
798 1382 : ++i;
799 : }
800 : }
801 : }
802 : }
803 : }
804 :
805 16 : void CSVWriter::updateReportingFrequency(OutputProcessor::ReportingFrequency reportingFrequency)
806 : {
807 16 : if (reportingFrequency < smallestReportingFrequency) {
808 13 : smallestReportingFrequency = reportingFrequency;
809 : }
810 16 : }
811 :
812 4 : std::string &CSVWriter::convertToMonth(EnergyPlusData &state, std::string &datetime)
813 : {
814 : // if running this function, there should only ever be 12 + design days values to change
815 : static const std::map<std::string, std::string> months({{"01", "January"},
816 : {"02", "February"},
817 : {"03", "March"},
818 : {"04", "April"},
819 : {"05", "May"},
820 : {"06", "June"},
821 : {"07", "July"},
822 : {"08", "August"},
823 : {"09", "September"},
824 : {"10", "October"},
825 : {"11", "November"},
826 4 : {"12", "December"}});
827 : // 01/01 24:00:00
828 8 : auto const month = datetime.substr(0, 2);
829 4 : auto const pos = datetime.find(' ');
830 8 : std::string time;
831 4 : if (pos != std::string::npos) {
832 4 : time = datetime.substr(pos);
833 : }
834 4 : if (time != " 24:00:00") {
835 0 : ShowFatalError(state, "Monthly output variables should occur at the end of the day.");
836 : }
837 4 : datetime = months.find(month)->second;
838 8 : return datetime;
839 : }
840 :
841 : void
842 7 : CSVWriter::writeOutput(EnergyPlusData &state, std::vector<std::string> const &outputVariables, InputOutputFile &outputFile, bool outputControl)
843 : {
844 7 : outputFile.ensure_open(state, "OpenOutputFiles", outputControl);
845 :
846 7 : print<FormatSyntax::FMT>(outputFile, "{}", "Date/Time,");
847 14 : std::string sep;
848 246 : for (auto it = outputVariables.begin(); it != outputVariables.end(); ++it) {
849 239 : if (!outputVariableIndices[std::distance(outputVariables.begin(), it)]) continue;
850 152 : print<FormatSyntax::FMT>(outputFile, "{}{}", sep, *it);
851 152 : if (sep.empty()) sep = ",";
852 : }
853 7 : print<FormatSyntax::FMT>(outputFile, "{}", '\n');
854 :
855 1423 : for (auto &item : outputs) {
856 2832 : std::string datetime = item.first;
857 1416 : if (smallestReportingFrequency < OutputProcessor::ReportingFrequency::Monthly) {
858 1412 : datetime = datetime.replace(datetime.find(' '), 1, " ");
859 : } else {
860 4 : convertToMonth(state, datetime);
861 : }
862 1416 : print<FormatSyntax::FMT>(outputFile, " {},", datetime);
863 5664 : item.second.erase(std::remove_if(item.second.begin(),
864 2832 : item.second.end(),
865 63896 : [&](const std::string &d) {
866 63896 : auto pos = (&d - &*item.second.begin());
867 63896 : return !outputVariableIndices[pos];
868 : }),
869 2832 : item.second.end());
870 29349 : auto result = std::find_if(item.second.rbegin(), item.second.rend(), [](std::string const &v) { return !v.empty(); });
871 2832 : auto last = item.second.end() - 1;
872 1416 : if (result != item.second.rend()) {
873 1416 : last = (result + 1).base();
874 : }
875 :
876 1416 : print<FormatSyntax::FMT>(outputFile, "{},", fmt::join(item.second.begin(), last, ","));
877 1416 : print<FormatSyntax::FMT>(outputFile, "{}\n", *last);
878 : }
879 :
880 7 : outputFile.close();
881 7 : }
882 :
883 771 : void ResultsFramework::setupOutputOptions(EnergyPlusData &state)
884 : {
885 771 : if (state.files.outputControl.csv) {
886 4 : tsEnabled = true;
887 4 : tsAndTabularEnabled = true;
888 : }
889 :
890 771 : if (!state.files.outputControl.json) {
891 769 : return;
892 : }
893 :
894 770 : int numberOfOutputSchemaObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Output:JSON");
895 770 : if (numberOfOutputSchemaObjects == 0) {
896 767 : return;
897 : }
898 :
899 6 : Array1D_string alphas(5);
900 : int numAlphas;
901 6 : Array1D<Real64> numbers(2);
902 : int numNumbers;
903 : int status;
904 3 : state.dataInputProcessing->inputProcessor->getObjectItem(state, "Output:JSON", 1, alphas, numAlphas, numbers, numNumbers, status);
905 :
906 3 : if (numAlphas > 0) {
907 6 : std::string option = alphas(1);
908 3 : if (UtilityRoutines::SameString(option, "TimeSeries")) {
909 1 : tsEnabled = true;
910 2 : } else if (UtilityRoutines::SameString(option, "TimeSeriesAndTabular")) {
911 2 : tsEnabled = true;
912 2 : tsAndTabularEnabled = true;
913 : }
914 :
915 : // defaults
916 3 : outputJSON = true;
917 3 : outputCBOR = false;
918 3 : outputMsgPack = false;
919 :
920 3 : if (numAlphas >= 2) {
921 2 : outputJSON = UtilityRoutines::SameString(alphas(2), "Yes");
922 : }
923 :
924 3 : if (numAlphas >= 3) {
925 2 : outputCBOR = UtilityRoutines::SameString(alphas(3), "Yes");
926 : }
927 :
928 3 : if (numAlphas >= 4) {
929 2 : outputMsgPack = UtilityRoutines::SameString(alphas(4), "Yes");
930 : }
931 : }
932 : }
933 :
934 11647089 : bool ResultsFramework::timeSeriesEnabled() const
935 : {
936 11647089 : return tsEnabled;
937 : }
938 :
939 127502 : bool ResultsFramework::timeSeriesAndTabularEnabled() const
940 : {
941 127502 : return tsAndTabularEnabled;
942 : }
943 :
944 0 : bool ResultsFramework::JSONEnabled() const
945 : {
946 0 : return outputJSON;
947 : }
948 :
949 0 : bool ResultsFramework::CBOREnabled() const
950 : {
951 0 : return outputCBOR;
952 : }
953 :
954 0 : bool ResultsFramework::MsgPackEnabled() const
955 : {
956 0 : return outputMsgPack;
957 : }
958 :
959 49 : void ResultsFramework::initializeRTSDataFrame(const OutputProcessor::ReportingFrequency reportFrequency,
960 : const Array1D<RealVariableType> &RVariableTypes,
961 : const int NumOfRVariable,
962 : const OutputProcessor::TimeStepType timeStepType)
963 : {
964 98 : Reference<RealVariables> RVar;
965 :
966 7812 : for (int Loop = 1; Loop <= NumOfRVariable; ++Loop) {
967 7763 : RVar >>= RVariableTypes(Loop).VarPtr;
968 7763 : auto &rVar(RVar());
969 7763 : if (rVar.Report && rVar.frequency == reportFrequency) {
970 756 : Variable var;
971 378 : if (RVariableTypes(Loop).units == OutputProcessor::Unit::customEMS) {
972 10 : var = Variable(RVariableTypes(Loop).VarName,
973 : reportFrequency,
974 5 : RVariableTypes(Loop).timeStepType,
975 5 : RVariableTypes(Loop).ReportID,
976 5 : RVariableTypes(Loop).units,
977 5 : RVariableTypes(Loop).unitNameCustomEMS);
978 : } else {
979 373 : var = Variable(RVariableTypes(Loop).VarName,
980 : reportFrequency,
981 373 : RVariableTypes(Loop).timeStepType,
982 373 : RVariableTypes(Loop).ReportID,
983 373 : RVariableTypes(Loop).units);
984 : }
985 378 : switch (reportFrequency) {
986 52 : case OutputProcessor::ReportingFrequency::EachCall: // each time UpdatedataandReport is called
987 78 : if ((timeStepType == OutputProcessor::TimeStepType::Zone) &&
988 26 : (RVariableTypes(Loop).timeStepType == OutputProcessor::TimeStepType::Zone)) {
989 2 : RIDetailedZoneTSData.setRDataFrameEnabled(true);
990 2 : RIDetailedZoneTSData.addVariable(var);
991 76 : } else if ((timeStepType == OutputProcessor::TimeStepType::System) &&
992 26 : (RVariableTypes(Loop).timeStepType == OutputProcessor::TimeStepType::System)) {
993 24 : RIDetailedHVACTSData.setRDataFrameEnabled(true);
994 24 : RIDetailedHVACTSData.addVariable(var);
995 : }
996 52 : break;
997 0 : case OutputProcessor::ReportingFrequency::TimeStep: // at 'EndTimeStepFlag'
998 0 : RITimestepTSData.setRDataFrameEnabled(true);
999 0 : RITimestepTSData.addVariable(var);
1000 0 : break;
1001 326 : case OutputProcessor::ReportingFrequency::Hourly: // at 'EndHourFlag'
1002 326 : RIHourlyTSData.setRDataFrameEnabled(true);
1003 326 : RIHourlyTSData.addVariable(var);
1004 326 : break;
1005 0 : case OutputProcessor::ReportingFrequency::Daily: // at 'EndDayFlag'
1006 0 : RIDailyTSData.setRDataFrameEnabled(true);
1007 0 : RIDailyTSData.addVariable(var);
1008 0 : break;
1009 0 : case OutputProcessor::ReportingFrequency::Monthly: // at end of month
1010 0 : RIMonthlyTSData.setRDataFrameEnabled(true);
1011 0 : RIMonthlyTSData.addVariable(var);
1012 0 : break;
1013 0 : case OutputProcessor::ReportingFrequency::Simulation: // once per environment 'EndEnvrnFlag'
1014 0 : RIRunPeriodTSData.setRDataFrameEnabled(true);
1015 0 : RIRunPeriodTSData.addVariable(var);
1016 0 : break;
1017 0 : case OutputProcessor::ReportingFrequency::Yearly: // at end of year
1018 0 : RIYearlyTSData.setRDataFrameEnabled(true);
1019 0 : RIYearlyTSData.addVariable(var);
1020 0 : break;
1021 0 : default:
1022 0 : assert(false);
1023 : }
1024 : }
1025 : }
1026 : // set the scanned variables to true or false
1027 49 : switch (reportFrequency) {
1028 14 : case OutputProcessor::ReportingFrequency::EachCall:
1029 14 : if (timeStepType == OutputProcessor::TimeStepType::Zone) {
1030 7 : RIDetailedZoneTSData.setRVariablesScanned(true);
1031 7 : } else if (timeStepType == OutputProcessor::TimeStepType::System) {
1032 7 : RIDetailedHVACTSData.setRVariablesScanned(true);
1033 : }
1034 14 : break;
1035 7 : case OutputProcessor::ReportingFrequency::TimeStep: // at 'EndTimeStepFlag'
1036 7 : RITimestepTSData.setRVariablesScanned(true);
1037 7 : break;
1038 7 : case OutputProcessor::ReportingFrequency::Hourly: // at 'EndHourFlag'
1039 7 : RIHourlyTSData.setRVariablesScanned(true);
1040 7 : break;
1041 7 : case OutputProcessor::ReportingFrequency::Daily: // at 'EndDayFlag'
1042 7 : RIDailyTSData.setRVariablesScanned(true);
1043 7 : break;
1044 7 : case OutputProcessor::ReportingFrequency::Monthly: // at end of month
1045 7 : RIMonthlyTSData.setRVariablesScanned(true);
1046 7 : break;
1047 7 : case OutputProcessor::ReportingFrequency::Simulation: // once per environment 'EndEnvrnFlag'
1048 7 : RIRunPeriodTSData.setRVariablesScanned(true);
1049 7 : break;
1050 0 : case OutputProcessor::ReportingFrequency::Yearly: // at end of year
1051 0 : RIYearlyTSData.setRVariablesScanned(true);
1052 0 : break;
1053 0 : default:
1054 0 : assert(false);
1055 : }
1056 49 : }
1057 :
1058 49 : void ResultsFramework::initializeITSDataFrame(const OutputProcessor::ReportingFrequency reportFrequency,
1059 : const Array1D<IntegerVariableType> &IVariableTypes,
1060 : const int NumOfIVariable,
1061 : const OutputProcessor::TimeStepType timeStepType)
1062 : {
1063 98 : Reference<IntegerVariables> IVar;
1064 :
1065 : // loop over values to suck in var info
1066 238 : for (int Loop = 1; Loop <= NumOfIVariable; ++Loop) {
1067 189 : IVar >>= IVariableTypes(Loop).VarPtr;
1068 189 : auto &iVar(IVar());
1069 189 : if (iVar.Report && iVar.frequency == reportFrequency) {
1070 30 : OutputVariable var(IVariableTypes(Loop).VarName,
1071 : reportFrequency,
1072 30 : IVariableTypes(Loop).timeStepType,
1073 30 : IVariableTypes(Loop).ReportID,
1074 90 : IVariableTypes(Loop).units);
1075 30 : switch (reportFrequency) {
1076 6 : case OutputProcessor::ReportingFrequency::EachCall: // each time UpdatedataandReport is called
1077 9 : if ((timeStepType == OutputProcessor::TimeStepType::Zone) &&
1078 3 : (IVariableTypes(Loop).timeStepType == OutputProcessor::TimeStepType::Zone)) {
1079 0 : RIDetailedZoneTSData.setIDataFrameEnabled(true);
1080 0 : RIDetailedZoneTSData.addVariable(var);
1081 9 : } else if ((timeStepType == OutputProcessor::TimeStepType::System) &&
1082 3 : (IVariableTypes(Loop).timeStepType == OutputProcessor::TimeStepType::System)) {
1083 3 : RIDetailedHVACTSData.setIDataFrameEnabled(true);
1084 3 : RIDetailedHVACTSData.addVariable(var);
1085 : }
1086 6 : break;
1087 0 : case OutputProcessor::ReportingFrequency::TimeStep: // at 'EndTimeStepFlag'
1088 0 : RITimestepTSData.setIDataFrameEnabled(true);
1089 0 : RITimestepTSData.addVariable(var);
1090 0 : break;
1091 24 : case OutputProcessor::ReportingFrequency::Hourly: // at 'EndHourFlag'
1092 24 : RIHourlyTSData.setIDataFrameEnabled(true);
1093 24 : RIHourlyTSData.addVariable(var);
1094 24 : break;
1095 0 : case OutputProcessor::ReportingFrequency::Daily: // at 'EndDayFlag'
1096 0 : RIDailyTSData.setIDataFrameEnabled(true);
1097 0 : RIDailyTSData.addVariable(var);
1098 0 : break;
1099 0 : case OutputProcessor::ReportingFrequency::Monthly: // at end of month
1100 0 : RIMonthlyTSData.setIDataFrameEnabled(true);
1101 0 : RIMonthlyTSData.addVariable(var);
1102 0 : break;
1103 0 : case OutputProcessor::ReportingFrequency::Simulation: // once per environment 'EndEnvrnFlag'
1104 0 : RIRunPeriodTSData.setIDataFrameEnabled(true);
1105 0 : RIRunPeriodTSData.addVariable(var);
1106 0 : break;
1107 0 : case OutputProcessor::ReportingFrequency::Yearly: // once per environment 'EndEnvrnFlag'
1108 0 : RIYearlyTSData.setIDataFrameEnabled(true);
1109 0 : RIYearlyTSData.addVariable(var);
1110 0 : break;
1111 0 : default:
1112 0 : assert(false);
1113 : }
1114 : }
1115 : }
1116 :
1117 : // set the scanned variables to true or false
1118 49 : switch (reportFrequency) {
1119 14 : case OutputProcessor::ReportingFrequency::EachCall:
1120 14 : if (timeStepType == OutputProcessor::TimeStepType::Zone) {
1121 7 : RIDetailedZoneTSData.setIVariablesScanned(true);
1122 7 : } else if (timeStepType == OutputProcessor::TimeStepType::System) {
1123 7 : RIDetailedHVACTSData.setIVariablesScanned(true);
1124 : }
1125 14 : break;
1126 7 : case OutputProcessor::ReportingFrequency::TimeStep: // at 'EndTimeStepFlag'
1127 7 : RITimestepTSData.setIVariablesScanned(true);
1128 7 : break;
1129 7 : case OutputProcessor::ReportingFrequency::Hourly: // at 'EndHourFlag'
1130 7 : RIHourlyTSData.setIVariablesScanned(true);
1131 7 : break;
1132 7 : case OutputProcessor::ReportingFrequency::Daily: // at 'EndDayFlag'
1133 7 : RIDailyTSData.setIVariablesScanned(true);
1134 7 : break;
1135 7 : case OutputProcessor::ReportingFrequency::Monthly: // at end of month
1136 7 : RIMonthlyTSData.setIVariablesScanned(true);
1137 7 : break;
1138 7 : case OutputProcessor::ReportingFrequency::Simulation: // once per environment 'EndEnvrnFlag'
1139 7 : RIRunPeriodTSData.setIVariablesScanned(true);
1140 7 : break;
1141 0 : case OutputProcessor::ReportingFrequency::Yearly: // once per environment 'EndEnvrnFlag'
1142 0 : RIYearlyTSData.setIVariablesScanned(true);
1143 0 : break;
1144 0 : default:
1145 0 : assert(false);
1146 : }
1147 49 : }
1148 :
1149 345735 : void ResultsFramework::initializeMeters(const Array1D<OutputProcessor::MeterType> &EnergyMeters,
1150 : const OutputProcessor::ReportingFrequency reportFrequency)
1151 : {
1152 345735 : switch (reportFrequency) {
1153 0 : case OutputProcessor::ReportingFrequency::EachCall:
1154 : // nothing to do; meters are not reported at this frequency
1155 0 : break;
1156 293532 : case OutputProcessor::ReportingFrequency::TimeStep: // at 'TimeStep'
1157 35540740 : for (auto Loop = 1; Loop <= EnergyMeters.isize(); ++Loop) {
1158 35247208 : if (EnergyMeters(Loop).RptTS || EnergyMeters(Loop).RptTSFO) {
1159 : MeterVariable var(
1160 100 : EnergyMeters(Loop).Name, reportFrequency, EnergyMeters(Loop).TSRptNum, EnergyMeters(Loop).Units, EnergyMeters(Loop).RptTSFO);
1161 50 : TSMeters.addVariable(var);
1162 50 : TSMeters.setRDataFrameEnabled(true);
1163 : }
1164 35247208 : if (EnergyMeters(Loop).RptAccTS || EnergyMeters(Loop).RptAccTSFO) {
1165 0 : MeterVariable var(EnergyMeters(Loop).Name,
1166 : reportFrequency,
1167 0 : EnergyMeters(Loop).TSAccRptNum,
1168 0 : EnergyMeters(Loop).Units,
1169 0 : EnergyMeters(Loop).RptAccTSFO);
1170 0 : TSMeters.addVariable(var);
1171 0 : TSMeters.setRDataFrameEnabled(true);
1172 : }
1173 293532 : }
1174 293532 : break;
1175 49894 : case OutputProcessor::ReportingFrequency::Hourly: // at 'Hourly'
1176 5504839 : for (auto Loop = 1; Loop <= EnergyMeters.isize(); ++Loop) {
1177 5454945 : if (EnergyMeters(Loop).RptHR || EnergyMeters(Loop).RptHRFO) {
1178 : MeterVariable var(
1179 1398 : EnergyMeters(Loop).Name, reportFrequency, EnergyMeters(Loop).HRRptNum, EnergyMeters(Loop).Units, EnergyMeters(Loop).RptHRFO);
1180 699 : HRMeters.addVariable(var);
1181 699 : HRMeters.setRDataFrameEnabled(true);
1182 : }
1183 5454945 : if (EnergyMeters(Loop).RptAccHR || EnergyMeters(Loop).RptAccHRFO) {
1184 0 : MeterVariable var(EnergyMeters(Loop).Name,
1185 : reportFrequency,
1186 0 : EnergyMeters(Loop).HRAccRptNum,
1187 0 : EnergyMeters(Loop).Units,
1188 0 : EnergyMeters(Loop).RptAccHRFO);
1189 0 : HRMeters.addVariable(var);
1190 0 : HRMeters.setRDataFrameEnabled(true);
1191 : }
1192 49894 : }
1193 49894 : break;
1194 769 : case OutputProcessor::ReportingFrequency::Daily: // at 'Daily'
1195 93658 : for (auto Loop = 1; Loop <= EnergyMeters.isize(); ++Loop) {
1196 92889 : if (EnergyMeters(Loop).RptDY || EnergyMeters(Loop).RptDYFO) {
1197 : MeterVariable var(
1198 142 : EnergyMeters(Loop).Name, reportFrequency, EnergyMeters(Loop).DYRptNum, EnergyMeters(Loop).Units, EnergyMeters(Loop).RptDYFO);
1199 71 : DYMeters.addVariable(var);
1200 71 : DYMeters.setRDataFrameEnabled(true);
1201 : }
1202 92889 : if (EnergyMeters(Loop).RptAccDY || EnergyMeters(Loop).RptAccDYFO) {
1203 0 : MeterVariable var(EnergyMeters(Loop).Name,
1204 : reportFrequency,
1205 0 : EnergyMeters(Loop).DYAccRptNum,
1206 0 : EnergyMeters(Loop).Units,
1207 0 : EnergyMeters(Loop).RptAccDYFO);
1208 0 : DYMeters.addVariable(var);
1209 0 : DYMeters.setRDataFrameEnabled(true);
1210 : }
1211 769 : }
1212 769 : break;
1213 769 : case OutputProcessor::ReportingFrequency::Monthly: // at 'Monthly'
1214 93658 : for (auto Loop = 1; Loop <= EnergyMeters.isize(); ++Loop) {
1215 92889 : if (EnergyMeters(Loop).RptMN || EnergyMeters(Loop).RptMNFO) {
1216 : MeterVariable var(
1217 8170 : EnergyMeters(Loop).Name, reportFrequency, EnergyMeters(Loop).MNRptNum, EnergyMeters(Loop).Units, EnergyMeters(Loop).RptMNFO);
1218 4085 : MNMeters.addVariable(var);
1219 4085 : MNMeters.setRDataFrameEnabled(true);
1220 : }
1221 92889 : if (EnergyMeters(Loop).RptAccMN || EnergyMeters(Loop).RptAccMNFO) {
1222 5 : MeterVariable var(EnergyMeters(Loop).Name,
1223 : reportFrequency,
1224 5 : EnergyMeters(Loop).MNAccRptNum,
1225 5 : EnergyMeters(Loop).Units,
1226 15 : EnergyMeters(Loop).RptAccMNFO);
1227 5 : MNMeters.addVariable(var);
1228 5 : MNMeters.setRDataFrameEnabled(true);
1229 : }
1230 769 : }
1231 769 : break;
1232 769 : case OutputProcessor::ReportingFrequency::Simulation: // at 'RunPeriod'/'SM'
1233 93658 : for (auto Loop = 1; Loop <= EnergyMeters.isize(); ++Loop) {
1234 92889 : if (EnergyMeters(Loop).RptSM || EnergyMeters(Loop).RptSMFO) {
1235 : MeterVariable var(
1236 5648 : EnergyMeters(Loop).Name, reportFrequency, EnergyMeters(Loop).SMRptNum, EnergyMeters(Loop).Units, EnergyMeters(Loop).RptSMFO);
1237 2824 : SMMeters.addVariable(var);
1238 2824 : SMMeters.setRDataFrameEnabled(true);
1239 : }
1240 92889 : if (EnergyMeters(Loop).RptAccSM || EnergyMeters(Loop).RptAccSMFO) {
1241 0 : MeterVariable var(EnergyMeters(Loop).Name,
1242 : reportFrequency,
1243 0 : EnergyMeters(Loop).SMAccRptNum,
1244 0 : EnergyMeters(Loop).Units,
1245 0 : EnergyMeters(Loop).RptAccSMFO);
1246 0 : SMMeters.addVariable(var);
1247 0 : SMMeters.setRDataFrameEnabled(true);
1248 : }
1249 769 : }
1250 769 : break;
1251 2 : case OutputProcessor::ReportingFrequency::Yearly: // at 'Yearly'
1252 236 : for (auto Loop = 1; Loop <= EnergyMeters.isize(); ++Loop) {
1253 234 : if (EnergyMeters(Loop).RptYR || EnergyMeters(Loop).RptYRFO) {
1254 : MeterVariable var(
1255 0 : EnergyMeters(Loop).Name, reportFrequency, EnergyMeters(Loop).YRRptNum, EnergyMeters(Loop).Units, EnergyMeters(Loop).RptYRFO);
1256 0 : YRMeters.addVariable(var);
1257 0 : YRMeters.setRDataFrameEnabled(true);
1258 : }
1259 234 : if (EnergyMeters(Loop).RptAccYR || EnergyMeters(Loop).RptAccYRFO) {
1260 0 : MeterVariable var(EnergyMeters(Loop).Name,
1261 : reportFrequency,
1262 0 : EnergyMeters(Loop).YRAccRptNum,
1263 0 : EnergyMeters(Loop).Units,
1264 0 : EnergyMeters(Loop).RptAccDYFO);
1265 0 : YRMeters.addVariable(var);
1266 0 : YRMeters.setRDataFrameEnabled(true);
1267 : }
1268 2 : }
1269 2 : break;
1270 0 : default:
1271 0 : assert(false);
1272 : }
1273 :
1274 : // set the scanned variables to true or false
1275 345735 : switch (reportFrequency) {
1276 0 : case OutputProcessor::ReportingFrequency::EachCall:
1277 : // case should not happen in Meters
1278 0 : break;
1279 293532 : case OutputProcessor::ReportingFrequency::TimeStep: // at TimeStepFlag
1280 293532 : TSMeters.setRVariablesScanned(true);
1281 293532 : break;
1282 49894 : case OutputProcessor::ReportingFrequency::Hourly: // at Hourly
1283 49894 : HRMeters.setRVariablesScanned(true);
1284 49894 : break;
1285 769 : case OutputProcessor::ReportingFrequency::Daily: // at Daily
1286 769 : DYMeters.setRVariablesScanned(true);
1287 769 : break;
1288 769 : case OutputProcessor::ReportingFrequency::Monthly: // at Monthly
1289 769 : MNMeters.setRVariablesScanned(true);
1290 769 : break;
1291 769 : case OutputProcessor::ReportingFrequency::Simulation: // at RunPeriod/SM
1292 769 : SMMeters.setRVariablesScanned(true);
1293 769 : break;
1294 2 : case OutputProcessor::ReportingFrequency::Yearly: // at Yearly
1295 2 : YRMeters.setRVariablesScanned(true);
1296 2 : break;
1297 0 : default:
1298 0 : assert(false);
1299 : }
1300 345735 : }
1301 :
1302 771 : void ResultsFramework::writeOutputs(EnergyPlusData &state)
1303 : {
1304 771 : if (state.files.outputControl.csv) {
1305 4 : writeCSVOutput(state);
1306 : }
1307 :
1308 771 : if (timeSeriesEnabled() && (outputJSON || outputCBOR || outputMsgPack)) {
1309 3 : writeTimeSeriesReports(state.files.json);
1310 : }
1311 :
1312 771 : if (timeSeriesAndTabularEnabled() && (outputJSON || outputCBOR || outputMsgPack)) {
1313 2 : writeReport(state.files.json);
1314 : }
1315 771 : }
1316 :
1317 4 : void ResultsFramework::writeCSVOutput(EnergyPlusData &state)
1318 : {
1319 4 : if (!hasOutputData()) {
1320 0 : return;
1321 : }
1322 8 : CSVWriter csv(outputVariables.size());
1323 8 : CSVWriter mtr_csv(outputVariables.size());
1324 :
1325 : // Output yearly time series data
1326 4 : if (hasRIYearlyTSData()) {
1327 0 : csv.parseTSOutputs(state, RIYearlyTSData.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::Yearly);
1328 : }
1329 :
1330 4 : if (hasYRMeters()) {
1331 0 : csv.parseTSOutputs(state, YRMeters.getJSON(true), outputVariables, OutputProcessor::ReportingFrequency::Yearly);
1332 0 : mtr_csv.parseTSOutputs(state, YRMeters.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::Yearly);
1333 : }
1334 :
1335 : // Output run period time series data
1336 4 : if (hasRIRunPeriodTSData()) {
1337 0 : csv.parseTSOutputs(state, RIRunPeriodTSData.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::Simulation);
1338 : }
1339 :
1340 4 : if (hasSMMeters()) {
1341 2 : csv.parseTSOutputs(state, SMMeters.getJSON(true), outputVariables, OutputProcessor::ReportingFrequency::Simulation);
1342 2 : mtr_csv.parseTSOutputs(state, SMMeters.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::Simulation);
1343 : }
1344 :
1345 : // Output monthly time series data
1346 4 : if (hasRIMonthlyTSData()) {
1347 0 : csv.parseTSOutputs(state, RIMonthlyTSData.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::Monthly);
1348 : }
1349 :
1350 4 : if (hasMNMeters()) {
1351 3 : csv.parseTSOutputs(state, MNMeters.getJSON(true), outputVariables, OutputProcessor::ReportingFrequency::Monthly);
1352 3 : mtr_csv.parseTSOutputs(state, MNMeters.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::Monthly);
1353 : }
1354 :
1355 : // Output daily time series data
1356 4 : if (hasRIDailyTSData()) {
1357 0 : csv.parseTSOutputs(state, RIDailyTSData.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::Daily);
1358 : }
1359 :
1360 4 : if (hasDYMeters()) {
1361 0 : csv.parseTSOutputs(state, DYMeters.getJSON(true), outputVariables, OutputProcessor::ReportingFrequency::Daily);
1362 0 : mtr_csv.parseTSOutputs(state, DYMeters.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::Daily);
1363 : }
1364 :
1365 : // Output hourly time series data
1366 4 : if (hasRIHourlyTSData()) {
1367 2 : csv.parseTSOutputs(state, RIHourlyTSData.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::Hourly);
1368 : }
1369 :
1370 4 : if (hasHRMeters()) {
1371 1 : csv.parseTSOutputs(state, HRMeters.getJSON(true), outputVariables, OutputProcessor::ReportingFrequency::Hourly);
1372 1 : mtr_csv.parseTSOutputs(state, HRMeters.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::Hourly);
1373 : }
1374 :
1375 : // Output timestep time series data
1376 4 : if (hasRITimestepTSData()) {
1377 0 : csv.parseTSOutputs(state, RITimestepTSData.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::TimeStep);
1378 : }
1379 :
1380 4 : if (hasTSMeters()) {
1381 0 : csv.parseTSOutputs(state, TSMeters.getJSON(true), outputVariables, OutputProcessor::ReportingFrequency::TimeStep);
1382 0 : mtr_csv.parseTSOutputs(state, TSMeters.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::TimeStep);
1383 : }
1384 :
1385 : // Output detailed HVAC time series data
1386 4 : if (hasRIDetailedHVACTSData()) {
1387 4 : csv.parseTSOutputs(state, RIDetailedHVACTSData.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::EachCall);
1388 : }
1389 :
1390 : // Output detailed Zone time series data
1391 4 : if (hasRIDetailedZoneTSData()) {
1392 2 : csv.parseTSOutputs(state, RIDetailedZoneTSData.getJSON(), outputVariables, OutputProcessor::ReportingFrequency::EachCall);
1393 : }
1394 :
1395 4 : csv.writeOutput(state, outputVariables, state.files.csv, state.files.outputControl.csv);
1396 4 : if (hasMeterData()) {
1397 3 : mtr_csv.writeOutput(state, outputVariables, state.files.mtr_csv, state.files.outputControl.csv);
1398 : }
1399 : }
1400 :
1401 3 : void ResultsFramework::writeTimeSeriesReports(JsonOutputFilePaths &jsonOutputFilePaths)
1402 : {
1403 : // Output detailed Zone time series data
1404 3 : if (hasRIDetailedZoneTSData()) {
1405 0 : RIDetailedZoneTSData.writeReport(jsonOutputFilePaths, outputJSON, outputCBOR, outputMsgPack);
1406 : }
1407 :
1408 : // Output detailed HVAC time series data
1409 3 : if (hasRIDetailedHVACTSData()) {
1410 1 : RIDetailedHVACTSData.writeReport(jsonOutputFilePaths, outputJSON, outputCBOR, outputMsgPack);
1411 : }
1412 :
1413 : // Output timestep time series data
1414 3 : if (hasRITimestepTSData()) {
1415 0 : RITimestepTSData.writeReport(jsonOutputFilePaths, outputJSON, outputCBOR, outputMsgPack);
1416 : }
1417 :
1418 : // Output hourly time series data
1419 3 : if (hasRIHourlyTSData()) {
1420 3 : RIHourlyTSData.writeReport(jsonOutputFilePaths, outputJSON, outputCBOR, outputMsgPack);
1421 : }
1422 :
1423 : // Output daily time series data
1424 3 : if (hasRIDailyTSData()) {
1425 0 : RIDailyTSData.writeReport(jsonOutputFilePaths, outputJSON, outputCBOR, outputMsgPack);
1426 : }
1427 :
1428 : // Output monthly time series data
1429 3 : if (hasRIMonthlyTSData()) {
1430 0 : RIMonthlyTSData.writeReport(jsonOutputFilePaths, outputJSON, outputCBOR, outputMsgPack);
1431 : }
1432 :
1433 : // Output run period time series data
1434 3 : if (hasRIRunPeriodTSData()) {
1435 0 : RIRunPeriodTSData.writeReport(jsonOutputFilePaths, outputJSON, outputCBOR, outputMsgPack);
1436 : }
1437 :
1438 : // Output yearly time series data
1439 3 : if (hasRIYearlyTSData()) {
1440 0 : RIYearlyTSData.writeReport(jsonOutputFilePaths, outputJSON, outputCBOR, outputMsgPack);
1441 : }
1442 3 : }
1443 :
1444 2 : void ResultsFramework::writeReport(JsonOutputFilePaths &jsonOutputFilePaths)
1445 : {
1446 4 : json root, outputVars, meterVars, meterData;
1447 2 : root = {{"SimulationResults", {{"Simulation", SimulationInformation.getJSON()}}}};
1448 :
1449 : // output variables
1450 2 : if (hasRIDetailedZoneTSData()) {
1451 0 : outputVars["Detailed-Zone"] = RIDetailedZoneTSData.getVariablesJSON();
1452 : }
1453 :
1454 2 : if (hasRIDetailedHVACTSData()) {
1455 1 : outputVars["Detailed-HVAC"] = RIDetailedHVACTSData.getVariablesJSON();
1456 : }
1457 :
1458 2 : if (hasRITimestepTSData()) {
1459 0 : outputVars["TimeStep"] = RITimestepTSData.getVariablesJSON();
1460 : }
1461 :
1462 2 : if (hasRIHourlyTSData()) {
1463 2 : outputVars["Hourly"] = RIHourlyTSData.getVariablesJSON();
1464 : }
1465 :
1466 2 : if (hasRIDailyTSData()) {
1467 0 : outputVars["Daily"], RIDailyTSData.getVariablesJSON();
1468 : }
1469 :
1470 2 : if (hasRIMonthlyTSData()) {
1471 0 : outputVars["Monthly"] = RIMonthlyTSData.getVariablesJSON();
1472 : }
1473 :
1474 2 : if (hasRIRunPeriodTSData()) {
1475 0 : outputVars["RunPeriod"] = RIRunPeriodTSData.getVariablesJSON();
1476 : }
1477 :
1478 2 : if (hasRIYearlyTSData()) {
1479 0 : outputVars["Yearly"] = RIYearlyTSData.getVariablesJSON();
1480 : }
1481 :
1482 : // output dictionary
1483 2 : outputVars["OutputDictionary"] = {{"Description", "Dictionary containing output variables that may be requested"}, {"Variables", RDD}};
1484 :
1485 : // meter variables
1486 :
1487 : // -- meter values
1488 2 : if (hasTSMeters()) {
1489 0 : meterVars["TimeStep"] = TSMeters.getVariablesJSON();
1490 : }
1491 :
1492 2 : if (hasHRMeters()) {
1493 1 : meterVars["Hourly"] = HRMeters.getVariablesJSON();
1494 : }
1495 :
1496 2 : if (hasDYMeters()) {
1497 0 : meterVars["Daily"] = DYMeters.getVariablesJSON();
1498 : }
1499 :
1500 2 : if (hasMNMeters()) {
1501 2 : meterVars["Monthly"] = MNMeters.getVariablesJSON();
1502 : }
1503 :
1504 2 : if (hasSMMeters()) {
1505 1 : meterVars["RunPeriod"] = SMMeters.getVariablesJSON();
1506 : }
1507 :
1508 2 : if (hasYRMeters()) {
1509 0 : meterVars["Yearly"] = YRMeters.getVariablesJSON();
1510 : }
1511 :
1512 2 : if (hasTSMeters()) {
1513 0 : meterData["TimeStep"] = TSMeters.getJSON();
1514 : }
1515 :
1516 2 : if (hasHRMeters()) {
1517 1 : meterData["Hourly"] = HRMeters.getJSON();
1518 : }
1519 :
1520 2 : if (hasDYMeters()) {
1521 0 : meterData["Daily"] = DYMeters.getJSON();
1522 : }
1523 :
1524 2 : if (hasMNMeters()) {
1525 2 : meterData["Monthly"] = MNMeters.getJSON();
1526 : }
1527 :
1528 2 : if (hasSMMeters()) {
1529 1 : meterData["RunPeriod"] = SMMeters.getJSON();
1530 : }
1531 :
1532 2 : if (hasYRMeters()) {
1533 0 : meterData["Yearly"] = YRMeters.getJSON();
1534 : }
1535 :
1536 : // -- meter dictionary
1537 2 : meterVars["MeterDictionary"] = {{"Description", "Dictionary containing meter variables that may be requested"}, {"Meters", MDD}};
1538 :
1539 2 : root["OutputVariables"] = outputVars;
1540 2 : root["MeterVariables"] = meterVars;
1541 2 : root["MeterData"] = meterData;
1542 2 : root["TabularReports"] = TabularReportsCollection.getJSON();
1543 :
1544 2 : if (outputJSON) {
1545 2 : FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputJsonFilePath, root);
1546 : }
1547 2 : if (outputCBOR) {
1548 1 : FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputCborFilePath, root);
1549 : }
1550 2 : if (outputMsgPack) {
1551 1 : FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputMsgPackFilePath, root);
1552 : }
1553 2 : }
1554 :
1555 58444 : void ResultsFramework::addReportVariable(std::string_view const keyedValue,
1556 : std::string_view const variableName,
1557 : std::string const &units,
1558 : OutputProcessor::ReportingFrequency const reportingInterval)
1559 : {
1560 116888 : outputVariables.emplace_back(fmt::format("{0}:{1} [{2}]({3})", keyedValue, variableName, units, reportingFrequency(reportingInterval)));
1561 58444 : }
1562 :
1563 : void
1564 7818 : ResultsFramework::addReportMeter(std::string const &meter, std::string const &units, OutputProcessor::ReportingFrequency const reportingInterval)
1565 : {
1566 15636 : outputVariables.emplace_back(fmt::format("{0} [{1}]({2})", meter, units, reportingFrequency(reportingInterval)));
1567 7818 : }
1568 :
1569 : } // namespace ResultsFramework
1570 :
1571 2313 : } // namespace EnergyPlus
|