LCOV - code coverage report
Current view: top level - EnergyPlus - ResultsFramework.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 494 617 80.1 %
Date: 2024-08-24 18:31:18 Functions: 59 80 73.8 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, 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             : 
      80             :     // trim string
      81       66547 :     std::string trim(std::string_view const s)
      82             :     {
      83       66547 :         if (s.empty()) {
      84        6109 :             return std::string{};
      85             :         }
      86       60438 :         auto const first = s.find_first_not_of(' ');
      87       60438 :         auto const last = s.find_last_not_of(' ');
      88       60438 :         if ((first == std::string::npos) || (last == std::string::npos)) {
      89           0 :             return std::string{};
      90             :         } else {
      91       60438 :             return std::string{s.substr(first, last - first + 1)};
      92             :         }
      93             :     }
      94             : 
      95             :     // Class SimInfo
      96         796 :     void SimInfo::setProgramVersion(const std::string &programVersion)
      97             :     {
      98         796 :         ProgramVersion = programVersion;
      99         796 :     }
     100             : 
     101           0 :     std::string SimInfo::getProgramVersion() const
     102             :     {
     103           0 :         return ProgramVersion;
     104             :     }
     105             : 
     106           0 :     void SimInfo::setSimulationEnvironment(const std::string &simulationEnvironment)
     107             :     {
     108           0 :         SimulationEnvironment = simulationEnvironment;
     109           0 :     }
     110             : 
     111           0 :     void SimInfo::setInputModelURI(const std::string &inputModelURI)
     112             :     {
     113           0 :         InputModelURI = inputModelURI;
     114           0 :     }
     115             : 
     116         796 :     void SimInfo::setStartDateTimeStamp(const std::string &startDateTimeStamp)
     117             :     {
     118         796 :         StartDateTimeStamp = startDateTimeStamp;
     119         796 :     }
     120             : 
     121         796 :     void SimInfo::setRunTime(const std::string &elapsedTime)
     122             :     {
     123         796 :         RunTime = elapsedTime;
     124         796 :     }
     125             : 
     126         796 :     void SimInfo::setNumErrorsWarmup(const std::string &numWarningsDuringWarmup, const std::string &numSevereDuringWarmup)
     127             :     {
     128         796 :         NumWarningsDuringWarmup = numWarningsDuringWarmup;
     129         796 :         NumSevereDuringWarmup = numSevereDuringWarmup;
     130         796 :     }
     131             : 
     132         796 :     void SimInfo::setNumErrorsSizing(const std::string &numWarningsDuringSizing, const std::string &numSevereDuringSizing)
     133             :     {
     134         796 :         NumWarningsDuringSizing = numWarningsDuringSizing;
     135         796 :         NumSevereDuringSizing = numSevereDuringSizing;
     136         796 :     }
     137             : 
     138         796 :     void SimInfo::setNumErrorsSummary(const std::string &numWarnings, const std::string &numSevere)
     139             :     {
     140         796 :         NumWarnings = numWarnings;
     141         796 :         NumSevere = numSevere;
     142         796 :     }
     143             : 
     144           2 :     json SimInfo::getJSON() const
     145             :     {
     146           2 :         json root = {{"ProgramVersion", ProgramVersion},
     147           2 :                      {"SimulationEnvironment", SimulationEnvironment},
     148           2 :                      {"InputModelURI", InputModelURI},
     149           2 :                      {"StartDateTimeStamp", StartDateTimeStamp},
     150           2 :                      {"RunTime", RunTime},
     151           4 :                      {"ErrorSummary", {{"NumWarnings", NumWarnings}, {"NumSevere", NumSevere}}},
     152           4 :                      {"ErrorSummaryWarmup", {{"NumWarnings", NumWarningsDuringWarmup}, {"NumSevere", NumSevereDuringWarmup}}},
     153         120 :                      {"ErrorSummarySizing", {{"NumWarnings", NumWarningsDuringSizing}, {"NumSevere", NumSevereDuringSizing}}}};
     154           2 :         return root;
     155             :     }
     156             : 
     157             :     // Class Variable
     158       36254 :     Variable::Variable(const std::string &VarName,
     159             :                        const OutputProcessor::ReportFreq reportFrequency,
     160             :                        const OutputProcessor::TimeStepType timeStepType,
     161             :                        const int ReportID,
     162       36254 :                        const Constant::Units units)
     163       36254 :         : m_varName(VarName), m_reportFreq(reportFrequency), m_timeStepType(timeStepType), m_rptID(ReportID), m_units(units)
     164             :     {
     165       36254 :     }
     166             : 
     167          52 :     Variable::Variable(const std::string &VarName,
     168             :                        const OutputProcessor::ReportFreq reportFrequency,
     169             :                        const OutputProcessor::TimeStepType timeStepType,
     170             :                        const int ReportID,
     171             :                        const Constant::Units units,
     172          52 :                        const std::string &customUnits)
     173         104 :         : m_varName(VarName), m_reportFreq(reportFrequency), m_timeStepType(timeStepType), m_rptID(ReportID), m_units(units),
     174          52 :           m_customUnits(customUnits)
     175             :     {
     176          52 :     }
     177             : 
     178         649 :     std::string Variable::variableName() const
     179             :     {
     180         649 :         return m_varName;
     181             :     }
     182             : 
     183           0 :     void Variable::setVariableName(const std::string &VarName)
     184             :     {
     185           0 :         m_varName = VarName;
     186           0 :     }
     187             : 
     188          96 :     std::string Variable::sReportFrequency() const
     189             :     {
     190             :         static constexpr std::array<std::string_view, (int)ReportFreq::Num> reportFreqStrings = {
     191             :             "Detailed", "TimeStep", "Hourly", "Daily", "Monthly", "RunPeriod", "Yearly"};
     192             : 
     193             :         static constexpr std::array<std::string_view, (int)TimeStepType::Num> timeStepTypeStrings = {"Detailed - Zone", "Detailed - HVAC"};
     194             : 
     195          98 :         return (m_reportFreq == ReportFreq::EachCall) ? std::string(timeStepTypeStrings[(int)m_timeStepType])
     196          96 :                                                       : std::string(reportFreqStrings[(int)m_reportFreq]);
     197             :     }
     198             : 
     199           0 :     OutputProcessor::ReportFreq Variable::iReportFrequency() const
     200             :     {
     201           0 :         return m_reportFreq;
     202             :     }
     203             : 
     204           0 :     void Variable::setReportFrequency(const OutputProcessor::ReportFreq reportFrequency)
     205             :     {
     206           0 :         m_reportFreq = reportFrequency;
     207           0 :     }
     208             : 
     209           0 :     OutputProcessor::TimeStepType Variable::timeStepType() const
     210             :     {
     211           0 :         return m_timeStepType;
     212             :     }
     213             : 
     214           0 :     void Variable::setTimeStepType(const OutputProcessor::TimeStepType timeStepType)
     215             :     {
     216           0 :         m_timeStepType = timeStepType;
     217           0 :     }
     218             : 
     219       36277 :     int Variable::reportID() const
     220             :     {
     221       36277 :         return m_rptID;
     222             :     }
     223             : 
     224           0 :     void Variable::setReportID(int Id)
     225             :     {
     226           0 :         m_rptID = Id;
     227           0 :     }
     228             : 
     229         646 :     Constant::Units Variable::units() const
     230             :     {
     231         646 :         return m_units;
     232             :     }
     233             : 
     234           0 :     void Variable::setUnits(const Constant::Units units)
     235             :     {
     236           0 :         m_units = units;
     237           0 :     }
     238             : 
     239         496 :     std::string Variable::customUnits() const
     240             :     {
     241         496 :         return m_customUnits;
     242             :     }
     243             : 
     244           0 :     void Variable::setCustomUnits(const std::string &customUnits)
     245             :     {
     246           0 :         m_customUnits = customUnits;
     247           0 :     }
     248             : 
     249      123089 :     void Variable::pushValue(const double val)
     250             :     {
     251      123089 :         m_values.push_back(val);
     252      123089 :     }
     253             : 
     254       40762 :     double Variable::value(size_t index) const
     255             :     {
     256       40762 :         return m_values.at(index);
     257             :     }
     258             : 
     259       41854 :     size_t Variable::numValues() const
     260             :     {
     261       41854 :         return m_values.size();
     262             :     }
     263             : 
     264          96 :     json Variable::getJSON() const
     265             :     {
     266          96 :         json root;
     267          96 :         if (m_customUnits.empty()) {
     268         960 :             root = {{"Name", m_varName}, {"Units", Constant::unitNames[(int)m_units]}, {"Frequency", sReportFrequency()}};
     269             :         } else {
     270           0 :             root = {{"Name", m_varName}, {"Units", m_customUnits}, {"Frequency", sReportFrequency()}};
     271             :         }
     272          96 :         return root;
     273           0 :     }
     274             : 
     275             :     // Class OutputVariable
     276           0 :     OutputVariable::OutputVariable(const std::string &VarName,
     277             :                                    const OutputProcessor::ReportFreq reportFrequency,
     278             :                                    const OutputProcessor::TimeStepType timeStepType,
     279             :                                    const int ReportID,
     280           0 :                                    const Constant::Units units)
     281           0 :         : Variable(VarName, reportFrequency, timeStepType, ReportID, units)
     282             :     {
     283           0 :     }
     284             : 
     285           0 :     OutputVariable::OutputVariable(const std::string &VarName,
     286             :                                    const OutputProcessor::ReportFreq reportFrequency,
     287             :                                    const OutputProcessor::TimeStepType timeStepType,
     288             :                                    const int ReportID,
     289             :                                    const Constant::Units units,
     290           0 :                                    const std::string &customUnits)
     291           0 :         : Variable(VarName, reportFrequency, timeStepType, ReportID, units, customUnits)
     292             :     {
     293           0 :     }
     294             : 
     295             :     // Class MeterVariable
     296        8360 :     MeterVariable::MeterVariable(const std::string &VarName,
     297             :                                  const OutputProcessor::ReportFreq reportFrequency,
     298             :                                  const int ReportID,
     299             :                                  const Constant::Units units,
     300             :                                  const bool MeterOnly,
     301        8360 :                                  const bool Accumulative)
     302        8360 :         : Variable(VarName, reportFrequency, OutputProcessor::TimeStepType::Zone, ReportID, units)
     303             :     {
     304        8360 :         acc = Accumulative;
     305        8360 :         meter_only = MeterOnly;
     306        8360 :     }
     307             : 
     308           0 :     bool MeterVariable::accumulative() const
     309             :     {
     310           0 :         return acc;
     311             :     }
     312             : 
     313           0 :     void MeterVariable::setAccumulative(bool state)
     314             :     {
     315           0 :         acc = state;
     316           0 :     }
     317             : 
     318         556 :     bool MeterVariable::meterOnly() const
     319             :     {
     320         556 :         return meter_only;
     321             :     }
     322             : 
     323           0 :     void MeterVariable::setMeterOnly(bool state)
     324             :     {
     325           0 :         meter_only = state;
     326           0 :     }
     327             : 
     328           0 :     json MeterVariable::getJSON() const
     329             :     {
     330           0 :         json root = Variable::getJSON();
     331           0 :         if (acc) {
     332           0 :             root["Cumulative"] = true;
     333             :         }
     334             :         //        if (meter_only) {
     335             :         //            root["MeterOnly"] = true;
     336             :         //        }
     337           0 :         return root;
     338           0 :     }
     339             : 
     340             :     // class DataFrame
     341       12736 :     DataFrame::DataFrame(const std::string &ReportFreq)
     342             :     {
     343       12736 :         ReportFrequency = ReportFreq;
     344       12736 :     }
     345             : 
     346       27917 :     void DataFrame::addVariable(Variable const &var)
     347             :     {
     348       27917 :         lastVarID = var.reportID();
     349       27917 :         variableMap.emplace(lastVarID, var);
     350       27917 :     }
     351             : 
     352           0 :     Variable &DataFrame::lastVariable()
     353             :     {
     354           0 :         return variableMap.at(lastVarID);
     355             :     }
     356             : 
     357       25089 :     void DataFrame::newRow(const int month, const int dayOfMonth, int hourOfDay, int curMin, int calendarYear)
     358             :     {
     359       25089 :         if (curMin > 0) {
     360       13909 :             hourOfDay -= 1;
     361             :         }
     362       25089 :         if (curMin == 60) {
     363        2010 :             curMin = 0;
     364        2010 :             hourOfDay += 1;
     365             :         }
     366             : 
     367       25089 :         if (beginningOfInterval) {
     368         648 :             if (hourOfDay == 24) {
     369          18 :                 hourOfDay = 0;
     370             :             }
     371         648 :             std::swap(hourOfDay, lastHour);
     372         648 :             std::swap(curMin, lastMinute);
     373             :         }
     374             :         // future start of ISO 8601 datetime output
     375             :         // fmt::format("YYYY-{:02d}/{:02d}T{:02d}:{:02d}:00", month, dayOfMonth, hourOfDay, curMin);
     376             :         // fmt::format("{:02d}/{:02d} {:02d}:{:02d}:00", month, dayOfMonth, hourOfDay, curMin);
     377       25089 :         if (iso8601) {
     378        1296 :             TS.emplace_back(fmt::format("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:00", calendarYear, month, dayOfMonth, hourOfDay, curMin));
     379             :         } else {
     380       48882 :             TS.emplace_back(fmt::format("{:02d}/{:02d} {:02d}:{:02d}:00", month, dayOfMonth, hourOfDay, curMin));
     381             :         }
     382       25089 :     }
     383             : 
     384             :     //    void DataFrame::newRow(const std::string &ts)
     385             :     //    {
     386             :     //        TS.emplace_back(ts);
     387             :     //    }
     388             : 
     389      604096 :     bool DataFrame::dataFrameEnabled() const
     390             :     {
     391      604096 :         return DataFrameEnabled;
     392             :     }
     393             : 
     394       36277 :     void DataFrame::setDataFrameEnabled(bool state)
     395             :     {
     396       36277 :         DataFrameEnabled = state;
     397       36277 :     }
     398             : 
     399      575622 :     void DataFrame::setVariablesScanned(bool state)
     400             :     {
     401      575622 :         VariablesScanned = state;
     402      575622 :     }
     403             : 
     404        8881 :     bool DataFrame::variablesScanned() const
     405             :     {
     406        8881 :         return VariablesScanned;
     407             :     }
     408             : 
     409       39208 :     void DataFrame::pushVariableValue(const int reportID, double value)
     410             :     {
     411       39208 :         variableMap[reportID].pushValue(value);
     412       39208 :     }
     413             : 
     414           7 :     json DataFrame::getVariablesJSON()
     415             :     {
     416           7 :         json arr = json::array();
     417         103 :         for (auto const &varMap : variableMap) {
     418          96 :             arr.push_back(varMap.second.getJSON());
     419           7 :         }
     420           7 :         return arr;
     421           0 :     }
     422             : 
     423          15 :     json DataFrame::getJSON() const
     424             :     {
     425          15 :         json root;
     426          15 :         json cols = json::array();
     427          15 :         json rows = json::array();
     428             : 
     429         508 :         for (auto const &varMap : variableMap) {
     430         493 :             if (varMap.second.customUnits().empty()) {
     431        3430 :                 cols.push_back({{"Variable", varMap.second.variableName()}, {"Units", Constant::unitNames[(int)varMap.second.units()]}});
     432             :             } else {
     433          21 :                 cols.push_back({{"Variable", varMap.second.variableName()}, {"Units", varMap.second.customUnits()}});
     434             :             }
     435          15 :         }
     436             : 
     437          15 :         json vals = json::array();
     438             : 
     439        3431 :         for (size_t row = 0; row < TS.size(); ++row) {
     440        3416 :             vals.clear();
     441             : 
     442       43716 :             for (auto const &varMap : variableMap) {
     443       40300 :                 if (row < varMap.second.numValues()) {
     444       39208 :                     vals.push_back(varMap.second.value(row));
     445             :                 } else {
     446        1092 :                     vals.push_back(nullptr);
     447             :                 }
     448        3416 :             }
     449       13664 :             rows.push_back({{TS.at(row), vals}});
     450             :         }
     451         150 :         root = {{"ReportFrequency", ReportFrequency}, {"Cols", cols}, {"Rows", rows}};
     452          30 :         return root;
     453          15 :     }
     454             : 
     455        8360 :     void MeterDataFrame::addVariable(MeterVariable const &var)
     456             :     {
     457        8360 :         lastVarID = var.reportID();
     458        8360 :         meterMap.emplace(lastVarID, var);
     459        8360 :     }
     460             : 
     461       83881 :     void MeterDataFrame::pushVariableValue(const int reportID, double value)
     462             :     {
     463       83881 :         meterMap[reportID].pushValue(value);
     464       83881 :     }
     465             : 
     466          20 :     json MeterDataFrame::getJSON(bool meterOnlyCheck) const
     467             :     {
     468          20 :         json root;
     469          20 :         json cols = json::array();
     470          20 :         json rows = json::array();
     471             : 
     472         210 :         for (auto const &varMap : meterMap) {
     473         190 :             if (!(meterOnlyCheck && varMap.second.meterOnly())) {
     474        1092 :                 cols.push_back({{"Variable", varMap.second.variableName()}, {"Units", Constant::unitNames[(int)varMap.second.units()]}});
     475             :             }
     476          20 :         }
     477             : 
     478          20 :         if (cols.empty()) return root;
     479             : 
     480          14 :         json vals = json::array();
     481             : 
     482         180 :         for (size_t row = 0; row < TS.size(); ++row) {
     483         166 :             vals.clear();
     484             : 
     485        1720 :             for (auto const &varMap : meterMap) {
     486        1554 :                 if (!(meterOnlyCheck && varMap.second.meterOnly())) {
     487        1554 :                     if (row < varMap.second.numValues()) {
     488        1554 :                         vals.push_back(varMap.second.value(row));
     489             :                     } else {
     490           0 :                         vals.push_back(nullptr);
     491             :                     }
     492             :                 }
     493         166 :             }
     494         664 :             rows.push_back({{TS.at(row), vals}});
     495             :         }
     496         140 :         root = {{"ReportFrequency", ReportFrequency}, {"Cols", cols}, {"Rows", rows}};
     497          14 :         return root;
     498          20 :     }
     499             : 
     500           5 :     void DataFrame::writeReport(JsonOutputFilePaths &jsonOutputFilePaths, bool outputJSON, bool outputCBOR, bool outputMsgPack)
     501             :     {
     502             : 
     503           5 :         json root = getJSON();
     504           5 :         if (ReportFrequency == "Detailed-HVAC") {
     505           1 :             if (outputJSON) {
     506           1 :                 FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputTSHvacJsonFilePath, root);
     507             :             }
     508           1 :             if (outputCBOR) {
     509           1 :                 FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputTSHvacCborFilePath, root);
     510             :             }
     511           1 :             if (outputMsgPack) {
     512           1 :                 FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputTSHvacMsgPackFilePath, root);
     513             :             }
     514           4 :         } else if (ReportFrequency == "Detailed-Zone") {
     515           0 :             if (outputJSON) {
     516           0 :                 FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputTSZoneJsonFilePath, root);
     517             :             }
     518           0 :             if (outputCBOR) {
     519           0 :                 FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputTSZoneCborFilePath, root);
     520             :             }
     521           0 :             if (outputMsgPack) {
     522           0 :                 FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputTSZoneMsgPackFilePath, root);
     523             :             }
     524           4 :         } else if (ReportFrequency == "TimeStep") {
     525           0 :             if (outputJSON) {
     526           0 :                 FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputTSJsonFilePath, root);
     527             :             }
     528           0 :             if (outputCBOR) {
     529           0 :                 FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputTSCborFilePath, root);
     530             :             }
     531           0 :             if (outputMsgPack) {
     532           0 :                 FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputTSMsgPackFilePath, root);
     533             :             }
     534           4 :         } else if (ReportFrequency == "Daily") {
     535           0 :             if (outputJSON) {
     536           0 :                 FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputDYJsonFilePath, root);
     537             :             }
     538           0 :             if (outputCBOR) {
     539           0 :                 FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputDYCborFilePath, root);
     540             :             }
     541           0 :             if (outputMsgPack) {
     542           0 :                 FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputDYMsgPackFilePath, root);
     543             :             }
     544           4 :         } else if (ReportFrequency == "Hourly") {
     545           4 :             if (outputJSON) {
     546           4 :                 FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputHRJsonFilePath, root);
     547             :             }
     548           4 :             if (outputCBOR) {
     549           1 :                 FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputHRCborFilePath, root);
     550             :             }
     551           4 :             if (outputMsgPack) {
     552           1 :                 FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputHRMsgPackFilePath, root);
     553             :             }
     554           0 :         } else if (ReportFrequency == "Monthly") {
     555           0 :             if (outputJSON) {
     556           0 :                 FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputMNJsonFilePath, root);
     557             :             }
     558           0 :             if (outputCBOR) {
     559           0 :                 FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputMNCborFilePath, root);
     560             :             }
     561           0 :             if (outputMsgPack) {
     562           0 :                 FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputMNMsgPackFilePath, root);
     563             :             }
     564           0 :         } else if (ReportFrequency == "RunPeriod") {
     565           0 :             if (outputJSON) {
     566           0 :                 FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputSMJsonFilePath, root);
     567             :             }
     568           0 :             if (outputCBOR) {
     569           0 :                 FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputSMCborFilePath, root);
     570             :             }
     571           0 :             if (outputMsgPack) {
     572           0 :                 FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputSMMsgPackFilePath, root);
     573             :             }
     574           0 :         } else if (ReportFrequency == "Yearly") {
     575           0 :             if (outputJSON) {
     576           0 :                 FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputYRJsonFilePath, root);
     577             :             }
     578           0 :             if (outputCBOR) {
     579           0 :                 FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputYRCborFilePath, root);
     580             :             }
     581           0 :             if (outputMsgPack) {
     582           0 :                 FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputYRMsgPackFilePath, root);
     583             :             }
     584             :         }
     585           5 :     }
     586             :     // class Table
     587             : 
     588        1155 :     Table::Table(Array2D_string const &body,
     589             :                  Array1D_string const &rowLabels,
     590             :                  Array1D_string const &columnLabels,
     591             :                  std::string const &tableName,
     592        1155 :                  std::string const &footnoteText)
     593             :     {
     594             : 
     595        1155 :         size_t sizeColumnLabels = columnLabels.size();
     596        1155 :         size_t sizeRowLabels = rowLabels.size();
     597        1155 :         TableName = tableName;
     598        1155 :         FootnoteText = footnoteText;
     599             : 
     600       10192 :         for (size_t iCol = 0, k = body.index(1, 1); iCol < sizeColumnLabels; ++iCol) {
     601        9037 :             ColHeaders.push_back(columnLabels[iCol]);
     602        9037 :             std::vector<std::string> col;
     603       75584 :             for (size_t iRow = 0; iRow < sizeRowLabels; ++iRow) {
     604       66547 :                 if (iCol == 0) {
     605             :                     // do this once only
     606        7407 :                     RowHeaders.push_back(rowLabels[iRow]);
     607             :                 }
     608       66547 :                 col.push_back(trim(body[k]));
     609       66547 :                 ++k;
     610             :             }
     611        9037 :             Data.push_back(col);
     612        9037 :         }
     613        1155 :     }
     614             : 
     615         285 :     json Table::getJSON() const
     616             :     {
     617         285 :         json root;
     618         285 :         json cols = json::array();
     619         285 :         json rows;
     620             : 
     621        2496 :         for (size_t col = 0; col < ColHeaders.size(); ++col) {
     622        2211 :             cols.push_back(ColHeaders[col]);
     623             :         }
     624             : 
     625        2106 :         for (size_t row = 0; row < RowHeaders.size(); ++row) {
     626        1821 :             json rowvec = json::array();
     627       17292 :             for (size_t col = 0; col < ColHeaders.size(); ++col) {
     628       15471 :                 rowvec.push_back(Data[col][row]);
     629             :             }
     630        1821 :             rows[RowHeaders[row]] = rowvec;
     631        1821 :         }
     632             : 
     633        2850 :         root = {{"TableName", TableName}, {"Cols", cols}, {"Rows", rows}};
     634             : 
     635         285 :         if (!FootnoteText.empty()) root["Footnote"] = FootnoteText;
     636         570 :         return root;
     637         285 :     }
     638             : 
     639             :     // class Report
     640             : 
     641          36 :     json Report::getJSON() const
     642             :     {
     643             : 
     644         324 :         json root = {{"ReportName", ReportName}, {"For", ReportForString}};
     645             : 
     646          36 :         json cols = json::array();
     647             : 
     648         321 :         for (auto const &table : Tables) {
     649         285 :             cols.push_back(table.getJSON());
     650          36 :         }
     651             : 
     652          36 :         root["Tables"] = cols;
     653          72 :         return root;
     654          36 :     }
     655             : 
     656             :     // class ReportsCollection
     657         796 :     ReportsCollection::ReportsCollection()
     658             :     {
     659         796 :     }
     660             : 
     661        1083 :     void ReportsCollection::addReportTable(Array2D_string const &body,
     662             :                                            Array1D_string const &rowLabels,
     663             :                                            Array1D_string const &columnLabels,
     664             :                                            std::string const &reportName,
     665             :                                            std::string const &reportForString,
     666             :                                            std::string const &tableName)
     667             :     {
     668        1083 :         addReportTable(body, rowLabels, columnLabels, reportName, reportForString, tableName, "");
     669        1083 :     }
     670             : 
     671        1155 :     void ReportsCollection::addReportTable(Array2D_string const &body,
     672             :                                            Array1D_string const &rowLabels,
     673             :                                            Array1D_string const &columnLabels,
     674             :                                            std::string const &reportName,
     675             :                                            std::string const &reportForString,
     676             :                                            std::string const &tableName,
     677             :                                            std::string const &footnoteText)
     678             :     {
     679        1155 :         std::string const key = reportName + reportForString;
     680             :         // Report *r;
     681        1155 :         Table tbl(body, rowLabels, columnLabels, tableName, footnoteText);
     682             : 
     683        1155 :         auto search = reportsMap.find(key);
     684        1155 :         if (search != reportsMap.end()) {
     685             :             // r = search->second;
     686         984 :             search->second.Tables.push_back(tbl);
     687             :         } else {
     688             :             // r = new Report();
     689         171 :             Report r;
     690         171 :             r.ReportName = reportName;
     691         171 :             r.ReportForString = reportForString;
     692         171 :             r.Tables.push_back(tbl);
     693         171 :             reportsMap.emplace(key, r);
     694         171 :         }
     695             : 
     696             :         // Table *tbl = new Table( body, rowLabels, columnLabels, tableName, footnoteText );
     697             :         // r->Tables.push_back( tbl );
     698        1155 :     }
     699             : 
     700           2 :     json ReportsCollection::getJSON() const
     701             :     {
     702           2 :         json root = json::array();
     703             : 
     704          38 :         for (auto const &iter : reportsMap) {
     705          36 :             root.push_back(iter.second.getJSON());
     706           2 :         }
     707           2 :         return root;
     708           0 :     }
     709             : 
     710          26 :     void CSVWriter::parseTSOutputs(EnergyPlusData &state,
     711             :                                    json const &data,
     712             :                                    std::vector<std::string> const &outputVariables,
     713             :                                    OutputProcessor::ReportFreq reportingFrequency)
     714             :     {
     715          26 :         if (data.empty()) return;
     716          20 :         updateReportFreq(reportingFrequency);
     717          20 :         std::vector<int> indices;
     718          20 :         std::unordered_set<std::string> seen;
     719          20 :         std::string search_string;
     720             : 
     721          40 :         std::string reportFrequency = data.at("ReportFrequency").get<std::string>();
     722          20 :         if (reportFrequency == "Detailed-HVAC" || reportFrequency == "Detailed-Zone") {
     723           6 :             reportFrequency = "Each Call";
     724             :         }
     725          20 :         auto const &columns = data.at("Cols");
     726         310 :         for (auto const &column : columns) {
     727             :             search_string =
     728         580 :                 fmt::format("{0} [{1}]({2})", column.at("Variable").get<std::string>(), column.at("Units").get<std::string>(), reportFrequency);
     729         580 :             auto found = std::find(outputVariables.begin(), outputVariables.end(), search_string);
     730         290 :             if (found == outputVariables.end()) {
     731             :                 search_string =
     732           0 :                     fmt::format("{0} [{1}]({2})", column.at("Variable").get<std::string>(), column.at("Units").get<std::string>(), "Each Call");
     733           0 :                 found = std::find(outputVariables.begin(), outputVariables.end(), search_string);
     734             :             }
     735         290 :             if (found == outputVariables.end()) {
     736           0 :                 ShowFatalError(state, fmt::format("Output variable ({0}) not found output variable list", search_string));
     737             :             }
     738         290 :             outputVariableIndices[std::distance(outputVariables.begin(), found)] = true;
     739         290 :             indices.emplace_back(std::distance(outputVariables.begin(), found));
     740         310 :         }
     741             : 
     742          20 :         auto const &rows = data.at("Rows");
     743        2729 :         for (auto const &row : rows) {
     744        5418 :             for (auto &el : row.items()) {
     745        2709 :                 auto found_key = outputs.find(el.key());
     746        2709 :                 if (found_key == outputs.end()) {
     747        2193 :                     std::vector<std::string> output(outputVariables.size());
     748        2193 :                     int i = 0;
     749       26187 :                     for (auto const &col : el.value()) {
     750       23994 :                         if (col.is_null()) {
     751           0 :                             output[indices[i]] = "";
     752             :                         } else {
     753       23994 :                             dtoa(col.get<double>(), s);
     754       23994 :                             output[indices[i]] = s;
     755             :                         }
     756       23994 :                         ++i;
     757        2193 :                     }
     758        2193 :                     outputs[el.key()] = output;
     759        2193 :                 } else {
     760         516 :                     int i = 0;
     761        1872 :                     for (auto const &col : el.value()) {
     762        1356 :                         if (col.is_null()) {
     763           0 :                             found_key->second[indices[i]] = "";
     764             :                         } else {
     765        1356 :                             dtoa(col.get<double>(), s);
     766        1356 :                             found_key->second[indices[i]] = s;
     767             :                         }
     768        1356 :                         ++i;
     769         516 :                     }
     770             :                 }
     771        5418 :             }
     772          20 :         }
     773          20 :     }
     774             : 
     775          20 :     void CSVWriter::updateReportFreq(OutputProcessor::ReportFreq reportingFrequency)
     776             :     {
     777          20 :         if (reportingFrequency < smallestReportFreq) {
     778          17 :             smallestReportFreq = reportingFrequency;
     779             :         }
     780          20 :     }
     781             : 
     782           4 :     std::string &CSVWriter::convertToMonth(std::string &datetime)
     783             :     {
     784             :         // if running this function, there should only ever be 12 + design days values to change
     785             :         static const std::map<std::string, std::string> months({{"01", "January"},
     786             :                                                                 {"02", "February"},
     787             :                                                                 {"03", "March"},
     788             :                                                                 {"04", "April"},
     789             :                                                                 {"05", "May"},
     790             :                                                                 {"06", "June"},
     791             :                                                                 {"07", "July"},
     792             :                                                                 {"08", "August"},
     793             :                                                                 {"09", "September"},
     794             :                                                                 {"10", "October"},
     795             :                                                                 {"11", "November"},
     796          28 :                                                                 {"12", "December"}});
     797             :         // 01/01 24:00:00
     798           4 :         std::string const month = datetime.substr(0, 2);
     799           4 :         size_t const pos = datetime.find(' ');
     800           4 :         std::string time;
     801           4 :         if (pos != std::string::npos) {
     802           4 :             time = datetime.substr(pos);
     803             :         }
     804             :         // This assert replaces ShowFatalError(state, "Monthly output variables should occur at the end of the day.");
     805           4 :         assert(time == " 24:00:00" || time == " 00:00:00");
     806             : 
     807           4 :         datetime = months.find(month)->second;
     808           4 :         return datetime;
     809           4 :     }
     810             : 
     811          10 :     void CSVWriter::writeOutput(EnergyPlusData &state,
     812             :                                 std::vector<std::string> const &outputVariables,
     813             :                                 InputOutputFile &outputFile,
     814             :                                 bool outputControl,
     815             :                                 bool rewriteTimestamp)
     816             :     {
     817          10 :         outputFile.ensure_open(state, "OpenOutputFiles", outputControl);
     818             : 
     819          10 :         print<FormatSyntax::FMT>(outputFile, "{}", "Date/Time,");
     820          10 :         std::string sep;
     821         470 :         for (auto it = outputVariables.begin(); it != outputVariables.end(); ++it) {
     822         460 :             if (!outputVariableIndices[std::distance(outputVariables.begin(), it)]) continue;
     823         290 :             print<FormatSyntax::FMT>(outputFile, "{}{}", sep, *it);
     824         290 :             if (sep.empty()) sep = ",";
     825          10 :         }
     826          10 :         print<FormatSyntax::FMT>(outputFile, "{}", '\n');
     827             : 
     828        2203 :         for (auto &item : outputs) {
     829        2193 :             std::string datetime = item.first;
     830        2193 :             if (rewriteTimestamp) {
     831        2143 :                 if (smallestReportFreq < OutputProcessor::ReportFreq::Month) {
     832        2139 :                     datetime = datetime.replace(datetime.find(' '), 1, "  ");
     833             :                 } else {
     834           4 :                     convertToMonth(datetime);
     835             :                 }
     836             :             }
     837        2193 :             print<FormatSyntax::FMT>(outputFile, " {},", datetime);
     838        4386 :             item.second.erase(std::remove_if(item.second.begin(),
     839        4386 :                                              item.second.end(),
     840       90897 :                                              [&](const std::string &d) {
     841       90897 :                                                  auto pos = (&d - &*item.second.begin());
     842       90897 :                                                  return !outputVariableIndices[pos];
     843             :                                              }),
     844        4386 :                               item.second.end());
     845       37442 :             auto result = std::find_if(item.second.rbegin(), item.second.rend(), [](std::string const &v) { return !v.empty(); });
     846        2193 :             auto last = item.second.end() - 1;
     847        2193 :             if (result != item.second.rend()) {
     848        2193 :                 last = (result + 1).base();
     849             :             }
     850             : 
     851        2193 :             print<FormatSyntax::FMT>(outputFile, "{},", fmt::join(item.second.begin(), last, ","));
     852        2193 :             print<FormatSyntax::FMT>(outputFile, "{}\n", *last);
     853        2203 :         }
     854             : 
     855          10 :         outputFile.close();
     856          10 :     }
     857             : 
     858         796 :     void ResultsFramework::setupOutputOptions(EnergyPlusData &state)
     859             :     {
     860         796 :         if (state.files.outputControl.csv) {
     861           6 :             tsEnabled = true;
     862           6 :             tsAndTabularEnabled = true;
     863             :         }
     864             : 
     865         796 :         if (!state.files.outputControl.json) {
     866         792 :             return;
     867             :         }
     868             : 
     869         795 :         int numberOfOutputSchemaObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Output:JSON");
     870         795 :         if (numberOfOutputSchemaObjects == 0) {
     871         791 :             return;
     872             :         }
     873             : 
     874           4 :         Array1D_string alphas(5);
     875             :         int numAlphas;
     876           4 :         Array1D<Real64> numbers(2);
     877             :         int numNumbers;
     878             :         int status;
     879           4 :         state.dataInputProcessing->inputProcessor->getObjectItem(state, "Output:JSON", 1, alphas, numAlphas, numbers, numNumbers, status);
     880             : 
     881           4 :         if (numAlphas > 0) {
     882           4 :             std::string option = alphas(1);
     883           4 :             if (Util::SameString(option, "TimeSeries")) {
     884           2 :                 tsEnabled = true;
     885           2 :             } else if (Util::SameString(option, "TimeSeriesAndTabular")) {
     886           2 :                 tsEnabled = true;
     887           2 :                 tsAndTabularEnabled = true;
     888             :             }
     889             : 
     890             :             // defaults
     891           4 :             outputJSON = true;
     892           4 :             outputCBOR = false;
     893           4 :             outputMsgPack = false;
     894             : 
     895           4 :             if (numAlphas >= 2) {
     896           2 :                 outputJSON = Util::SameString(alphas(2), "Yes");
     897             :             }
     898             : 
     899           4 :             if (numAlphas >= 3) {
     900           2 :                 outputCBOR = Util::SameString(alphas(3), "Yes");
     901             :             }
     902             : 
     903           4 :             if (numAlphas >= 4) {
     904           2 :                 outputMsgPack = Util::SameString(alphas(4), "Yes");
     905             :             }
     906           4 :         }
     907           4 :     }
     908             : 
     909    19416514 :     bool ResultsFramework::timeSeriesEnabled() const
     910             :     {
     911    19416514 :         return tsEnabled;
     912             :     }
     913             : 
     914      145281 :     bool ResultsFramework::timeSeriesAndTabularEnabled() const
     915             :     {
     916      145281 :         return tsAndTabularEnabled;
     917             :     }
     918             : 
     919           0 :     bool ResultsFramework::JSONEnabled() const
     920             :     {
     921           0 :         return outputJSON;
     922             :     }
     923             : 
     924           0 :     bool ResultsFramework::CBOREnabled() const
     925             :     {
     926           0 :         return outputCBOR;
     927             :     }
     928             : 
     929           0 :     bool ResultsFramework::MsgPackEnabled() const
     930             :     {
     931           0 :         return outputMsgPack;
     932             :     }
     933             : 
     934        2864 :     void ResultsFramework::initializeTSDataFrame(const OutputProcessor::ReportFreq reportFrequency,
     935             :                                                  const std::vector<OutputProcessor::OutVar *> &Variables,
     936             :                                                  const OutputProcessor::TimeStepType timeStepType)
     937             :     {
     938      462408 :         for (auto *var : Variables) {
     939             : 
     940      459544 :             if (var->Report && var->freq == reportFrequency) {
     941       27946 :                 Variable rfvar;
     942       27946 :                 if (var->units == Constant::Units::customEMS) {
     943          52 :                     rfvar = Variable(var->keyColonName, reportFrequency, var->timeStepType, var->ReportID, var->units, var->unitNameCustomEMS);
     944             :                 } else {
     945       27894 :                     rfvar = Variable(var->keyColonName, reportFrequency, var->timeStepType, var->ReportID, var->units);
     946             :                 }
     947             : 
     948       27946 :                 switch (reportFrequency) {
     949          58 :                 case OutputProcessor::ReportFreq::EachCall: { // each time UpdatedataandReport is called
     950          58 :                     if (timeStepType == var->timeStepType) {
     951          29 :                         detailedTSData[(int)timeStepType].setDataFrameEnabled(true);
     952          29 :                         detailedTSData[(int)timeStepType].addVariable(rfvar);
     953             :                     }
     954          58 :                 } break;
     955       27888 :                 case OutputProcessor::ReportFreq::Hour:       // at 'EndHourFlag'
     956             :                 case OutputProcessor::ReportFreq::TimeStep:   // at 'EndTimeStepFlag'
     957             :                 case OutputProcessor::ReportFreq::Day:        // at 'EndDayFlag'
     958             :                 case OutputProcessor::ReportFreq::Month:      // at 'EndMonthFlag'
     959             :                 case OutputProcessor::ReportFreq::Simulation: // once per environment 'EndEnvrnFlag'
     960             :                 case OutputProcessor::ReportFreq::Year: {     // at end of year
     961       27888 :                     freqTSData[(int)reportFrequency].setDataFrameEnabled(true);
     962       27888 :                     freqTSData[(int)reportFrequency].addVariable(rfvar);
     963       27888 :                 } break;
     964           0 :                 default: {
     965           0 :                     assert(false);
     966             :                 } break;
     967             :                 }
     968       27946 :             }
     969        2864 :         }
     970             :         // set the scanned variables to true or false
     971        2864 :         switch (reportFrequency) {
     972          20 :         case OutputProcessor::ReportFreq::EachCall: {
     973          20 :             detailedTSData[(int)timeStepType].setVariablesScanned(true);
     974          20 :         } break;
     975        2844 :         case OutputProcessor::ReportFreq::TimeStep:   // at 'EndTimeStepFlag'
     976             :         case OutputProcessor::ReportFreq::Hour:       // at 'EndHourFlag'
     977             :         case OutputProcessor::ReportFreq::Day:        // at 'EndDayFlag'
     978             :         case OutputProcessor::ReportFreq::Month:      // at end of month
     979             :         case OutputProcessor::ReportFreq::Simulation: // once per environment 'EndEnvrnFlag'
     980             :         case OutputProcessor::ReportFreq::Year: {     // at end of year
     981        2844 :             detailedTSData[(int)timeStepType].setVariablesScanned(true);
     982        2844 :         } break;
     983           0 :         default: {
     984           0 :             assert(false);
     985             :         } break;
     986             :         }
     987        2864 :     }
     988             : 
     989      572758 :     void ResultsFramework::initializeMeters(const std::vector<OutputProcessor::Meter *> &meters, const OutputProcessor::ReportFreq freq)
     990             :     {
     991      572758 :         switch (freq) {
     992           0 :         case OutputProcessor::ReportFreq::EachCall: {
     993             :             // nothing to do; meters are not reported at this frequency
     994           0 :         } break;
     995      572758 :         case OutputProcessor::ReportFreq::TimeStep:   // at 'TimeStep'
     996             :         case OutputProcessor::ReportFreq::Hour:       // at 'Hourly'
     997             :         case OutputProcessor::ReportFreq::Day:        // at 'Daily'
     998             :         case OutputProcessor::ReportFreq::Month:      // at 'Monthly'
     999             :         case OutputProcessor::ReportFreq::Simulation: // at 'RunPeriod'/'SM'
    1000             :         case OutputProcessor::ReportFreq::Year: {     // at 'Yearly'
    1001    57828987 :             for (auto const *meter : meters) {
    1002    57256229 :                 auto const &period = meter->periods[(int)freq];
    1003    57256229 :                 if (period.Rpt || period.RptFO) {
    1004        8355 :                     Meters[(int)freq].addVariable(MeterVariable(meter->Name, freq, period.RptNum, meter->units, period.RptFO));
    1005        8355 :                     Meters[(int)freq].setDataFrameEnabled(true);
    1006             :                 }
    1007    57256229 :                 if (period.accRpt || period.accRptFO) {
    1008           5 :                     Meters[(int)freq].addVariable(MeterVariable(meter->Name, freq, period.accRptNum, meter->units, period.accRptFO));
    1009           5 :                     Meters[(int)freq].setDataFrameEnabled(true);
    1010             :                 }
    1011      572758 :             }
    1012      572758 :         } break;
    1013             : 
    1014           0 :         default: {
    1015           0 :             assert(false);
    1016             :         } break;
    1017             :         } // switch (frequency)
    1018             : 
    1019             :         // set the scanned variables to true or false
    1020      572758 :         switch (freq) {
    1021           0 :         case OutputProcessor::ReportFreq::EachCall:
    1022             :             // case should not happen in Meters
    1023           0 :             break;
    1024      572758 :         case OutputProcessor::ReportFreq::TimeStep:   // at TimeStepFlag
    1025             :         case OutputProcessor::ReportFreq::Hour:       // at Hourly
    1026             :         case OutputProcessor::ReportFreq::Day:        // at Daily
    1027             :         case OutputProcessor::ReportFreq::Month:      // at Monthly
    1028             :         case OutputProcessor::ReportFreq::Simulation: // at RunPeriod/SM
    1029             :         case OutputProcessor::ReportFreq::Year: {     // at Yearly
    1030      572758 :             Meters[(int)freq].setVariablesScanned(true);
    1031      572758 :         } break;
    1032           0 :         default:
    1033           0 :             assert(false);
    1034             :         }
    1035      572758 :     }
    1036             : 
    1037         796 :     void ResultsFramework::writeOutputs(EnergyPlusData &state)
    1038             :     {
    1039         796 :         if (state.files.outputControl.csv) {
    1040           6 :             writeCSVOutput(state);
    1041             :         }
    1042             : 
    1043         796 :         if (timeSeriesEnabled() && (outputJSON || outputCBOR || outputMsgPack)) {
    1044           4 :             writeTimeSeriesReports(state.files.json);
    1045             :         }
    1046             : 
    1047         796 :         if (timeSeriesAndTabularEnabled() && (outputJSON || outputCBOR || outputMsgPack)) {
    1048           2 :             writeReport(state.files.json);
    1049             :         }
    1050         796 :     }
    1051             : 
    1052           6 :     void ResultsFramework::writeCSVOutput(EnergyPlusData &state)
    1053             :     {
    1054             :         using OutputProcessor::ReportFreq;
    1055             : 
    1056           6 :         if (!hasOutputData()) {
    1057           0 :             return;
    1058             :         }
    1059           6 :         CSVWriter csv(outputVariables.size());
    1060           6 :         CSVWriter mtr_csv(outputVariables.size());
    1061             : 
    1062          42 :         for (ReportFreq freq :
    1063          48 :              {ReportFreq::Year, ReportFreq::Simulation, ReportFreq::Month, ReportFreq::Day, ReportFreq::Hour, ReportFreq::TimeStep}) {
    1064             :             // Output yearly time series data
    1065          36 :             if (hasTSData(freq)) {
    1066           4 :                 csv.parseTSOutputs(state, freqTSData[(int)freq].getJSON(), outputVariables, freq);
    1067             :             }
    1068             : 
    1069          36 :             if (hasMeters(freq)) {
    1070           8 :                 csv.parseTSOutputs(state, Meters[(int)freq].getJSON(true), outputVariables, freq);
    1071           8 :                 mtr_csv.parseTSOutputs(state, Meters[(int)freq].getJSON(), outputVariables, freq);
    1072             :             }
    1073             :         }
    1074             : 
    1075          18 :         for (TimeStepType timeStepType : {TimeStepType::System, TimeStepType::Zone}) {
    1076             :             // Output detailed HVAC time series data
    1077          12 :             if (hasDetailedTSData(timeStepType)) {
    1078           6 :                 csv.parseTSOutputs(state, detailedTSData[(int)timeStepType].getJSON(), outputVariables, ReportFreq::EachCall);
    1079             :             }
    1080             :         }
    1081             : 
    1082           6 :         csv.writeOutput(state, outputVariables, state.files.csv, state.files.outputControl.csv, rewriteTimestamp);
    1083           6 :         if (hasMeterData()) {
    1084           4 :             mtr_csv.writeOutput(state, outputVariables, state.files.mtr_csv, state.files.outputControl.csv, rewriteTimestamp);
    1085             :         }
    1086           6 :     }
    1087             : 
    1088           4 :     void ResultsFramework::writeTimeSeriesReports(JsonOutputFilePaths &jsonOutputFilePaths)
    1089             :     {
    1090             :         // Output detailed Zone & HVAC time series data
    1091          12 :         for (TimeStepType timeStepType : {TimeStepType::Zone, TimeStepType::System}) {
    1092           8 :             if (hasDetailedTSData(timeStepType)) {
    1093           1 :                 detailedTSData[(int)timeStepType].writeReport(jsonOutputFilePaths, outputJSON, outputCBOR, outputMsgPack);
    1094             :             }
    1095             :         }
    1096             : 
    1097             :         // Output timestep time series data
    1098          28 :         for (ReportFreq freq :
    1099          32 :              {ReportFreq::TimeStep, ReportFreq::Hour, ReportFreq::Day, ReportFreq::Month, ReportFreq::Simulation, ReportFreq::Year}) {
    1100          24 :             if (hasFreqTSData(freq)) {
    1101           4 :                 freqTSData[(int)freq].writeReport(jsonOutputFilePaths, outputJSON, outputCBOR, outputMsgPack);
    1102             :             }
    1103             :         }
    1104           4 :     }
    1105             : 
    1106           2 :     void ResultsFramework::writeReport(JsonOutputFilePaths &jsonOutputFilePaths)
    1107             :     {
    1108           2 :         json root, outputVars, meterVars, meterData;
    1109          14 :         root = {{"SimulationResults", {{"Simulation", SimulationInformation.getJSON()}}}};
    1110             : 
    1111             :         // output variables
    1112             : 
    1113             :         // This could be constexpr except that json maps do not take string_view keys
    1114           2 :         static std::array<std::string, (int)TimeStepType::Num> const timeStepStrings = {"Detailed-Zone", "Detailed-HVAC"};
    1115           6 :         for (TimeStepType timeStep : {TimeStepType::Zone, TimeStepType::System}) {
    1116           4 :             if (hasDetailedTSData(timeStep)) {
    1117           1 :                 outputVars[timeStepStrings[(int)timeStep]] = detailedTSData[(int)timeStep].getVariablesJSON();
    1118             :             }
    1119             :         }
    1120             : 
    1121             :         // Same issue here
    1122             :         static std::array<std::string, (int)ReportFreq::Num> const freqStrings = {
    1123           2 :             "Detailed", "TimeStep", "Hourly", "Daily", "Monthly", "RunPeriod", "Yearly"};
    1124          14 :         for (ReportFreq freq :
    1125          16 :              {ReportFreq::Year, ReportFreq::Simulation, ReportFreq::Month, ReportFreq::Day, ReportFreq::Hour, ReportFreq::TimeStep}) {
    1126          12 :             if (hasFreqTSData(freq)) {
    1127           2 :                 outputVars[freqStrings[(int)freq]] = freqTSData[(int)freq].getVariablesJSON();
    1128             :             }
    1129             :         }
    1130             : 
    1131             :         // output dictionary
    1132          14 :         outputVars["OutputDictionary"] = {{"Description", "Dictionary containing output variables that may be requested"}, {"Variables", RDD}};
    1133             : 
    1134             :         // meter variables
    1135             : 
    1136             :         // -- meter values
    1137          14 :         for (ReportFreq freq :
    1138          16 :              {ReportFreq::Year, ReportFreq::Simulation, ReportFreq::Month, ReportFreq::Day, ReportFreq::Hour, ReportFreq::TimeStep}) {
    1139          12 :             if (hasMeters(freq)) {
    1140           4 :                 meterVars[freqStrings[(int)freq]] = Meters[(int)freq].getVariablesJSON();
    1141           4 :                 meterData[freqStrings[(int)freq]] = Meters[(int)freq].getJSON();
    1142             :             }
    1143             :         }
    1144             : 
    1145             :         // -- meter dictionary
    1146          14 :         meterVars["MeterDictionary"] = {{"Description", "Dictionary containing meter variables that may be requested"}, {"Meters", MDD}};
    1147             : 
    1148           2 :         root["OutputVariables"] = outputVars;
    1149           2 :         root["MeterVariables"] = meterVars;
    1150           2 :         root["MeterData"] = meterData;
    1151           2 :         root["TabularReports"] = TabularReportsCollection.getJSON();
    1152             : 
    1153           2 :         if (outputJSON) {
    1154           2 :             FileSystem::writeFile<FileSystem::FileTypes::JSON>(jsonOutputFilePaths.outputJsonFilePath, root);
    1155             :         }
    1156           2 :         if (outputCBOR) {
    1157           1 :             FileSystem::writeFile<FileSystem::FileTypes::CBOR>(jsonOutputFilePaths.outputCborFilePath, root);
    1158             :         }
    1159           2 :         if (outputMsgPack) {
    1160           1 :             FileSystem::writeFile<FileSystem::FileTypes::MsgPack>(jsonOutputFilePaths.outputMsgPackFilePath, root);
    1161             :         }
    1162           2 :     }
    1163             : 
    1164       61042 :     void ResultsFramework::addReportVariable(std::string_view const keyedValue,
    1165             :                                              std::string_view const variableName,
    1166             :                                              std::string_view const units,
    1167             :                                              OutputProcessor::ReportFreq const freq)
    1168             :     {
    1169      122084 :         outputVariables.emplace_back(fmt::format("{0}:{1} [{2}]({3})", keyedValue, variableName, units, reportFreqNames[(int)freq]));
    1170       61042 :     }
    1171             : 
    1172        8478 :     void ResultsFramework::addReportMeter(std::string const &meter, std::string_view units, OutputProcessor::ReportFreq const freq)
    1173             :     {
    1174       16956 :         outputVariables.emplace_back(fmt::format("{0} [{1}]({2})", meter, units, reportFreqNames[(int)freq]));
    1175        8478 :     }
    1176             : 
    1177             : } // namespace ResultsFramework
    1178             : 
    1179             : } // namespace EnergyPlus

Generated by: LCOV version 1.14