LCOV - code coverage report
Current view: top level - EnergyPlus - OutputReportTabularAnnual.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 55 919 6.0 %
Date: 2024-08-23 23:50:59 Functions: 5 30 16.7 %

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

Generated by: LCOV version 1.14