LCOV - code coverage report
Current view: top level - EnergyPlus - ResultsFramework.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 47.2 % 602 284
Test Date: 2025-05-22 16:09:37 Functions: 57.5 % 80 46

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

Generated by: LCOV version 2.0-1