LCOV - code coverage report
Current view: top level - EnergyPlus - ResultsFramework.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 81.3 % 621 505
Test Date: 2025-06-02 07:23:51 Functions: 73.8 % 80 59

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

Generated by: LCOV version 2.0-1