LCOV - code coverage report
Current view: top level - EnergyPlus - OutputReportTabularAnnual.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 5.6 % 921 52
Test Date: 2025-06-02 07:23:51 Functions: 16.7 % 30 5

            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 <list>
      51              : #include <ostream>
      52              : #include <string>
      53              : #include <vector>
      54              : 
      55              : // ObjexxFCL Headers
      56              : #include <ObjexxFCL/Array1D.hh>
      57              : #include <ObjexxFCL/Array2D.hh>
      58              : #include <ObjexxFCL/Array2S.hh>
      59              : 
      60              : // EnergyPlus Headers
      61              : #include <EnergyPlus/CostEstimateManager.hh>
      62              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      63              : #include <EnergyPlus/DataEnvironment.hh>
      64              : #include <EnergyPlus/DataHVACGlobals.hh>
      65              : #include <EnergyPlus/General.hh>
      66              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      67              : #include <EnergyPlus/OutputProcessor.hh>
      68              : #include <EnergyPlus/OutputReportData.hh>
      69              : #include <EnergyPlus/OutputReportTabular.hh>
      70              : #include <EnergyPlus/OutputReportTabularAnnual.hh>
      71              : #include <EnergyPlus/SQLiteProcedures.hh>
      72              : #include <EnergyPlus/ScheduleManager.hh>
      73              : #include <EnergyPlus/UtilityRoutines.hh>
      74              : 
      75              : namespace EnergyPlus::OutputReportTabularAnnual {
      76              : 
      77          799 : void GetInputTabularAnnual(EnergyPlusData &state)
      78              : {
      79              :     // Jason Glazer, August 2015
      80              :     // The function assigns the input information for
      81              :     // REPORT:TABLE:ANNUAL also known as row per object
      82              :     // reports that are defined by the user. The input
      83              :     // information is assigned to a data structure that
      84              :     // is used for both user defined monthly reports and
      85              :     // predefined monthly reports.
      86              : 
      87         2397 :     static std::string const currentModuleObject("Output:Table:Annual");
      88              : 
      89              :     int jAlpha;
      90              :     int numParams;            // Number of elements combined
      91              :     int numAlphas;            // Number of elements in the alpha array
      92              :     int numNums;              // Number of elements in the numeric array
      93          799 :     Array1D_string alphArray; // character string data
      94          799 :     Array1D<Real64> numArray; // numeric data
      95              :     int IOStat;               // IO Status when calling get input subroutine
      96              :     // static bool ErrorsFound( false );
      97          799 :     int objCount(0);
      98              :     int curNumDgts;
      99          799 :     AnnualFieldSet::AggregationKind curAgg(AnnualFieldSet::AggregationKind::sumOrAvg);
     100              : 
     101          799 :     auto &annualTables = state.dataOutputReportTabularAnnual->annualTables;
     102              : 
     103          799 :     objCount = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, currentModuleObject);
     104          799 :     if (objCount > 0) {
     105              : 
     106            1 :         state.dataOutRptTab->WriteTabularFiles = true;
     107              : 
     108              :         // if not a run period using weather do not create reports
     109            1 :         if (!state.dataGlobal->DoWeathSim) {
     110            2 :             ShowWarningError(
     111              :                 state,
     112            2 :                 format("{} requested with SimulationControl Run Simulation for Weather File Run Periods set to No so {} will not be generated",
     113              :                        currentModuleObject,
     114              :                        currentModuleObject));
     115            1 :             return;
     116              :         }
     117              :     }
     118          798 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, currentModuleObject, numParams, numAlphas, numNums);
     119          798 :     alphArray.allocate(numAlphas);
     120          798 :     numArray.dimension(numNums, 0.0);
     121          798 :     for (int tabNum = 1; tabNum <= objCount; ++tabNum) {
     122            0 :         state.dataInputProcessing->inputProcessor->getObjectItem(state, currentModuleObject, tabNum, alphArray, numAlphas, numArray, numNums, IOStat);
     123            0 :         if (numAlphas >= 5) {
     124            0 :             annualTables.push_back(AnnualTable(state, alphArray(1), alphArray(2), alphArray(3)));
     125              :             // the remaining fields are repeating in groups of three and need to be added to the data structure
     126            0 :             for (jAlpha = 4; jAlpha <= numAlphas; jAlpha += 2) {
     127            0 :                 std::string curVarMtr = alphArray(jAlpha);
     128            0 :                 if (curVarMtr.empty()) {
     129            0 :                     ShowWarningError(state,
     130            0 :                                      format("{}: Blank column specified in '{}', need to provide a variable or meter or EMS variable name ",
     131              :                                             currentModuleObject,
     132              :                                             alphArray(1)));
     133              :                 }
     134            0 :                 if (jAlpha <= numAlphas) {
     135            0 :                     std::string aggregationString = alphArray(jAlpha + 1);
     136            0 :                     curAgg = stringToAggKind(state, aggregationString);
     137            0 :                 } else {
     138            0 :                     curAgg = AnnualFieldSet::AggregationKind::sumOrAvg; // if missing aggregation type use SumOrAverage
     139              :                 }
     140            0 :                 int indexNums = 1 + (jAlpha - 3) / 2; // compute the corresponding field index in the numArray
     141            0 :                 if (indexNums <= numNums) {
     142            0 :                     curNumDgts = numArray(indexNums);
     143              :                 } else {
     144            0 :                     curNumDgts = 2;
     145              :                 }
     146            0 :                 if (!curVarMtr.empty()) {
     147            0 :                     annualTables.back().addFieldSet(curVarMtr, curAgg, curNumDgts);
     148              :                 }
     149            0 :             }
     150            0 :             annualTables.back().setupGathering(state);
     151              :         } else {
     152            0 :             ShowSevereError(state, format("{}: Must enter at least the first six fields.", currentModuleObject));
     153              :         }
     154              :     }
     155          800 : }
     156              : 
     157            0 : void AnnualTable::addFieldSet(std::string varName, AnnualFieldSet::AggregationKind aggKind, int dgts)
     158              : // Jason Glazer, August 2015
     159              : // This method is used along with the constructor to convert the GetInput for REPORT:TABLE:ANNUAL
     160              : // into the class data.
     161              : {
     162            0 :     m_annualFields.push_back(AnnualFieldSet(varName, aggKind, dgts));
     163            0 :     m_annualFields.back().m_colHead = varName; // use the variable name for the column heading
     164            0 : }
     165              : 
     166            0 : void AnnualTable::addFieldSet(std::string varName, std::string colName, AnnualFieldSet::AggregationKind aggKind, int dgts)
     167              : // Jason Glazer, August 2015
     168              : // This overloaded method allows for a specific column name to be different than the output variable or meter name
     169              : {
     170            0 :     m_annualFields.push_back(AnnualFieldSet(varName, aggKind, dgts));
     171            0 :     m_annualFields.back().m_colHead = colName; // use the user supplied column heading instead of just the variable name
     172            0 : }
     173              : 
     174            0 : void AnnualTable::setupGathering(EnergyPlusData &state)
     175              : // Jason Glazer, August 2015
     176              : // This method is used after GetInput for REPORT:TABLE:ANNUAL to set up how output variables, meters,
     177              : // input fields, and ems variables are gathered.
     178              : {
     179            0 :     OutputProcessor::VariableType typeVar = OutputProcessor::VariableType::Invalid;
     180              :     OutputProcessor::StoreType avgSumVar;
     181              :     OutputProcessor::TimeStepType stepTypeVar;
     182            0 :     Constant::Units unitsVar = Constant::Units::None;
     183            0 :     Array1D_string namesOfKeys;   // keyNames
     184            0 :     Array1D_int indexesForKeyVar; // keyVarIndexes
     185            0 :     std::list<std::string> allKeys;
     186              : 
     187            0 :     std::string filterFieldUpper = m_filter;
     188            0 :     std::transform(filterFieldUpper.begin(), filterFieldUpper.end(), filterFieldUpper.begin(), ::toupper);
     189            0 :     bool useFilter = (m_filter.size() != 0);
     190              : 
     191            0 :     std::vector<AnnualFieldSet>::iterator fldStIt;
     192            0 :     for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
     193            0 :         int keyCount = fldStIt->getVariableKeyCountandTypeFromFldSt(state, typeVar, avgSumVar, stepTypeVar, unitsVar);
     194            0 :         fldStIt->getVariableKeysFromFldSt(state, typeVar, keyCount, fldStIt->m_namesOfKeys, fldStIt->m_indexesForKeyVar);
     195            0 :         for (std::string nm : fldStIt->m_namesOfKeys) {
     196            0 :             std::string nmUpper = nm;
     197            0 :             std::transform(nmUpper.begin(), nmUpper.end(), nmUpper.begin(), ::toupper);
     198            0 :             if (!useFilter || nmUpper.find(filterFieldUpper) != std::string::npos) {
     199            0 :                 allKeys.push_back(nm); // create list of all items
     200              :             }
     201            0 :         }
     202            0 :         fldStIt->m_typeOfVar = typeVar;
     203            0 :         fldStIt->m_varAvgSum = avgSumVar;
     204            0 :         fldStIt->m_varStepType = stepTypeVar;
     205            0 :         fldStIt->m_varUnits = unitsVar;
     206            0 :         fldStIt->m_keyCount = keyCount;
     207              :     }
     208            0 :     allKeys.sort();
     209            0 :     allKeys.unique();                                                        // will now just have a list of the unique keys that is sorted
     210            0 :     std::copy(allKeys.begin(), allKeys.end(), back_inserter(m_objectNames)); // copy list to the object names
     211              :     // size all columns list of cells to be the size of the
     212            0 :     for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
     213            0 :         fldStIt->m_cell.resize(m_objectNames.size());
     214              :     }
     215              :     // for each column (field set) set the rows cell to the output variable index (for variables)
     216              :     int foundKeyIndex;
     217            0 :     int tableRowIndex = 0;
     218            0 :     for (std::vector<std::string>::iterator objNmIt = m_objectNames.begin(); objNmIt != m_objectNames.end(); ++objNmIt) {
     219            0 :         for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
     220            0 :             foundKeyIndex = -1;
     221            0 :             for (std::string::size_type i = 0; i < fldStIt->m_namesOfKeys.size(); i++) {
     222            0 :                 if (fldStIt->m_namesOfKeys[i] == *objNmIt) {
     223            0 :                     foundKeyIndex = i;
     224            0 :                     break;
     225              :                 }
     226              :             }
     227            0 :             if (foundKeyIndex > -1) {
     228            0 :                 fldStIt->m_cell[tableRowIndex].indexesForKeyVar = fldStIt->m_indexesForKeyVar[foundKeyIndex];
     229              :             } else {
     230            0 :                 fldStIt->m_cell[tableRowIndex].indexesForKeyVar = -1; // flag value that cell is not gathered
     231              :             }
     232            0 :             if (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximum ||
     233            0 :                 fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximumDuringHoursShown) {
     234            0 :                 fldStIt->m_cell[tableRowIndex].result = -9.9e99;
     235            0 :             } else if (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimum ||
     236            0 :                        fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimumDuringHoursShown) {
     237            0 :                 fldStIt->m_cell[tableRowIndex].result = 9.9e99;
     238              :             } else {
     239            0 :                 fldStIt->m_cell[tableRowIndex].result = 0.0;
     240              :             }
     241            0 :             fldStIt->m_cell[tableRowIndex].duration = 0.0;
     242            0 :             fldStIt->m_cell[tableRowIndex].timeStamp = 0;
     243              :         }
     244            0 :         tableRowIndex++;
     245            0 :     }
     246            0 : }
     247              : 
     248          799 : void checkAggregationOrderForAnnual(EnergyPlusData &state)
     249              : {
     250          799 :     std::vector<AnnualTable>::iterator annualTableIt;
     251          799 :     bool invalidAggregationOrderFound = false;
     252          799 :     auto &annualTables = state.dataOutputReportTabularAnnual->annualTables;
     253          799 :     if (!state.dataGlobal->DoWeathSim) { // if no weather simulation than no reading of MonthlyInput array
     254          792 :         return;
     255              :     }
     256            7 :     for (annualTableIt = annualTables.begin(); annualTableIt != annualTables.end(); ++annualTableIt) {
     257            0 :         if (annualTableIt->invalidAggregationOrder(state)) {
     258            0 :             invalidAggregationOrderFound = true;
     259              :         }
     260              :     }
     261            7 :     if (invalidAggregationOrderFound) {
     262            0 :         ShowFatalError(state, "OutputReportTabularAnnual: Invalid aggregations detected, no simulation performed.");
     263              :     }
     264          799 : }
     265              : 
     266              : // Generate an error message if an advanced aggregation kind columns don't follow the appropriate column - Glazer 2017
     267            0 : bool AnnualTable::invalidAggregationOrder(EnergyPlusData &state)
     268              : {
     269            0 :     std::vector<AnnualFieldSet>::iterator fldStIt;
     270            0 :     bool foundMinOrMax = false;
     271            0 :     bool foundHourAgg = false;
     272            0 :     bool missingMaxOrMinError = false;
     273            0 :     bool missingHourAggError = false;
     274            0 :     for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
     275            0 :         if ((fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximum) ||
     276            0 :             (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimum)) {
     277            0 :             foundMinOrMax = true;
     278            0 :         } else if ((fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonZero) ||
     279            0 :                    (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursZero) ||
     280            0 :                    (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursPositive) ||
     281            0 :                    (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonPositive) ||
     282            0 :                    (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNegative) ||
     283            0 :                    (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonNegative)) {
     284            0 :             foundHourAgg = true;
     285            0 :         } else if (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::valueWhenMaxMin) {
     286            0 :             if (!foundMinOrMax) {
     287            0 :                 missingMaxOrMinError = true;
     288              :             }
     289            0 :         } else if ((fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::sumOrAverageHoursShown) ||
     290            0 :                    (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximumDuringHoursShown) ||
     291            0 :                    (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimumDuringHoursShown)) {
     292            0 :             if (!foundHourAgg) {
     293            0 :                 missingHourAggError = true;
     294              :             }
     295              :         }
     296              :     }
     297            0 :     if (missingMaxOrMinError) {
     298            0 :         ShowSevereError(state,
     299            0 :                         format("The Output:Table:Annual report named=\"{}\" has a valueWhenMaxMin aggregation type for a column without a previous "
     300              :                                "column that uses either the minimum or maximum aggregation types. The report will not be generated.",
     301            0 :                                m_name));
     302              :     }
     303            0 :     if (missingHourAggError) {
     304            0 :         ShowSevereError(state,
     305            0 :                         format("The Output:Table:Annual report named=\"{}\" has a --DuringHoursShown aggregation type for a column without a "
     306              :                                "previous field that uses one of the Hour-- aggregation types. The report will not be generated.",
     307            0 :                                m_name));
     308              :     }
     309            0 :     return (missingHourAggError || missingMaxOrMinError);
     310            0 : }
     311              : 
     312       497501 : void GatherAnnualResultsForTimeStep(EnergyPlusData &state, OutputProcessor::TimeStepType kindOfTimeStep)
     313              : {
     314              :     // Jason Glazer, August 2015
     315              :     // This function is not part of the class but acts as an interface between procedural code and the class by
     316              :     // gathering data for each of the AnnualTable objects
     317       497501 :     std::vector<AnnualTable>::iterator annualTableIt;
     318       497501 :     auto &annualTables = state.dataOutputReportTabularAnnual->annualTables;
     319       497501 :     for (annualTableIt = annualTables.begin(); annualTableIt != annualTables.end(); ++annualTableIt) {
     320            0 :         annualTableIt->gatherForTimestep(state, kindOfTimeStep);
     321              :     }
     322       497501 : }
     323              : 
     324            0 : void AnnualTable::gatherForTimestep(EnergyPlusData &state, OutputProcessor::TimeStepType kindOfTimeStep)
     325              : {
     326              :     // Jason Glazer, August 2015
     327              :     // For each cell of the table, gather the value as indicated by the type of aggregation
     328              : 
     329              :     int timestepTimeStamp;
     330            0 :     Real64 elapsedTime = AnnualTable::getElapsedTime(state, kindOfTimeStep);
     331            0 :     Real64 secondsInTimeStep = AnnualTable::getSecondsInTimeStep(state, kindOfTimeStep);
     332            0 :     bool activeMinMax = false;
     333            0 :     bool activeHoursShown = false;
     334              :     // if schedule is used and the current value is zero, don't gather values
     335            0 :     if (m_sched != nullptr && m_sched->getCurrentVal() == 0.0) {
     336            0 :         return;
     337              :     }
     338              :     // loop through the fields
     339            0 :     std::vector<AnnualFieldSet>::iterator fldStIt;
     340            0 :     std::vector<AnnualFieldSet>::iterator fldStRemainIt;
     341            0 :     for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     342            0 :         for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
     343            0 :             OutputProcessor::VariableType curTypeOfVar = fldStIt->m_typeOfVar;
     344            0 :             OutputProcessor::TimeStepType curStepType = fldStIt->m_varStepType;
     345            0 :             if (curStepType == kindOfTimeStep) // this is a much simpler conditional than the code in monthly gathering
     346              :             {
     347            0 :                 int curVarNum = fldStIt->m_cell[row].indexesForKeyVar;
     348            0 :                 if (curVarNum > -1) {
     349            0 :                     Real64 curValue = GetInternalVariableValue(state, curTypeOfVar, curVarNum);
     350              :                     // Get the value from the result array
     351            0 :                     Real64 oldResultValue = fldStIt->m_cell[row].result;
     352              :                     // int oldTimeStamp = fldStIt->m_cell[row].timeStamp;
     353            0 :                     Real64 oldDuration = fldStIt->m_cell[row].duration;
     354              :                     // Zero the revised values (as default if not set later)
     355            0 :                     Real64 newResultValue = 0.0;
     356            0 :                     int newTimeStamp = 0;
     357            0 :                     Real64 newDuration = 0.0;
     358            0 :                     bool activeNewValue = false;
     359              :                     // the current timestamp
     360            0 :                     int minuteCalculated = OutputProcessor::DetermineMinuteForReporting(state);
     361            0 :                     General::EncodeMonDayHrMin(
     362            0 :                         timestepTimeStamp, state.dataEnvrn->Month, state.dataEnvrn->DayOfMonth, state.dataGlobal->HourOfDay, minuteCalculated);
     363              :                     // perform the selected aggregation type
     364              :                     // the following types of aggregations are not gathered at this point:
     365              :                     // noAggregation, valueWhenMaxMin, sumOrAverageHoursShown,     maximumDuringHoursShown, minimumDuringHoursShown:
     366            0 :                     switch (fldStIt->m_aggregate) {
     367            0 :                     case AnnualFieldSet::AggregationKind::sumOrAvg:
     368            0 :                         if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Sum) { // if it is a summed variable
     369            0 :                             newResultValue = oldResultValue + curValue;
     370              :                         } else {
     371            0 :                             newResultValue = oldResultValue + curValue * elapsedTime; // for averaging - weight by elapsed time
     372              :                         }
     373            0 :                         newDuration = oldDuration + elapsedTime;
     374            0 :                         activeNewValue = true;
     375            0 :                         break;
     376            0 :                     case AnnualFieldSet::AggregationKind::maximum:
     377              :                         // per MJW when a summed variable is used divide it by the length of the time step
     378            0 :                         if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Sum) { // if it is a summed variable
     379            0 :                             curValue /= secondsInTimeStep;
     380              :                         }
     381            0 :                         if (curValue > oldResultValue) {
     382            0 :                             newResultValue = curValue;
     383            0 :                             newTimeStamp = timestepTimeStamp;
     384            0 :                             activeMinMax = true;
     385            0 :                             activeNewValue = true;
     386              :                         } else {
     387            0 :                             activeMinMax = false; // reset this
     388              :                         }
     389            0 :                         break;
     390            0 :                     case AnnualFieldSet::AggregationKind::minimum:
     391              :                         // per MJW when a summed variable is used divide it by the length of the time step
     392            0 :                         if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Sum) { // if it is a summed variable
     393            0 :                             curValue /= secondsInTimeStep;
     394              :                         }
     395            0 :                         if (curValue < oldResultValue) {
     396            0 :                             newResultValue = curValue;
     397            0 :                             newTimeStamp = timestepTimeStamp;
     398            0 :                             activeMinMax = true;
     399            0 :                             activeNewValue = true;
     400              :                         } else {
     401            0 :                             activeMinMax = false; // reset this
     402              :                         }
     403            0 :                         break;
     404            0 :                     case AnnualFieldSet::AggregationKind::hoursNonZero:
     405            0 :                         if (curValue != 0) {
     406            0 :                             newResultValue = oldResultValue + elapsedTime;
     407            0 :                             activeHoursShown = true;
     408            0 :                             activeNewValue = true;
     409              :                         } else {
     410            0 :                             activeHoursShown = false;
     411              :                         }
     412            0 :                         break;
     413            0 :                     case AnnualFieldSet::AggregationKind::hoursZero:
     414            0 :                         if (curValue == 0) {
     415            0 :                             newResultValue = oldResultValue + elapsedTime;
     416            0 :                             activeHoursShown = true;
     417            0 :                             activeNewValue = true;
     418              :                         } else {
     419            0 :                             activeHoursShown = false;
     420              :                         }
     421            0 :                         break;
     422            0 :                     case AnnualFieldSet::AggregationKind::hoursPositive:
     423            0 :                         if (curValue > 0) {
     424            0 :                             newResultValue = oldResultValue + elapsedTime;
     425            0 :                             activeHoursShown = true;
     426            0 :                             activeNewValue = true;
     427              :                         } else {
     428            0 :                             activeHoursShown = false;
     429              :                         }
     430            0 :                         break;
     431            0 :                     case AnnualFieldSet::AggregationKind::hoursNonPositive:
     432            0 :                         if (curValue <= 0) {
     433            0 :                             newResultValue = oldResultValue + elapsedTime;
     434            0 :                             activeHoursShown = true;
     435            0 :                             activeNewValue = true;
     436              :                         } else {
     437            0 :                             activeHoursShown = false;
     438              :                         }
     439            0 :                         break;
     440            0 :                     case AnnualFieldSet::AggregationKind::hoursNegative:
     441            0 :                         if (curValue < 0) {
     442            0 :                             newResultValue = oldResultValue + elapsedTime;
     443            0 :                             activeHoursShown = true;
     444            0 :                             activeNewValue = true;
     445              :                         } else {
     446            0 :                             activeHoursShown = false;
     447              :                         }
     448            0 :                         break;
     449            0 :                     case AnnualFieldSet::AggregationKind::hoursNonNegative:
     450            0 :                         if (curValue >= 0) {
     451            0 :                             newResultValue = oldResultValue + elapsedTime;
     452            0 :                             activeHoursShown = true;
     453            0 :                             activeNewValue = true;
     454              :                         } else {
     455            0 :                             activeHoursShown = false;
     456              :                         }
     457            0 :                         break;
     458            0 :                     case AnnualFieldSet::AggregationKind::hoursInTenPercentBins:
     459              :                     case AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax:
     460              :                     case AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax:
     461              :                     case AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero:
     462              :                     case AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev:
     463              :                     case AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev:
     464              :                         //  for all of the binning options add the value to the deferred
     465            0 :                         if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Sum) {                     // if it is a summed variable
     466            0 :                             fldStIt->m_cell[row].deferredResults.push_back(curValue /= secondsInTimeStep); // divide by time just like max and min
     467              :                         } else {
     468            0 :                             fldStIt->m_cell[row].deferredResults.push_back(curValue);
     469              :                         }
     470            0 :                         fldStIt->m_cell[row].deferredElapsed.push_back(elapsedTime); // save the amount of time for this particular value
     471            0 :                         newDuration = oldDuration + elapsedTime;
     472            0 :                         break;
     473            0 :                     case AnnualFieldSet::AggregationKind::noAggregation:
     474              :                     case AnnualFieldSet::AggregationKind::valueWhenMaxMin:
     475              :                     case AnnualFieldSet::AggregationKind::sumOrAverageHoursShown:
     476              :                     case AnnualFieldSet::AggregationKind::maximumDuringHoursShown:
     477              :                     case AnnualFieldSet::AggregationKind::minimumDuringHoursShown:
     478              :                         // do nothing
     479            0 :                         break;
     480              :                     } // end switch fldStIt->m_aggregate
     481              : 
     482              :                     // if the new value has been set then set the monthly values to the
     483              :                     // new columns. This skips the aggregation types that don't even get
     484              :                     // triggered now such as valueWhenMinMax and all the agg*HoursShown
     485            0 :                     if (activeNewValue) {
     486            0 :                         fldStIt->m_cell[row].result = newResultValue;
     487            0 :                         fldStIt->m_cell[row].timeStamp = newTimeStamp;
     488            0 :                         fldStIt->m_cell[row].duration = newDuration;
     489              :                     }
     490              :                     // if a minimum or maximum value was set this timeStep then
     491              :                     // scan the remaining columns of the table looking for values
     492              :                     // that are aggregation type "ValueWhenMaxMin" and set their values
     493              :                     // if another minimum or maximum column is found then end
     494              :                     // the scan (it will be taken care of when that column is done)
     495            0 :                     if (activeMinMax) {
     496            0 :                         for (fldStRemainIt = fldStIt + 1; fldStRemainIt != m_annualFields.end(); ++fldStRemainIt) {
     497            0 :                             if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::maximum ||
     498            0 :                                 fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::minimum) {
     499              :                                 // end scanning since these might reset
     500            0 :                                 break; // for fldStRemainIt
     501            0 :                             } else if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::valueWhenMaxMin) {
     502              :                                 // this case is when the value should be set
     503            0 :                                 OutputProcessor::VariableType scanTypeOfVar = fldStRemainIt->m_typeOfVar;
     504              :                                 // int scanStepType = fldStRemainIt->m_varStepType;
     505            0 :                                 int scanVarNum = fldStRemainIt->m_cell[row].indexesForKeyVar;
     506            0 :                                 if (scanVarNum > -1) {
     507            0 :                                     Real64 scanValue = GetInternalVariableValue(state, scanTypeOfVar, scanVarNum);
     508              :                                     // When a summed variable is used divide it by the length of the time step
     509            0 :                                     if (fldStRemainIt->m_varAvgSum == OutputProcessor::StoreType::Sum) { // if it is a summed variable
     510            0 :                                         scanValue /= secondsInTimeStep;
     511              :                                     }
     512            0 :                                     fldStRemainIt->m_cell[row].result = scanValue;
     513              :                                 }
     514              :                             } else {
     515              :                                 // do nothing
     516              :                             }
     517              :                         }
     518              :                     }
     519              :                     // If the hours variable is active then scan through the rest of the variables
     520              :                     // and accumulate
     521            0 :                     if (activeHoursShown) {
     522            0 :                         for (fldStRemainIt = fldStIt + 1; fldStRemainIt != m_annualFields.end(); ++fldStRemainIt) {
     523            0 :                             OutputProcessor::VariableType scanTypeOfVar = fldStRemainIt->m_typeOfVar;
     524              :                             // int scanStepType = fldStRemainIt->m_varStepType;
     525            0 :                             int scanVarNum = fldStRemainIt->m_cell[row].indexesForKeyVar;
     526            0 :                             Real64 oldScanValue = fldStRemainIt->m_cell[row].result;
     527            0 :                             if (scanVarNum > -1) {
     528            0 :                                 Real64 scanValue = GetInternalVariableValue(state, scanTypeOfVar, scanVarNum);
     529            0 :                                 if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursZero ||
     530            0 :                                     fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonZero ||
     531            0 :                                     fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursPositive ||
     532            0 :                                     fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonPositive ||
     533            0 :                                     fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNegative ||
     534            0 :                                     fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::hoursNonNegative) {
     535              :                                     // end scanning since these might reset
     536            0 :                                     break; // for fldStRemainIt
     537            0 :                                 } else if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::sumOrAverageHoursShown) {
     538            0 :                                     if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Sum) { // if it is a summed variable
     539            0 :                                         fldStRemainIt->m_cell[row].result = oldScanValue + scanValue;
     540              :                                     } else {
     541            0 :                                         fldStRemainIt->m_cell[row].result =
     542            0 :                                             oldScanValue + scanValue * elapsedTime; // for averaging - weight by elapsed time
     543              :                                     }
     544            0 :                                     fldStRemainIt->m_cell[row].duration += elapsedTime;
     545            0 :                                 } else if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::minimumDuringHoursShown) {
     546            0 :                                     if (fldStRemainIt->m_varAvgSum == OutputProcessor::StoreType::Sum) { // if it is a summed variable
     547            0 :                                         scanValue /= secondsInTimeStep;
     548              :                                     }
     549            0 :                                     if (scanValue < oldScanValue) {
     550            0 :                                         fldStRemainIt->m_cell[row].result = scanValue;
     551            0 :                                         fldStRemainIt->m_cell[row].timeStamp = timestepTimeStamp;
     552              :                                     }
     553            0 :                                 } else if (fldStRemainIt->m_aggregate == AnnualFieldSet::AggregationKind::maximumDuringHoursShown) {
     554            0 :                                     if (fldStRemainIt->m_varAvgSum == OutputProcessor::StoreType::Sum) { // if it is a summed variable
     555            0 :                                         scanValue /= secondsInTimeStep;
     556              :                                     }
     557            0 :                                     if (scanValue > oldScanValue) {
     558            0 :                                         fldStRemainIt->m_cell[row].result = scanValue;
     559            0 :                                         fldStRemainIt->m_cell[row].timeStamp = timestepTimeStamp;
     560              :                                     }
     561              :                                 } else {
     562              :                                     // do nothing
     563              :                                 }
     564              :                             }
     565            0 :                             activeHoursShown = false; // fixed CR8317
     566              :                         }
     567              :                     }
     568              :                 }
     569              :             }
     570              :         }
     571              :     }
     572            0 : }
     573              : 
     574            0 : void ResetAnnualGathering(EnergyPlusData &state)
     575              : {
     576              :     // Jason Glazer, October 2015
     577              :     // This function is not part of the class but acts as an interface between procedural code and the class by
     578              :     // resetting data for each of the AnnualTable objects
     579            0 :     std::vector<AnnualTable>::iterator annualTableIt;
     580            0 :     auto &annualTables = state.dataOutputReportTabularAnnual->annualTables;
     581            0 :     for (annualTableIt = annualTables.begin(); annualTableIt != annualTables.end(); ++annualTableIt) {
     582            0 :         annualTableIt->resetGathering();
     583              :     }
     584            0 : }
     585              : 
     586            0 : void AnnualTable::resetGathering()
     587              : {
     588            0 :     std::vector<AnnualFieldSet>::iterator fldStIt;
     589            0 :     for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     590            0 :         for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
     591            0 :             if (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximum ||
     592            0 :                 fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximumDuringHoursShown) {
     593            0 :                 fldStIt->m_cell[row].result = -9.9e99;
     594            0 :             } else if (fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimum ||
     595            0 :                        fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimumDuringHoursShown) {
     596            0 :                 fldStIt->m_cell[row].result = 9.9e99;
     597              :             } else {
     598            0 :                 fldStIt->m_cell[row].result = 0.0;
     599              :             }
     600            0 :             fldStIt->m_cell[row].duration = 0.0;
     601            0 :             fldStIt->m_cell[row].timeStamp = 0;
     602              :             // if any defered results
     603            0 :             fldStIt->m_cell[row].deferredResults.clear();
     604            0 :             fldStIt->m_cell[row].deferredElapsed.clear();
     605              :         }
     606              :     }
     607            0 : }
     608              : 
     609            0 : Real64 AnnualTable::getElapsedTime(EnergyPlusData &state, OutputProcessor::TimeStepType kindOfTimeStep)
     610              : {
     611              :     Real64 elapsedTime;
     612            0 :     if (kindOfTimeStep == OutputProcessor::TimeStepType::Zone) {
     613            0 :         elapsedTime = state.dataHVACGlobal->TimeStepSys;
     614              :     } else {
     615            0 :         elapsedTime = state.dataGlobal->TimeStepZone;
     616              :     }
     617            0 :     return elapsedTime;
     618              : }
     619              : 
     620            0 : Real64 AnnualTable::getSecondsInTimeStep(EnergyPlusData &state, OutputProcessor::TimeStepType kindOfTimeStep)
     621              : {
     622              :     Real64 secondsInTimeStep;
     623            0 :     if (kindOfTimeStep == OutputProcessor::TimeStepType::Zone) {
     624            0 :         secondsInTimeStep = state.dataHVACGlobal->TimeStepSysSec;
     625              :     } else {
     626            0 :         secondsInTimeStep = state.dataGlobal->TimeStepZoneSec;
     627              :     }
     628            0 :     return secondsInTimeStep;
     629              : }
     630              : 
     631            6 : void WriteAnnualTables(EnergyPlusData &state)
     632              : {
     633            6 :     auto &annualTables = state.dataOutputReportTabularAnnual->annualTables;
     634           12 :     for (int iUnitSystem = 0; iUnitSystem <= 1; iUnitSystem++) {
     635           12 :         OutputReportTabular::UnitsStyle unitsStyle_cur = state.dataOutRptTab->unitsStyle;
     636           12 :         bool produceTabular = true;
     637           12 :         bool produceSQLite = false;
     638           12 :         if (produceDualUnitsFlags(iUnitSystem,
     639           12 :                                   state.dataOutRptTab->unitsStyle,
     640           12 :                                   state.dataOutRptTab->unitsStyle_SQLite,
     641              :                                   unitsStyle_cur,
     642              :                                   produceTabular,
     643              :                                   produceSQLite)) {
     644            6 :             break;
     645              :         }
     646              : 
     647              :         // Jason Glazer, August 2015
     648              :         // This function is not part of the class but acts as an interface between procedural code and the class by
     649              :         // invoking the writeTable member function for each of the AnnualTable objects
     650            6 :         std::vector<AnnualTable>::iterator annualTableIt;
     651            6 :         for (annualTableIt = annualTables.begin(); annualTableIt != annualTables.end(); ++annualTableIt) {
     652            0 :             annualTableIt->writeTable(state, unitsStyle_cur, produceTabular, produceSQLite);
     653              :         }
     654            6 :     }
     655            6 : }
     656              : 
     657            0 : void AnnualTable::writeTable(EnergyPlusData &state, OutputReportTabular::UnitsStyle unitsStyle, bool produceTabular_para, bool produceSQLite_para)
     658              : {
     659            0 :     Array1D_string columnHead;
     660            0 :     Array1D_int columnWidth;
     661            0 :     Array1D_string rowHead;
     662            0 :     Array2D_string tableBody;
     663            0 :     Real64 veryLarge = 1.0E280;
     664            0 :     Real64 verySmall = -1.0E280;
     665            0 :     std::vector<std::string> aggString;
     666            0 :     std::string energyUnitsString;
     667            0 :     std::string varNameWithUnits;
     668              :     int indexUnitConv;
     669              :     Real64 curVal;
     670            0 :     std::string curUnits;
     671              :     Real64 curConversionFactor;
     672              :     Real64 curConversionOffset;
     673              :     Real64 minVal;
     674              :     Real64 maxVal;
     675              :     Real64 sumVal;
     676              :     Real64 sumDuration;
     677            0 :     bool createBinRangeTable = false;
     678              : 
     679              :     static Real64 const storedMaxVal(std::numeric_limits<Real64>::max());
     680              :     static Real64 const storedMinVal(std::numeric_limits<Real64>::lowest());
     681              : 
     682            0 :     aggString = setupAggString();
     683            0 :     Real64 energyUnitsConversionFactor = AnnualTable::setEnergyUnitStringAndFactor(unitsStyle, energyUnitsString);
     684              : 
     685              :     // Compute the columns related to the binning schemes
     686            0 :     computeBinColumns(state, unitsStyle);
     687              : 
     688              :     // Use title case names of variables if available for column headers
     689            0 :     columnHeadersToTitleCase(state);
     690              : 
     691              :     // first loop through and count how many 'columns' are defined
     692              :     // since max and min actually define two columns (the value
     693              :     // and the timestamp).
     694            0 :     int columnCount = 0;
     695            0 :     std::vector<AnnualFieldSet>::iterator fldStIt;
     696            0 :     for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
     697            0 :         columnCount += columnCountForAggregation(fldStIt->m_aggregate);
     698              :     }
     699            0 :     columnHead.allocate(columnCount);
     700            0 :     columnWidth.dimension(columnCount);
     701            0 :     columnWidth = 14;                        // array assignment - same for all columns
     702            0 :     int rowCount = m_objectNames.size() + 4; // add blank, sum/avg, min, max rows.
     703            0 :     int rowSumAvg = m_objectNames.size() + 2;
     704            0 :     int rowMin = m_objectNames.size() + 3;
     705            0 :     int rowMax = m_objectNames.size() + 4;
     706              : 
     707            0 :     rowHead.allocate(rowCount);
     708            0 :     for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     709            0 :         rowHead(row + 1) = m_objectNames[row];
     710              :     }
     711            0 :     rowHead(rowSumAvg) = "Annual Sum or Average";
     712            0 :     rowHead(rowMin) = "Minimum of Rows";
     713            0 :     rowHead(rowMax) = "Maximum of Rows";
     714              : 
     715            0 :     tableBody.allocate(columnCount, rowCount);
     716            0 :     tableBody = ""; // set entire table to blank as default
     717            0 :     int columnRecount = 0;
     718            0 :     for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
     719            0 :         std::string curAggString = aggString[(int)fldStIt->m_aggregate];
     720            0 :         if (curAggString.size() > 0) {
     721            0 :             curAggString = " {" + trim(curAggString) + '}';
     722              :         }
     723              :         // do the unit conversions
     724            0 :         if (unitsStyle == OutputReportTabular::UnitsStyle::InchPound || unitsStyle == OutputReportTabular::UnitsStyle::InchPoundExceptElectricity) {
     725            0 :             varNameWithUnits = format("{} [{}]", fldStIt->m_variMeter, Constant::unitNames[(int)fldStIt->m_varUnits]);
     726            0 :             OutputReportTabular::LookupSItoIP(state, varNameWithUnits, indexUnitConv, curUnits);
     727            0 :             OutputReportTabular::GetUnitConversion(state, indexUnitConv, curConversionFactor, curConversionOffset, curUnits);
     728              :         } else { // just do the Joule conversion
     729              :             // if units is in Joules, convert if specified
     730            0 :             if (fldStIt->m_varUnits == Constant::Units::J) {
     731            0 :                 curUnits = energyUnitsString;
     732            0 :                 curConversionFactor = energyUnitsConversionFactor;
     733            0 :                 curConversionOffset = 0.0;
     734              :             } else { // if not joules don't perform conversion
     735            0 :                 curUnits = Constant::unitNames[(int)fldStIt->m_varUnits];
     736            0 :                 curConversionFactor = 1.0;
     737            0 :                 curConversionOffset = 0.0;
     738              :             }
     739              :         }
     740            0 :         int curAgg = fldStIt->m_aggregate;
     741            0 :         columnRecount += columnCountForAggregation(fldStIt->m_aggregate);
     742            0 :         if ((curAgg == AnnualFieldSet::AggregationKind::sumOrAvg) || (curAgg == AnnualFieldSet::AggregationKind::sumOrAverageHoursShown)) {
     743              :             // put in the name of the variable for the column
     744            0 :             columnHead(columnRecount) = fldStIt->m_colHead + curAggString + " [" + curUnits + ']';
     745            0 :             sumVal = 0.0;
     746            0 :             sumDuration = 0.0;
     747            0 :             minVal = storedMaxVal;
     748            0 :             maxVal = storedMinVal;
     749              : 
     750            0 :             for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     751            0 :                 if (fldStIt->m_cell[row].indexesForKeyVar >= 0) {
     752            0 :                     if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Average) { // if it is a average variable divide by duration
     753            0 :                         if (fldStIt->m_cell[row].duration != 0.0) {
     754            0 :                             curVal = ((fldStIt->m_cell[row].result / fldStIt->m_cell[row].duration) * curConversionFactor) + curConversionOffset;
     755              :                         } else {
     756            0 :                             curVal = 0.0;
     757              :                         }
     758            0 :                         sumVal += (fldStIt->m_cell[row].result * curConversionFactor) + curConversionOffset;
     759            0 :                         sumDuration += fldStIt->m_cell[row].duration;
     760              :                     } else {
     761            0 :                         curVal = (fldStIt->m_cell[row].result * curConversionFactor) + curConversionOffset;
     762            0 :                         sumVal += curVal;
     763              :                     }
     764            0 :                     tableBody(columnRecount, row + 1) = OutputReportTabular::RealToStr(curVal, fldStIt->m_showDigits);
     765            0 :                     if (curVal > maxVal) {
     766            0 :                         maxVal = curVal;
     767              :                     }
     768            0 :                     if (curVal < minVal) {
     769            0 :                         minVal = curVal;
     770              :                     }
     771              :                 } else {
     772            0 :                     tableBody(columnRecount, row + 1) = "-";
     773              :                 }
     774              : 
     775              :             } // row
     776              :             // add the summary to bottom
     777            0 :             if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Average) { // if it is a average variable divide by duration
     778            0 :                 if (sumDuration > 0) {
     779            0 :                     tableBody(columnRecount, rowSumAvg) = OutputReportTabular::RealToStr(sumVal / sumDuration, fldStIt->m_showDigits);
     780              :                 } else {
     781            0 :                     tableBody(columnRecount, rowSumAvg) = "";
     782              :                 }
     783              :             } else {
     784            0 :                 tableBody(columnRecount, rowSumAvg) = OutputReportTabular::RealToStr(sumVal, fldStIt->m_showDigits);
     785              :             }
     786            0 :             if (minVal != storedMaxVal) {
     787            0 :                 tableBody(columnRecount, rowMax) = OutputReportTabular::RealToStr(minVal, fldStIt->m_showDigits);
     788              :             }
     789            0 :             if (maxVal != storedMinVal) {
     790            0 :                 tableBody(columnRecount, rowMin) = OutputReportTabular::RealToStr(maxVal, fldStIt->m_showDigits);
     791              :             }
     792            0 :         } else if ((curAgg == AnnualFieldSet::AggregationKind::hoursZero) || (curAgg == AnnualFieldSet::AggregationKind::hoursNonZero) ||
     793            0 :                    (curAgg == AnnualFieldSet::AggregationKind::hoursPositive) || (curAgg == AnnualFieldSet::AggregationKind::hoursNonPositive) ||
     794            0 :                    (curAgg == AnnualFieldSet::AggregationKind::hoursNegative) || (curAgg == AnnualFieldSet::AggregationKind::hoursNonNegative)) {
     795              :             // put in the name of the variable for the column
     796            0 :             columnHead(columnRecount) = fldStIt->m_colHead + curAggString + " [HOURS]";
     797            0 :             sumVal = 0.0;
     798            0 :             minVal = storedMaxVal;
     799            0 :             maxVal = storedMinVal;
     800            0 :             for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     801            0 :                 curVal = fldStIt->m_cell[row].result;
     802            0 :                 curVal = curVal * curConversionFactor + curConversionOffset;
     803            0 :                 tableBody(columnRecount, row + 1) = OutputReportTabular::RealToStr(curVal, fldStIt->m_showDigits);
     804            0 :                 sumVal += curVal;
     805            0 :                 if (curVal > maxVal) {
     806            0 :                     maxVal = curVal;
     807              :                 }
     808            0 :                 if (curVal < minVal) {
     809            0 :                     minVal = curVal;
     810              :                 }
     811              :             } // row
     812              :             // add the summary to bottom
     813            0 :             tableBody(columnRecount, rowSumAvg) = OutputReportTabular::RealToStr(sumVal, fldStIt->m_showDigits);
     814            0 :             if (minVal != storedMaxVal) {
     815            0 :                 tableBody(columnRecount, rowMax) = OutputReportTabular::RealToStr(minVal, fldStIt->m_showDigits);
     816              :             }
     817            0 :             if (maxVal != storedMinVal) {
     818            0 :                 tableBody(columnRecount, rowMin) = OutputReportTabular::RealToStr(maxVal, fldStIt->m_showDigits);
     819              :             }
     820            0 :         } else if (curAgg == AnnualFieldSet::AggregationKind::valueWhenMaxMin) {
     821            0 :             if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Sum) {
     822            0 :                 curUnits += "/s";
     823              :             }
     824            0 :             fixUnitsPerSecond(curUnits, curConversionFactor);
     825            0 :             columnHead(columnRecount) = fldStIt->m_colHead + curAggString + " [" + curUnits + ']';
     826            0 :             minVal = storedMaxVal;
     827            0 :             maxVal = storedMinVal;
     828            0 :             for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     829            0 :                 curVal = fldStIt->m_cell[row].result;
     830            0 :                 curVal = curVal * curConversionFactor + curConversionOffset;
     831            0 :                 tableBody(columnRecount, row + 1) = OutputReportTabular::RealToStr(curVal, fldStIt->m_showDigits);
     832            0 :                 if (curVal > maxVal) {
     833            0 :                     maxVal = curVal;
     834              :                 }
     835            0 :                 if (curVal < minVal) {
     836            0 :                     minVal = curVal;
     837              :                 }
     838              :             } // row
     839              :             // add the summary to bottom
     840            0 :             if (minVal != storedMaxVal) {
     841            0 :                 tableBody(columnRecount, rowMin) = OutputReportTabular::RealToStr(minVal, fldStIt->m_showDigits);
     842              :             }
     843            0 :             if (maxVal != storedMinVal) {
     844            0 :                 tableBody(columnRecount, rowMax) = OutputReportTabular::RealToStr(maxVal, fldStIt->m_showDigits);
     845              :             }
     846            0 :         } else if ((curAgg == AnnualFieldSet::AggregationKind::maximum) || (curAgg == AnnualFieldSet::AggregationKind::minimum) ||
     847            0 :                    (curAgg == AnnualFieldSet::AggregationKind::maximumDuringHoursShown) ||
     848              :                    (curAgg == AnnualFieldSet::AggregationKind::minimumDuringHoursShown)) {
     849              :             // put in the name of the variable for the column
     850            0 :             if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Sum) { // if it is a summed variable
     851            0 :                 curUnits += "/s";
     852              :             }
     853            0 :             fixUnitsPerSecond(curUnits, curConversionFactor);
     854            0 :             columnHead(columnRecount - 1) = fldStIt->m_colHead + curAggString + " [" + curUnits + ']';
     855            0 :             columnHead(columnRecount) = fldStIt->m_colHead + " {TIMESTAMP}";
     856            0 :             minVal = storedMaxVal;
     857            0 :             maxVal = storedMinVal;
     858            0 :             for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     859            0 :                 curVal = fldStIt->m_cell[row].result;
     860              :                 // CR7788 the conversion factors were causing an overflow for the InchPound case since the
     861              :                 // value was very small
     862              :                 // restructured the following lines to hide showing HUGE and -HUGE values in output table CR8154 Glazer
     863            0 :                 if ((curVal < veryLarge) && (curVal > verySmall)) {
     864            0 :                     curVal = curVal * curConversionFactor + curConversionOffset;
     865            0 :                     if (curVal > maxVal) {
     866            0 :                         maxVal = curVal;
     867              :                     }
     868            0 :                     if (curVal < minVal) {
     869            0 :                         minVal = curVal;
     870              :                     }
     871            0 :                     if (curVal < veryLarge && curVal > verySmall) {
     872            0 :                         tableBody(columnRecount - 1, row + 1) = OutputReportTabular::RealToStr(curVal, fldStIt->m_showDigits);
     873              :                     } else {
     874            0 :                         tableBody(columnRecount - 1, row + 1) = "-";
     875              :                     }
     876            0 :                     tableBody(columnRecount, row + 1) = OutputReportTabular::DateToString(fldStIt->m_cell[row].timeStamp);
     877              :                 } else {
     878            0 :                     tableBody(columnRecount - 1, row + 1) = "-";
     879            0 :                     tableBody(columnRecount, row + 1) = "-";
     880              :                 }
     881              :             } // row
     882              :             // add the summary to bottom
     883              :             // Don't include if the original min and max values are still present
     884            0 :             if (minVal < veryLarge) {
     885            0 :                 tableBody(columnRecount - 1, rowMin) = OutputReportTabular::RealToStr(minVal, fldStIt->m_showDigits);
     886              :             } else {
     887            0 :                 tableBody(columnRecount - 1, rowMin) = "-";
     888              :             }
     889            0 :             if (maxVal > verySmall) {
     890            0 :                 tableBody(columnRecount - 1, rowMax) = OutputReportTabular::RealToStr(maxVal, fldStIt->m_showDigits);
     891              :             } else {
     892            0 :                 tableBody(columnRecount - 1, rowMax) = "-";
     893              :             }
     894            0 :         } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax) {
     895              :             // put in the name of the variable for the column
     896            0 :             if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Sum) { // if it is a summed variable
     897            0 :                 curUnits += "/s";
     898              :             }
     899            0 :             fixUnitsPerSecond(curUnits, curConversionFactor);
     900            0 :             for (int iBin = 0; iBin != 10; iBin++) {
     901            0 :                 char binIndicator = iBin + 65;
     902            0 :                 columnHead(columnRecount - 9 + iBin) = fldStIt->m_colHead + curAggString + " BIN " + binIndicator;
     903            0 :                 for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     904            0 :                     tableBody(columnRecount - 9 + iBin, row + 1) =
     905            0 :                         OutputReportTabular::RealToStr(fldStIt->m_cell[row].m_timeInBin[iBin], fldStIt->m_showDigits);
     906              :                 }
     907            0 :                 tableBody(columnRecount - 9 + iBin, rowSumAvg) =
     908            0 :                     OutputReportTabular::RealToStr(fldStIt->m_timeInBinTotal[iBin], fldStIt->m_showDigits);
     909              :             }
     910            0 :             createBinRangeTable = true;
     911            0 :         } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax) {
     912              :             // put in the name of the variable for the column
     913            0 :             if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Sum) { // if it is a summed variable
     914            0 :                 curUnits += "/s";
     915              :             }
     916            0 :             fixUnitsPerSecond(curUnits, curConversionFactor);
     917            0 :             for (int iBin = 0; iBin != 10; iBin++) {
     918            0 :                 char binIndicator = iBin + 65;
     919            0 :                 columnHead(columnRecount - 9 + iBin) = fldStIt->m_colHead + curAggString + " BIN " + binIndicator;
     920            0 :                 for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     921            0 :                     tableBody(columnRecount - 9 + iBin, row + 1) =
     922            0 :                         OutputReportTabular::RealToStr(fldStIt->m_cell[row].m_timeInBin[iBin], fldStIt->m_showDigits);
     923              :                 }
     924            0 :                 tableBody(columnRecount - 9 + iBin, rowSumAvg) =
     925            0 :                     OutputReportTabular::RealToStr(fldStIt->m_timeInBinTotal[iBin], fldStIt->m_showDigits);
     926              :             }
     927            0 :             columnHead(columnRecount - 10) = fldStIt->m_colHead + curAggString + " LESS THAN BIN A";
     928            0 :             for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     929            0 :                 tableBody(columnRecount - 10, row + 1) =
     930            0 :                     OutputReportTabular::RealToStr(fldStIt->m_cell[row].m_timeBelowBottomBin, fldStIt->m_showDigits);
     931              :             }
     932            0 :             tableBody(columnRecount - 10, rowSumAvg) = OutputReportTabular::RealToStr(fldStIt->m_timeBelowBottomBinTotal, fldStIt->m_showDigits);
     933            0 :             createBinRangeTable = true;
     934            0 :         } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero) {
     935              :             // put in the name of the variable for the column
     936            0 :             if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Sum) { // if it is a summed variable
     937            0 :                 curUnits += "/s";
     938              :             }
     939            0 :             fixUnitsPerSecond(curUnits, curConversionFactor);
     940            0 :             for (int iBin = 0; iBin != 10; iBin++) {
     941            0 :                 char binIndicator = iBin + 65;
     942            0 :                 columnHead(columnRecount - 10 + iBin) = fldStIt->m_colHead + curAggString + " BIN " + binIndicator;
     943            0 :                 for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     944            0 :                     tableBody(columnRecount - 10 + iBin, row + 1) =
     945            0 :                         OutputReportTabular::RealToStr(fldStIt->m_cell[row].m_timeInBin[iBin], fldStIt->m_showDigits);
     946              :                 }
     947            0 :                 tableBody(columnRecount - 10 + iBin, rowSumAvg) =
     948            0 :                     OutputReportTabular::RealToStr(fldStIt->m_timeInBinTotal[iBin], fldStIt->m_showDigits);
     949              :             }
     950            0 :             columnHead(columnRecount) = fldStIt->m_colHead + curAggString + " MORE THAN BIN J";
     951            0 :             for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
     952            0 :                 tableBody(columnRecount, row + 1) = OutputReportTabular::RealToStr(fldStIt->m_cell[row].m_timeAboveTopBin, fldStIt->m_showDigits);
     953              :             }
     954            0 :             tableBody(columnRecount, rowSumAvg) = OutputReportTabular::RealToStr(fldStIt->m_timeAboveTopBinTotal, fldStIt->m_showDigits);
     955            0 :             createBinRangeTable = true;
     956              :         } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenPercentBins ||
     957              :                    curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev ||
     958              :                    curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev) {
     959              :         }
     960            0 :     } // fldStIt
     961            0 :     if (produceTabular_para) {
     962            0 :         OutputReportTabular::WriteReportHeaders(state, m_name, "Entire Facility", OutputProcessor::StoreType::Average);
     963            0 :         OutputReportTabular::WriteSubtitle(state, "Custom Annual Report");
     964            0 :         OutputReportTabular::WriteTable(state, tableBody, rowHead, columnHead, columnWidth, true); // transpose annual XML tables.
     965              :     }
     966            0 :     if (produceSQLite_para) {
     967            0 :         if (state.dataSQLiteProcedures->sqlite) {
     968            0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
     969              :                 tableBody, rowHead, columnHead, m_name, "Entire Facility", "Custom Annual Report");
     970              :         }
     971              :     }
     972              :     // for the new binning aggregation types create a second table of the bin ranges
     973            0 :     if (createBinRangeTable) {
     974            0 :         Array1D_string colHeadRange;
     975            0 :         Array1D_int colWidthRange;
     976            0 :         Array1D_string rowHeadRange;
     977            0 :         Array2D_string tableBodyRange;
     978            0 :         colHeadRange.allocate(10);
     979            0 :         colWidthRange.allocate(10);
     980            0 :         colWidthRange = 14; // array assignment - same for all columns
     981            0 :         rowHeadRange.allocate(2);
     982            0 :         rowHeadRange(1) = ">=";
     983            0 :         rowHeadRange(2) = "<";
     984            0 :         tableBodyRange.allocate(10, 2);
     985            0 :         for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
     986            0 :             int curAgg = fldStIt->m_aggregate;
     987            0 :             if ((curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax) ||
     988            0 :                 (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax) ||
     989              :                 (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero)) {
     990            0 :                 tableBodyRange = ""; // set entire table to blank as default
     991            0 :                 Real64 binBottom = fldStIt->m_bottomBinValue;
     992            0 :                 Real64 binTop = fldStIt->m_topBinValue;
     993            0 :                 Real64 numBins = 10.;
     994            0 :                 Real64 intervalSize = (binTop - binBottom) / numBins;
     995              : 
     996              :                 // could not get the following to work using
     997            0 :                 colHeadRange(1) = "BIN A";
     998            0 :                 colHeadRange(2) = "BIN B";
     999            0 :                 colHeadRange(3) = "BIN C";
    1000            0 :                 colHeadRange(4) = "BIN D";
    1001            0 :                 colHeadRange(5) = "BIN E";
    1002            0 :                 colHeadRange(6) = "BIN F";
    1003            0 :                 colHeadRange(7) = "BIN G";
    1004            0 :                 colHeadRange(8) = "BIN H";
    1005            0 :                 colHeadRange(9) = "BIN I";
    1006            0 :                 colHeadRange(10) = "BIN J";
    1007            0 :                 for (int iBin = 0; iBin != 10; iBin++) {
    1008              :                     // colHeadRange( iBin + 1 ) = "BIN " + ( char )( iBin + 65 ); // not sure why this does not work
    1009            0 :                     tableBodyRange(iBin + 1, 1) = OutputReportTabular::RealToStr(binBottom + float(iBin) * intervalSize, fldStIt->m_showDigits);
    1010            0 :                     tableBodyRange(iBin + 1, 2) = OutputReportTabular::RealToStr(binBottom + float(iBin + 1) * intervalSize, fldStIt->m_showDigits);
    1011              :                 }
    1012            0 :                 if (produceTabular_para) {
    1013            0 :                     OutputReportTabular::WriteSubtitle(state, "Bin Sizes for: " + fldStIt->m_colHead);
    1014            0 :                     OutputReportTabular::WriteTable(
    1015              :                         state, tableBodyRange, rowHeadRange, colHeadRange, colWidthRange, true); // transpose annual XML tables.
    1016              :                 }
    1017            0 :                 if (produceSQLite_para) {
    1018            0 :                     if (state.dataSQLiteProcedures->sqlite) {
    1019            0 :                         state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    1020              :                             tableBodyRange, rowHeadRange, colHeadRange, m_name, "Entire Facility", "Bin Sizes");
    1021              :                     }
    1022              :                 }
    1023              :             }
    1024              :         }
    1025            0 :     }
    1026            0 : }
    1027              : 
    1028            0 : std::vector<std::string> AnnualTable::setupAggString()
    1029              : {
    1030            0 :     std::vector<std::string> retStringVec;
    1031            0 :     retStringVec.resize(20);
    1032            0 :     retStringVec[AnnualFieldSet::AggregationKind::sumOrAvg] = "";
    1033            0 :     retStringVec[AnnualFieldSet::AggregationKind::maximum] = " MAXIMUM ";
    1034            0 :     retStringVec[AnnualFieldSet::AggregationKind::minimum] = " MINIMUM ";
    1035            0 :     retStringVec[AnnualFieldSet::AggregationKind::valueWhenMaxMin] = " AT MAX/MIN ";
    1036            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursZero] = " HOURS ZERO ";
    1037            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursNonZero] = " HOURS NON-ZERO ";
    1038            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursPositive] = " HOURS POSITIVE ";
    1039            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursNonPositive] = " HOURS NON-POSITIVE ";
    1040            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursNegative] = " HOURS NEGATIVE ";
    1041            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursNonNegative] = " HOURS NON-NEGATIVE ";
    1042            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursInTenPercentBins] = " HOURS IN";            // " HOURS IN TEN PERCENT BINS ";
    1043            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax] = " HOURS IN";           // " HOURS IN TEN BINS MIN TO MAX ";
    1044            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax] = " HOURS IN";          // " HOURS IN TEN BINS ZERO TO MAX ";
    1045            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero] = " HOURS IN";          // " HOURS IN TEN BINS MIN TO ZERO ";
    1046            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev] = " HOURS IN"; // " HOURS IN TEN BINS PLUS OR MINUS TWO STD DEV ";
    1047            0 :     retStringVec[AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev] =
    1048            0 :         " HOURS IN"; // " HOURS IN TEN BINS PLUS OR MINUS THREE STD DEV ";
    1049            0 :     retStringVec[AnnualFieldSet::AggregationKind::noAggregation] = " NO AGGREGATION ";
    1050            0 :     retStringVec[AnnualFieldSet::AggregationKind::sumOrAverageHoursShown] = " FOR HOURS SHOWN ";
    1051            0 :     retStringVec[AnnualFieldSet::AggregationKind::maximumDuringHoursShown] = " MAX FOR HOURS SHOWN ";
    1052            0 :     retStringVec[AnnualFieldSet::AggregationKind::minimumDuringHoursShown] = " MIN FOR HOURS SHOWN ";
    1053            0 :     return retStringVec;
    1054            0 : }
    1055              : 
    1056            0 : Real64 AnnualTable::setEnergyUnitStringAndFactor(OutputReportTabular::UnitsStyle const unitsStyle, std::string &unitString)
    1057              : {
    1058              :     Real64 convFactor;
    1059              :     // set the unit conversion
    1060            0 :     if (unitsStyle == OutputReportTabular::UnitsStyle::None) {
    1061            0 :         unitString = "J";
    1062            0 :         convFactor = 1.0;
    1063            0 :     } else if (unitsStyle == OutputReportTabular::UnitsStyle::JtoKWH) {
    1064            0 :         unitString = "kWh";
    1065            0 :         convFactor = 1.0 / 3600000.0;
    1066            0 :     } else if (unitsStyle == OutputReportTabular::UnitsStyle::JtoMJ) {
    1067            0 :         unitString = "MJ";
    1068            0 :         convFactor = 1.0 / 1000000.0;
    1069            0 :     } else if (unitsStyle == OutputReportTabular::UnitsStyle::JtoGJ) {
    1070            0 :         unitString = "GJ";
    1071            0 :         convFactor = 1.0 / 1000000000.0;
    1072              :     } else { // Should never happen but assures compilers of initialization
    1073            0 :         unitString = "J";
    1074            0 :         convFactor = 1.0;
    1075              :     }
    1076            0 :     return convFactor;
    1077              : }
    1078              : 
    1079            0 : void AnnualTable::fixUnitsPerSecond(std::string &unitString, Real64 &conversionFactor)
    1080              : {
    1081            0 :     if (unitString == "J/s") {
    1082            0 :         unitString = "W";
    1083            0 :     } else if (unitString == "kWh/s") {
    1084            0 :         unitString = "W";
    1085            0 :         conversionFactor *= 3600000.0;
    1086            0 :     } else if (unitString == "GJ/s") {
    1087            0 :         unitString = "kW";
    1088            0 :         conversionFactor *= 1000000.0;
    1089            0 :     } else if (unitString == "MJ/s") {
    1090            0 :         unitString = "kW";
    1091            0 :         conversionFactor *= 1000.0;
    1092            0 :     } else if (unitString == "therm/s") {
    1093            0 :         unitString = "kBtu/h";
    1094            0 :         conversionFactor *= 360000.0;
    1095            0 :     } else if (unitString == "kBtu/s") {
    1096            0 :         unitString = "kBtu/h";
    1097            0 :         conversionFactor *= 3600.0;
    1098            0 :     } else if (unitString == "ton-hrs/s") {
    1099            0 :         unitString = "ton";
    1100            0 :         conversionFactor *= 3600.0;
    1101              :     }
    1102            0 : }
    1103              : 
    1104            0 : AnnualFieldSet::AggregationKind stringToAggKind(EnergyPlusData &state, std::string inString)
    1105              : // Jason Glazer, August 2015
    1106              : // The function converts a string into an enumeration that describes the type of aggregation
    1107              : // used in REPORT:TABLE:ANNUAL.
    1108              : {
    1109              :     AnnualFieldSet::AggregationKind outAggType;
    1110              : 
    1111            0 :     if (Util::SameString(inString, "SumOrAverage")) {
    1112            0 :         outAggType = AnnualFieldSet::AggregationKind::sumOrAvg;
    1113            0 :     } else if (Util::SameString(inString, "Maximum")) {
    1114            0 :         outAggType = AnnualFieldSet::AggregationKind::maximum;
    1115            0 :     } else if (Util::SameString(inString, "Minimum")) {
    1116            0 :         outAggType = AnnualFieldSet::AggregationKind::minimum;
    1117            0 :     } else if (Util::SameString(inString, "ValueWhenMaximumOrMinimum")) {
    1118            0 :         outAggType = AnnualFieldSet::AggregationKind::valueWhenMaxMin;
    1119            0 :     } else if (Util::SameString(inString, "HoursZero")) {
    1120            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursZero;
    1121            0 :     } else if (Util::SameString(inString, "HoursNonzero")) {
    1122            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursNonZero;
    1123            0 :     } else if (Util::SameString(inString, "HoursPositive")) {
    1124            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursPositive;
    1125            0 :     } else if (Util::SameString(inString, "HoursNonpositive")) {
    1126            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursNonPositive;
    1127            0 :     } else if (Util::SameString(inString, "HoursNegative")) {
    1128            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursNegative;
    1129            0 :     } else if (Util::SameString(inString, "HoursNonNegative")) {
    1130            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursNonNegative;
    1131            0 :     } else if (Util::SameString(inString, "HoursInTenPercentBins")) {
    1132            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursInTenPercentBins;
    1133            0 :     } else if (Util::SameString(inString, "HourInTenBinsMinToMax")) {
    1134            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax;
    1135            0 :     } else if (Util::SameString(inString, "HourInTenBinsZeroToMax")) {
    1136            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax;
    1137            0 :     } else if (Util::SameString(inString, "HourInTenBinsMinToZero")) {
    1138            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero;
    1139            0 :     } else if (Util::SameString(inString, "HoursInTenBinsPlusMinusTwoStdDev")) {
    1140            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev;
    1141            0 :     } else if (Util::SameString(inString, "HoursInTenBinsPlusMinusThreeStdDev")) {
    1142            0 :         outAggType = AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev;
    1143            0 :     } else if (Util::SameString(inString, "NoAggregation")) {
    1144            0 :         outAggType = AnnualFieldSet::AggregationKind::noAggregation;
    1145            0 :     } else if (Util::SameString(inString, "SumOrAverageDuringHoursShown")) {
    1146            0 :         outAggType = AnnualFieldSet::AggregationKind::sumOrAverageHoursShown;
    1147            0 :     } else if (Util::SameString(inString, "MaximumDuringHoursShown")) {
    1148            0 :         outAggType = AnnualFieldSet::AggregationKind::maximumDuringHoursShown;
    1149            0 :     } else if (Util::SameString(inString, "MinimumDuringHoursShown")) {
    1150            0 :         outAggType = AnnualFieldSet::AggregationKind::minimumDuringHoursShown;
    1151              :     } else {
    1152            0 :         outAggType = AnnualFieldSet::AggregationKind::sumOrAvg;
    1153            0 :         ShowWarningError(state, format("Invalid aggregation type=\"{}\"  Defaulting to SumOrAverage.", inString));
    1154              :     }
    1155            0 :     return outAggType;
    1156              : }
    1157              : 
    1158            0 : int AnnualTable::columnCountForAggregation(AnnualFieldSet::AggregationKind curAgg)
    1159              : {
    1160            0 :     int returnCount = 0;
    1161            0 :     if (curAgg == AnnualFieldSet::AggregationKind::sumOrAvg || curAgg == AnnualFieldSet::AggregationKind::valueWhenMaxMin ||
    1162            0 :         curAgg == AnnualFieldSet::AggregationKind::hoursZero || curAgg == AnnualFieldSet::AggregationKind::hoursNonZero ||
    1163            0 :         curAgg == AnnualFieldSet::AggregationKind::hoursPositive || curAgg == AnnualFieldSet::AggregationKind::hoursNonPositive ||
    1164            0 :         curAgg == AnnualFieldSet::AggregationKind::hoursNegative || curAgg == AnnualFieldSet::AggregationKind::hoursNonNegative ||
    1165            0 :         curAgg == AnnualFieldSet::AggregationKind::sumOrAverageHoursShown || curAgg == AnnualFieldSet::AggregationKind::noAggregation) {
    1166            0 :         returnCount = 1;
    1167            0 :     } else if (curAgg == AnnualFieldSet::AggregationKind::maximum || curAgg == AnnualFieldSet::AggregationKind::minimum ||
    1168            0 :                curAgg == AnnualFieldSet::AggregationKind::maximumDuringHoursShown ||
    1169              :                curAgg == AnnualFieldSet::AggregationKind::minimumDuringHoursShown) {
    1170            0 :         returnCount = 2;
    1171            0 :     } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax) {
    1172            0 :         returnCount = 10;
    1173            0 :     } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax ||
    1174              :                curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero) {
    1175            0 :         returnCount = 11;
    1176            0 :     } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenPercentBins ||
    1177            0 :                curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev ||
    1178              :                curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev) {
    1179            0 :         returnCount = 12;
    1180              :     }
    1181            0 :     return returnCount;
    1182              : }
    1183              : 
    1184            0 : std::string AnnualTable::trim(const std::string &str)
    1185              : {
    1186            0 :     std::string whitespace = " \t";
    1187            0 :     const size_t strBegin = str.find_first_not_of(whitespace);
    1188            0 :     if (strBegin == std::string::npos) {
    1189            0 :         return ""; // no content
    1190              :     }
    1191              : 
    1192            0 :     const size_t strEnd = str.find_last_not_of(whitespace);
    1193            0 :     const size_t strRange = strEnd - strBegin + 1;
    1194              : 
    1195            0 :     return str.substr(strBegin, strRange);
    1196            0 : }
    1197              : 
    1198            6 : void AddAnnualTableOfContents(EnergyPlusData &state, std::ostream &nameOfStream)
    1199              : {
    1200              :     // Jason Glazer, August 2015
    1201              :     // This function is not part of the class but acts as an interface between procedural code and the class by
    1202              :     // invoking the writeTable member function for each of the AnnualTable objects
    1203            6 :     std::vector<AnnualTable>::iterator annualTableIt;
    1204            6 :     auto &annualTables = state.dataOutputReportTabularAnnual->annualTables;
    1205            6 :     for (annualTableIt = annualTables.begin(); annualTableIt != annualTables.end(); ++annualTableIt) {
    1206            0 :         annualTableIt->addTableOfContents(nameOfStream);
    1207              :     }
    1208            6 : }
    1209              : 
    1210            0 : void AnnualTable::addTableOfContents(std::ostream &nameOfStream)
    1211              : {
    1212            0 :     nameOfStream << "<p><b>" << m_name << "</b></p> |\n";
    1213            0 :     nameOfStream << "<a href=\"#" << OutputReportTabular::MakeAnchorName(m_name, "Entire Facility") << "\">" << "Entire Facility" << "</a>    |   \n";
    1214            0 : }
    1215              : 
    1216            0 : void AnnualTable::computeBinColumns(EnergyPlusData &state, OutputReportTabular::UnitsStyle const unitsStyle_para)
    1217              : {
    1218            0 :     std::vector<AnnualFieldSet>::iterator fldStIt;
    1219            0 :     Real64 constexpr veryLarge = 1.0E280;
    1220            0 :     Real64 constexpr verySmall = -1.0E280;
    1221            0 :     for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
    1222            0 :         int curAgg = fldStIt->m_aggregate;
    1223              :         // for columns with binning aggregation types compute the statistics
    1224            0 :         if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax || curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax ||
    1225            0 :             curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero || curAgg == AnnualFieldSet::AggregationKind::hoursInTenPercentBins ||
    1226            0 :             curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev ||
    1227              :             curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev) {
    1228              :             // the size the deferred vectors should be same for all rows
    1229            0 :             if (allRowsSameSizeDefferedVectors(fldStIt)) {
    1230            0 :                 convertUnitForDeferredResults(state, fldStIt, unitsStyle_para);
    1231            0 :                 std::vector<Real64> deferredTotalForColumn;
    1232            0 :                 Real64 minVal = veryLarge;
    1233            0 :                 Real64 maxVal = verySmall;
    1234            0 :                 Real64 sum = 0;
    1235            0 :                 Real64 curVal = 0.0;
    1236            0 :                 for (unsigned int jDefRes = 0; jDefRes != fldStIt->m_cell[0].deferredResults.size(); jDefRes++) {
    1237            0 :                     sum = 0;
    1238            0 :                     for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
    1239            0 :                         curVal = fldStIt->m_cell[row].deferredResults[jDefRes];
    1240            0 :                         sum += curVal;
    1241            0 :                         if (curVal > maxVal) {
    1242            0 :                             maxVal = curVal;
    1243              :                         }
    1244            0 :                         if (curVal < minVal) {
    1245            0 :                             minVal = curVal;
    1246              :                         }
    1247              :                     }
    1248            0 :                     deferredTotalForColumn.push_back(sum / float(m_objectNames.size())); // put average value into the total row
    1249              :                 }
    1250            0 :                 if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToMax) {
    1251            0 :                     fldStIt->m_topBinValue = maxVal;
    1252            0 :                     fldStIt->m_bottomBinValue = minVal;
    1253            0 :                 } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsZeroToMax) {
    1254            0 :                     fldStIt->m_topBinValue = maxVal;
    1255            0 :                     fldStIt->m_bottomBinValue = 0.0;
    1256            0 :                 } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsMinToZero) {
    1257            0 :                     fldStIt->m_topBinValue = 0.0;
    1258            0 :                     fldStIt->m_bottomBinValue = minVal;
    1259            0 :                 } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenPercentBins) {
    1260            0 :                     fldStIt->m_topBinValue = 1.0;
    1261            0 :                     fldStIt->m_bottomBinValue = 0.0;
    1262              :                 } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusTwoStdDev) {
    1263              :                 } else if (curAgg == AnnualFieldSet::AggregationKind::hoursInTenBinsPlusMinusThreeStdDev) {
    1264              :                 }
    1265              :                 // compute the actual amount of time spent in each bin and above and below
    1266            0 :                 for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
    1267            0 :                     fldStIt->m_cell[row].m_timeInBin = calculateBins(10,
    1268            0 :                                                                      fldStIt->m_cell[row].deferredResults,
    1269            0 :                                                                      fldStIt->m_cell[row].deferredElapsed,
    1270            0 :                                                                      fldStIt->m_topBinValue,
    1271            0 :                                                                      fldStIt->m_bottomBinValue,
    1272            0 :                                                                      fldStIt->m_cell[row].m_timeAboveTopBin,
    1273            0 :                                                                      fldStIt->m_cell[row].m_timeBelowBottomBin);
    1274              :                 }
    1275              :                 // do the total row binning
    1276            0 :                 fldStIt->m_timeInBinTotal = calculateBins(10,
    1277              :                                                           deferredTotalForColumn,
    1278            0 :                                                           fldStIt->m_cell[0].deferredElapsed,
    1279            0 :                                                           fldStIt->m_topBinValue,
    1280            0 :                                                           fldStIt->m_bottomBinValue,
    1281            0 :                                                           fldStIt->m_timeAboveTopBinTotal,
    1282            0 :                                                           fldStIt->m_timeBelowBottomBinTotal);
    1283            0 :             }
    1284              :         }
    1285              :     }
    1286            0 : }
    1287              : 
    1288            0 : bool AnnualTable::allRowsSameSizeDefferedVectors(std::vector<AnnualFieldSet>::iterator fldStIt)
    1289              : {
    1290            0 :     bool returnFlag = true;
    1291            0 :     unsigned int sizeOfDeferred = 0;
    1292            0 :     for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
    1293            0 :         if (sizeOfDeferred == 0) {
    1294            0 :             sizeOfDeferred = fldStIt->m_cell[row].deferredResults.size();
    1295              :         } else {
    1296            0 :             if (fldStIt->m_cell[row].deferredResults.size() != sizeOfDeferred) {
    1297            0 :                 returnFlag = false;
    1298            0 :                 return returnFlag;
    1299              :             }
    1300              :         }
    1301              :     }
    1302            0 :     return returnFlag;
    1303              : }
    1304              : 
    1305            0 : void AnnualTable::convertUnitForDeferredResults(EnergyPlusData &state,
    1306              :                                                 std::vector<AnnualFieldSet>::iterator fldStIt,
    1307              :                                                 OutputReportTabular::UnitsStyle const unitsStyle)
    1308              : {
    1309              :     Real64 curConversionFactor;
    1310              :     Real64 curConversionOffset;
    1311            0 :     std::string curUnits;
    1312            0 :     std::string energyUnitsString;
    1313              :     Real64 curSI;
    1314              :     Real64 curIP;
    1315            0 :     Real64 energyUnitsConversionFactor = AnnualTable::setEnergyUnitStringAndFactor(unitsStyle, energyUnitsString);
    1316              :     // do the unit conversions
    1317            0 :     if (unitsStyle == OutputReportTabular::UnitsStyle::InchPound || unitsStyle == OutputReportTabular::UnitsStyle::InchPoundExceptElectricity) {
    1318              :         int indexUnitConv;
    1319            0 :         std::string varNameWithUnits = format("{} [{}]", fldStIt->m_variMeter, Constant::unitNames[(int)fldStIt->m_varUnits]);
    1320            0 :         OutputReportTabular::LookupSItoIP(state, varNameWithUnits, indexUnitConv, curUnits);
    1321            0 :         OutputReportTabular::GetUnitConversion(state, indexUnitConv, curConversionFactor, curConversionOffset, curUnits);
    1322            0 :     } else { // just do the Joule conversion
    1323              :         // if units is in Joules, convert if specified
    1324            0 :         if (fldStIt->m_varUnits == Constant::Units::J) {
    1325            0 :             curUnits = energyUnitsString;
    1326            0 :             curConversionFactor = energyUnitsConversionFactor;
    1327            0 :             curConversionOffset = 0.0;
    1328              :         } else { // if not joules don't perform conversion
    1329            0 :             curUnits = Constant::unitNames[(int)fldStIt->m_varUnits];
    1330            0 :             curConversionFactor = 1.0;
    1331            0 :             curConversionOffset = 0.0;
    1332              :         }
    1333              :     }
    1334            0 :     if (fldStIt->m_varAvgSum == OutputProcessor::StoreType::Sum) {
    1335            0 :         curUnits += "/s";
    1336              :     }
    1337            0 :     fixUnitsPerSecond(curUnits, curConversionFactor);
    1338            0 :     if (curConversionFactor != 1.0 || curConversionOffset != 0.0) {
    1339            0 :         for (unsigned int row = 0; row != m_objectNames.size(); row++) { // loop through by row.
    1340            0 :             for (unsigned int jDefRes = 0; jDefRes != fldStIt->m_cell[0].deferredResults.size(); jDefRes++) {
    1341            0 :                 curSI = fldStIt->m_cell[row].deferredResults[jDefRes];
    1342            0 :                 curIP = curSI * curConversionFactor + curConversionOffset;
    1343            0 :                 fldStIt->m_cell[row].deferredResults[jDefRes] = curIP;
    1344              :             }
    1345              :         }
    1346              :     }
    1347            0 : }
    1348              : 
    1349            0 : std::vector<Real64> AnnualTable::calculateBins(int const numberOfBins,
    1350              :                                                std::vector<Real64> valuesToBin,
    1351              :                                                std::vector<Real64> corrElapsedTime,
    1352              :                                                Real64 const topOfBins,
    1353              :                                                Real64 const bottomOfBins,
    1354              :                                                Real64 &timeAboveTopBin,
    1355              :                                                Real64 &timeBelowBottomBin)
    1356              : {
    1357            0 :     std::vector<Real64> returnBins(0.0);
    1358            0 :     returnBins.resize(numberOfBins);
    1359            0 :     Real64 intervalSize = (topOfBins - bottomOfBins) / float(numberOfBins);
    1360            0 :     timeAboveTopBin = 0.0;
    1361            0 :     timeBelowBottomBin = 0.0;
    1362            0 :     std::vector<Real64>::iterator elapsedTimeIt;
    1363            0 :     elapsedTimeIt = corrElapsedTime.begin();
    1364            0 :     std::vector<Real64>::iterator valueIt;
    1365            0 :     for (valueIt = valuesToBin.begin(); valueIt != valuesToBin.end(); ++valueIt) {
    1366            0 :         if (*valueIt < bottomOfBins) {
    1367            0 :             timeBelowBottomBin += *elapsedTimeIt;
    1368            0 :         } else if (*valueIt >= topOfBins) {
    1369            0 :             timeAboveTopBin += *elapsedTimeIt;
    1370              :         } else {
    1371              :             // determine which bin the results are in
    1372            0 :             int binNum = int((*valueIt - bottomOfBins) / intervalSize);
    1373            0 :             if (binNum < numberOfBins && binNum >= 0) {
    1374            0 :                 returnBins[binNum] += *elapsedTimeIt;
    1375              :             }
    1376              :         }
    1377            0 :         ++elapsedTimeIt;
    1378              :     }
    1379            0 :     return returnBins;
    1380            0 : }
    1381              : 
    1382            0 : void AnnualTable::columnHeadersToTitleCase(EnergyPlusData &state)
    1383              : {
    1384            0 :     std::vector<AnnualFieldSet>::iterator fldStIt;
    1385            0 :     for (fldStIt = m_annualFields.begin(); fldStIt != m_annualFields.end(); ++fldStIt) {
    1386            0 :         if (fldStIt->m_variMeter == fldStIt->m_colHead) {
    1387            0 :             if (fldStIt->m_indexesForKeyVar.size() > 0) {
    1388            0 :                 int varNum = fldStIt->m_indexesForKeyVar[0];
    1389            0 :                 if (fldStIt->m_typeOfVar == OutputProcessor::VariableType::Real) {
    1390            0 :                     fldStIt->m_colHead = state.dataOutputProcessor->outVars[varNum]->name;
    1391            0 :                 } else if (fldStIt->m_typeOfVar == OutputProcessor::VariableType::Meter) {
    1392            0 :                     fldStIt->m_colHead = state.dataOutputProcessor->meters[varNum]->Name;
    1393              :                 }
    1394              :             }
    1395              :         }
    1396              :     }
    1397            0 : }
    1398              : 
    1399            0 : void AnnualTable::clearTable()
    1400              : {
    1401            0 :     m_name = "";
    1402            0 :     m_filter = "";
    1403            0 :     m_sched = nullptr;
    1404            0 :     m_objectNames.clear();
    1405            0 :     m_annualFields.clear();
    1406            0 : }
    1407              : 
    1408            0 : std::vector<std::string> AnnualTable::inspectTable()
    1409              : {
    1410              :     // added function just to inspect the main private AnnualTable members because no other
    1411              :     // interface to the AnnualTable class is output oriented except writeTable and that is very complex.
    1412            0 :     std::vector<std::string> ret;
    1413            0 :     ret.push_back(m_name);
    1414            0 :     ret.push_back(m_filter);
    1415            0 :     ret.push_back(m_sched->Name);
    1416            0 :     return ret;
    1417            0 : }
    1418              : 
    1419            0 : std::vector<std::string> AnnualTable::inspectTableFieldSets(int fldIndex)
    1420              : {
    1421              :     // added function just to inspect the private field set members of AnnualTable because no other
    1422              :     // interface to the AnnualTable class is output oriented except writeTable and that is very complex.
    1423            0 :     std::vector<std::string> ret;
    1424            0 :     AnnualFieldSet fldSt;
    1425            0 :     fldSt = m_annualFields[fldIndex];
    1426            0 :     ret.push_back(fldSt.m_colHead);
    1427            0 :     ret.push_back(fldSt.m_variMeter);
    1428            0 :     ret.push_back(std::string(Constant::unitNames[(int)fldSt.m_varUnits]));
    1429            0 :     std::string outStr = std::to_string(fldSt.m_showDigits);
    1430              :     // ints
    1431            0 :     ret.push_back(outStr);
    1432            0 :     outStr = std::to_string((int)fldSt.m_typeOfVar);
    1433            0 :     ret.push_back(outStr);
    1434            0 :     outStr = std::to_string(fldSt.m_keyCount);
    1435            0 :     ret.push_back(outStr);
    1436            0 :     outStr = std::to_string((int)fldSt.m_varAvgSum);
    1437            0 :     ret.push_back(outStr);
    1438            0 :     outStr = std::to_string((int)fldSt.m_varStepType);
    1439            0 :     ret.push_back(outStr);
    1440            0 :     outStr = std::to_string(fldSt.m_aggregate);
    1441            0 :     ret.push_back(outStr);
    1442              :     // floats
    1443            0 :     outStr = std::to_string(fldSt.m_bottomBinValue);
    1444            0 :     ret.push_back(outStr);
    1445            0 :     outStr = std::to_string(fldSt.m_topBinValue);
    1446            0 :     ret.push_back(outStr);
    1447            0 :     outStr = std::to_string(fldSt.m_timeAboveTopBinTotal);
    1448            0 :     ret.push_back(outStr);
    1449            0 :     outStr = std::to_string(fldSt.m_timeBelowBottomBinTotal);
    1450            0 :     ret.push_back(outStr);
    1451              :     // cell value
    1452            0 :     if (fldSt.m_cell.size() > 0) {
    1453            0 :         outStr = std::to_string(fldSt.m_cell[0].result);
    1454            0 :         ret.push_back(outStr);
    1455              :     }
    1456            0 :     return ret;
    1457            0 : }
    1458              : 
    1459              : } // namespace EnergyPlus::OutputReportTabularAnnual
        

Generated by: LCOV version 2.0-1