LCOV - code coverage report
Current view: top level - EnergyPlus - EconomicTariff.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 73.6 % 2819 2076
Test Date: 2025-06-02 07:23:51 Functions: 100.0 % 41 41

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cassert>
      50              : 
      51              : // ObjexxFCL Headers
      52              : #include <ObjexxFCL/Array.functions.hh>
      53              : #include <ObjexxFCL/Fmath.hh>
      54              : #include <ObjexxFCL/numeric.hh>
      55              : #include <ObjexxFCL/string.functions.hh>
      56              : 
      57              : // EnergyPlus Headers
      58              : #include <EnergyPlus/CostEstimateManager.hh>
      59              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      60              : #include <EnergyPlus/DataEnvironment.hh>
      61              : #include <EnergyPlus/DataGlobalConstants.hh>
      62              : #include <EnergyPlus/DataIPShortCuts.hh>
      63              : #include <EnergyPlus/DisplayRoutines.hh>
      64              : #include <EnergyPlus/EconomicTariff.hh>
      65              : #include <EnergyPlus/General.hh>
      66              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      67              : #include <EnergyPlus/OutputProcessor.hh>
      68              : #include <EnergyPlus/OutputReportPredefined.hh>
      69              : #include <EnergyPlus/OutputReportTabular.hh>
      70              : #include <EnergyPlus/ResultsFramework.hh>
      71              : #include <EnergyPlus/SQLiteProcedures.hh>
      72              : #include <EnergyPlus/ScheduleManager.hh>
      73              : #include <EnergyPlus/UtilityRoutines.hh>
      74              : 
      75              : namespace EnergyPlus::EconomicTariff {
      76              : 
      77              : // MODULE INFORMATION:
      78              : //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
      79              : //    DATE WRITTEN   May 2004
      80              : 
      81              : //    Compute utility bills for a building based on energy
      82              : //    use estimate.
      83              : 
      84              : constexpr std::array<std::string_view, (int)EconConv::Num> convEnergyStrings = {
      85              :     "", "kWh", "Therm", "MMBtu", "MJ", "kBTU", "MCF", "CCF", "m3", "gal", "kgal"};
      86              : constexpr std::array<std::string_view, (int)EconConv::Num> convDemandStrings = {
      87              :     "", "kW", "Therm", "MMBtu", "MJ", "kBTU", "MCF", "CCF", "m3", "gal", "kgal"};
      88              : constexpr std::array<std::string_view, (int)EconConv::Num> econConvNamesUC = {
      89              :     "USERDEFINED", "KWH", "THERM", "MMBTU", "MJ", "KBTU", "MCF", "CCF", "M3", "GAL", "KGAL"};
      90              : 
      91              : constexpr std::array<std::string_view, (int)DemandWindow::Num> demandWindowStrings = {"/Hr", "/Hr", "/Hr", "/Day", "/Wk"};
      92              : 
      93              : constexpr std::array<std::string_view, (int)BuySell::Num> buySellNames = {"BuyFromUtility", "SellToUtility", "NetMetering"};
      94              : constexpr std::array<std::string_view, (int)BuySell::Num> buySellNamesUC = {"BUYFROMUTILITY", "SELLTOUTILITY", "NETMETERING"};
      95              : 
      96              : constexpr std::array<std::string_view, (int)Season::Num> seasonNames = {"Unused", "Winter", "Spring", "Summer", "Fall", "Annual", "Monthly"};
      97              : constexpr std::array<std::string_view, (int)Season::Num> seasonNamesUC = {"Unused", "WINTER", "SPRING", "SUMMER", "FALL", "ANNUAL", "MONTHLY"};
      98              : 
      99              : constexpr std::array<std::string_view, (int)Op::Num> opNamesUC = {"SUM",
     100              :                                                                   "MULTIPLY",
     101              :                                                                   "SUBTRACT",
     102              :                                                                   "DIVIDE",
     103              :                                                                   "ABSOLUTE",
     104              :                                                                   "INTEGER",
     105              :                                                                   "SIGN",
     106              :                                                                   "ROUND",
     107              :                                                                   "MAXIMUM",
     108              :                                                                   "MINIMUM",
     109              :                                                                   "EXCEEDS",
     110              :                                                                   "ANNUALMINIMUM",
     111              :                                                                   "ANNUALMAXIMUM",
     112              :                                                                   "ANNUALSUM",
     113              :                                                                   "ANNUALAVERAGE",
     114              :                                                                   "ANNUALOR",
     115              :                                                                   "ANNUALAND",
     116              :                                                                   "ANNUALMAXIMUMZERO",
     117              :                                                                   "ANNUALMINIMUMZERO",
     118              :                                                                   "IF",
     119              :                                                                   "GREATERTHAN",
     120              :                                                                   "GREATEREQUAL",
     121              :                                                                   "LESSTHAN",
     122              :                                                                   "LESSEQUAL",
     123              :                                                                   "EQUAL",
     124              :                                                                   "NOTEQUAL",
     125              :                                                                   "AND",
     126              :                                                                   "OR",
     127              :                                                                   "NOT",
     128              :                                                                   "ADD",
     129              :                                                                   "FROM"};
     130              : 
     131              : constexpr std::array<std::string_view, (int)Op::Num> opNames2UC = {
     132              :     "SUM",   "MULT",   "SUBT",   "DIV", "ABS", "INT", "SIGN", "ROUND", "MAX", "MIN", "EXCEEDS", "ANMIN", "ANMAX", "ANSUM", "ANAVG", "ANOR",
     133              :     "ANAND", "ANMAXZ", "ANMINZ", "IF",  "GT",  "GE",  "LT",   "LE",    "EQ",  "NE",  "AND",     "OR",    "NOT",   "ADD",   "NOOP"};
     134              : 
     135              : constexpr std::array<std::string_view, (int)Cat::Num> catNames = {
     136              :     "EnergyCharges", "DemandCharges", "ServiceCharges", "Basis", "Adjustment", "Surcharge", "Subtotal", "Taxes", "Total", "NotIncluded"};
     137              : constexpr std::array<std::string_view, (int)Cat::Num> catNamesUC = {
     138              :     "ENERGYCHARGES", "DEMANDCHARGES", "SERVICECHARGES", "BASIS", "ADJUSTMENT", "SURCHARGE", "SUBTOTAL", "TAXES", "TOTAL", "NOTINCLUDED"};
     139              : 
     140              : constexpr std::array<std::string_view, (int)Native::Num> nativeNames = {"TotalEnergy",
     141              :                                                                         "TotalDemand",
     142              :                                                                         "PeakEnergy",
     143              :                                                                         "PeakDemand",
     144              :                                                                         "ShoulderEnergy",
     145              :                                                                         "ShoulderDemand",
     146              :                                                                         "OffPeakEnergy",
     147              :                                                                         "OffPeakDemand",
     148              :                                                                         "MidPeakEnergy",
     149              :                                                                         "MidPeakDemand",
     150              :                                                                         "PeakExceedsOffPeak",
     151              :                                                                         "OffPeakExceedsPeak",
     152              :                                                                         "PeakExceedsMidPeak",
     153              :                                                                         "MidPeakExceedsPeak",
     154              :                                                                         "PeakExceedsShoulder",
     155              :                                                                         "ShoulderExceedsPeak",
     156              :                                                                         "IsWinter",
     157              :                                                                         "IsNotWinter",
     158              :                                                                         "IsSpring",
     159              :                                                                         "IsNotSpring",
     160              :                                                                         "IsSummer",
     161              :                                                                         "IsNotSummer",
     162              :                                                                         "IsAutumn",
     163              :                                                                         "IsNotAutumn",
     164              :                                                                         "PeakAndShoulderEnergy",
     165              :                                                                         "PeakAndShoulderDemand",
     166              :                                                                         "PeakAndMidPeakEnergy",
     167              :                                                                         "PeakAndMidPeakDemand",
     168              :                                                                         "ShoulderAndOffPeakEnergy",
     169              :                                                                         "ShoulderAndOffPeakDemand",
     170              :                                                                         "PeakAndOffPeakEnergy",
     171              :                                                                         "PeakAndOffPeakDemand",
     172              :                                                                         "RealTimePriceCosts",
     173              :                                                                         "AboveCustomerBaseCosts",
     174              :                                                                         "BelowCustomerBaseCosts",
     175              :                                                                         "AboveCustomerBaseEnergy",
     176              :                                                                         "BelowCustomerBaseEnergy"};
     177              : constexpr std::array<std::string_view, (int)Native::Num> nativeNamesUC = {"TOTALENERGY",
     178              :                                                                           "TOTALDEMAND",
     179              :                                                                           "PEAKENERGY",
     180              :                                                                           "PEAKDEMAND",
     181              :                                                                           "SHOULDERENERGY",
     182              :                                                                           "SHOULDERDEMAND",
     183              :                                                                           "OFFPEAKENERGY",
     184              :                                                                           "OFFPEAKDEMAND",
     185              :                                                                           "MIDPEAKENERGY",
     186              :                                                                           "MIDPEAKDEMAND",
     187              :                                                                           "PEAKEXCEEDSOFFPEAK",
     188              :                                                                           "OFFPEAKEXCEEDSPEAK",
     189              :                                                                           "PEAKEXCEEDSMIDPEAK",
     190              :                                                                           "MIDPEAKEXCEEDSPEAK",
     191              :                                                                           "PEAKEXCEEDSSHOULDER",
     192              :                                                                           "SHOULDEREXCEEDSPEAK",
     193              :                                                                           "ISWINTER",
     194              :                                                                           "ISNOTWINTER",
     195              :                                                                           "ISSPRING",
     196              :                                                                           "ISNOTSPRING",
     197              :                                                                           "ISSUMMER",
     198              :                                                                           "ISNOTSUMMER",
     199              :                                                                           "ISAUTUMN",
     200              :                                                                           "ISNOTAUTUMN",
     201              :                                                                           "PEAKANDSHOULDERENERGY",
     202              :                                                                           "PEAKANDSHOULDERDEMAND",
     203              :                                                                           "PEAKANDMIDPEAKENERGY",
     204              :                                                                           "PEAKANDMIDPEAKDEMAND",
     205              :                                                                           "SHOULDERANDOFFPEAKENERGY",
     206              :                                                                           "SHOULDERANDOFFPEAKDEMAND",
     207              :                                                                           "PEAKANDOFFPEAKENERGY",
     208              :                                                                           "PEAKANDOFFPEAKDEMAND",
     209              :                                                                           "REALTIMEPRICECOSTS",
     210              :                                                                           "ABOVECUSTOMERBASECOSTS",
     211              :                                                                           "BELOWCUSTOMERBASECOSTS",
     212              :                                                                           "ABOVECUSTOMERBASEENERGY",
     213              :                                                                           "BELOWCUSTOMERBASEENERGY"};
     214              : 
     215              : constexpr std::array<std::string_view, (int)VarUnitType::Num> varUnitTypeNames = {"Energy", "Demand", "Dimensionless", "Currency"};
     216              : constexpr std::array<std::string_view, (int)VarUnitType::Num> varUnitTypeNamesUC = {"ENERGY", "DEMAND", "DIMENSIONLESS", "CURRENCY"};
     217              : 
     218       491880 : void UpdateUtilityBills(EnergyPlusData &state)
     219              : {
     220              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
     221              :     //    DATE WRITTEN   September 2003
     222              : 
     223              :     //    Single routine used to call all get input
     224              :     //    routines for economics.
     225              : 
     226       491880 :     auto &s_econ = state.dataEconTariff;
     227              : 
     228       491880 :     if (s_econ->Update_GetInput) {
     229          799 :         bool ErrorsFound = false;
     230              : 
     231          799 :         GetInputEconomicsTariff(state, ErrorsFound);
     232              :         // do rest of GetInput only if at least one tariff is defined.
     233          799 :         GetInputEconomicsCurrencyType(state, ErrorsFound);
     234          799 :         if (s_econ->numTariff >= 1) {
     235          101 :             if (!ErrorsFound && state.dataOutRptTab->displayEconomicResultSummary) {
     236          128 :                 OutputReportTabular::AddTOCEntry(state, "Economics Results Summary Report", "Entire Facility");
     237              :             }
     238          101 :             CreateCategoryNativeVariables(state);
     239          101 :             GetInputEconomicsQualify(state, ErrorsFound);
     240          101 :             GetInputEconomicsChargeSimple(state, ErrorsFound);
     241          101 :             GetInputEconomicsChargeBlock(state, ErrorsFound);
     242          101 :             GetInputEconomicsRatchet(state, ErrorsFound);
     243          101 :             GetInputEconomicsVariable(state, ErrorsFound);
     244          101 :             GetInputEconomicsComputation(state, ErrorsFound);
     245          101 :             CreateDefaultComputation(state);
     246              :         }
     247          799 :         s_econ->Update_GetInput = false;
     248          799 :         if (ErrorsFound) {
     249            0 :             ShowFatalError(state, "UpdateUtilityBills: Preceding errors cause termination.");
     250              :         }
     251              :     }
     252       491880 :     if (state.dataGlobal->DoOutputReporting && (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather)) {
     253       254136 :         GatherForEconomics(state);
     254              :     }
     255       491880 : }
     256              : 
     257              : //======================================================================================================================
     258              : //======================================================================================================================
     259              : 
     260              : //    GET INPUT ROUTINES
     261              : 
     262              : //======================================================================================================================
     263              : //======================================================================================================================
     264              : 
     265          799 : void GetInputEconomicsTariff(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
     266              : {
     267              :     // SUBROUTINE INFORMATION:
     268              :     //       AUTHOR         Jason Glazer of GARD Analytics, Inc.
     269              :     //       DATE WRITTEN   May 2004
     270              :     //       MODIFIED       Aug. 2017, Julien Marrec of EffiBEM. Handled conversions factor based on meter resources
     271              :     //
     272              :     // PURPOSE OF THIS SUBROUTINE:
     273              :     // This subroutine reads the input file for "UtilityCost:Tariff" objects
     274              :     // It will be the right conversion factors based on the associated meter resource type
     275              :     // meaning if "CCF" is picked, the conversion factor isn't the same whether it's a water meter or a fuel meter.
     276              : 
     277              :     static constexpr std::string_view RoutineName("GetInputEconomicsTariff: ");
     278              :     static constexpr std::string_view routineName = "GetInputEconomicsTariff";
     279              : 
     280              :     int NumAlphas; // Number of elements in the alpha array
     281              :     int NumNums;   // Number of elements in the numeric array
     282              :     int IOStat;    // IO Status when calling get input subroutine
     283              :     bool isNotNumeric;
     284              :     // variables for getting report variable/meter index
     285              :     int KeyCount;
     286              :     OutputProcessor::VariableType TypeVar;
     287              :     OutputProcessor::StoreType AvgSumVar;
     288              :     OutputProcessor::TimeStepType StepTypeVar;
     289          799 :     Constant::Units UnitsVar = Constant::Units::None; // Units sting, may be blank
     290          799 :     Array1D_string NamesOfKeys;                       // Specific key name
     291          799 :     Array1D_int IndexesForKeyVar;                     // Array index
     292              : 
     293          799 :     auto &s_ipsc = state.dataIPShortCut;
     294          799 :     auto &s_econ = state.dataEconTariff;
     295              : 
     296          799 :     std::string_view CurrentModuleObject = "UtilityCost:Tariff";
     297          799 :     s_econ->numTariff = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     298          799 :     s_econ->tariff.allocate(s_econ->numTariff);
     299         1100 :     for (int iInObj = 1; iInObj <= s_econ->numTariff; ++iInObj) {
     300          602 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     301              :                                                                  CurrentModuleObject,
     302              :                                                                  iInObj,
     303          301 :                                                                  s_ipsc->cAlphaArgs,
     304              :                                                                  NumAlphas,
     305          301 :                                                                  s_ipsc->rNumericArgs,
     306              :                                                                  NumNums,
     307              :                                                                  IOStat,
     308          301 :                                                                  s_ipsc->lNumericFieldBlanks,
     309          301 :                                                                  s_ipsc->lAlphaFieldBlanks,
     310          301 :                                                                  s_ipsc->cAlphaFieldNames,
     311          301 :                                                                  s_ipsc->cNumericFieldNames);
     312              : 
     313          301 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     314          301 :         auto &tariff = s_econ->tariff(iInObj);
     315              : 
     316              :         // check to make sure none of the values are another economic object
     317         3802 :         for (int jFld = 1; jFld <= NumAlphas; ++jFld) {
     318              :             //  args are always turned to upper case but this is okay...
     319         3501 :             if (hasi(s_ipsc->cAlphaArgs(jFld), "UtilityCost:")) {
     320            0 :                 ShowWarningError(state, format("{}{}=\"{}\".", RoutineName, CurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     321            0 :                 ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
     322              :             }
     323              :         }
     324              :         // name of the tariff
     325          301 :         tariff.tariffName = s_ipsc->cAlphaArgs(1);
     326              :         // check if tariff name is unique
     327          301 :         int found = 0;
     328          704 :         for (int jObj = 1; jObj <= iInObj - 1; ++jObj) {
     329          403 :             if (tariff.tariffName == s_econ->tariff(jObj).tariffName) {
     330            0 :                 found = jObj;
     331            0 :                 break;
     332              :             }
     333              :         }
     334          301 :         if (found > 0) {
     335            0 :             ShowSevereDuplicateName(state, eoh);
     336            0 :             ErrorsFound = true;
     337              :         }
     338              :         // name of the report meter
     339          301 :         tariff.reportMeter = s_ipsc->cAlphaArgs(2);
     340              :         // call the key count function but only need count during this pass
     341          301 :         GetVariableKeyCountandType(state, tariff.reportMeter, KeyCount, TypeVar, AvgSumVar, StepTypeVar, UnitsVar);
     342              :         // if no meters found for that name
     343          301 :         if (KeyCount == 0) {
     344            1 :             ShowWarningError(state, format("{}{}=\"{}\" missing meter", RoutineName, CurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     345            2 :             ShowContinueError(
     346              :                 state,
     347            2 :                 format("Meter referenced is not present due to a lack of equipment that uses that energy source/meter:\"{}\".", tariff.reportMeter));
     348            1 :             tariff.reportMeterIndx = -1;
     349              :         } else {
     350          300 :             NamesOfKeys.allocate(KeyCount);
     351          300 :             IndexesForKeyVar.allocate(KeyCount);
     352          300 :             GetVariableKeys(state, tariff.reportMeter, TypeVar, NamesOfKeys, IndexesForKeyVar);
     353              :             // although this retrieves all keys for a variable, we only need one so the first one is chosen
     354          300 :             if (KeyCount > 1) {
     355            0 :                 ShowWarningError(state, format("{}{}=\"{}\" multiple keys", RoutineName, CurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     356            0 :                 ShowContinueError(state, "... Multiple keys for variable select. First key will be used.");
     357              :             }
     358              :             // assign the index
     359          300 :             tariff.reportMeterIndx = IndexesForKeyVar(1);
     360              :             // get rid of the arrays used to get the variable number
     361          300 :             NamesOfKeys.deallocate();
     362          300 :             IndexesForKeyVar.deallocate();
     363              :         }
     364              : 
     365              :         // Start by checking what type of meter we do have, some units can be used for several resources with different conversion factors
     366              :         // Explicitly assume it's not a water meter nor an electric meter nor a gas meter (was already done in constructor though)
     367          301 :         tariff.kindMtr = MeterType::Other;
     368              : 
     369              :         // Determine whether this meter is related to electricity, or water, or gas
     370          301 :         if (tariff.reportMeterIndx != -1) {
     371          300 :             switch (state.dataOutputProcessor->meters[tariff.reportMeterIndx]->resource) {
     372              :             // Various types of electricity meters
     373          195 :             case Constant::eResource::Electricity: {
     374          195 :                 tariff.kindMtr = MeterType::ElecSimple;
     375          195 :             } break;
     376            0 :             case Constant::eResource::ElectricityProduced: {
     377            0 :                 tariff.kindMtr = MeterType::ElecProduced;
     378            0 :             } break;
     379           11 :             case Constant::eResource::ElectricityPurchased: {
     380           11 :                 tariff.kindMtr = MeterType::ElecPurchased;
     381           11 :             } break;
     382            1 :             case Constant::eResource::ElectricitySurplusSold: {
     383            1 :                 tariff.kindMtr = MeterType::ElecSurplusSold;
     384            1 :             } break;
     385            7 :             case Constant::eResource::ElectricityNet: {
     386            7 :                 tariff.kindMtr = MeterType::ElecNet;
     387            7 :             } break;
     388              :             // Handle the case where its a water meter
     389            1 :             case Constant::eResource::Water:
     390              :             case Constant::eResource::OnSiteWater:
     391              :             case Constant::eResource::MainsWater:
     392              :             case Constant::eResource::RainWater:
     393              :             case Constant::eResource::WellWater:
     394              :             case Constant::eResource::Condensate: {
     395            1 :                 tariff.kindMtr = MeterType::Water;
     396            1 :             } break;
     397              :             // Or a Natural Gas meter
     398           85 :             case Constant::eResource::NaturalGas: {
     399           85 :                 tariff.kindMtr = MeterType::Gas;
     400           85 :             } break;
     401            0 :             default: {
     402            0 :                 tariff.kindMtr = MeterType::Other; // Do or assert something here?
     403            0 :             } break;
     404              :             } // switch
     405              :         }
     406              : 
     407              :         // Assign the right conversion factors based on the resource type
     408              : 
     409              :         // If it's a water meter
     410              :         // We set demandConv to something analogous to m3/h
     411          301 :         switch (tariff.kindMtr) {
     412            1 :         case MeterType::Water: {
     413              :             // conversion factor
     414            1 :             tariff.convChoice = static_cast<EconConv>(getEnumValue(econConvNamesUC, s_ipsc->cAlphaArgs(3)));
     415            1 :             switch (tariff.convChoice) {
     416            1 :             case EconConv::USERDEF: {
     417            1 :                 tariff.energyConv = s_ipsc->rNumericArgs(1); // energy conversion factor
     418            1 :                 tariff.demandConv = s_ipsc->rNumericArgs(2); // demand conversion factor
     419            1 :             } break;
     420              : 
     421            0 :             case EconConv::M3: {
     422            0 :                 tariff.energyConv = 1.0;
     423            0 :                 tariff.demandConv = 3600.0;
     424            0 :             } break;
     425              : 
     426            0 :             case EconConv::CCF: {
     427            0 :                 tariff.energyConv = 0.35314666721488586;
     428            0 :                 tariff.demandConv = 0.35314666721488586 * 3600;
     429            0 :             } break;
     430              : 
     431            0 :             case EconConv::GAL: {
     432            0 :                 tariff.energyConv = 264.1720523602524;
     433            0 :                 tariff.demandConv = 264.1720523602524 * 3600;
     434            0 :             } break;
     435              : 
     436            0 :             case EconConv::KGAL: {
     437            0 :                 tariff.energyConv = 0.2641720523602524;
     438            0 :                 tariff.demandConv = 0.2641720523602524 * 3600;
     439            0 :             } break;
     440              : 
     441            0 :             default: { // ERROR: not a valid conversion, default to M3
     442            0 :                 tariff.convChoice = EconConv::M3;
     443            0 :                 tariff.energyConv = 1.0;
     444            0 :                 tariff.demandConv = 3600.0;
     445            0 :                 ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3), "M3");
     446            0 :             } break;
     447              :             } // switch (tariff.convChoice)
     448              : 
     449            1 :         } break;
     450              : 
     451              :             // If it's an electric meter
     452              :             // Volumetric units such as MCF or CCF doesn't make sense IMHO (JM)
     453              :             // THERM is strange for an electric meter but currently I accept but issue a warning
     454          214 :         case MeterType::ElecSimple:
     455              :         case MeterType::ElecProduced:
     456              :         case MeterType::ElecPurchased:
     457              :         case MeterType::ElecSurplusSold:
     458              :         case MeterType::ElecNet: {
     459          214 :             tariff.convChoice = static_cast<EconConv>(getEnumValue(econConvNamesUC, s_ipsc->cAlphaArgs(3)));
     460              : 
     461          214 :             switch (tariff.convChoice) {
     462            0 :             case EconConv::USERDEF: {
     463            0 :                 tariff.energyConv = s_ipsc->rNumericArgs(1); // energy conversion factor
     464            0 :                 tariff.demandConv = s_ipsc->rNumericArgs(2); // demand conversion factor
     465            0 :             } break;
     466              : 
     467          214 :             case EconConv::KWH: {
     468          214 :                 tariff.energyConv = 0.0000002778;
     469          214 :                 tariff.demandConv = 0.001;
     470          214 :             } break;
     471              : 
     472            0 :             case EconConv::MJ: {
     473            0 :                 tariff.energyConv = 0.000001;
     474            0 :                 tariff.demandConv = 0.0036;
     475            0 :             } break;
     476              : 
     477            0 :             case EconConv::MMBTU: {
     478            0 :                 tariff.energyConv = 9.4781712e-10;
     479            0 :                 tariff.demandConv = 0.000003412;
     480            0 :             } break;
     481              : 
     482            0 :             case EconConv::KBTU: {
     483            0 :                 tariff.energyConv = 9.4781712e-7;
     484            0 :                 tariff.demandConv = 0.003412;
     485            0 :             } break;
     486              : 
     487              :                 // We accept the following choices, but issue a warning
     488            0 :             case EconConv::THERM: {
     489            0 :                 tariff.energyConv = 9.4781712e-9;
     490            0 :                 tariff.demandConv = 0.00003412;
     491            0 :                 ShowWarningCustom(
     492              :                     state,
     493              :                     eoh,
     494            0 :                     format("{}=\"{}\", Therm is an unusual choice for an electric resource.", s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3)));
     495            0 :             } break;
     496              : 
     497              :                 // Otherwise, default to kWh
     498            0 :             default: {
     499            0 :                 tariff.convChoice = EconConv::KWH;
     500            0 :                 tariff.energyConv = 0.0000002778;
     501            0 :                 tariff.demandConv = 0.001;
     502            0 :                 ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3), "KWH");
     503            0 :             } break;
     504              :             } // switch (tariff.convChoice)
     505          214 :         } break;
     506              : 
     507              :             // If it's a gas meter
     508           85 :         case MeterType::Gas: {
     509           85 :             tariff.convChoice = static_cast<EconConv>(getEnumValue(econConvNamesUC, s_ipsc->cAlphaArgs(3)));
     510           85 :             switch (tariff.convChoice) {
     511            0 :             case EconConv::USERDEF: {
     512            0 :                 tariff.energyConv = s_ipsc->rNumericArgs(1); // energy conversion factor
     513            0 :                 tariff.demandConv = s_ipsc->rNumericArgs(2); // demand conversion factor
     514            0 :             } break;
     515              : 
     516            0 :             case EconConv::KWH: {
     517            0 :                 tariff.energyConv = 0.0000002778;
     518            0 :                 tariff.demandConv = 0.001;
     519            0 :             } break;
     520              : 
     521            1 :             case EconConv::THERM: {
     522            1 :                 tariff.energyConv = 9.4781712e-9;
     523            1 :                 tariff.demandConv = 0.00003412;
     524            1 :             } break;
     525              : 
     526            0 :             case EconConv::MMBTU: {
     527            0 :                 tariff.energyConv = 9.4781712e-10;
     528            0 :                 tariff.demandConv = 0.000003412;
     529            0 :             } break;
     530              : 
     531            0 :             case EconConv::MJ: {
     532            0 :                 tariff.energyConv = 0.000001;
     533            0 :                 tariff.demandConv = 0.0036;
     534            0 :             } break;
     535              : 
     536            0 :             case EconConv::KBTU: {
     537            0 :                 tariff.energyConv = 9.4781712e-7;
     538            0 :                 tariff.demandConv = 0.003412;
     539            0 :             } break;
     540              :                 // Volumetric units for natural gas
     541              :                 // Actually assuming 1 therm = 1 CCF (= 100 ft^3)
     542           84 :             case EconConv::MCF: {
     543           84 :                 tariff.energyConv = 9.4781712e-10;
     544           84 :                 tariff.demandConv = 0.000003412;
     545           84 :             } break;
     546              : 
     547            0 :             case EconConv::CCF: {
     548            0 :                 tariff.energyConv = 9.4781712e-9;
     549            0 :                 tariff.demandConv = 0.00003412;
     550            0 :             } break;
     551              : 
     552              :                 // Obtained from converting CCF above to m^3 so the same heat content of natural gas is used (1 therm = 1 CCF)
     553            0 :             case EconConv::M3: {
     554            0 :                 tariff.energyConv = 2.6839192e-10;
     555            0 :                 tariff.demandConv = 9.6617081E-05;
     556            0 :             } break;
     557              : 
     558              :                 // Otherwise, default to kWh
     559            0 :             default: {
     560            0 :                 tariff.convChoice = EconConv::KWH;
     561            0 :                 tariff.energyConv = 0.0000002778;
     562            0 :                 tariff.demandConv = 0.001;
     563            0 :                 ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3), "KWH");
     564            0 :             } break;
     565              :             } // witch (tariff.convChoice)
     566           85 :         } break;
     567              : 
     568              :             // It it's neither an electric, water or gas meter, we cannot accept volumetric units
     569              :             // because we cannot infer the heat content
     570            1 :         case MeterType::Other: {
     571            1 :             tariff.convChoice = static_cast<EconConv>(getEnumValue(econConvNamesUC, s_ipsc->cAlphaArgs(3)));
     572            1 :             switch (tariff.convChoice) {
     573            0 :             case EconConv::USERDEF: {
     574            0 :                 tariff.energyConv = s_ipsc->rNumericArgs(1); // energy conversion factor
     575            0 :                 tariff.demandConv = s_ipsc->rNumericArgs(2); // demand conversion factor
     576            0 :             } break;
     577              : 
     578            0 :             case EconConv::KWH: {
     579            0 :                 tariff.energyConv = 0.0000002778;
     580            0 :                 tariff.demandConv = 0.001;
     581            0 :             } break;
     582              : 
     583            0 :             case EconConv::THERM: {
     584            0 :                 tariff.energyConv = 9.4781712e-9;
     585            0 :                 tariff.demandConv = 0.00003412;
     586            0 :             } break;
     587              : 
     588            0 :             case EconConv::MMBTU: {
     589            0 :                 tariff.energyConv = 9.4781712e-10;
     590            0 :                 tariff.demandConv = 0.000003412;
     591            0 :             } break;
     592              : 
     593            0 :             case EconConv::MJ: {
     594            0 :                 tariff.energyConv = 0.000001;
     595            0 :                 tariff.demandConv = 0.0036;
     596            0 :             } break;
     597              : 
     598            0 :             case EconConv::KBTU: {
     599            0 :                 tariff.energyConv = 9.4781712e-7;
     600            0 :                 tariff.demandConv = 0.003412;
     601            0 :             } break;
     602              : 
     603              :                 // Otherwise, default to kWh
     604            1 :             default: {
     605            1 :                 tariff.convChoice = EconConv::KWH;
     606            1 :                 tariff.energyConv = 0.0000002778;
     607            1 :                 tariff.demandConv = 0.001;
     608            1 :                 ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3), "KWH");
     609            1 :             } break;
     610              :             } // switch (tariff.convChoice)
     611            1 :         } break;
     612              : 
     613            0 :         default: {
     614            0 :         } break;
     615              :         } // Default conversion factors have been applied from here on
     616              : 
     617              :         // schedules
     618              :         // period schedule
     619          301 :         if (len(s_ipsc->cAlphaArgs(4)) > 0) {
     620           15 :             if ((tariff.periodSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(4))) == nullptr) {
     621            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(4), s_ipsc->cAlphaArgs(4));
     622            0 :                 ErrorsFound = true;
     623              :             }
     624              :         }
     625              : 
     626              :         // season schedule
     627          301 :         if (len(s_ipsc->cAlphaArgs(5)) > 0) {
     628           31 :             if ((tariff.seasonSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(5))) == nullptr) {
     629            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaArgs(5));
     630            0 :                 ErrorsFound = true;
     631              :             }
     632              :         }
     633              : 
     634              :         // month schedule
     635          301 :         if (len(s_ipsc->cAlphaArgs(6)) > 0) {
     636            0 :             if ((tariff.monthSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(6))) == nullptr) {
     637            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(6), s_ipsc->cAlphaArgs(6));
     638            0 :                 ErrorsFound = true;
     639              :             }
     640              :         }
     641              :         // type of demand window
     642          301 :         if (Util::SameString(s_ipsc->cAlphaArgs(7), "QuarterHour")) {
     643              :             // check to make sure that the demand window and the TIMESTEP IN HOUR are consistent.
     644              :             { // Why is this a nested scope?
     645            1 :                 switch (state.dataGlobal->TimeStepsInHour) {
     646            0 :                 case 1:
     647              :                 case 3:
     648              :                 case 5:
     649              :                 case 15: {
     650            0 :                     tariff.demandWindow = DemandWindow::Hour;
     651            0 :                     tariff.demWinTime = 1.00;
     652            0 :                     ShowWarningError(state, format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     653            0 :                     ShowContinueError(state,
     654            0 :                                       format("Demand window of QuarterHour is not consistent with number of timesteps per hour [{}].",
     655            0 :                                              state.dataGlobal->TimeStepsInHour));
     656            0 :                     ShowContinueError(state, "Demand window will be set to FullHour, and the simulation continues.");
     657            0 :                 } break;
     658            0 :                 case 2:
     659              :                 case 6:
     660              :                 case 10:
     661              :                 case 30: {
     662            0 :                     tariff.demandWindow = DemandWindow::Half;
     663            0 :                     tariff.demWinTime = 0.50;
     664            0 :                     ShowWarningError(state, format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     665            0 :                     ShowContinueError(state,
     666            0 :                                       format("Demand window of QuarterHour is not consistent with number of timesteps per hour [{}].",
     667            0 :                                              state.dataGlobal->TimeStepsInHour));
     668            0 :                     ShowContinueError(state, "Demand window will be set to HalfHour, and the simulation continues.");
     669            0 :                 } break;
     670            1 :                 case 4:
     671              :                 case 12:
     672              :                 case 20:
     673              :                 case 60: {
     674            1 :                     tariff.demandWindow = DemandWindow::Quarter;
     675            1 :                     tariff.demWinTime = 0.25;
     676            1 :                 } break;
     677            0 :                 default: {
     678            0 :                     assert(false);
     679              :                 } break;
     680              :                 }
     681              :             }
     682          300 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(7), "HalfHour")) {
     683              :             {
     684          111 :                 switch (state.dataGlobal->TimeStepsInHour) {
     685            0 :                 case 1:
     686              :                 case 3:
     687              :                 case 5:
     688              :                 case 15: {
     689            0 :                     tariff.demandWindow = DemandWindow::Hour;
     690            0 :                     tariff.demWinTime = 1.00;
     691            0 :                     ShowWarningError(state, format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     692            0 :                     ShowContinueError(state,
     693            0 :                                       format("Demand window of HalfHour is not consistent with number of timesteps per hour [{}].",
     694            0 :                                              state.dataGlobal->TimeStepsInHour));
     695            0 :                     ShowContinueError(state, "Demand window will be set to FullHour, and the simulation continues.");
     696            0 :                 } break;
     697          111 :                 case 2:
     698              :                 case 4:
     699              :                 case 6:
     700              :                 case 10:
     701              :                 case 12:
     702              :                 case 20:
     703              :                 case 30:
     704              :                 case 60: {
     705          111 :                     tariff.demandWindow = DemandWindow::Half;
     706          111 :                     tariff.demWinTime = 0.50;
     707          111 :                 } break;
     708            0 :                 default: {
     709              :                     // assert(false); // EconomicTariff unit test gets here with NumOfTimeStepInHour == 0
     710            0 :                 } break;
     711              :                 }
     712              :             }
     713          189 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(7), "FullHour")) {
     714            0 :             tariff.demandWindow = DemandWindow::Hour;
     715            0 :             tariff.demWinTime = 1.00;
     716          189 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(7), "Day")) {
     717            0 :             tariff.demandWindow = DemandWindow::Day;
     718            0 :             tariff.demWinTime = 24.00;
     719          189 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(7), "Week")) {
     720            0 :             tariff.demandWindow = DemandWindow::Week;
     721            0 :             tariff.demWinTime = 24.0 * 7.0;
     722              :         } else {
     723              :             // if not entered default to the same logic as quarter of an hour
     724              :             {
     725          189 :                 switch (state.dataGlobal->TimeStepsInHour) {
     726            0 :                 case 1:
     727              :                 case 3:
     728              :                 case 5:
     729              :                 case 15: {
     730            0 :                     tariff.demandWindow = DemandWindow::Hour;
     731            0 :                     tariff.demWinTime = 1.00;
     732            0 :                 } break;
     733          116 :                 case 2:
     734              :                 case 6:
     735              :                 case 10:
     736              :                 case 30: {
     737          116 :                     tariff.demandWindow = DemandWindow::Half;
     738          116 :                     tariff.demWinTime = 0.50;
     739          116 :                 } break;
     740           73 :                 case 4:
     741              :                 case 12:
     742              :                 case 20:
     743              :                 case 60: {
     744           73 :                     tariff.demandWindow = DemandWindow::Quarter;
     745           73 :                     tariff.demWinTime = 0.25;
     746           73 :                 } break;
     747            0 :                 default: {
     748              :                     // assert(false); // EconomicTariff unit test got here with NumOfTimeStepInHour == 0
     749            0 :                 } break;
     750              :                 }
     751              :             }
     752              :         }
     753              :         // monthly charge
     754          301 :         tariff.monthChgVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(8), isNotNumeric);
     755          301 :         tariff.monthChgPt =
     756          301 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(8), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, iInObj);
     757              :         // minimum monthly charge
     758          301 :         if (len(s_ipsc->cAlphaArgs(9)) > 0) {
     759            2 :             tariff.minMonthChgVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(9), isNotNumeric);
     760              :         } else {
     761          299 :             tariff.minMonthChgVal = -HUGE_(-1.0); // set to a very negative value
     762              :         }
     763          301 :         tariff.minMonthChgPt =
     764          301 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(9), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, iInObj);
     765              :         // real time pricing
     766          301 :         tariff.chargeSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(10));
     767          301 :         tariff.baseUseSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(11));
     768              :         // group name for separate distribution and transmission rates
     769          301 :         tariff.groupName = s_ipsc->cAlphaArgs(12);
     770              :         // buy or sell option
     771              : 
     772          301 :         if (s_ipsc->lAlphaFieldBlanks(13)) {
     773          298 :             tariff.buyOrSell = BuySell::BuyFromUtility;
     774            3 :         } else if ((tariff.buyOrSell = static_cast<BuySell>(getEnumValue(buySellNamesUC, s_ipsc->cAlphaArgs(13)))) == BuySell::Invalid) {
     775            0 :             ShowSevereInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(13), s_ipsc->cAlphaArgs(13));
     776            0 :             ErrorsFound = true;
     777              :         }
     778              : 
     779              :         // check if meter is consistent with buy or sell option
     780          301 :         if (tariff.buyOrSell == BuySell::SellToUtility) {
     781            1 :             if (!Util::SameString(tariff.reportMeter, "ELECTRICITYSURPLUSSOLD:FACILITY")) {
     782            0 :                 ShowWarningError(state, format("{}{}=\"{}\" atypical meter", RoutineName, CurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     783            0 :                 ShowContinueError(state, format("The meter chosen \"{}\" is not typically used with the sellToUtility option.", tariff.reportMeter));
     784            0 :                 ShowContinueError(state, "Usually the ElectricitySurplusSold:Facility meter is selected when the sellToUtility option is used.");
     785              :             }
     786          300 :         } else if (tariff.buyOrSell == BuySell::NetMetering) {
     787            1 :             if (!Util::SameString(tariff.reportMeter, "ELECTRICITYNET:FACILITY")) {
     788            0 :                 ShowWarningError(state, format("{}{}=\"{}\" atypical meter", RoutineName, CurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     789            0 :                 ShowContinueError(state, format("The meter chosen \"{}\" is not typically used with the netMetering option.", tariff.reportMeter));
     790            0 :                 ShowContinueError(state, "Usually the ElectricityNet:Facility meter is selected when the netMetering option is used.");
     791              :             }
     792          299 :         } else if (tariff.buyOrSell == BuySell::BuyFromUtility) {
     793          299 :             if (hasi(tariff.reportMeter, "Elec")) { // test if electric meter
     794          229 :                 if (!(Util::SameString(tariff.reportMeter, "Electricity:Facility") ||
     795          229 :                       Util::SameString(tariff.reportMeter, "ElectricityPurchased:Facility"))) {
     796            6 :                     ShowWarningError(state, format("{}{}=\"{}\" atypical meter", RoutineName, CurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     797           12 :                     ShowContinueError(state,
     798           12 :                                       format("The meter chosen \"{}\" is not typically used with the buyFromUtility option.", tariff.reportMeter));
     799           18 :                     ShowContinueError(state,
     800              :                                       "Usually the Electricity:Facility meter or the ElectricityPurchased:Facility is selected when the "
     801              :                                       "buyFromUtility option is used.");
     802              :                 }
     803              :             }
     804              :         }
     805              : 
     806              :         // initialize gathering arrays
     807         3913 :         for (int kMonth = 1; kMonth <= NumMonths; ++kMonth) {
     808         3612 :             tariff.seasonForMonth(kMonth) = Season::Invalid;
     809        21672 :             for (int lPeriod = 0; lPeriod < (int)Period::Num; ++lPeriod) {
     810        18060 :                 tariff.gatherEnergy(kMonth)[lPeriod] = 0.0;
     811        18060 :                 tariff.gatherDemand(kMonth)[lPeriod] = 0.0;
     812              :             }
     813              :         }
     814              : 
     815              :         // assume that the tariff is qualified
     816          301 :         tariff.isQualified = true;
     817          301 :         tariff.ptDisqualifier = 0;
     818              :         // assume that the tariff is not selected
     819          301 :         tariff.isSelected = false;
     820          301 :         tariff.totalAnnualCost = 0.0;
     821              :         // now create the Table Of Contents entries for an HTML file
     822          301 :         if (state.dataOutRptTab->displayTariffReport) {
     823          282 :             OutputReportTabular::AddTOCEntry(state, "Tariff Report", tariff.tariffName);
     824              :         }
     825              :         // associate the resource number with each tariff
     826          301 :         if (tariff.reportMeterIndx != -1) {
     827          300 :             tariff.resource = state.dataOutputProcessor->meters[tariff.reportMeterIndx]->resource;
     828              :         }
     829              :     }
     830          799 : }
     831              : 
     832          101 : void GetInputEconomicsQualify(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
     833              : {
     834              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
     835              :     //    DATE WRITTEN   May 2004
     836              : 
     837              :     //    Read the input file for "Economics:Qualify" objects.
     838              : 
     839              :     static constexpr std::string_view RoutineName("GetInputEconomicsQualify: ");
     840              :     static constexpr std::string_view routineName = "GetInputEconomicsQualify";
     841              : 
     842              :     int iInObj;    // loop index variable for reading in objects
     843              :     int NumAlphas; // Number of elements in the alpha array
     844              :     int NumNums;   // Number of elements in the numeric array
     845              :     int IOStat;    // IO Status when calling get input subroutine
     846              :     bool isNotNumeric;
     847              :     int jFld;
     848              : 
     849          101 :     auto &s_econ = state.dataEconTariff;
     850          101 :     auto &s_ipsc = state.dataIPShortCut;
     851              : 
     852          101 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Qualify";
     853          101 :     s_econ->numQualify = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     854          101 :     s_econ->qualify.allocate(s_econ->numQualify);
     855              : 
     856          319 :     for (iInObj = 1; iInObj <= s_econ->numQualify; ++iInObj) {
     857          436 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     858          218 :                                                                  s_ipsc->cCurrentModuleObject,
     859              :                                                                  iInObj,
     860          218 :                                                                  s_ipsc->cAlphaArgs,
     861              :                                                                  NumAlphas,
     862          218 :                                                                  s_ipsc->rNumericArgs,
     863              :                                                                  NumNums,
     864              :                                                                  IOStat,
     865          218 :                                                                  s_ipsc->lNumericFieldBlanks,
     866          218 :                                                                  s_ipsc->lAlphaFieldBlanks,
     867          218 :                                                                  s_ipsc->cAlphaFieldNames,
     868          218 :                                                                  s_ipsc->cNumericFieldNames);
     869              : 
     870          218 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     871              : 
     872          218 :         auto &qualify = s_econ->qualify(iInObj);
     873              : 
     874              :         // check to make sure none of the values are another economic object
     875         1744 :         for (jFld = 1; jFld <= NumAlphas; ++jFld) {
     876         1526 :             if (hasi(s_ipsc->cAlphaArgs(jFld), "UtilityCost:")) {
     877            0 :                 ShowWarningError(state, format("{}{}=\"{}\".", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     878            0 :                 ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
     879              :             }
     880              :         }
     881              :         // index of the tariff name in the tariff array
     882          218 :         qualify.tariffIndx = FindTariffIndex(state, s_ipsc->cAlphaArgs(2), s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject);
     883          218 :         warnIfNativeVarname(state, s_ipsc->cAlphaArgs(1), qualify.tariffIndx, ErrorsFound, s_ipsc->cCurrentModuleObject);
     884          218 :         qualify.namePt =
     885          218 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(1), true, varIsAssigned, varNotYetDefined, ObjType::Qualify, iInObj, qualify.tariffIndx);
     886              :         // index of the variable in the variable array
     887          218 :         qualify.sourcePt =
     888          218 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(3), true, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, qualify.tariffIndx);
     889              :         // indicator if maximum test otherwise minimum
     890          218 :         if (s_ipsc->cAlphaArgs(4) == "MINIMUM") {
     891          110 :             qualify.isMaximum = false;
     892          108 :         } else if (s_ipsc->cAlphaArgs(4) == "MAXIMUM") {
     893          108 :             qualify.isMaximum = true;
     894              :         } else {
     895            0 :             ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(4), s_ipsc->cAlphaArgs(4), "Maximum");
     896            0 :             qualify.isMaximum = true;
     897              :         }
     898              :         // value of the threshold
     899          218 :         qualify.thresholdVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(5), isNotNumeric);
     900          218 :         qualify.thresholdPt =
     901          218 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(5), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, qualify.tariffIndx);
     902              :         // enumerated list of the kind of season
     903          218 :         if ((qualify.season = static_cast<Season>(getEnumValue(seasonNamesUC, s_ipsc->cAlphaArgs(6)))) == Season::Invalid) {
     904            0 :             ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(6), s_ipsc->cAlphaArgs(6), "Annual");
     905            0 :             qualify.season = Season::Annual;
     906              :         }
     907              : 
     908              :         // indicator if consecutive months otherwise count
     909          218 :         if (s_ipsc->cAlphaArgs(7) == "COUNT") {
     910          218 :             qualify.isConsecutive = false;
     911            0 :         } else if (s_ipsc->cAlphaArgs(7) == "CONSECUTIVE") {
     912            0 :             qualify.isConsecutive = true;
     913              :         } else {
     914            0 :             ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaArgs(5), "Consecutive");
     915            0 :             qualify.isConsecutive = true;
     916              :         }
     917              :         // number of months the test must be good for
     918          218 :         qualify.numberOfMonths = s_ipsc->rNumericArgs(1);
     919              :     }
     920          101 : }
     921              : 
     922          101 : void GetInputEconomicsChargeSimple(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
     923              : {
     924              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
     925              :     //    DATE WRITTEN   May 2004
     926              : 
     927              :     //    Read the input file for "Economics:Charge:Simple" objects.
     928              : 
     929              :     static constexpr std::string_view RoutineName("GetInputEconomicsChargeSimple: ");
     930              :     static constexpr std::string_view routineName = "GetInputEconomicsChargeSimple";
     931              :     int NumAlphas; // Number of elements in the alpha array
     932              :     int NumNums;   // Number of elements in the numeric array
     933              :     int IOStat;    // IO Status when calling get input subroutine
     934              :     bool isNotNumeric;
     935              : 
     936          101 :     auto &s_econ = state.dataEconTariff;
     937          101 :     auto &s_ipsc = state.dataIPShortCut;
     938          101 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Charge:Simple";
     939              : 
     940          101 :     s_econ->numChargeSimple = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     941          101 :     s_econ->chargeSimple.allocate(s_econ->numChargeSimple);
     942         1715 :     for (int iInObj = 1; iInObj <= s_econ->numChargeSimple; ++iInObj) {
     943         1614 :         auto &chargeSimple = s_econ->chargeSimple(iInObj);
     944         3228 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     945         1614 :                                                                  s_ipsc->cCurrentModuleObject,
     946              :                                                                  iInObj,
     947         1614 :                                                                  s_ipsc->cAlphaArgs,
     948              :                                                                  NumAlphas,
     949         1614 :                                                                  s_ipsc->rNumericArgs,
     950              :                                                                  NumNums,
     951              :                                                                  IOStat,
     952         1614 :                                                                  s_ipsc->lNumericFieldBlanks,
     953         1614 :                                                                  s_ipsc->lAlphaFieldBlanks,
     954         1614 :                                                                  s_ipsc->cAlphaFieldNames,
     955         1614 :                                                                  s_ipsc->cNumericFieldNames);
     956              : 
     957         1614 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     958              : 
     959              :         // check to make sure none of the values are another economic object
     960        11298 :         for (int jFld = 1; jFld <= NumAlphas; ++jFld) {
     961         9684 :             if (hasi(s_ipsc->cAlphaArgs(jFld), "UtilityCost:")) {
     962            0 :                 ShowWarningError(state, format("{}{}=\"{}\".", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     963            0 :                 ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
     964              :             }
     965              :         }
     966              :         // index of the tariff name in the tariff array
     967         1614 :         chargeSimple.tariffIndx = FindTariffIndex(state, s_ipsc->cAlphaArgs(2), s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject);
     968         1614 :         warnIfNativeVarname(state, s_ipsc->cAlphaArgs(1), chargeSimple.tariffIndx, ErrorsFound, s_ipsc->cCurrentModuleObject);
     969         1614 :         chargeSimple.namePt = AssignVariablePt(
     970         1614 :             state, s_ipsc->cAlphaArgs(1), true, varIsAssigned, varNotYetDefined, ObjType::ChargeSimple, iInObj, chargeSimple.tariffIndx);
     971              :         // index of the variable in the variable array
     972         1614 :         chargeSimple.sourcePt =
     973         1614 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(3), true, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, chargeSimple.tariffIndx);
     974              :         // enumerated list of the kind of season
     975         1614 :         chargeSimple.season = static_cast<Season>(getEnumValue(seasonNamesUC, s_ipsc->cAlphaArgs(4)));
     976         1614 :         if (chargeSimple.season == Season::Invalid) {
     977            0 :             ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(4), s_ipsc->cAlphaArgs(4), "Annual");
     978            0 :             chargeSimple.season = Season::Annual;
     979              :         }
     980              : 
     981              :         // check to make sure a seasonal schedule is specified if the season is not annual
     982         1614 :         if (chargeSimple.season != Season::Annual) {
     983          147 :             if (chargeSimple.tariffIndx != 0) {
     984          147 :                 if (s_econ->tariff(chargeSimple.tariffIndx).seasonSched == nullptr) {
     985            0 :                     ShowWarningError(state, format("{}{}=\"{}\" invalid data", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     986            0 :                     ShowContinueError(state, format("{}=\"{}\".", s_ipsc->cAlphaFieldNames(4), s_ipsc->cAlphaArgs(4)));
     987            0 :                     ShowContinueError(state,
     988              :                                       " a Season other than Annual is used but no Season Schedule Name is specified in the UtilityCost:Tariff.");
     989              :                 }
     990              :             }
     991              :         }
     992              :         // index of the category in the variable array
     993         1614 :         chargeSimple.categoryPt =
     994         1614 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(5), true, varIsAssigned, varNotYetDefined, ObjType::Category, iInObj, chargeSimple.tariffIndx);
     995              :         // cost per unit value or variable
     996         1614 :         chargeSimple.costPerVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(6), isNotNumeric);
     997         1614 :         chargeSimple.costPerPt = AssignVariablePt(
     998         1614 :             state, s_ipsc->cAlphaArgs(6), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, chargeSimple.tariffIndx);
     999              :     }
    1000          101 : }
    1001              : 
    1002          101 : void GetInputEconomicsChargeBlock(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
    1003              : {
    1004              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1005              :     //    DATE WRITTEN   May 2004
    1006              : 
    1007              :     //    Read the input file for "Economics:Charge:Block" objects.
    1008              : 
    1009              :     static constexpr std::string_view RoutineName("GetInputEconomicsChargeBlock: ");
    1010              :     static constexpr std::string_view routineName = "GetInputEconomicsChargeBlock";
    1011              : 
    1012              :     int NumAlphas; // Number of elements in the alpha array
    1013              :     int NumNums;   // Number of elements in the numeric array
    1014              :     int IOStat;    // IO Status when calling get input subroutine
    1015              :     bool isNotNumeric;
    1016              :     int alphaOffset;        // offset used in blocks for alpha array
    1017          101 :     Real64 hugeNumber(0.0); // Autodesk Value not used but suppresses warning about HUGE_() call
    1018              : 
    1019          101 :     auto &s_econ = state.dataEconTariff;
    1020          101 :     auto &s_ipsc = state.dataIPShortCut;
    1021          101 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Charge:Block";
    1022              : 
    1023          101 :     hugeNumber = HUGE_(hugeNumber);
    1024          101 :     s_econ->numChargeBlock = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1025          101 :     s_econ->chargeBlock.allocate(s_econ->numChargeBlock);
    1026          386 :     for (int iInObj = 1; iInObj <= s_econ->numChargeBlock; ++iInObj) {
    1027          285 :         auto &chargeBlock = s_econ->chargeBlock(iInObj);
    1028          570 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1029          285 :                                                                  s_ipsc->cCurrentModuleObject,
    1030              :                                                                  iInObj,
    1031          285 :                                                                  s_ipsc->cAlphaArgs,
    1032              :                                                                  NumAlphas,
    1033          285 :                                                                  s_ipsc->rNumericArgs,
    1034              :                                                                  NumNums,
    1035              :                                                                  IOStat,
    1036          285 :                                                                  s_ipsc->lNumericFieldBlanks,
    1037          285 :                                                                  s_ipsc->lAlphaFieldBlanks,
    1038          285 :                                                                  s_ipsc->cAlphaFieldNames,
    1039          285 :                                                                  s_ipsc->cNumericFieldNames);
    1040              : 
    1041          285 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    1042              : 
    1043              :         // check to make sure none of the values are another economic object
    1044         4178 :         for (int jFld = 1; jFld <= NumAlphas; ++jFld) {
    1045         3893 :             if (hasi(s_ipsc->cAlphaArgs(jFld), "UtilityCost:")) {
    1046            0 :                 ShowWarningError(state, format("{}{}=\"{}\".", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1047            0 :                 ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
    1048              :             }
    1049              :         }
    1050              :         // index of the tariff name in the tariff array
    1051          285 :         chargeBlock.tariffIndx = FindTariffIndex(state, s_ipsc->cAlphaArgs(2), s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject);
    1052          285 :         warnIfNativeVarname(state, s_ipsc->cAlphaArgs(1), chargeBlock.tariffIndx, ErrorsFound, s_ipsc->cCurrentModuleObject);
    1053          285 :         chargeBlock.namePt = AssignVariablePt(
    1054          285 :             state, s_ipsc->cAlphaArgs(1), true, varIsAssigned, varNotYetDefined, ObjType::ChargeBlock, iInObj, chargeBlock.tariffIndx);
    1055              :         // index of the variable in the variable array
    1056          285 :         chargeBlock.sourcePt =
    1057          285 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(3), true, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, chargeBlock.tariffIndx);
    1058              :         // enumerated list of the kind of season
    1059          285 :         chargeBlock.season = static_cast<Season>(getEnumValue(seasonNamesUC, s_ipsc->cAlphaArgs(4)));
    1060          285 :         if (chargeBlock.season == Season::Invalid) {
    1061            0 :             ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(4), s_ipsc->cAlphaArgs(4), "Annual");
    1062            0 :             chargeBlock.season = Season::Annual;
    1063              :         }
    1064              : 
    1065              :         // check to make sure a seasonal schedule is specified if the season is not annual
    1066          285 :         if (chargeBlock.season != Season::Annual) {
    1067           27 :             if (chargeBlock.tariffIndx != 0) {
    1068           27 :                 if (s_econ->tariff(chargeBlock.tariffIndx).seasonSched == nullptr) {
    1069            0 :                     ShowWarningError(state, format("{}{}=\"{}\" invalid data", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1070            0 :                     ShowContinueError(state, format("{}=\"{}\".", s_ipsc->cAlphaFieldNames(4), s_ipsc->cAlphaArgs(4)));
    1071            0 :                     ShowContinueError(state,
    1072              :                                       " a Season other than Annual is used but no Season Schedule Name is specified in the UtilityCost:Tariff.");
    1073              :                 }
    1074              :             }
    1075              :         }
    1076              :         // index of the category in the variable array
    1077          285 :         chargeBlock.categoryPt =
    1078          285 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(5), true, varIsAssigned, varNotYetDefined, ObjType::Category, iInObj, chargeBlock.tariffIndx);
    1079              :         // index of the remaining into variable in the variable array
    1080          285 :         chargeBlock.remainingPt =
    1081          285 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(6), true, varIsAssigned, varNotYetDefined, ObjType::Category, iInObj, chargeBlock.tariffIndx);
    1082              :         // block size multiplier
    1083          285 :         if (len(s_ipsc->cAlphaArgs(7)) == 0) { // if blank
    1084          190 :             chargeBlock.blkSzMultVal = 1.0;    // default is 1 if left blank
    1085          190 :             chargeBlock.blkSzMultPt = 0;
    1086              :         } else {
    1087           95 :             chargeBlock.blkSzMultVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(7), isNotNumeric);
    1088           95 :             chargeBlock.blkSzMultPt = AssignVariablePt(
    1089           95 :                 state, s_ipsc->cAlphaArgs(7), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, chargeBlock.tariffIndx);
    1090              :         }
    1091              :         // number of blocks used
    1092          285 :         chargeBlock.numBlk = (NumAlphas - 7) / 2;
    1093         1234 :         for (int jBlk = 1; jBlk <= chargeBlock.numBlk; ++jBlk) {
    1094          949 :             alphaOffset = 7 + (jBlk - 1) * 2;
    1095              :             // catch the "remaining" code word for the block size
    1096          949 :             if (Util::SameString(s_ipsc->cAlphaArgs(alphaOffset + 1), "REMAINING")) {
    1097          284 :                 chargeBlock.blkSzVal(jBlk) = hugeNumber / 1000000; // using small portion of largest possible value to prevent overflow
    1098          284 :                 chargeBlock.blkSzPt(jBlk) = 0;
    1099              :             } else {
    1100              :                 // array of block size
    1101          665 :                 chargeBlock.blkSzVal(jBlk) = Util::ProcessNumber(s_ipsc->cAlphaArgs(alphaOffset + 1), isNotNumeric);
    1102              : 
    1103          665 :                 chargeBlock.blkSzPt(jBlk) = AssignVariablePt(state,
    1104          665 :                                                              s_ipsc->cAlphaArgs(alphaOffset + 1),
    1105              :                                                              isNotNumeric,
    1106              :                                                              varIsArgument,
    1107              :                                                              varNotYetDefined,
    1108              :                                                              ObjType::Invalid,
    1109              :                                                              0,
    1110              :                                                              chargeBlock.tariffIndx);
    1111              :             }
    1112              :             // array of block cost
    1113          949 :             chargeBlock.blkCostVal(jBlk) = Util::ProcessNumber(s_ipsc->cAlphaArgs(alphaOffset + 2), isNotNumeric);
    1114          949 :             chargeBlock.blkCostPt(jBlk) = AssignVariablePt(state,
    1115          949 :                                                            s_ipsc->cAlphaArgs(alphaOffset + 2),
    1116              :                                                            isNotNumeric,
    1117              :                                                            varIsArgument,
    1118              :                                                            varNotYetDefined,
    1119              :                                                            ObjType::Invalid,
    1120              :                                                            0,
    1121              :                                                            chargeBlock.tariffIndx);
    1122              :         }
    1123              :     }
    1124          101 : }
    1125              : 
    1126          101 : void GetInputEconomicsRatchet(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
    1127              : {
    1128              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1129              :     //    DATE WRITTEN   May 2004
    1130              : 
    1131              :     //    Read the input file for "Economics:Ratchet" objects.
    1132              : 
    1133              :     static constexpr std::string_view RoutineName("GetInputEconomicsRatchet: ");
    1134              :     static constexpr std::string_view routineName = "GetInputEconomicsRatchet";
    1135              : 
    1136              :     int NumAlphas; // Number of elements in the alpha array
    1137              :     int NumNums;   // Number of elements in the numeric array
    1138              :     int IOStat;    // IO Status when calling get input subroutine
    1139              :     bool isNotNumeric;
    1140              : 
    1141          101 :     auto &s_econ = state.dataEconTariff;
    1142          101 :     auto &s_ipsc = state.dataIPShortCut;
    1143          101 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Ratchet";
    1144              : 
    1145          101 :     s_econ->numRatchet = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1146          101 :     s_econ->ratchet.allocate(s_econ->numRatchet);
    1147          102 :     for (int iInObj = 1; iInObj <= s_econ->numRatchet; ++iInObj) {
    1148            1 :         auto &ratchet = s_econ->ratchet(iInObj);
    1149              : 
    1150            2 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1151            1 :                                                                  s_ipsc->cCurrentModuleObject,
    1152              :                                                                  iInObj,
    1153            1 :                                                                  s_ipsc->cAlphaArgs,
    1154              :                                                                  NumAlphas,
    1155            1 :                                                                  s_ipsc->rNumericArgs,
    1156              :                                                                  NumNums,
    1157              :                                                                  IOStat,
    1158            1 :                                                                  s_ipsc->lNumericFieldBlanks,
    1159            1 :                                                                  s_ipsc->lAlphaFieldBlanks,
    1160            1 :                                                                  s_ipsc->cAlphaFieldNames,
    1161            1 :                                                                  s_ipsc->cNumericFieldNames);
    1162              : 
    1163            1 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    1164              : 
    1165              :         // check to make sure none of the values are another economic object
    1166            9 :         for (int jFld = 1; jFld <= NumAlphas; ++jFld) {
    1167            8 :             if (hasi(s_ipsc->cAlphaArgs(jFld), "UtilityCost:")) {
    1168            0 :                 ShowWarningError(state, format("{}{}=\"{}\".", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1169            0 :                 ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
    1170              :             }
    1171              :         }
    1172              :         // index of the tariff name in the tariff array
    1173            1 :         ratchet.tariffIndx = FindTariffIndex(state, s_ipsc->cAlphaArgs(2), s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject);
    1174            1 :         warnIfNativeVarname(state, s_ipsc->cAlphaArgs(1), ratchet.tariffIndx, ErrorsFound, s_ipsc->cCurrentModuleObject);
    1175            1 :         ratchet.namePt =
    1176            1 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(1), true, varIsAssigned, varNotYetDefined, ObjType::Ratchet, iInObj, ratchet.tariffIndx);
    1177              :         // index of the variable in the variable array
    1178            1 :         ratchet.baselinePt =
    1179            1 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(3), true, varIsArgument, varNotYetDefined, ObjType::Ratchet, iInObj, ratchet.tariffIndx);
    1180              :         // index of the variable in the variable array
    1181            1 :         ratchet.adjustmentPt =
    1182            1 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(4), true, varIsArgument, varNotYetDefined, ObjType::Ratchet, iInObj, ratchet.tariffIndx);
    1183              :         // seasons to and from
    1184            1 :         ratchet.seasonFrom = static_cast<Season>(getEnumValue(seasonNamesUC, s_ipsc->cAlphaArgs(5)));
    1185            1 :         if (ratchet.seasonFrom == Season::Invalid) {
    1186            0 :             ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaArgs(5), "Annual");
    1187            0 :             ratchet.seasonFrom = Season::Annual;
    1188              :         }
    1189            1 :         ratchet.seasonTo = static_cast<Season>(getEnumValue(seasonNamesUC, s_ipsc->cAlphaArgs(6)));
    1190            1 :         if (ratchet.seasonTo == Season::Invalid) {
    1191            0 :             ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(6), s_ipsc->cAlphaArgs(56), "Annual");
    1192            0 :             ratchet.seasonTo = Season::Annual;
    1193              :         }
    1194              : 
    1195              :         // ratchet multiplier
    1196            1 :         ratchet.multiplierVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(7), isNotNumeric);
    1197            1 :         ratchet.multiplierPt =
    1198            1 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(7), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, ratchet.tariffIndx);
    1199              :         // ratchet offset
    1200            1 :         ratchet.offsetVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(8), isNotNumeric);
    1201            1 :         ratchet.offsetPt =
    1202            1 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(8), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, ratchet.tariffIndx);
    1203              :     }
    1204          101 : }
    1205              : 
    1206          101 : void GetInputEconomicsVariable(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
    1207              : {
    1208              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1209              :     //    DATE WRITTEN   May 2004
    1210              : 
    1211              :     //    Read the input file for "Economics:Variable" objects.
    1212              : 
    1213              :     static constexpr std::string_view RoutineName("GetInputEconomicsVariable: ");
    1214              :     static constexpr std::string_view routineName = "GetInputEconomicsVariable";
    1215              : 
    1216              :     int NumAlphas; // Number of elements in the alpha array
    1217              :     int NumNums;   // Number of elements in the numeric array
    1218              :     int IOStat;    // IO Status when calling get input subroutine
    1219              : 
    1220          101 :     auto &s_econ = state.dataEconTariff;
    1221          101 :     auto &s_ipsc = state.dataIPShortCut;
    1222              : 
    1223          101 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Variable";
    1224          101 :     int numEconVarObj = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1225          187 :     for (int iInObj = 1; iInObj <= numEconVarObj; ++iInObj) {
    1226          172 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1227           86 :                                                                  s_ipsc->cCurrentModuleObject,
    1228              :                                                                  iInObj,
    1229           86 :                                                                  s_ipsc->cAlphaArgs,
    1230              :                                                                  NumAlphas,
    1231           86 :                                                                  s_ipsc->rNumericArgs,
    1232              :                                                                  NumNums,
    1233              :                                                                  IOStat,
    1234           86 :                                                                  s_ipsc->lNumericFieldBlanks,
    1235           86 :                                                                  s_ipsc->lAlphaFieldBlanks,
    1236           86 :                                                                  s_ipsc->cAlphaFieldNames,
    1237           86 :                                                                  s_ipsc->cNumericFieldNames);
    1238              : 
    1239           86 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
    1240              : 
    1241              :         // check to make sure none of the values are another economic object
    1242          344 :         for (int jFld = 1; jFld <= NumAlphas; ++jFld) {
    1243          258 :             if (hasi(s_ipsc->cAlphaArgs(jFld), "UtilityCost:")) {
    1244            0 :                 ShowWarningError(state, format("{}{}=\"{}\".", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1245            0 :                 ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
    1246              :             }
    1247              :         }
    1248           86 :         int tariffPt = FindTariffIndex(state, s_ipsc->cAlphaArgs(2), s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject);
    1249           86 :         int variablePt = AssignVariablePt(state, s_ipsc->cAlphaArgs(1), true, varIsArgument, varUserDefined, ObjType::Variable, iInObj, tariffPt);
    1250           86 :         warnIfNativeVarname(state, s_ipsc->cAlphaArgs(1), tariffPt, ErrorsFound, s_ipsc->cCurrentModuleObject);
    1251           86 :         auto &econVar = s_econ->econVar(variablePt);
    1252              : 
    1253              :         // validate the kind of variable - not used internally except for validation
    1254           86 :         econVar.varUnitType = static_cast<VarUnitType>(getEnumValue(varUnitTypeNamesUC, s_ipsc->cAlphaArgs(3)));
    1255           86 :         if (econVar.varUnitType == VarUnitType::Invalid) {
    1256            0 :             ShowSevereInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3));
    1257            0 :             ErrorsFound = true;
    1258            0 :             econVar.varUnitType = VarUnitType::Dimensionless;
    1259              :         }
    1260              : 
    1261              :         // move number inputs into econVar
    1262         1118 :         for (int jVal = 1; jVal <= NumNums; ++jVal) {
    1263         1032 :             econVar.values(jVal) = s_ipsc->rNumericArgs(jVal);
    1264              :         }
    1265              :         // fill the rest of the array with the last value entered
    1266           86 :         if (NumNums < NumMonths) {
    1267            0 :             for (int jVal = NumNums + 1; jVal <= NumMonths; ++jVal) {
    1268            0 :                 econVar.values(jVal) = s_ipsc->rNumericArgs(NumNums);
    1269              :             }
    1270              :         }
    1271              :     }
    1272          101 : }
    1273              : 
    1274          101 : void GetInputEconomicsComputation(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
    1275              : {
    1276              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1277              :     //    DATE WRITTEN   May 2004
    1278              : 
    1279              :     //    Read the input file for "Economics:Computation" objects.
    1280              :     //    This object is only used for very complex rates.
    1281              : 
    1282              :     static constexpr std::string_view RoutineName("GetInputEconomicsComputation: ");
    1283              : 
    1284              :     int NumAlphas; // Number of elements in the alpha array
    1285              :     int NumNums;   // Number of elements in the numeric array
    1286              :     int IOStat;    // IO Status when calling get input subroutine
    1287              : 
    1288          101 :     auto &s_econ = state.dataEconTariff;
    1289          101 :     auto &s_ipsc = state.dataIPShortCut;
    1290              : 
    1291          101 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Computation";
    1292          101 :     s_econ->numComputation = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1293          101 :     s_econ->computation.allocate(s_econ->numTariff); // not the number of Computations but the number of tariffs
    1294              :     // set default values for computation
    1295          402 :     for (auto &e : s_econ->computation) {
    1296          301 :         e.computeName.clear();
    1297          301 :         e.firstStep = 0;
    1298          301 :         e.lastStep = -1;
    1299          301 :         e.isUserDef = false;
    1300          101 :     }
    1301          102 :     for (int iInObj = 1; iInObj <= s_econ->numComputation; ++iInObj) {
    1302            2 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1303            1 :                                                                  s_ipsc->cCurrentModuleObject,
    1304              :                                                                  iInObj,
    1305            1 :                                                                  s_ipsc->cAlphaArgs,
    1306              :                                                                  NumAlphas,
    1307            1 :                                                                  s_ipsc->rNumericArgs,
    1308              :                                                                  NumNums,
    1309              :                                                                  IOStat,
    1310            1 :                                                                  s_ipsc->lNumericFieldBlanks,
    1311            1 :                                                                  s_ipsc->lAlphaFieldBlanks,
    1312            1 :                                                                  s_ipsc->cAlphaFieldNames,
    1313            1 :                                                                  s_ipsc->cNumericFieldNames);
    1314              :         // check to make sure none of the values are another economic object
    1315            9 :         for (int jFld = 1; jFld <= NumAlphas; ++jFld) {
    1316            8 :             if (hasi(s_ipsc->cAlphaArgs(jFld), "UtilityCost:")) {
    1317            0 :                 ShowWarningError(state, format("{}{}=\"{}\".", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1318            0 :                 ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
    1319              :             }
    1320              :         }
    1321            1 :         int tariffPt = FindTariffIndex(state, s_ipsc->cAlphaArgs(2), s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject);
    1322            1 :         warnIfNativeVarname(state, s_ipsc->cAlphaArgs(1), tariffPt, ErrorsFound, s_ipsc->cCurrentModuleObject);
    1323              :         // tariff and computation share the same index, the tariff index
    1324              :         // so all references are to the tariffPt
    1325            1 :         auto &computation = s_econ->computation(tariffPt);
    1326              : 
    1327            1 :         if (isWithinRange(state, tariffPt, 1, s_econ->numTariff)) {
    1328            1 :             computation.computeName = s_ipsc->cAlphaArgs(1);
    1329            1 :             computation.firstStep = s_econ->numSteps + 1;
    1330            7 :             for (int jLine = 3; jLine <= NumAlphas; ++jLine) {
    1331            6 :                 parseComputeLine(state, s_ipsc->cAlphaArgs(jLine), tariffPt);
    1332              :             }
    1333            1 :             computation.lastStep = s_econ->numSteps;
    1334              :             // check to make sure that some steps were defined
    1335            1 :             if (computation.firstStep >= computation.lastStep) {
    1336            0 :                 computation.firstStep = 0;
    1337            0 :                 computation.lastStep = -1;
    1338            0 :                 computation.isUserDef = false;
    1339            0 :                 ShowSevereError(state, format("{}{}=\"{}\" invalid data.", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1340            0 :                 ShowContinueError(state, "... No lines in the computation can be interpreted ");
    1341            0 :                 ErrorsFound = true;
    1342              :             } else {
    1343            1 :                 computation.isUserDef = true;
    1344              :             }
    1345              :         } else {
    1346            0 :             ShowSevereError(state, format("{}{}=\"{}\" invalid data.", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1347            0 :             ShowContinueError(state, format("... not found {}=\"{}\".", s_ipsc->cAlphaFieldNames(2), s_ipsc->cAlphaArgs(2)));
    1348            0 :             ErrorsFound = true;
    1349              :         }
    1350              :     }
    1351          101 : }
    1352              : 
    1353          799 : void GetInputEconomicsCurrencyType(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
    1354              : {
    1355              :     //       AUTHOR         Jason Glazer
    1356              :     //       DATE WRITTEN   August 2008
    1357              : 
    1358              :     //   Sets the type of currency (U.S. Dollar, Euro, Yen, etc.. )
    1359              :     //   This is a "unique" object.
    1360              : 
    1361              :     static constexpr std::string_view RoutineName("GetInputEconomicsCurrencyType: ");
    1362              : 
    1363              :     int NumCurrencyType;
    1364              :     int NumAlphas; // Number of elements in the alpha array
    1365              :     int NumNums;   // Number of elements in the numeric array
    1366              :     int IOStat;    // IO Status when calling get input subroutine
    1367              :     int i;
    1368              : 
    1369          799 :     auto &s_ipsc = state.dataIPShortCut;
    1370          799 :     s_ipsc->cCurrentModuleObject = "CurrencyType";
    1371              : 
    1372          799 :     initializeMonetaryUnit(state);
    1373          799 :     NumCurrencyType = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1374          799 :     state.dataCostEstimateManager->selectedMonetaryUnit = 0; // invalid
    1375          799 :     if (NumCurrencyType == 0) {
    1376          797 :         state.dataCostEstimateManager->selectedMonetaryUnit = 1; // USD - U.S. Dollar
    1377            2 :     } else if (NumCurrencyType == 1) {
    1378            4 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1379            2 :                                                                  s_ipsc->cCurrentModuleObject,
    1380              :                                                                  1,
    1381            2 :                                                                  s_ipsc->cAlphaArgs,
    1382              :                                                                  NumAlphas,
    1383            2 :                                                                  s_ipsc->rNumericArgs,
    1384              :                                                                  NumNums,
    1385              :                                                                  IOStat,
    1386            2 :                                                                  s_ipsc->lNumericFieldBlanks,
    1387            2 :                                                                  s_ipsc->lAlphaFieldBlanks,
    1388            2 :                                                                  s_ipsc->cAlphaFieldNames,
    1389            2 :                                                                  s_ipsc->cNumericFieldNames);
    1390              :         // Monetary Unit
    1391            2 :         for (i = 1; i <= (int)state.dataCostEstimateManager->monetaryUnit.size(); ++i) {
    1392            2 :             if (Util::SameString(s_ipsc->cAlphaArgs(1), state.dataCostEstimateManager->monetaryUnit(i).code)) {
    1393            2 :                 state.dataCostEstimateManager->selectedMonetaryUnit = i;
    1394            2 :                 break;
    1395              :             }
    1396              :         }
    1397            2 :         if (state.dataCostEstimateManager->selectedMonetaryUnit == 0) {
    1398            0 :             ShowSevereError(state, format("{}{}=\"{}\" invalid data.", RoutineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
    1399            0 :             ShowContinueError(state, format("... invalid {}.", s_ipsc->cAlphaFieldNames(1)));
    1400            0 :             ErrorsFound = true;
    1401              :         }
    1402            0 :     } else if (NumCurrencyType > 1) {
    1403            0 :         ShowWarningError(state,
    1404            0 :                          format("{}{} Only one instance of this object is allowed. USD will be used.", RoutineName, s_ipsc->cCurrentModuleObject));
    1405            0 :         state.dataCostEstimateManager->selectedMonetaryUnit = 1; // USD - U.S. Dollar
    1406              :     }
    1407          799 : }
    1408              : 
    1409            6 : void parseComputeLine(EnergyPlusData &state, std::string const &lineOfCompute, int const fromTariff)
    1410              : {
    1411              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1412              :     //    DATE WRITTEN   June 2004
    1413              : 
    1414              :     //   Converts a single line in the ECONOMICS:COMPUTE
    1415              :     //   command into tokens for computation
    1416              : 
    1417              :     //   Scan the line from the end of the line to the front of the
    1418              :     //   line and search for operators and variables. All items
    1419              :     //   are put into the step array.
    1420              : 
    1421            6 :     auto &s_econ = state.dataEconTariff;
    1422              : 
    1423            6 :     std::string word;
    1424              : 
    1425            6 :     size_t endOfWord = len(lineOfCompute) - 1;
    1426           32 :     while (endOfWord != std::string::npos) {
    1427              :         // get a single word (text string delimited by spaces)
    1428           26 :         GetLastWord(lineOfCompute, endOfWord, word);
    1429              :         // first see if word is an operator
    1430           26 :         Op op = static_cast<Op>(getEnumValue(opNamesUC, word));
    1431           26 :         if (op == Op::Invalid) {
    1432           20 :             static_cast<Op>(getEnumValue(opNames2UC, word));
    1433              :         }
    1434              : 
    1435              :         // if not an operator then look for
    1436           26 :         if (op != Op::Invalid) {
    1437            6 :             incrementSteps(state);
    1438            6 :             s_econ->steps(s_econ->numSteps).type = StepType::Op;
    1439            6 :             s_econ->steps(s_econ->numSteps).op = op;
    1440              : 
    1441              :         } else {
    1442              :             int varNum;
    1443              :             // see if argument or assignment (assignment will be first string on line)
    1444           20 :             if (endOfWord != std::string::npos) {
    1445           14 :                 varNum = AssignVariablePt(state, word, true, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, fromTariff);
    1446              :             } else {
    1447            6 :                 varNum = AssignVariablePt(state, word, true, varIsAssigned, varNotYetDefined, ObjType::AssignCompute, 0, fromTariff);
    1448              :             }
    1449              : 
    1450              :             // if a token is found then put it into step array
    1451           20 :             if (varNum == 0) {
    1452            0 :                 ShowWarningError(state, format("In UtilityCost:Computation line: {}", lineOfCompute));
    1453            0 :                 ShowContinueError(state, format("  Do not recognize: {} Will skip.", word));
    1454              :             } else {
    1455           20 :                 incrementSteps(state);
    1456           20 :                 s_econ->steps(s_econ->numSteps).type = StepType::Var;
    1457           20 :                 s_econ->steps(s_econ->numSteps).varNum = varNum;
    1458              :             }
    1459              :         }
    1460              :     }
    1461              : 
    1462            6 :     incrementSteps(state);
    1463            6 :     s_econ->steps(s_econ->numSteps).type = StepType::EOL; // at the end of the line show a zero to clear the stack
    1464            6 : }
    1465              : 
    1466           26 : void GetLastWord(std::string const &lineOfText, std::string::size_type &endOfScan, std::string &aWord)
    1467              : {
    1468              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1469              :     //    DATE WRITTEN   June 2004
    1470              : 
    1471              :     //   Returns the last substring of the line of text to the
    1472              :     //   left of the endOfSubStrg pointer. A substring is
    1473              :     //   delimited by spaces.  Quotes are not significant
    1474              :     //   (they are treated just like any other non-space character)
    1475              : 
    1476              :     //   Scan the string from the end.
    1477              : 
    1478           26 :     size_t curEndOfScan = endOfScan;
    1479           26 :     if (curEndOfScan != std::string::npos) {
    1480           26 :         if (curEndOfScan >= len(lineOfText)) {
    1481            0 :             curEndOfScan = len(lineOfText) - 1;
    1482              :         }
    1483              :         // check if currently on a space or not
    1484              :         bool isInWord;
    1485              :         size_t beginOfWord;
    1486              :         size_t endOfWord;
    1487           26 :         if (lineOfText[curEndOfScan] == ' ') {
    1488           20 :             isInWord = false;
    1489           20 :             beginOfWord = 0;
    1490           20 :             endOfWord = 0;
    1491              :         } else {
    1492            6 :             isInWord = true;
    1493            6 :             beginOfWord = curEndOfScan;
    1494            6 :             endOfWord = curEndOfScan;
    1495              :         }
    1496              :         // scan backwards from
    1497              :         bool isSpace;
    1498          274 :         for (size_t iString = curEndOfScan; iString <= curEndOfScan; --iString) { // Unsigned will wrap to npos after 0
    1499          268 :             if (lineOfText[iString] == ' ') {
    1500           40 :                 isSpace = true;
    1501              :             } else {
    1502          228 :                 isSpace = false;
    1503              :             }
    1504              :             // all logical conditions of isSpace and isInWord
    1505          268 :             if (isSpace) {
    1506           40 :                 if (isInWord) {
    1507              :                     // found the space in front of the word
    1508           20 :                     break;
    1509              :                 } else {
    1510              :                     // still have not found the back of the word
    1511              :                     // do nothing
    1512              :                 }
    1513              :             } else {
    1514          228 :                 if (isInWord) {
    1515              :                     // still have not found the space in front of the word
    1516          208 :                     beginOfWord = iString;
    1517              :                 } else {
    1518              :                     // found the last character of the word
    1519           20 :                     endOfWord = iString;
    1520           20 :                     beginOfWord = iString;
    1521           20 :                     isInWord = true;
    1522              :                 }
    1523              :             }
    1524              :         }
    1525           26 :         aWord = lineOfText.substr(beginOfWord, endOfWord - beginOfWord + 1);
    1526           26 :         endOfScan = beginOfWord - 1;
    1527              :     } else {
    1528            0 :         endOfScan = std::string::npos;
    1529            0 :         aWord = "";
    1530              :     }
    1531           26 : }
    1532              : 
    1533          799 : void initializeMonetaryUnit(EnergyPlusData &state)
    1534              : {
    1535              :     //       AUTHOR         Jason Glazer
    1536              :     //       DATE WRITTEN   August 2008
    1537              : 
    1538              :     //   Sets the type of monetary unit array.
    1539              : 
    1540              :     //   Uses get input structure similar to other objects
    1541              :     //   The monetaryUnitSymbols.xls spreadsheet helps create the code for this routine
    1542              : 
    1543              :     //   www.xe.com/symbols.php
    1544              : 
    1545          799 :     int numMonetaryUnit = 111;
    1546          799 :     state.dataCostEstimateManager->monetaryUnit.allocate(numMonetaryUnit);
    1547          799 :     state.dataCostEstimateManager->monetaryUnit(1).code = "USD";
    1548          799 :     state.dataCostEstimateManager->monetaryUnit(2).code = "AFN";
    1549          799 :     state.dataCostEstimateManager->monetaryUnit(3).code = "ALL";
    1550          799 :     state.dataCostEstimateManager->monetaryUnit(4).code = "ANG";
    1551          799 :     state.dataCostEstimateManager->monetaryUnit(5).code = "ARS";
    1552          799 :     state.dataCostEstimateManager->monetaryUnit(6).code = "AUD";
    1553          799 :     state.dataCostEstimateManager->monetaryUnit(7).code = "AWG";
    1554          799 :     state.dataCostEstimateManager->monetaryUnit(8).code = "AZN";
    1555          799 :     state.dataCostEstimateManager->monetaryUnit(9).code = "BAM";
    1556          799 :     state.dataCostEstimateManager->monetaryUnit(10).code = "BBD";
    1557          799 :     state.dataCostEstimateManager->monetaryUnit(11).code = "BGN";
    1558          799 :     state.dataCostEstimateManager->monetaryUnit(12).code = "BMD";
    1559          799 :     state.dataCostEstimateManager->monetaryUnit(13).code = "BND";
    1560          799 :     state.dataCostEstimateManager->monetaryUnit(14).code = "BOB";
    1561          799 :     state.dataCostEstimateManager->monetaryUnit(15).code = "BRL";
    1562          799 :     state.dataCostEstimateManager->monetaryUnit(16).code = "BSD";
    1563          799 :     state.dataCostEstimateManager->monetaryUnit(17).code = "BWP";
    1564          799 :     state.dataCostEstimateManager->monetaryUnit(18).code = "BYR";
    1565          799 :     state.dataCostEstimateManager->monetaryUnit(19).code = "BZD";
    1566          799 :     state.dataCostEstimateManager->monetaryUnit(20).code = "CAD";
    1567          799 :     state.dataCostEstimateManager->monetaryUnit(21).code = "CHF";
    1568          799 :     state.dataCostEstimateManager->monetaryUnit(22).code = "CLP";
    1569          799 :     state.dataCostEstimateManager->monetaryUnit(23).code = "CNY";
    1570          799 :     state.dataCostEstimateManager->monetaryUnit(24).code = "COP";
    1571          799 :     state.dataCostEstimateManager->monetaryUnit(25).code = "CRC";
    1572          799 :     state.dataCostEstimateManager->monetaryUnit(26).code = "CUP";
    1573          799 :     state.dataCostEstimateManager->monetaryUnit(27).code = "CZK";
    1574          799 :     state.dataCostEstimateManager->monetaryUnit(28).code = "DKK";
    1575          799 :     state.dataCostEstimateManager->monetaryUnit(29).code = "DOP";
    1576          799 :     state.dataCostEstimateManager->monetaryUnit(30).code = "EEK";
    1577          799 :     state.dataCostEstimateManager->monetaryUnit(31).code = "EGP";
    1578          799 :     state.dataCostEstimateManager->monetaryUnit(32).code = "EUR";
    1579          799 :     state.dataCostEstimateManager->monetaryUnit(33).code = "FJD";
    1580          799 :     state.dataCostEstimateManager->monetaryUnit(34).code = "GBP";
    1581          799 :     state.dataCostEstimateManager->monetaryUnit(35).code = "GHC";
    1582          799 :     state.dataCostEstimateManager->monetaryUnit(36).code = "GIP";
    1583          799 :     state.dataCostEstimateManager->monetaryUnit(37).code = "GTQ";
    1584          799 :     state.dataCostEstimateManager->monetaryUnit(38).code = "GYD";
    1585          799 :     state.dataCostEstimateManager->monetaryUnit(39).code = "HKD";
    1586          799 :     state.dataCostEstimateManager->monetaryUnit(40).code = "HNL";
    1587          799 :     state.dataCostEstimateManager->monetaryUnit(41).code = "HRK";
    1588          799 :     state.dataCostEstimateManager->monetaryUnit(42).code = "HUF";
    1589          799 :     state.dataCostEstimateManager->monetaryUnit(43).code = "IDR";
    1590          799 :     state.dataCostEstimateManager->monetaryUnit(44).code = "ILS";
    1591          799 :     state.dataCostEstimateManager->monetaryUnit(45).code = "IMP";
    1592          799 :     state.dataCostEstimateManager->monetaryUnit(46).code = "INR";
    1593          799 :     state.dataCostEstimateManager->monetaryUnit(47).code = "IRR";
    1594          799 :     state.dataCostEstimateManager->monetaryUnit(48).code = "ISK";
    1595          799 :     state.dataCostEstimateManager->monetaryUnit(49).code = "JEP";
    1596          799 :     state.dataCostEstimateManager->monetaryUnit(50).code = "JMD";
    1597          799 :     state.dataCostEstimateManager->monetaryUnit(51).code = "JPY";
    1598          799 :     state.dataCostEstimateManager->monetaryUnit(52).code = "KGS";
    1599          799 :     state.dataCostEstimateManager->monetaryUnit(53).code = "KHR";
    1600          799 :     state.dataCostEstimateManager->monetaryUnit(54).code = "KPW";
    1601          799 :     state.dataCostEstimateManager->monetaryUnit(55).code = "KRW";
    1602          799 :     state.dataCostEstimateManager->monetaryUnit(56).code = "KYD";
    1603          799 :     state.dataCostEstimateManager->monetaryUnit(57).code = "KZT";
    1604          799 :     state.dataCostEstimateManager->monetaryUnit(58).code = "LAK";
    1605          799 :     state.dataCostEstimateManager->monetaryUnit(59).code = "LBP";
    1606          799 :     state.dataCostEstimateManager->monetaryUnit(60).code = "LKR";
    1607          799 :     state.dataCostEstimateManager->monetaryUnit(61).code = "LRD";
    1608          799 :     state.dataCostEstimateManager->monetaryUnit(62).code = "LTL";
    1609          799 :     state.dataCostEstimateManager->monetaryUnit(63).code = "LVL";
    1610          799 :     state.dataCostEstimateManager->monetaryUnit(64).code = "MKD";
    1611          799 :     state.dataCostEstimateManager->monetaryUnit(65).code = "MNT";
    1612          799 :     state.dataCostEstimateManager->monetaryUnit(66).code = "MUR";
    1613          799 :     state.dataCostEstimateManager->monetaryUnit(67).code = "MXN";
    1614          799 :     state.dataCostEstimateManager->monetaryUnit(68).code = "MYR";
    1615          799 :     state.dataCostEstimateManager->monetaryUnit(69).code = "MZN";
    1616          799 :     state.dataCostEstimateManager->monetaryUnit(70).code = "NAD";
    1617          799 :     state.dataCostEstimateManager->monetaryUnit(71).code = "NGN";
    1618          799 :     state.dataCostEstimateManager->monetaryUnit(72).code = "NIO";
    1619          799 :     state.dataCostEstimateManager->monetaryUnit(73).code = "NOK";
    1620          799 :     state.dataCostEstimateManager->monetaryUnit(74).code = "NPR";
    1621          799 :     state.dataCostEstimateManager->monetaryUnit(75).code = "NZD";
    1622          799 :     state.dataCostEstimateManager->monetaryUnit(76).code = "OMR";
    1623          799 :     state.dataCostEstimateManager->monetaryUnit(77).code = "PAB";
    1624          799 :     state.dataCostEstimateManager->monetaryUnit(78).code = "PEN";
    1625          799 :     state.dataCostEstimateManager->monetaryUnit(79).code = "PHP";
    1626          799 :     state.dataCostEstimateManager->monetaryUnit(80).code = "PKR";
    1627          799 :     state.dataCostEstimateManager->monetaryUnit(81).code = "PLN";
    1628          799 :     state.dataCostEstimateManager->monetaryUnit(82).code = "PYG";
    1629          799 :     state.dataCostEstimateManager->monetaryUnit(83).code = "QAR";
    1630          799 :     state.dataCostEstimateManager->monetaryUnit(84).code = "RON";
    1631          799 :     state.dataCostEstimateManager->monetaryUnit(85).code = "RSD";
    1632          799 :     state.dataCostEstimateManager->monetaryUnit(86).code = "RUB";
    1633          799 :     state.dataCostEstimateManager->monetaryUnit(87).code = "SAR";
    1634          799 :     state.dataCostEstimateManager->monetaryUnit(88).code = "SBD";
    1635          799 :     state.dataCostEstimateManager->monetaryUnit(89).code = "SCR";
    1636          799 :     state.dataCostEstimateManager->monetaryUnit(90).code = "SEK";
    1637          799 :     state.dataCostEstimateManager->monetaryUnit(91).code = "SGD";
    1638          799 :     state.dataCostEstimateManager->monetaryUnit(92).code = "SHP";
    1639          799 :     state.dataCostEstimateManager->monetaryUnit(93).code = "SOS";
    1640          799 :     state.dataCostEstimateManager->monetaryUnit(94).code = "SRD";
    1641          799 :     state.dataCostEstimateManager->monetaryUnit(95).code = "SVC";
    1642          799 :     state.dataCostEstimateManager->monetaryUnit(96).code = "SYP";
    1643          799 :     state.dataCostEstimateManager->monetaryUnit(97).code = "THB";
    1644          799 :     state.dataCostEstimateManager->monetaryUnit(98).code = "TRL";
    1645          799 :     state.dataCostEstimateManager->monetaryUnit(99).code = "TRY";
    1646          799 :     state.dataCostEstimateManager->monetaryUnit(100).code = "TTD";
    1647          799 :     state.dataCostEstimateManager->monetaryUnit(101).code = "TVD";
    1648          799 :     state.dataCostEstimateManager->monetaryUnit(102).code = "TWD";
    1649          799 :     state.dataCostEstimateManager->monetaryUnit(103).code = "UAH";
    1650          799 :     state.dataCostEstimateManager->monetaryUnit(104).code = "UYU";
    1651          799 :     state.dataCostEstimateManager->monetaryUnit(105).code = "UZS";
    1652          799 :     state.dataCostEstimateManager->monetaryUnit(106).code = "VEF";
    1653          799 :     state.dataCostEstimateManager->monetaryUnit(107).code = "VND";
    1654          799 :     state.dataCostEstimateManager->monetaryUnit(108).code = "XCD";
    1655          799 :     state.dataCostEstimateManager->monetaryUnit(109).code = "YER";
    1656          799 :     state.dataCostEstimateManager->monetaryUnit(110).code = "ZAR";
    1657          799 :     state.dataCostEstimateManager->monetaryUnit(111).code = "ZWD";
    1658              : 
    1659          799 :     state.dataCostEstimateManager->monetaryUnit(1).txt = "$";
    1660          799 :     state.dataCostEstimateManager->monetaryUnit(2).txt = "AFN";
    1661          799 :     state.dataCostEstimateManager->monetaryUnit(3).txt = "Lek";
    1662          799 :     state.dataCostEstimateManager->monetaryUnit(4).txt = "ANG";
    1663          799 :     state.dataCostEstimateManager->monetaryUnit(5).txt = "$";
    1664          799 :     state.dataCostEstimateManager->monetaryUnit(6).txt = "$";
    1665          799 :     state.dataCostEstimateManager->monetaryUnit(7).txt = "AWG";
    1666          799 :     state.dataCostEstimateManager->monetaryUnit(8).txt = "AZN";
    1667          799 :     state.dataCostEstimateManager->monetaryUnit(9).txt = "KM";
    1668          799 :     state.dataCostEstimateManager->monetaryUnit(10).txt = "$";
    1669          799 :     state.dataCostEstimateManager->monetaryUnit(11).txt = "BGN";
    1670          799 :     state.dataCostEstimateManager->monetaryUnit(12).txt = "$";
    1671          799 :     state.dataCostEstimateManager->monetaryUnit(13).txt = "$";
    1672          799 :     state.dataCostEstimateManager->monetaryUnit(14).txt = "$b";
    1673          799 :     state.dataCostEstimateManager->monetaryUnit(15).txt = "R$";
    1674          799 :     state.dataCostEstimateManager->monetaryUnit(16).txt = "$";
    1675          799 :     state.dataCostEstimateManager->monetaryUnit(17).txt = "P";
    1676          799 :     state.dataCostEstimateManager->monetaryUnit(18).txt = "p.";
    1677          799 :     state.dataCostEstimateManager->monetaryUnit(19).txt = "BZ$";
    1678          799 :     state.dataCostEstimateManager->monetaryUnit(20).txt = "$";
    1679          799 :     state.dataCostEstimateManager->monetaryUnit(21).txt = "CHF";
    1680          799 :     state.dataCostEstimateManager->monetaryUnit(22).txt = "$";
    1681          799 :     state.dataCostEstimateManager->monetaryUnit(23).txt = "CNY";
    1682          799 :     state.dataCostEstimateManager->monetaryUnit(24).txt = "$";
    1683          799 :     state.dataCostEstimateManager->monetaryUnit(25).txt = "CRC";
    1684          799 :     state.dataCostEstimateManager->monetaryUnit(26).txt = "CUP";
    1685          799 :     state.dataCostEstimateManager->monetaryUnit(27).txt = "CZK";
    1686          799 :     state.dataCostEstimateManager->monetaryUnit(28).txt = "kr";
    1687          799 :     state.dataCostEstimateManager->monetaryUnit(29).txt = "RD$";
    1688          799 :     state.dataCostEstimateManager->monetaryUnit(30).txt = "kr";
    1689          799 :     state.dataCostEstimateManager->monetaryUnit(31).txt = "£";
    1690          799 :     state.dataCostEstimateManager->monetaryUnit(32).txt = "EUR";
    1691          799 :     state.dataCostEstimateManager->monetaryUnit(33).txt = "$";
    1692          799 :     state.dataCostEstimateManager->monetaryUnit(34).txt = "£";
    1693          799 :     state.dataCostEstimateManager->monetaryUnit(35).txt = "¢";
    1694          799 :     state.dataCostEstimateManager->monetaryUnit(36).txt = "£";
    1695          799 :     state.dataCostEstimateManager->monetaryUnit(37).txt = "Q";
    1696          799 :     state.dataCostEstimateManager->monetaryUnit(38).txt = "$";
    1697          799 :     state.dataCostEstimateManager->monetaryUnit(39).txt = "HK$";
    1698          799 :     state.dataCostEstimateManager->monetaryUnit(40).txt = "L";
    1699          799 :     state.dataCostEstimateManager->monetaryUnit(41).txt = "kn";
    1700          799 :     state.dataCostEstimateManager->monetaryUnit(42).txt = "Ft";
    1701          799 :     state.dataCostEstimateManager->monetaryUnit(43).txt = "Rp";
    1702          799 :     state.dataCostEstimateManager->monetaryUnit(44).txt = "ILS";
    1703          799 :     state.dataCostEstimateManager->monetaryUnit(45).txt = "£";
    1704          799 :     state.dataCostEstimateManager->monetaryUnit(46).txt = "INR";
    1705          799 :     state.dataCostEstimateManager->monetaryUnit(47).txt = "IRR";
    1706          799 :     state.dataCostEstimateManager->monetaryUnit(48).txt = "kr";
    1707          799 :     state.dataCostEstimateManager->monetaryUnit(49).txt = "£";
    1708          799 :     state.dataCostEstimateManager->monetaryUnit(50).txt = "J$";
    1709          799 :     state.dataCostEstimateManager->monetaryUnit(51).txt = "Â¥";
    1710          799 :     state.dataCostEstimateManager->monetaryUnit(52).txt = "KGS";
    1711          799 :     state.dataCostEstimateManager->monetaryUnit(53).txt = "KHR";
    1712          799 :     state.dataCostEstimateManager->monetaryUnit(54).txt = "KPW";
    1713          799 :     state.dataCostEstimateManager->monetaryUnit(55).txt = "KRW";
    1714          799 :     state.dataCostEstimateManager->monetaryUnit(56).txt = "$";
    1715          799 :     state.dataCostEstimateManager->monetaryUnit(57).txt = "KZT";
    1716          799 :     state.dataCostEstimateManager->monetaryUnit(58).txt = "LAK";
    1717          799 :     state.dataCostEstimateManager->monetaryUnit(59).txt = "£";
    1718          799 :     state.dataCostEstimateManager->monetaryUnit(60).txt = "LKR";
    1719          799 :     state.dataCostEstimateManager->monetaryUnit(61).txt = "$";
    1720          799 :     state.dataCostEstimateManager->monetaryUnit(62).txt = "Lt";
    1721          799 :     state.dataCostEstimateManager->monetaryUnit(63).txt = "Ls";
    1722          799 :     state.dataCostEstimateManager->monetaryUnit(64).txt = "MKD";
    1723          799 :     state.dataCostEstimateManager->monetaryUnit(65).txt = "MNT";
    1724          799 :     state.dataCostEstimateManager->monetaryUnit(66).txt = "MUR";
    1725          799 :     state.dataCostEstimateManager->monetaryUnit(67).txt = "$";
    1726          799 :     state.dataCostEstimateManager->monetaryUnit(68).txt = "RM";
    1727          799 :     state.dataCostEstimateManager->monetaryUnit(69).txt = "MT";
    1728          799 :     state.dataCostEstimateManager->monetaryUnit(70).txt = "$";
    1729          799 :     state.dataCostEstimateManager->monetaryUnit(71).txt = "NGN";
    1730          799 :     state.dataCostEstimateManager->monetaryUnit(72).txt = "C$";
    1731          799 :     state.dataCostEstimateManager->monetaryUnit(73).txt = "kr";
    1732          799 :     state.dataCostEstimateManager->monetaryUnit(74).txt = "NPR";
    1733          799 :     state.dataCostEstimateManager->monetaryUnit(75).txt = "$";
    1734          799 :     state.dataCostEstimateManager->monetaryUnit(76).txt = "OMR";
    1735          799 :     state.dataCostEstimateManager->monetaryUnit(77).txt = "B/.";
    1736          799 :     state.dataCostEstimateManager->monetaryUnit(78).txt = "S/.";
    1737          799 :     state.dataCostEstimateManager->monetaryUnit(79).txt = "Php";
    1738          799 :     state.dataCostEstimateManager->monetaryUnit(80).txt = "PKR";
    1739          799 :     state.dataCostEstimateManager->monetaryUnit(81).txt = "PLN";
    1740          799 :     state.dataCostEstimateManager->monetaryUnit(82).txt = "Gs";
    1741          799 :     state.dataCostEstimateManager->monetaryUnit(83).txt = "QAR";
    1742          799 :     state.dataCostEstimateManager->monetaryUnit(84).txt = "lei";
    1743          799 :     state.dataCostEstimateManager->monetaryUnit(85).txt = "RSD";
    1744          799 :     state.dataCostEstimateManager->monetaryUnit(86).txt = "RUB";
    1745          799 :     state.dataCostEstimateManager->monetaryUnit(87).txt = "SAR";
    1746          799 :     state.dataCostEstimateManager->monetaryUnit(88).txt = "$";
    1747          799 :     state.dataCostEstimateManager->monetaryUnit(89).txt = "SCR";
    1748          799 :     state.dataCostEstimateManager->monetaryUnit(90).txt = "kr";
    1749          799 :     state.dataCostEstimateManager->monetaryUnit(91).txt = "$";
    1750          799 :     state.dataCostEstimateManager->monetaryUnit(92).txt = "£";
    1751          799 :     state.dataCostEstimateManager->monetaryUnit(93).txt = "S";
    1752          799 :     state.dataCostEstimateManager->monetaryUnit(94).txt = "$";
    1753          799 :     state.dataCostEstimateManager->monetaryUnit(95).txt = "$";
    1754          799 :     state.dataCostEstimateManager->monetaryUnit(96).txt = "£";
    1755          799 :     state.dataCostEstimateManager->monetaryUnit(97).txt = "THB";
    1756          799 :     state.dataCostEstimateManager->monetaryUnit(98).txt = "TRL";
    1757          799 :     state.dataCostEstimateManager->monetaryUnit(99).txt = "YTL";
    1758          799 :     state.dataCostEstimateManager->monetaryUnit(100).txt = "TT$";
    1759          799 :     state.dataCostEstimateManager->monetaryUnit(101).txt = "$";
    1760          799 :     state.dataCostEstimateManager->monetaryUnit(102).txt = "NT$";
    1761          799 :     state.dataCostEstimateManager->monetaryUnit(103).txt = "UAH";
    1762          799 :     state.dataCostEstimateManager->monetaryUnit(104).txt = "$U";
    1763          799 :     state.dataCostEstimateManager->monetaryUnit(105).txt = "UZS";
    1764          799 :     state.dataCostEstimateManager->monetaryUnit(106).txt = "Bs";
    1765          799 :     state.dataCostEstimateManager->monetaryUnit(107).txt = "VND";
    1766          799 :     state.dataCostEstimateManager->monetaryUnit(108).txt = "$";
    1767          799 :     state.dataCostEstimateManager->monetaryUnit(109).txt = "YER";
    1768          799 :     state.dataCostEstimateManager->monetaryUnit(110).txt = "R";
    1769          799 :     state.dataCostEstimateManager->monetaryUnit(111).txt = "Z$";
    1770              : 
    1771          799 :     state.dataCostEstimateManager->monetaryUnit(1).html = "$";
    1772          799 :     state.dataCostEstimateManager->monetaryUnit(2).html = "&#x060b;";
    1773          799 :     state.dataCostEstimateManager->monetaryUnit(3).html = "Lek";
    1774          799 :     state.dataCostEstimateManager->monetaryUnit(4).html = "&#x0192;";
    1775          799 :     state.dataCostEstimateManager->monetaryUnit(5).html = "$";
    1776          799 :     state.dataCostEstimateManager->monetaryUnit(6).html = "$";
    1777          799 :     state.dataCostEstimateManager->monetaryUnit(7).html = "&#x0192;";
    1778          799 :     state.dataCostEstimateManager->monetaryUnit(8).html = "&#x043c;&#x0430;&#x043d;";
    1779          799 :     state.dataCostEstimateManager->monetaryUnit(9).html = "KM";
    1780          799 :     state.dataCostEstimateManager->monetaryUnit(10).html = "$";
    1781          799 :     state.dataCostEstimateManager->monetaryUnit(11).html = "&#x043b;&#x0432;";
    1782          799 :     state.dataCostEstimateManager->monetaryUnit(12).html = "$";
    1783          799 :     state.dataCostEstimateManager->monetaryUnit(13).html = "$";
    1784          799 :     state.dataCostEstimateManager->monetaryUnit(14).html = "$b";
    1785          799 :     state.dataCostEstimateManager->monetaryUnit(15).html = "R$";
    1786          799 :     state.dataCostEstimateManager->monetaryUnit(16).html = "$";
    1787          799 :     state.dataCostEstimateManager->monetaryUnit(17).html = "P";
    1788          799 :     state.dataCostEstimateManager->monetaryUnit(18).html = "p.";
    1789          799 :     state.dataCostEstimateManager->monetaryUnit(19).html = "BZ$";
    1790          799 :     state.dataCostEstimateManager->monetaryUnit(20).html = "$";
    1791          799 :     state.dataCostEstimateManager->monetaryUnit(21).html = "CHF";
    1792          799 :     state.dataCostEstimateManager->monetaryUnit(22).html = "$";
    1793          799 :     state.dataCostEstimateManager->monetaryUnit(23).html = "&#x5143;";
    1794          799 :     state.dataCostEstimateManager->monetaryUnit(24).html = "$";
    1795          799 :     state.dataCostEstimateManager->monetaryUnit(25).html = "&#x20a1;";
    1796          799 :     state.dataCostEstimateManager->monetaryUnit(26).html = "&#x20b1;";
    1797          799 :     state.dataCostEstimateManager->monetaryUnit(27).html = "&#x004b;&#x010d;";
    1798          799 :     state.dataCostEstimateManager->monetaryUnit(28).html = "kr";
    1799          799 :     state.dataCostEstimateManager->monetaryUnit(29).html = "RD$";
    1800          799 :     state.dataCostEstimateManager->monetaryUnit(30).html = "kr";
    1801          799 :     state.dataCostEstimateManager->monetaryUnit(31).html = "£";
    1802          799 :     state.dataCostEstimateManager->monetaryUnit(32).html = "&#x20ac;";
    1803          799 :     state.dataCostEstimateManager->monetaryUnit(33).html = "$";
    1804          799 :     state.dataCostEstimateManager->monetaryUnit(34).html = "£";
    1805          799 :     state.dataCostEstimateManager->monetaryUnit(35).html = "¢";
    1806          799 :     state.dataCostEstimateManager->monetaryUnit(36).html = "£";
    1807          799 :     state.dataCostEstimateManager->monetaryUnit(37).html = "Q";
    1808          799 :     state.dataCostEstimateManager->monetaryUnit(38).html = "$";
    1809          799 :     state.dataCostEstimateManager->monetaryUnit(39).html = "HK$";
    1810          799 :     state.dataCostEstimateManager->monetaryUnit(40).html = "L";
    1811          799 :     state.dataCostEstimateManager->monetaryUnit(41).html = "kn";
    1812          799 :     state.dataCostEstimateManager->monetaryUnit(42).html = "Ft";
    1813          799 :     state.dataCostEstimateManager->monetaryUnit(43).html = "Rp";
    1814          799 :     state.dataCostEstimateManager->monetaryUnit(44).html = "&#x20aa;";
    1815          799 :     state.dataCostEstimateManager->monetaryUnit(45).html = "£";
    1816          799 :     state.dataCostEstimateManager->monetaryUnit(46).html = "&#x20a8;";
    1817          799 :     state.dataCostEstimateManager->monetaryUnit(47).html = "&#xfdfc;";
    1818          799 :     state.dataCostEstimateManager->monetaryUnit(48).html = "kr";
    1819          799 :     state.dataCostEstimateManager->monetaryUnit(49).html = "£";
    1820          799 :     state.dataCostEstimateManager->monetaryUnit(50).html = "J$";
    1821          799 :     state.dataCostEstimateManager->monetaryUnit(51).html = "Â¥";
    1822          799 :     state.dataCostEstimateManager->monetaryUnit(52).html = "&#x043b;&#x0432;";
    1823          799 :     state.dataCostEstimateManager->monetaryUnit(53).html = "&#x17db;";
    1824          799 :     state.dataCostEstimateManager->monetaryUnit(54).html = "&#x20a9;";
    1825          799 :     state.dataCostEstimateManager->monetaryUnit(55).html = "&#x20a9;";
    1826          799 :     state.dataCostEstimateManager->monetaryUnit(56).html = "$";
    1827          799 :     state.dataCostEstimateManager->monetaryUnit(57).html = "&#x043b;&#x0432;";
    1828          799 :     state.dataCostEstimateManager->monetaryUnit(58).html = "&#x20ad;";
    1829          799 :     state.dataCostEstimateManager->monetaryUnit(59).html = "£";
    1830          799 :     state.dataCostEstimateManager->monetaryUnit(60).html = "&#x20a8;";
    1831          799 :     state.dataCostEstimateManager->monetaryUnit(61).html = "$";
    1832          799 :     state.dataCostEstimateManager->monetaryUnit(62).html = "Lt";
    1833          799 :     state.dataCostEstimateManager->monetaryUnit(63).html = "Ls";
    1834          799 :     state.dataCostEstimateManager->monetaryUnit(64).html = "&#x0434;&#x0435;&#x043d;";
    1835          799 :     state.dataCostEstimateManager->monetaryUnit(65).html = "&#x20ae;";
    1836          799 :     state.dataCostEstimateManager->monetaryUnit(66).html = "&#x20a8;";
    1837          799 :     state.dataCostEstimateManager->monetaryUnit(67).html = "$";
    1838          799 :     state.dataCostEstimateManager->monetaryUnit(68).html = "RM";
    1839          799 :     state.dataCostEstimateManager->monetaryUnit(69).html = "MT";
    1840          799 :     state.dataCostEstimateManager->monetaryUnit(70).html = "$";
    1841          799 :     state.dataCostEstimateManager->monetaryUnit(71).html = "&#x20a6;";
    1842          799 :     state.dataCostEstimateManager->monetaryUnit(72).html = "C$";
    1843          799 :     state.dataCostEstimateManager->monetaryUnit(73).html = "kr";
    1844          799 :     state.dataCostEstimateManager->monetaryUnit(74).html = "&#x20a8;";
    1845          799 :     state.dataCostEstimateManager->monetaryUnit(75).html = "$";
    1846          799 :     state.dataCostEstimateManager->monetaryUnit(76).html = "&#xfdfc;";
    1847          799 :     state.dataCostEstimateManager->monetaryUnit(77).html = "B/.";
    1848          799 :     state.dataCostEstimateManager->monetaryUnit(78).html = "S/.";
    1849          799 :     state.dataCostEstimateManager->monetaryUnit(79).html = "Php";
    1850          799 :     state.dataCostEstimateManager->monetaryUnit(80).html = "&#x20a8;";
    1851          799 :     state.dataCostEstimateManager->monetaryUnit(81).html = "&#x007a;&#x0142;";
    1852          799 :     state.dataCostEstimateManager->monetaryUnit(82).html = "Gs";
    1853          799 :     state.dataCostEstimateManager->monetaryUnit(83).html = "&#xfdfc;";
    1854          799 :     state.dataCostEstimateManager->monetaryUnit(84).html = "lei";
    1855          799 :     state.dataCostEstimateManager->monetaryUnit(85).html = "&#x0414;&#x0438;&#x043d;&#x002e;";
    1856          799 :     state.dataCostEstimateManager->monetaryUnit(86).html = "&#x0440;&#x0443;&#x0431;";
    1857          799 :     state.dataCostEstimateManager->monetaryUnit(87).html = "&#xfdfc;";
    1858          799 :     state.dataCostEstimateManager->monetaryUnit(88).html = "$";
    1859          799 :     state.dataCostEstimateManager->monetaryUnit(89).html = "&#x20a8;";
    1860          799 :     state.dataCostEstimateManager->monetaryUnit(90).html = "kr";
    1861          799 :     state.dataCostEstimateManager->monetaryUnit(91).html = "$";
    1862          799 :     state.dataCostEstimateManager->monetaryUnit(92).html = "£";
    1863          799 :     state.dataCostEstimateManager->monetaryUnit(93).html = "S";
    1864          799 :     state.dataCostEstimateManager->monetaryUnit(94).html = "$";
    1865          799 :     state.dataCostEstimateManager->monetaryUnit(95).html = "$";
    1866          799 :     state.dataCostEstimateManager->monetaryUnit(96).html = "£";
    1867          799 :     state.dataCostEstimateManager->monetaryUnit(97).html = "&#x0e3f;";
    1868          799 :     state.dataCostEstimateManager->monetaryUnit(98).html = "&#x20a4;";
    1869          799 :     state.dataCostEstimateManager->monetaryUnit(99).html = "YTL";
    1870          799 :     state.dataCostEstimateManager->monetaryUnit(100).html = "TT$";
    1871          799 :     state.dataCostEstimateManager->monetaryUnit(101).html = "$";
    1872          799 :     state.dataCostEstimateManager->monetaryUnit(102).html = "NT$";
    1873          799 :     state.dataCostEstimateManager->monetaryUnit(103).html = "&#x20b4;";
    1874          799 :     state.dataCostEstimateManager->monetaryUnit(104).html = "$U";
    1875          799 :     state.dataCostEstimateManager->monetaryUnit(105).html = "&#x043b;&#x0432;";
    1876          799 :     state.dataCostEstimateManager->monetaryUnit(106).html = "Bs";
    1877          799 :     state.dataCostEstimateManager->monetaryUnit(107).html = "&#x20ab;";
    1878          799 :     state.dataCostEstimateManager->monetaryUnit(108).html = "$";
    1879          799 :     state.dataCostEstimateManager->monetaryUnit(109).html = "&#xfdfc;";
    1880          799 :     state.dataCostEstimateManager->monetaryUnit(110).html = "R";
    1881          799 :     state.dataCostEstimateManager->monetaryUnit(111).html = "Z$";
    1882          799 : }
    1883              : 
    1884         2205 : int FindTariffIndex(
    1885              :     EnergyPlusData &state, std::string const &nameOfTariff, std::string const &nameOfReferingObj, bool &ErrorsFound, std::string const &nameOfCurObj)
    1886              : {
    1887              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1888              :     //    DATE WRITTEN   May 2004
    1889              : 
    1890              :     //    Find the index for the tariff string provided or else
    1891              :     //    raise a warning.
    1892              : 
    1893         2205 :     auto &s_econ = state.dataEconTariff;
    1894              : 
    1895              :     int FindTariffIndex;
    1896         2205 :     int found = 0;
    1897              : 
    1898         4050 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    1899         4050 :         if (Util::SameString(nameOfTariff, s_econ->tariff(iTariff).tariffName)) {
    1900         2205 :             found = iTariff;
    1901         2205 :             break;
    1902              :         }
    1903              :     }
    1904         2205 :     if (found > 0) {
    1905         2205 :         FindTariffIndex = found;
    1906              :     } else {
    1907            0 :         ShowSevereError(state, format("{}=\"{}\" invalid tariff referenced", nameOfCurObj, nameOfReferingObj));
    1908            0 :         ShowContinueError(state, format("not found UtilityCost:Tariff=\"{}\".", nameOfTariff));
    1909            0 :         ErrorsFound = true;
    1910            0 :         FindTariffIndex = 0;
    1911              :     }
    1912         2205 :     return FindTariffIndex;
    1913              : }
    1914              : 
    1915         2205 : void warnIfNativeVarname(
    1916              :     EnergyPlusData &state, std::string const &objName, int const curTariffIndex, bool &ErrorsFound, std::string const &curobjName)
    1917              : {
    1918              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1919              :     //    DATE WRITTEN   March 2007
    1920              : 
    1921              :     //   Issue a warning if the variable name (usually the object name) is
    1922              :     //   one of the names of native variables
    1923         2205 :     auto &s_econ = state.dataEconTariff;
    1924              : 
    1925         2205 :     bool throwError = false;
    1926         2205 :     if (getEnumValue(nativeNamesUC, objName) != -1) {
    1927            0 :         throwError = true;
    1928         2205 :     } else if (getEnumValue(catNamesUC, objName) != -1) {
    1929            0 :         throwError = true;
    1930              :     }
    1931              : 
    1932         2205 :     if (throwError) {
    1933            0 :         ErrorsFound = true;
    1934            0 :         if (curTariffIndex >= 1 && curTariffIndex <= s_econ->numTariff) {
    1935            0 :             ShowSevereError(state, format("UtilityCost:Tariff=\"{}\" invalid referenced name", s_econ->tariff(curTariffIndex).tariffName));
    1936            0 :             ShowContinueError(state, format("{}=\"{}\" You cannot name an object using the same name as a native variable.", curobjName, objName));
    1937              :         } else {
    1938            0 :             ShowSevereError(state, format("{}=\"{}\" You cannot name an object using the same name as a native variable.", curobjName, objName));
    1939              :         }
    1940              :     }
    1941         2205 : }
    1942              : 
    1943        24819 : int AssignVariablePt(EnergyPlusData &state,
    1944              :                      std::string_view const stringIn,
    1945              :                      bool const flagIfNotNumeric,
    1946              :                      int const useOfVar,
    1947              :                      int const varSpecific,
    1948              :                      ObjType const econObjKind,
    1949              :                      int const objIndex,
    1950              :                      int const tariffPt)
    1951              : {
    1952              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1953              :     //    DATE WRITTEN   May 2004
    1954              : 
    1955              :     //   If the string is not numeric, check if it is a valid string to use as
    1956              :     //   a variable name. Check if name has been used before and if not create
    1957              :     //   the variable using the string as its name.
    1958              :     //   Return the index of the variable.
    1959              : 
    1960        24819 :     auto &s_econ = state.dataEconTariff;
    1961              :     int AssignVariablePt;
    1962              : 
    1963        24819 :     if (flagIfNotNumeric && (len(stringIn) >= 1)) {
    1964        20571 :         std::string inNoSpaces = RemoveSpaces(state, stringIn);
    1965        20571 :         int found = 0;
    1966        20571 :         if (allocated(s_econ->econVar)) {
    1967      1804304 :             for (int iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    1968      1788067 :                 if (s_econ->econVar(iVar).tariffIndx == tariffPt) {
    1969       470786 :                     if (Util::SameString(s_econ->econVar(iVar).name, inNoSpaces)) {
    1970         4233 :                         found = iVar;
    1971         4233 :                         break;
    1972              :                     }
    1973              :                 }
    1974              :             }
    1975              :         }
    1976        20571 :         if (found > 0) {
    1977         4233 :             AssignVariablePt = found;
    1978         4233 :             if (s_econ->econVar(found).kindOfObj == ObjType::Invalid) {
    1979           88 :                 s_econ->econVar(found).kindOfObj = econObjKind;
    1980           88 :                 if (s_econ->econVar(found).index == 0) {
    1981           88 :                     s_econ->econVar(found).index = objIndex;
    1982              :                 }
    1983              :             }
    1984              :         } else {
    1985        16338 :             incrementEconVar(state);
    1986        16338 :             s_econ->econVar(s_econ->numEconVar).name = inNoSpaces;
    1987        16338 :             s_econ->econVar(s_econ->numEconVar).kindOfObj = econObjKind;
    1988        16338 :             s_econ->econVar(s_econ->numEconVar).index = objIndex;
    1989        16338 :             AssignVariablePt = s_econ->numEconVar;
    1990              :         }
    1991              :         // now set the flag for the type of usage the variable has
    1992        20571 :         if (useOfVar == varIsArgument) {
    1993        13537 :             s_econ->econVar(AssignVariablePt).isArgument = true;
    1994         7034 :         } else if (useOfVar == varIsAssigned) {
    1995         7034 :             s_econ->econVar(AssignVariablePt).isAssigned = true;
    1996              :         }
    1997        20571 :         s_econ->econVar(AssignVariablePt).tariffIndx = tariffPt;
    1998              :         // if the user defines the UtilityCost:Computation then this is called when reading the
    1999              :         // UtilityCost:Tariff with varNotYetDefined but they are already defined because
    2000              :         // the subroutine CreateCategoryNativeVariables has already been called.
    2001              : 
    2002              :         //        if (!((varSpecific == varNotYetDefined) && (econVar(AssignVariablePt).specific >= catEnergyCharges))) {
    2003        26909 :         if ((varSpecific != varNotYetDefined) ||
    2004         6338 :             (s_econ->econVar(AssignVariablePt).kindOfObj != ObjType::Category && s_econ->econVar(AssignVariablePt).kindOfObj != ObjType::Native)) {
    2005        16448 :             s_econ->econVar(AssignVariablePt).specific = varSpecific;
    2006              :         }
    2007        20571 :     } else { // if the string was numeric return a zero
    2008         4248 :         AssignVariablePt = 0;
    2009              :     }
    2010        24819 :     return AssignVariablePt;
    2011              : }
    2012              : 
    2013        16338 : void incrementEconVar(EnergyPlusData &state)
    2014              : {
    2015              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    2016              :     //    DATE WRITTEN   May 2004
    2017              : 
    2018              :     //   Increment the Increase the size of the
    2019              : 
    2020        16338 :     int constexpr sizeIncrement(100);
    2021        16338 :     auto &s_econ = state.dataEconTariff;
    2022              : 
    2023        16338 :     if (!allocated(s_econ->econVar)) {
    2024          101 :         s_econ->econVar.allocate(sizeIncrement);
    2025          101 :         s_econ->sizeEconVar = sizeIncrement;
    2026          101 :         s_econ->numEconVar = 1;
    2027              :     } else {
    2028        16237 :         ++s_econ->numEconVar;
    2029              :         // if larger than current size grow the array
    2030        16237 :         if (s_econ->numEconVar > s_econ->sizeEconVar) {
    2031          105 :             s_econ->econVar.redimension(s_econ->sizeEconVar += sizeIncrement);
    2032              :         }
    2033              :     }
    2034        16338 :     auto &econVar = s_econ->econVar(s_econ->numEconVar);
    2035              : 
    2036              :     // initialize new record) //Autodesk Most of these match default initialization so not needed
    2037        16338 :     econVar.name = "";
    2038        16338 :     econVar.tariffIndx = 0;
    2039        16338 :     econVar.kindOfObj = ObjType::Invalid;
    2040        16338 :     econVar.index = 0;
    2041        16338 :     std::fill(econVar.values.begin(), econVar.values.end(), 0.0);
    2042        16338 :     econVar.isArgument = false;
    2043        16338 :     econVar.isAssigned = false;
    2044        16338 :     econVar.specific = varNotYetDefined;
    2045              :     //        econVar( numEconVar ).values = 0.0; //Autodesk Already initialized above
    2046              :     // Autodesk Don't initialize cntMeDependOn
    2047        16338 :     econVar.Operator = Op::Invalid;
    2048        16338 :     econVar.firstOperand = 1; // Autodesk Default initialization sets this to 0
    2049        16338 :     econVar.lastOperand = 0;
    2050        16338 :     econVar.activeNow = false;
    2051        16338 :     econVar.isEvaluated = false;
    2052              :     // Autodesk Don't initialize isReported
    2053              :     // Autodesk Don't initialize varUnitType
    2054        16338 : }
    2055              : 
    2056        17494 : void incrementSteps(EnergyPlusData &state)
    2057              : {
    2058              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    2059              :     //    DATE WRITTEN   June 2004
    2060              : 
    2061              :     //   Increment the step array counter and if
    2062              :     //   necessary increase the size of the array.
    2063              : 
    2064        17494 :     auto &s_econ = state.dataEconTariff;
    2065        17494 :     int constexpr sizeIncrement(100);
    2066              : 
    2067        17494 :     if (!allocated(s_econ->steps)) {
    2068          101 :         s_econ->steps.allocate(sizeIncrement);
    2069          101 :         s_econ->sizeSteps = sizeIncrement;
    2070          101 :         s_econ->numSteps = 1;
    2071              :     } else {
    2072        17393 :         ++s_econ->numSteps;
    2073              :         // if larger than current size grow the array
    2074        17393 :         if (s_econ->numSteps > s_econ->sizeSteps) {
    2075          101 :             s_econ->steps.redimension(s_econ->sizeSteps += sizeIncrement);
    2076              :         }
    2077              :     }
    2078              :     // initialize new record
    2079        17494 :     s_econ->steps(s_econ->numSteps).type = StepType::EOL;
    2080        17494 : }
    2081              : 
    2082        20571 : std::string RemoveSpaces(EnergyPlusData &state, std::string_view const StringIn)
    2083              : {
    2084              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    2085              :     //    DATE WRITTEN   May 2004
    2086              : 
    2087              :     //   Return the string with all spaces removed.
    2088              : 
    2089        20571 :     std::string StringOut;
    2090        20571 :     bool foundSpaces = false;
    2091       324553 :     for (std::string::size_type iString = 0; iString < len(StringIn); ++iString) {
    2092       303982 :         if (StringIn[iString] != ' ') {
    2093       303982 :             StringOut += StringIn[iString];
    2094              :         } else {
    2095            0 :             foundSpaces = true;
    2096              :         }
    2097              :     }
    2098        20571 :     if (foundSpaces) {
    2099            0 :         ShowWarningError(state, format("UtilityCost: Spaces were removed from the variable=\"{}\".", StringIn));
    2100            0 :         ShowContinueError(state, format("...Resultant variable=\"{}\".", StringOut));
    2101              :     }
    2102        20571 :     return StringOut;
    2103            0 : }
    2104              : 
    2105          101 : void CreateCategoryNativeVariables(EnergyPlusData &state)
    2106              : {
    2107              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    2108              :     //    DATE WRITTEN   May 2004
    2109              : 
    2110              :     //    For each tariff create variables that are used for the
    2111              :     //    categories (i.e., EnergyCharges).
    2112              : 
    2113          101 :     auto &s_econ = state.dataEconTariff;
    2114          402 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    2115          301 :         auto &tariff = s_econ->tariff(iTariff);
    2116              : 
    2117              :         // category variables first
    2118         3311 :         for (int iCat = 0; iCat < (int)Cat::Num; ++iCat) {
    2119         3010 :             tariff.cats[iCat] = AssignVariablePt(state, catNames[iCat], true, varIsAssigned, iCat, ObjType::Category, 0, iTariff);
    2120              :         }
    2121              : 
    2122          301 :         tariff.firstCategory = tariff.cats[(int)Cat::EnergyCharges];
    2123          301 :         tariff.lastCategory = tariff.cats[(int)Cat::NotIncluded];
    2124              : 
    2125              :         // category variables first
    2126              : 
    2127        11438 :         for (int iNative = 0; iNative < (int)Native::Num; ++iNative) {
    2128        11137 :             tariff.natives[iNative] = AssignVariablePt(state, nativeNames[iNative], true, varIsArgument, iNative, ObjType::Native, 0, iTariff);
    2129              :         }
    2130          301 :         tariff.firstNative = tariff.natives[(int)Native::TotalEnergy];
    2131          301 :         tariff.lastNative = tariff.natives[(int)Native::BelowCustomerBaseEnergy];
    2132              :     }
    2133          101 : }
    2134              : 
    2135              : //======================================================================================================================
    2136              : //======================================================================================================================
    2137              : 
    2138              : //    DEFAULT COMPUTATION RELATED ROUTINES
    2139              : 
    2140              : //======================================================================================================================
    2141              : //======================================================================================================================
    2142              : 
    2143          101 : void CreateDefaultComputation(EnergyPlusData &state)
    2144              : {
    2145              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    2146              :     //    DATE WRITTEN   June 2004
    2147              : 
    2148              :     // PURPOSE OF THIS SUBROUTINE:
    2149              :     //    For most tariffs defined in EnergyPlus no specific
    2150              :     //    ECONOMICS:COMPUTATION will be entered. In that case,
    2151              :     //    a default sequence of computation steps needs to be
    2152              :     //    created.  This routine creates the default
    2153              :     //    computation steps.
    2154              :     //    Object           Fields         Depend On Fields
    2155              :     //    Qualify          namePt         sourcePt
    2156              :     //                                    thresholdPt
    2157              :     //    Charge:Simple    namePt         sourcePt
    2158              :     //                     categoryPt     costPerPt
    2159              :     //    Charge:Block     namePt         sourcePt
    2160              :     //                     categoryPt     blkSzMultPt
    2161              :     //                     remainingPt    blkSzPt
    2162              :     //                                    blkCostPt
    2163              :     //    Ratchet          namePt         baselinePt
    2164              :     //                                    adjustmentPt
    2165              :     //                                    multiplierPt
    2166              :     //                                    offsetPt
    2167              :     //    These will be formed into expressions that look like
    2168              :     //      namePt NOOP sourcePt thresholdPt
    2169              :     //    The different Charges are combined using the SUM operation
    2170              :     //    into categories.
    2171              :     //      category SUM chg1Name chg2Name chg3Name
    2172              :     //    Since the dependency array has one target and multiple
    2173              :     //    parameters, remainingPt is shown as a separate equation that
    2174              :     //    depends on namePt for Charge:Block. The equation will not be
    2175              :     //    displayed or processed except in the sort.
    2176              :     //      remainingPt NOOP namePt
    2177              :     //    Many lines of the computation will include just the name of
    2178              :     //    a single variable which triggers the calculation for that
    2179              :     //    charge, ratchet or qualify.
    2180              :     //      chg1Name
    2181              :     //    It is also possible that two variables referenced within one
    2182              :     //    object could include a dependency relationship also. For
    2183              :     //    example, the blkSzPt could be calculated using the same sourePt
    2184              :     //    in Charge:Block.
    2185              : 
    2186              :     // METHODOLOGY EMPLOYED:
    2187              :     //    Since some ECONOMCIS:* objects depend on other variables
    2188              :     //    first must create the order of when to perform the
    2189              :     //    computations. First a dependency table is created that
    2190              :     //    indicates what variables are dependent on other variables.
    2191              :     //    A directed acyclic graph (DAG) describes the general
    2192              :     //    problem which is usually solved using a topological
    2193              :     //    sorting algorithm.
    2194              :     //    Each line/step is generated and put into the depend
    2195              :     //    array. Also in the array are counts of how many items it
    2196              :     //    depends on and a list of entries that are dependent on that
    2197              :     //    line.
    2198              : 
    2199          101 :     auto &s_econ = state.dataEconTariff;
    2200              : 
    2201              :     // for each tariff that does not have a UtilityCost:Computation object go through the variables
    2202          402 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    2203          301 :         auto &tariff = s_econ->tariff(iTariff);
    2204          301 :         auto &computation = s_econ->computation(iTariff);
    2205          301 :         if (!computation.isUserDef) {
    2206              :             // clear all variables so that they are not active
    2207        58847 :             for (int jVar = 1; jVar <= s_econ->numEconVar; ++jVar) {
    2208        58547 :                 s_econ->econVar(jVar).activeNow = false;
    2209              :             }
    2210              :             // make all native variables active
    2211        11400 :             for (int jVar = tariff.firstNative; jVar <= tariff.lastNative; ++jVar) {
    2212        11100 :                 s_econ->econVar(jVar).activeNow = true;
    2213              :             }
    2214              :             //"clear" the dependOn array
    2215          300 :             s_econ->numOperand = 0;
    2216              :             // Define the preset equations (category summation)
    2217          300 :             int curTotal = tariff.cats[(int)Cat::Total];
    2218          300 :             int curSubtotal = tariff.cats[(int)Cat::Subtotal];
    2219          300 :             int curBasis = tariff.cats[(int)Cat::Basis];
    2220              :             // total SUM subtotal taxes
    2221          300 :             s_econ->econVar(curTotal).Operator = Op::SUM;
    2222          300 :             s_econ->econVar(curTotal).activeNow = true;
    2223          300 :             addOperand(state, curTotal, curSubtotal);
    2224          300 :             addOperand(state, curTotal, tariff.cats[(int)Cat::Taxes]);
    2225              :             // subtotal SUM basis adjustments surcharges
    2226          300 :             s_econ->econVar(curSubtotal).Operator = Op::SUM;
    2227          300 :             s_econ->econVar(curSubtotal).activeNow = true;
    2228          300 :             addOperand(state, curSubtotal, curBasis);
    2229          300 :             addOperand(state, curSubtotal, tariff.cats[(int)Cat::Adjustment]);
    2230          300 :             addOperand(state, curSubtotal, tariff.cats[(int)Cat::Surcharge]);
    2231              :             // basis SUM EnergyCharges DemandCharges ServiceCharges
    2232          300 :             s_econ->econVar(curBasis).Operator = Op::SUM;
    2233          300 :             s_econ->econVar(curBasis).activeNow = true;
    2234          300 :             addOperand(state, curBasis, tariff.cats[(int)Cat::EnergyCharges]);
    2235          300 :             addOperand(state, curBasis, tariff.cats[(int)Cat::DemandCharges]);
    2236          300 :             addOperand(state, curBasis, tariff.cats[(int)Cat::ServiceCharges]);
    2237              :             // set up the equations for other objects
    2238          300 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::EnergyCharges]);
    2239          300 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::DemandCharges]);
    2240          300 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::ServiceCharges]);
    2241          300 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::Adjustment]);
    2242          300 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::Surcharge]);
    2243          300 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::Taxes]);
    2244              :             // add the real time pricing to the energy charges
    2245          300 :             if (tariff.chargeSched != nullptr) {
    2246            1 :                 addOperand(state, tariff.cats[(int)Cat::EnergyCharges], tariff.natives[(int)Native::RealTimePriceCosts]);
    2247              :             }
    2248              :             // now add equations with NOOP to represent each object with its
    2249              :             // dependencies
    2250              :             // Qualify
    2251         1048 :             for (int kObj = 1; kObj <= s_econ->numQualify; ++kObj) {
    2252          748 :                 auto const &qualify = s_econ->qualify(kObj);
    2253          748 :                 if (qualify.tariffIndx == iTariff) {
    2254          217 :                     int curObject = qualify.namePt;
    2255          217 :                     s_econ->econVar(curObject).Operator = Op::NOOP;
    2256          217 :                     s_econ->econVar(curObject).activeNow = true;
    2257          217 :                     addOperand(state, curObject, qualify.sourcePt);
    2258          217 :                     addOperand(state, curObject, qualify.thresholdPt);
    2259              :                 }
    2260              :             }
    2261              :             // Ratchet
    2262          314 :             for (int kObj = 1; kObj <= s_econ->numRatchet; ++kObj) {
    2263           14 :                 auto const &ratchet = s_econ->ratchet(kObj);
    2264           14 :                 if (ratchet.tariffIndx == iTariff) {
    2265            1 :                     int curObject = ratchet.namePt;
    2266            1 :                     s_econ->econVar(curObject).Operator = Op::NOOP;
    2267            1 :                     s_econ->econVar(curObject).activeNow = true;
    2268            1 :                     addOperand(state, curObject, ratchet.baselinePt);
    2269            1 :                     addOperand(state, curObject, ratchet.adjustmentPt);
    2270            1 :                     addOperand(state, curObject, ratchet.multiplierPt);
    2271            1 :                     addOperand(state, curObject, ratchet.offsetPt);
    2272              :                 }
    2273              :             }
    2274              :             // ChargeSimple
    2275         5498 :             for (int kObj = 1; kObj <= s_econ->numChargeSimple; ++kObj) {
    2276         5198 :                 auto const &chargeSimple = s_econ->chargeSimple(kObj);
    2277         5198 :                 if (chargeSimple.tariffIndx == iTariff) {
    2278         1610 :                     int curObject = chargeSimple.namePt;
    2279         1610 :                     s_econ->econVar(curObject).Operator = Op::NOOP;
    2280         1610 :                     s_econ->econVar(curObject).activeNow = true;
    2281         1610 :                     addOperand(state, curObject, chargeSimple.sourcePt);
    2282         1610 :                     addOperand(state, curObject, chargeSimple.costPerPt);
    2283              :                 }
    2284              :             }
    2285              :             // ChargeBlock
    2286         1282 :             for (int kObj = 1; kObj <= s_econ->numChargeBlock; ++kObj) {
    2287          982 :                 auto const &chargeBlock = s_econ->chargeBlock(kObj);
    2288          982 :                 if (chargeBlock.tariffIndx == iTariff) {
    2289          285 :                     int curObject = chargeBlock.namePt;
    2290          285 :                     s_econ->econVar(curObject).Operator = Op::NOOP;
    2291          285 :                     s_econ->econVar(curObject).activeNow = true;
    2292          285 :                     addOperand(state, curObject, chargeBlock.sourcePt);
    2293          285 :                     addOperand(state, curObject, chargeBlock.blkSzMultPt);
    2294         1234 :                     for (int mBlock = 1; mBlock <= chargeBlock.numBlk; ++mBlock) {
    2295          949 :                         addOperand(state, curObject, chargeBlock.blkSzPt(mBlock));
    2296          949 :                         addOperand(state, curObject, chargeBlock.blkCostPt(mBlock));
    2297              :                     }
    2298              :                     // now add a new "equation" for dependency of remainingPt on namePt
    2299          285 :                     int remainPt = chargeBlock.remainingPt;
    2300          285 :                     if (remainPt > 0) {
    2301            1 :                         s_econ->econVar(remainPt).Operator = Op::NOOP;
    2302            1 :                         s_econ->econVar(remainPt).activeNow = true;
    2303            1 :                         addOperand(state, remainPt, curObject);
    2304              :                     }
    2305              :                 }
    2306              :             }
    2307              :             // Economic:Variable
    2308              :             // make all of the user defined variables as active
    2309        58847 :             for (int iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    2310        58547 :                 if (s_econ->econVar(iVar).tariffIndx == iTariff) {
    2311        16284 :                     if (s_econ->econVar(iVar).kindOfObj == ObjType::Variable) {
    2312           86 :                         s_econ->econVar(iVar).activeNow = true;
    2313              :                     }
    2314              :                 }
    2315              :             }
    2316              :             // make sure no computation is already user defined
    2317          300 :             if (computation.firstStep != 0) {
    2318            0 :                 ShowWarningError(state, format("In UtilityCost:Tariff: Overwriting user defined tariff {}", tariff.tariffName));
    2319              :             }
    2320              :             // initialize the computation
    2321          300 :             computation.computeName = "Autogenerated - " + tariff.tariffName;
    2322          300 :             computation.firstStep = s_econ->numSteps + 1;
    2323          300 :             computation.lastStep = -1; // this will be incremented by addStep
    2324          300 :             computation.isUserDef = false;
    2325              :             // now all "equations" are defined, treat the variables with the list
    2326              :             // of dependencies as a directed acyclic graph and use "count down" algorithm
    2327              :             // to do a topological sort of the variables into the order for computation
    2328              :             // First, clear the counters
    2329        58847 :             for (int jVar = 1; jVar <= s_econ->numEconVar; ++jVar) {
    2330        58547 :                 s_econ->econVar(jVar).cntMeDependOn = 0;
    2331              :             }
    2332              :             // Second, add up the number of dependencies on each variable
    2333        58847 :             for (int iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    2334        58547 :                 if (s_econ->econVar(iVar).activeNow) {
    2335        15984 :                     if (s_econ->econVar(iVar).lastOperand >= s_econ->econVar(iVar).firstOperand) {
    2336         3624 :                         s_econ->econVar(iVar).cntMeDependOn = 1 + s_econ->econVar(iVar).lastOperand - s_econ->econVar(iVar).firstOperand;
    2337              :                     }
    2338              :                 }
    2339              :             }
    2340              :             // Third, start removing items with zero connections and decrease each
    2341              :             //   counter.
    2342          300 :             int numNoDepend = -1;
    2343          300 :             int loopCount = 0;
    2344         1565 :             while ((numNoDepend != 0) || (loopCount > 100000)) {
    2345         1265 :                 numNoDepend = 0;
    2346       240114 :                 for (int iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    2347       238849 :                     if (s_econ->econVar(iVar).activeNow) {
    2348              :                         // find a variable that has no more dangling dependencies
    2349        18947 :                         if (s_econ->econVar(iVar).cntMeDependOn == 0) {
    2350              :                             // If the variable is a native variable then
    2351              :                             // IF (econVar(iVar)%kindOfObj .NE. iEconVarObjType::Native) THEN
    2352        15984 :                             if ((s_econ->econVar(iVar).kindOfObj != ObjType::Native) && (s_econ->econVar(iVar).kindOfObj != ObjType::Variable)) {
    2353         4798 :                                 if (s_econ->econVar(iVar).lastOperand >= s_econ->econVar(iVar).firstOperand) {
    2354              :                                     // transfer variables and operator to the computation and list of steps
    2355              :                                     // go through the operands backwards (end of line is evaluated first)
    2356        10214 :                                     for (int kOperand = s_econ->econVar(iVar).lastOperand; kOperand >= s_econ->econVar(iVar).firstOperand;
    2357              :                                          --kOperand) {
    2358         6590 :                                         incrementSteps(state);
    2359         6590 :                                         s_econ->steps(s_econ->numSteps) = s_econ->operands(kOperand);
    2360              :                                     }
    2361              :                                     // append the operator (either SUM or NOOP)
    2362         3624 :                                     incrementSteps(state);
    2363         3624 :                                     s_econ->steps(s_econ->numSteps).type = StepType::Op;
    2364         3624 :                                     s_econ->steps(s_econ->numSteps).op = s_econ->econVar(iVar).Operator;
    2365              :                                     // append the variable itself
    2366         3624 :                                     incrementSteps(state);
    2367         3624 :                                     s_econ->steps(s_econ->numSteps).type = StepType::Var;
    2368         3624 :                                     s_econ->steps(s_econ->numSteps).varNum = iVar;
    2369              :                                     // at the end of the line show a zero to clear the stack
    2370         3624 :                                     incrementSteps(state);
    2371         3624 :                                     s_econ->steps(s_econ->numSteps).type = StepType::EOL;
    2372              :                                 }
    2373              :                             }
    2374              :                             // go through each other variable looking for places where this variable is used
    2375              :                             // and decrement their counters.
    2376      3099009 :                             for (int jVar = 1; jVar <= s_econ->numEconVar; ++jVar) {
    2377      3083025 :                                 if (s_econ->econVar(jVar).activeNow) {
    2378       760876 :                                     for (int kOperand = s_econ->econVar(jVar).firstOperand; kOperand <= s_econ->econVar(jVar).lastOperand;
    2379              :                                          ++kOperand) {
    2380       325003 :                                         int referVar = s_econ->operands(kOperand).varNum;
    2381       325003 :                                         if (iVar == referVar) {
    2382         6590 :                                             --s_econ->econVar(jVar).cntMeDependOn;
    2383              :                                             // for each variable that has been decremented to zero increment the counter
    2384         6590 :                                             if (s_econ->econVar(jVar).cntMeDependOn <= 0) {
    2385         3624 :                                                 ++numNoDepend;
    2386              :                                             }
    2387              :                                         }
    2388              :                                     }
    2389              :                                 }
    2390              :                             }
    2391              :                             // make the variable inactive
    2392        15984 :                             s_econ->econVar(iVar).activeNow = false;
    2393              :                         }
    2394              :                     }
    2395              :                 }
    2396         1265 :                 ++loopCount;
    2397              :             }
    2398          300 :             if (loopCount > 100000) {
    2399            0 :                 ShowWarningError(state,
    2400            0 :                                  format("UtilityCost:Tariff: Loop count exceeded when counting dependencies in tariff: {}", tariff.tariffName));
    2401              :             }
    2402              :             // make sure that all variables associated with the tariff are included
    2403          300 :             bool remainingVarFlag = false;
    2404        58847 :             for (int iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    2405        58547 :                 if (s_econ->econVar(iVar).activeNow) {
    2406            0 :                     remainingVarFlag = true;
    2407              :                 }
    2408              :             }
    2409          300 :             if (remainingVarFlag) {
    2410            0 :                 ShowWarningError(state,
    2411            0 :                                  format("CreateDefaultComputation: In UtilityCost:Computation: Circular or invalid dependencies found in tariff: {}",
    2412            0 :                                         tariff.tariffName));
    2413            0 :                 ShowContinueError(state, "  UtilityCost variables that may have invalid dependencies and the variables they are dependent on.");
    2414            0 :                 for (int iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    2415            0 :                     if (s_econ->econVar(iVar).tariffIndx == iTariff) {
    2416            0 :                         if (s_econ->econVar(iVar).activeNow) {
    2417            0 :                             ShowContinueError(state, format("     {}", s_econ->econVar(iVar).name));
    2418            0 :                             for (int kOperand = s_econ->econVar(iVar).firstOperand; kOperand <= s_econ->econVar(iVar).lastOperand; ++kOperand) {
    2419            0 :                                 ShowContinueError(state, format("        ->  {}", s_econ->econVar(s_econ->operands(kOperand).varNum).name));
    2420              :                             }
    2421              :                         }
    2422              :                     }
    2423              :                 }
    2424              :             }
    2425              :             // set the end of the computations
    2426          300 :             computation.lastStep = s_econ->numSteps;
    2427          300 :             if (computation.firstStep >= computation.lastStep) {
    2428            0 :                 computation.firstStep = 0;
    2429            0 :                 computation.lastStep = -1;
    2430            0 :                 ShowWarningError(state,
    2431            0 :                                  format("CreateDefaultComputation: In UtilityCost:Computation: No lines in the auto-generated computation can be "
    2432              :                                         "interpreted in tariff: {}",
    2433            0 :                                         tariff.tariffName));
    2434              :             }
    2435              :         }
    2436              :     }
    2437          101 : }
    2438              : 
    2439        10422 : void addOperand(EnergyPlusData &state, int const varMe, int const varOperand)
    2440              : {
    2441              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    2442              :     //    DATE WRITTEN   July 2004
    2443              : 
    2444              :     //   Used by CreateDefaultComputation to create the dependency
    2445              :     //   relationship in the EconVar array
    2446              : 
    2447        10422 :     int constexpr sizeIncrement(100);
    2448        10422 :     auto &s_econ = state.dataEconTariff;
    2449              : 
    2450        10422 :     if (varOperand != 0) {
    2451              :         // increment the numOperand and allocate/reallocate the array
    2452              :         // if necessary
    2453         6590 :         if (!allocated(s_econ->operands)) {
    2454          101 :             s_econ->operands.allocate(sizeIncrement);
    2455          101 :             s_econ->sizeOperand = sizeIncrement;
    2456          101 :             s_econ->numOperand = 1;
    2457              :         } else {
    2458         6489 :             ++s_econ->numOperand;
    2459              :             // if larger than current size grow the array
    2460         6489 :             if (s_econ->numOperand > s_econ->sizeOperand) {
    2461            0 :                 s_econ->operands.redimension(s_econ->sizeOperand += sizeIncrement);
    2462              :             }
    2463              :         }
    2464         6590 :         auto &econVar = s_econ->econVar(varMe);
    2465              : 
    2466              :         // now add the dependency relationship
    2467         6590 :         s_econ->operands(s_econ->numOperand).type = StepType::Var;
    2468         6590 :         s_econ->operands(s_econ->numOperand).varNum = varOperand;
    2469         6590 :         econVar.lastOperand = s_econ->numOperand;
    2470              :         // if it is the first time addOperand was called with the varMe value
    2471              :         // then set the first pointer as well
    2472         6590 :         if (varMe != s_econ->addOperand_prevVarMe) {
    2473         3624 :             econVar.firstOperand = s_econ->numOperand;
    2474         3624 :             s_econ->addOperand_prevVarMe = varMe;
    2475              :         }
    2476              :     }
    2477        10422 : }
    2478              : 
    2479         1800 : void addChargesToOperand(EnergyPlusData &state, int const curTariff, int const curPointer)
    2480              : {
    2481              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    2482              :     //    DATE WRITTEN   July 2004
    2483              : 
    2484              :     //   Used by CreateDefaultComputation to create the "equation"
    2485              :     //   for the categories that are summations of ECONOMICS:CHARGES:BLOCK
    2486              :     //   and ECONOMICS:CHARGES:SIMPLE
    2487              : 
    2488         1800 :     auto const &s_econ = state.dataEconTariff;
    2489         1800 :     auto const &chargeSimple = s_econ->chargeSimple;
    2490         1800 :     auto const &chargeBlock = s_econ->chargeBlock;
    2491              : 
    2492         1800 :     s_econ->econVar(curPointer).Operator = Op::SUM;
    2493         1800 :     s_econ->econVar(curPointer).activeNow = true;
    2494        32988 :     for (int kObj = 1; kObj <= s_econ->numChargeSimple; ++kObj) {
    2495        31188 :         if (chargeSimple(kObj).tariffIndx == curTariff) {
    2496         9660 :             if (chargeSimple(kObj).categoryPt == curPointer) {
    2497         1610 :                 addOperand(state, curPointer, chargeSimple(kObj).namePt);
    2498              :             }
    2499              :         }
    2500              :     }
    2501         7692 :     for (int kObj = 1; kObj <= s_econ->numChargeBlock; ++kObj) {
    2502         5892 :         if (chargeBlock(kObj).tariffIndx == curTariff) {
    2503         1710 :             if (chargeBlock(kObj).categoryPt == curPointer) {
    2504          284 :                 addOperand(state, curPointer, chargeBlock(kObj).namePt);
    2505              :             }
    2506              :         }
    2507              :     }
    2508         1800 : }
    2509              : 
    2510              : //======================================================================================================================
    2511              : //======================================================================================================================
    2512              : 
    2513              : //    GATHER TIMESTEP VALUES ROUTINE
    2514              : 
    2515              : //======================================================================================================================
    2516              : //======================================================================================================================
    2517              : 
    2518       254136 : void GatherForEconomics(EnergyPlusData &state)
    2519              : {
    2520              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    2521              :     //    DATE WRITTEN   June 2004
    2522              : 
    2523              :     //   Gathers the data each timestep and updates the arrays
    2524              :     //   holding the data that will be used by the tariff
    2525              :     //   calculation.
    2526              : 
    2527              :     Real64 curInstantValue;
    2528              :     Real64 curDemand;
    2529              :     Real64 curEnergy;
    2530              :     Real64 curRTPprice;    // real time price
    2531              :     Real64 curRTPbaseline; // real time price customer baseline load
    2532              :     Real64 curRTPenergy;   // energy applied to real time price
    2533              :     Real64 curRTPcost;     // cost for energy for current time
    2534              : 
    2535       254136 :     auto &s_econ = state.dataEconTariff;
    2536              : 
    2537       254136 :     if (s_econ->numTariff >= 1) {
    2538        70080 :         for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    2539        35040 :             auto &tariff = s_econ->tariff(iTariff);
    2540              :             // if the meter is defined get the value
    2541        35040 :             if (tariff.reportMeterIndx != -1) {
    2542        35040 :                 curInstantValue = GetCurrentMeterValue(state, tariff.reportMeterIndx);
    2543              :             } else {
    2544            0 :                 curInstantValue = 0.0;
    2545              :             }
    2546              :             // remember the demand is still energy over a period of time divided by the
    2547              :             // length of time. This gathers the energy also.
    2548        35040 :             tariff.collectEnergy += curInstantValue;
    2549        35040 :             tariff.collectTime += state.dataGlobal->TimeStepZoneSec;
    2550              :             // added *SecInHour when adding RTP support August 2008
    2551        35040 :             if (tariff.collectTime >= tariff.demWinTime * Constant::rSecsInHour) {
    2552              :                 // get current value that has been converted into desired units
    2553        35040 :                 curDemand = tariff.demandConv * tariff.collectEnergy / tariff.collectTime;
    2554        35040 :                 curEnergy = tariff.energyConv * tariff.collectEnergy;
    2555              :                 // get the schedule values
    2556              :                 // remember no confirmation of schedule values occurs prior to now
    2557              :                 // The season schedule
    2558        35040 :                 Season curSeason = (tariff.seasonSched != nullptr) ? static_cast<Season>(tariff.seasonSched->getCurrentVal()) : Season::Winter;
    2559        35040 :                 int curPeriod = (tariff.periodSched != nullptr) ? tariff.periodSched->getCurrentVal() : 1;
    2560              : 
    2561              :                 int curMonth =
    2562            0 :                     (tariff.monthSched != nullptr) ? tariff.monthSched->getCurrentVal() :
    2563              :                                                    // #7814 - Have to be careful with DST. tariff::seasonForMonth is overwritten at each timestep, and
    2564              :                                                    // only the last value is retained, so make sure to capture the right one
    2565        70080 :                         (((state.dataGlobal->HourOfDay + state.dataEnvrn->DSTIndicator) <= Constant::iHoursInDay) ? state.dataEnvrn->Month
    2566       105120 :                                                                                                                   : state.dataEnvrn->MonthTomorrow);
    2567              : 
    2568        35040 :                 bool isGood = false;
    2569        35040 :                 if (curSeason == Season::Winter || curSeason == Season::Spring || curSeason == Season::Summer || curSeason == Season::Fall ||
    2570              :                     curSeason == Season::Annual) {
    2571        35040 :                     if (isWithinRange(state, curPeriod, 1, 4)) {
    2572        35040 :                         if (isWithinRange(state, curMonth, 1, 12)) {
    2573        35040 :                             isGood = true;
    2574              :                         }
    2575              :                     }
    2576              :                 }
    2577        35040 :                 if (isGood) {
    2578        35040 :                     tariff.seasonForMonth(curMonth) = curSeason;
    2579        35040 :                     tariff.gatherEnergy(curMonth)[(int)curPeriod] += curEnergy;
    2580        35040 :                     if (tariff.gatherDemand(curMonth)[(int)curPeriod] < curDemand) {
    2581          377 :                         tariff.gatherDemand(curMonth)[(int)curPeriod] = curDemand;
    2582              :                     }
    2583              :                 } else {
    2584            0 :                     ShowWarningError(state, format("UtilityCost:Tariff: While gathering for: {}", tariff.tariffName));
    2585            0 :                     ShowContinueError(state, "Invalid schedule values - outside of range");
    2586              :                 }
    2587              :                 // Real Time Pricing
    2588        35040 :                 if (tariff.chargeSched != nullptr) {
    2589            0 :                     curRTPprice = tariff.chargeSched->getCurrentVal();
    2590              :                     // if customer baseline load schedule is used, subtract that off of the
    2591              :                     // current energy
    2592            0 :                     if (tariff.baseUseSched != nullptr) {
    2593            0 :                         curRTPbaseline = tariff.baseUseSched->getCurrentVal();
    2594            0 :                         curRTPenergy = curEnergy - curRTPbaseline;
    2595              :                     } else {
    2596            0 :                         curRTPenergy = curEnergy;
    2597              :                     }
    2598              :                     // calculate the real time cost for current times energy
    2599            0 :                     curRTPcost = curRTPenergy * curRTPprice;
    2600            0 :                     tariff.RTPcost(curMonth) += curRTPcost;
    2601            0 :                     if (curRTPcost > 0) {
    2602            0 :                         tariff.RTPaboveBaseCost(curMonth) += curRTPcost;
    2603              :                     } else {
    2604            0 :                         tariff.RTPbelowBaseCost(curMonth) += curRTPcost;
    2605              :                     }
    2606            0 :                     if (curRTPenergy > 0) {
    2607            0 :                         tariff.RTPaboveBaseEnergy(curMonth) += curRTPenergy;
    2608              :                     } else {
    2609            0 :                         tariff.RTPbelowBaseEnergy(curMonth) += curRTPenergy;
    2610              :                     }
    2611              :                 }
    2612              :                 // reset the counters
    2613        35040 :                 tariff.collectEnergy = 0.0;
    2614        35040 :                 tariff.collectTime = 0.0;
    2615              :             }
    2616              :         }
    2617              :     }
    2618       254136 : }
    2619              : 
    2620        71598 : bool isWithinRange(EnergyPlusData &state, int const testVal, int const minThreshold, int const maxThreshold)
    2621              : {
    2622              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    2623              :     //    DATE WRITTEN   July 2004
    2624              : 
    2625              :     //   Simple function to check if an integer is equal to or between
    2626              :     //   two other values.
    2627              : 
    2628              :     bool isWithinRange;
    2629              : 
    2630        71598 :     if (maxThreshold < minThreshold) {
    2631            0 :         ShowWarningError(state, "UtilityCost: Invalid thresholds in IsWithinRange routine.");
    2632              :     }
    2633        71598 :     if ((testVal <= maxThreshold) && (testVal >= minThreshold)) {
    2634        71598 :         isWithinRange = true;
    2635              :     } else {
    2636            0 :         isWithinRange = false;
    2637              :     }
    2638        71598 :     return isWithinRange;
    2639              : }
    2640              : 
    2641              : //======================================================================================================================
    2642              : //======================================================================================================================
    2643              : 
    2644              : //    COMPUTE THE UTILITY BILLS AND CREATE REPORTS
    2645              : 
    2646              : //======================================================================================================================
    2647              : //======================================================================================================================
    2648              : 
    2649          799 : void ComputeTariff(EnergyPlusData &state)
    2650              : {
    2651              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    2652              :     //    DATE WRITTEN   July 2004
    2653              : 
    2654              :     //    Perform the calculation steps to compute the monthly
    2655              :     //    utility bills for the user entered tariffs.
    2656              :     //    The list of steps for the tariff computation are in order
    2657              :     //    for stack based computation (reverse polish notation)
    2658              : 
    2659          799 :     auto &s_econ = state.dataEconTariff;
    2660              : 
    2661              :     // values used in specific operations
    2662          799 :     Array1D<Real64> a(NumMonths);
    2663          799 :     Array1D<Real64> b(NumMonths);
    2664          799 :     Array1D<Real64> c(NumMonths);
    2665          799 :     Array1D<Real64> d(NumMonths);
    2666              : 
    2667          799 :     int constexpr noVar(0);
    2668              : 
    2669              :     Real64 annualAggregate;
    2670              : 
    2671          799 :     if (!state.files.outputControl.writeTabular(state)) {
    2672            1 :         state.dataOutRptTab->WriteTabularFiles = false;
    2673            1 :         return;
    2674              :     }
    2675              : 
    2676          798 :     Real64 hugeValue = HUGE_(Real64());
    2677              :     //  Clear the isEvaluated flags for all economics variables.
    2678        16971 :     for (int nVar = 1; nVar <= s_econ->numEconVar; ++nVar) {
    2679        16173 :         s_econ->econVar(nVar).isEvaluated = false;
    2680              :     }
    2681              : 
    2682          798 :     if (s_econ->numTariff == 0) {
    2683          698 :         return;
    2684              :     }
    2685              : 
    2686          100 :     state.dataOutRptTab->WriteTabularFiles = true;
    2687          100 :     setNativeVariables(state);
    2688              :     int aPt;
    2689              :     int bPt;
    2690              :     int cPt;
    2691          398 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    2692        17608 :         for (int jStep = s_econ->computation(iTariff).firstStep; jStep <= s_econ->computation(iTariff).lastStep; ++jStep) {
    2693        17310 :             auto const &step = s_econ->steps(jStep);
    2694        17310 :             int annualCnt = 0;
    2695              : 
    2696              :             // end of line - assign variable and clear stack
    2697              :             // if the stack still has two items on it then assign the values to the
    2698              :             // pointer otherwise if it follows a NOOP line it will only have one item
    2699              :             // that has already been assigned and no further action is required.
    2700        17310 :             if (step.type == StepType::EOL) {
    2701         3592 :                 if (s_econ->topOfStack >= 2) {
    2702         1517 :                     popStack(state, b, bPt); // pop the variable pointer
    2703         1517 :                     popStack(state, a, aPt); // pop the values
    2704         1517 :                     if (isWithinRange(state, bPt, 1, s_econ->numEconVar)) {
    2705         1517 :                         s_econ->econVar(bPt).values = a;
    2706              :                     }
    2707              :                 }
    2708         3592 :                 s_econ->topOfStack = 0;
    2709              : 
    2710              :                 // Variable
    2711        13718 :             } else if (step.type == StepType::Var) {
    2712        10126 :                 pushStack(state, s_econ->econVar(step.varNum).values, step.varNum);
    2713              : 
    2714              :                 // Operator
    2715         3592 :             } else if (step.type == StepType::Op) {
    2716         3592 :                 switch (step.op) {
    2717              : 
    2718         1517 :                 case Op::SUM: {
    2719         1517 :                     a = 0.0;
    2720         5781 :                     for (int kStack = 1, kStack_end = s_econ->topOfStack; kStack <= kStack_end; ++kStack) { // popStack modifies topOfStack
    2721         4264 :                         popStack(state, b, bPt);
    2722         4264 :                         a += b;
    2723              :                     }
    2724         1517 :                     pushStack(state, a, noVar);
    2725         1517 :                 } break;
    2726              : 
    2727            0 :                 case Op::MULTIPLY: {
    2728            0 :                     popStack(state, b, bPt);
    2729            0 :                     popStack(state, a, aPt);
    2730            0 :                     pushStack(state, a * b, noVar);
    2731            0 :                 } break;
    2732              : 
    2733            0 :                 case Op::SUBTRACT: {
    2734            0 :                     popStack(state, b, bPt);
    2735            0 :                     popStack(state, a, aPt);
    2736            0 :                     pushStack(state, b - a, noVar);
    2737            0 :                 } break;
    2738              : 
    2739            0 :                 case Op::DIVIDE: {
    2740            0 :                     popStack(state, a, aPt);
    2741            0 :                     popStack(state, b, bPt);
    2742            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2743            0 :                         c(lMonth) = (b(lMonth) != 0.0) ? (a(lMonth) / b(lMonth)) : 0.0;
    2744              :                     }
    2745            0 :                     pushStack(state, c, noVar);
    2746            0 :                 } break;
    2747              : 
    2748            0 :                 case Op::ABSOLUTEVALUE: {
    2749            0 :                     popStack(state, a, aPt);
    2750            0 :                     pushStack(state, ObjexxFCL::abs(a), noVar);
    2751            0 :                 } break;
    2752              : 
    2753            0 :                 case Op::INTEGER: {
    2754            0 :                     popStack(state, a, aPt);
    2755            0 :                     pushStack(state, Array1D_double(Array1D_int(a)), noVar);
    2756            0 :                 } break;
    2757              : 
    2758            0 :                 case Op::SIGN: {
    2759            0 :                     popStack(state, a, aPt);
    2760            0 :                     pushStack(state, sign(1.0, a), noVar);
    2761              :                     //        CASE (opROUND)
    2762              :                     //          CALL popStack(b,bPt)
    2763              :                     //          CALL popStack(a,aPt)
    2764              :                     //          DO lMonth = 1,MaxNumMonths
    2765              :                     //            IF ((b(lMonth) .LE. 5) .AND. (b(lMonth) .GE. -5)) THEN
    2766              :                     //              c(lMonth) = FLOAT(INT(a(lMonth) / (10 ** b(lMonth))) * (10 ** b(lMonth)))
    2767              :                     //            END IF
    2768              :                     //          END DO
    2769              :                     //          CALL pushStack(c,noVar)
    2770            0 :                 } break;
    2771              : 
    2772            0 :                 case Op::MAXIMUM: {
    2773            0 :                     a = -hugeValue;
    2774            0 :                     for (int kStack = 1, kStack_end = s_econ->topOfStack; kStack <= kStack_end; ++kStack) { // popStack modifies topOfStack
    2775            0 :                         popStack(state, b, bPt);
    2776            0 :                         for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2777            0 :                             if (b(lMonth) > a(lMonth)) {
    2778            0 :                                 a(lMonth) = b(lMonth);
    2779              :                             }
    2780              :                         }
    2781              :                     }
    2782            0 :                     pushStack(state, a, noVar);
    2783            0 :                 } break;
    2784              : 
    2785            0 :                 case Op::MINIMUM: {
    2786            0 :                     a = hugeValue;
    2787            0 :                     for (int kStack = 1, kStack_end = s_econ->topOfStack; kStack <= kStack_end; ++kStack) { // popStack modifies topOfStack
    2788            0 :                         popStack(state, b, bPt);
    2789            0 :                         for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2790            0 :                             if (b(lMonth) < a(lMonth)) {
    2791            0 :                                 a(lMonth) = b(lMonth);
    2792              :                             }
    2793              :                         }
    2794              :                     }
    2795            0 :                     pushStack(state, a, noVar);
    2796            0 :                 } break;
    2797              : 
    2798            0 :                 case Op::EXCEEDS: {
    2799            0 :                     popStack(state, b, bPt);
    2800            0 :                     popStack(state, a, aPt);
    2801            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2802            0 :                         if (a(lMonth) > b(lMonth)) {
    2803            0 :                             c(lMonth) = a(lMonth) - b(lMonth);
    2804              :                         } else {
    2805            0 :                             c(lMonth) = 0.0;
    2806              :                         }
    2807              :                     }
    2808            0 :                     pushStack(state, c, noVar);
    2809            0 :                 } break;
    2810              : 
    2811            0 :                 case Op::ANNUALMINIMUM: {
    2812              :                     // takes the minimum but ignores zeros
    2813            0 :                     annualAggregate = hugeValue;
    2814            0 :                     popStack(state, a, aPt);
    2815            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2816            0 :                         if (a(lMonth) != 0) {
    2817            0 :                             if (a(lMonth) < annualAggregate) {
    2818            0 :                                 annualAggregate = a(lMonth);
    2819              :                             }
    2820              :                         }
    2821              :                     }
    2822              :                     // if all months are zero then hugeValue still in annual but should be zero
    2823            0 :                     if (annualAggregate == hugeValue) {
    2824            0 :                         annualAggregate = 0.0;
    2825              :                     }
    2826            0 :                     c = annualAggregate;
    2827            0 :                     pushStack(state, c, noVar);
    2828            0 :                 } break;
    2829              : 
    2830            0 :                 case Op::ANNUALMAXIMUM: {
    2831              :                     // takes the maximum but ignores zeros
    2832            0 :                     annualAggregate = -hugeValue;
    2833            0 :                     popStack(state, a, aPt);
    2834            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2835            0 :                         if (a(lMonth) != 0) {
    2836            0 :                             if (a(lMonth) > annualAggregate) {
    2837            0 :                                 annualAggregate = a(lMonth);
    2838              :                             }
    2839              :                         }
    2840              :                     }
    2841              :                     // if all months are zero then hugeValue still in annual but should be zero
    2842            0 :                     if (annualAggregate == -hugeValue) {
    2843            0 :                         annualAggregate = 0.0;
    2844              :                     }
    2845            0 :                     c = annualAggregate;
    2846            0 :                     pushStack(state, c, noVar);
    2847            0 :                 } break;
    2848              : 
    2849            0 :                 case Op::ANNUALSUM: {
    2850              :                     // takes the maximum but ignores zeros
    2851            0 :                     annualAggregate = 0.0;
    2852            0 :                     popStack(state, a, aPt);
    2853            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2854            0 :                         annualAggregate += a(lMonth);
    2855              :                     }
    2856            0 :                     c = annualAggregate;
    2857            0 :                     pushStack(state, c, noVar);
    2858            0 :                 } break;
    2859              : 
    2860            0 :                 case Op::ANNUALAVERAGE: {
    2861              :                     // takes the annual sum but ignores zeros
    2862            0 :                     annualAggregate = 0.0;
    2863            0 :                     popStack(state, a, aPt);
    2864            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2865            0 :                         if (a(lMonth) != 0) {
    2866            0 :                             annualAggregate += a(lMonth);
    2867            0 :                             ++annualCnt;
    2868              :                         }
    2869              :                     }
    2870              :                     // if all months are zero then return zero
    2871            0 :                     c = (annualCnt != 0) ? (annualAggregate / annualCnt) : 0.0;
    2872            0 :                     pushStack(state, c, noVar);
    2873            0 :                 } break;
    2874              : 
    2875            0 :                 case Op::ANNUALOR: {
    2876            0 :                     popStack(state, a, aPt);
    2877            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2878            0 :                         if (a(lMonth) != 0) {
    2879            0 :                             ++annualCnt;
    2880              :                         }
    2881              :                     }
    2882              :                     // if any months is not zero then "true"
    2883            0 :                     c = (annualCnt >= 1) ? 1.0 : 0.0;
    2884            0 :                     pushStack(state, c, noVar);
    2885            0 :                 } break;
    2886              : 
    2887            0 :                 case Op::ANNUALAND: {
    2888            0 :                     popStack(state, a, aPt);
    2889            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2890            0 :                         if (a(lMonth) != 0) {
    2891            0 :                             ++annualCnt;
    2892              :                         }
    2893              :                     }
    2894              :                     // if all months are not zero then "true"
    2895            0 :                     c = (annualCnt == NumMonths) ? 1.0 : 0.0;
    2896            0 :                     pushStack(state, c, noVar);
    2897            0 :                 } break;
    2898              : 
    2899            0 :                 case Op::ANNUALMAXIMUMZERO: {
    2900              :                     // takes the maximum including zeros
    2901            0 :                     annualAggregate = -hugeValue;
    2902            0 :                     popStack(state, a, aPt);
    2903            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2904            0 :                         if (a(lMonth) > annualAggregate) {
    2905            0 :                             annualAggregate = a(lMonth);
    2906              :                         }
    2907              :                     }
    2908            0 :                     c = annualAggregate;
    2909            0 :                     pushStack(state, c, noVar);
    2910            0 :                 } break;
    2911              : 
    2912            0 :                 case Op::ANNUALMINIMUMZERO: {
    2913              :                     // takes the maximum including zeros
    2914            0 :                     annualAggregate = hugeValue;
    2915            0 :                     popStack(state, a, aPt);
    2916            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2917            0 :                         if (a(lMonth) < annualAggregate) {
    2918            0 :                             annualAggregate = a(lMonth);
    2919              :                         }
    2920              :                     }
    2921            0 :                     c = annualAggregate;
    2922            0 :                     pushStack(state, c, noVar);
    2923            0 :                 } break;
    2924              : 
    2925            0 :                 case Op::IF: {
    2926            0 :                     popStack(state, c, cPt);
    2927            0 :                     popStack(state, b, bPt);
    2928            0 :                     popStack(state, a, aPt);
    2929            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2930            0 :                         d(lMonth) = (a(lMonth) != 0) ? b(lMonth) : c(lMonth);
    2931              :                     }
    2932            0 :                     pushStack(state, d, noVar);
    2933            0 :                 } break;
    2934              : 
    2935            0 :                 case Op::GREATERTHAN: {
    2936            0 :                     popStack(state, b, bPt);
    2937            0 :                     popStack(state, a, aPt);
    2938            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2939            0 :                         c(lMonth) = (a(lMonth) > b(lMonth)) ? 1.0 : 0.0;
    2940              :                     }
    2941            0 :                     pushStack(state, c, noVar);
    2942            0 :                 } break;
    2943              : 
    2944            0 :                 case Op::GREATEREQUAL: {
    2945            0 :                     popStack(state, b, bPt);
    2946            0 :                     popStack(state, a, aPt);
    2947            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2948            0 :                         if (a(lMonth) >= b(lMonth)) {
    2949            0 :                             c(lMonth) = 1.0;
    2950              :                         } else {
    2951            0 :                             c(lMonth) = 0.0;
    2952              :                         }
    2953              :                     }
    2954            0 :                     pushStack(state, c, noVar);
    2955            0 :                 } break;
    2956              : 
    2957            0 :                 case Op::LESSTHAN: {
    2958            0 :                     popStack(state, b, bPt);
    2959            0 :                     popStack(state, a, aPt);
    2960            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2961            0 :                         c(lMonth) = (a(lMonth) < b(lMonth)) ? 1.0 : 0.0;
    2962              :                     }
    2963            0 :                     pushStack(state, c, noVar);
    2964            0 :                 } break;
    2965              : 
    2966            0 :                 case Op::LESSEQUAL: {
    2967            0 :                     popStack(state, b, bPt);
    2968            0 :                     popStack(state, a, aPt);
    2969            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2970            0 :                         c(lMonth) = (a(lMonth) <= b(lMonth)) ? 1.0 : 0.0;
    2971              :                     }
    2972            0 :                     pushStack(state, c, noVar);
    2973            0 :                 } break;
    2974              : 
    2975            0 :                 case Op::EQUAL: {
    2976            0 :                     popStack(state, b, bPt);
    2977            0 :                     popStack(state, a, aPt);
    2978            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2979            0 :                         c(lMonth) = (a(lMonth) == b(lMonth)) ? 1.0 : 0.0;
    2980              :                     }
    2981            0 :                     pushStack(state, c, noVar);
    2982            0 :                 } break;
    2983              : 
    2984            0 :                 case Op::NOTEQUAL: {
    2985            0 :                     popStack(state, b, bPt);
    2986            0 :                     popStack(state, a, aPt);
    2987            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2988            0 :                         c(lMonth) = (a(lMonth) != b(lMonth)) ? 1.0 : 0.0;
    2989              :                     }
    2990            0 :                     pushStack(state, c, noVar);
    2991            0 :                 } break;
    2992              : 
    2993            0 :                 case Op::AND: {
    2994            0 :                     popStack(state, b, bPt);
    2995            0 :                     popStack(state, a, aPt);
    2996            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    2997            0 :                         c(lMonth) = ((a(lMonth) != 0) && (b(lMonth) != 0)) ? 1.0 : 0.0;
    2998              :                     }
    2999            0 :                     pushStack(state, c, noVar);
    3000            0 :                 } break;
    3001              : 
    3002            0 :                 case Op::OR: {
    3003            0 :                     popStack(state, b, bPt);
    3004            0 :                     popStack(state, a, aPt);
    3005            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    3006            0 :                         c(lMonth) = ((a(lMonth) != 0) || (b(lMonth) != 0)) ? 1.0 : 0.0;
    3007              :                     }
    3008            0 :                     pushStack(state, c, noVar);
    3009            0 :                 } break;
    3010              : 
    3011            0 :                 case Op::NOT: {
    3012            0 :                     popStack(state, a, aPt);
    3013            0 :                     for (int lMonth = 1; lMonth <= NumMonths; ++lMonth) {
    3014            0 :                         c(lMonth) = (a(lMonth) == 0) ? 1.0 : 0.0;
    3015              :                     }
    3016            0 :                     pushStack(state, c, noVar);
    3017            0 :                 } break;
    3018              : 
    3019            0 :                 case Op::ADD: {
    3020            0 :                     popStack(state, b, bPt);
    3021            0 :                     popStack(state, a, aPt);
    3022            0 :                     pushStack(state, a + b, noVar);
    3023            0 :                 } break;
    3024              : 
    3025         2075 :                 case Op::NOOP: {
    3026              :                     // do nothing but clear the stack
    3027         2075 :                     s_econ->topOfStack = 0;
    3028              :                     // No longer pushing a zero to fix bug
    3029              :                     // and push zero
    3030              :                     // a = 0
    3031         2075 :                 } break;
    3032              : 
    3033            0 :                 default: {
    3034            0 :                 } break;
    3035              :                 }
    3036              :             }
    3037              :         }
    3038          298 :         checkMinimumMonthlyCharge(state, iTariff);
    3039              :     }
    3040          100 :     selectTariff(state);
    3041          100 :     LEEDtariffReporting(state);
    3042         2896 : }
    3043              : 
    3044        11643 : void pushStack(EnergyPlusData &state, Array1A<Real64> const monthlyArray, int const variablePointer)
    3045              : {
    3046              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3047              :     //    DATE WRITTEN   July 2004
    3048              : 
    3049              :     //    A stack is used in the evaluation of the tariff since
    3050              :     //    the variables and operators are in a reverse polish
    3051              :     //    notation order. The stack operates on a last-in
    3052              :     //    first out basis. The stack consists of both a pointer
    3053              :     //    to the variable and the twelve monthly values.
    3054              :     //    This routine puts an item on the top of the stack.
    3055              : 
    3056        11643 :     monthlyArray.dim(NumMonths);
    3057              : 
    3058        11643 :     Array1D<Real64> curMonthlyArray(NumMonths);
    3059        11643 :     int constexpr sizeIncrement(50);
    3060              : 
    3061        11643 :     auto &s_econ = state.dataEconTariff;
    3062        11643 :     auto &stack = s_econ->stack;
    3063        11643 :     auto const &econVar = s_econ->econVar;
    3064        11643 :     auto const &tariff = s_econ->tariff;
    3065              : 
    3066        11643 :     curMonthlyArray = monthlyArray;
    3067        11643 :     if (!allocated(stack)) {
    3068          100 :         stack.allocate(sizeIncrement);
    3069          100 :         s_econ->sizeStack = sizeIncrement;
    3070          100 :         s_econ->topOfStack = 1;
    3071              :     } else {
    3072        11543 :         ++s_econ->topOfStack;
    3073              :         // if larger than current size grow the array
    3074        11543 :         if (s_econ->topOfStack > s_econ->sizeStack) {
    3075            0 :             stack.redimension(s_econ->sizeStack += sizeIncrement);
    3076              :         }
    3077              :     }
    3078              :     // now push the values on to the stack
    3079        11643 :     stack(s_econ->topOfStack).varPt = variablePointer;
    3080              :     // check if variable has been evaluated if it is CHARGE:SIMPLE, CHARGE:BLOCK, RATCHET, or QUALIFY
    3081              :     // if it has not overwrite the values for monthlyArray with the evaluated values
    3082        11643 :     if (variablePointer != 0) {
    3083        10126 :         if (!econVar(variablePointer).isEvaluated) {
    3084              : 
    3085         8249 :             switch (econVar(variablePointer).kindOfObj) {
    3086         1585 :             case ObjType::ChargeSimple:
    3087         1585 :                 evaluateChargeSimple(state, variablePointer);
    3088         1585 :                 break;
    3089          277 :             case ObjType::ChargeBlock:
    3090          277 :                 evaluateChargeBlock(state, variablePointer);
    3091          277 :                 break;
    3092            1 :             case ObjType::Ratchet:
    3093            1 :                 evaluateRatchet(state, variablePointer);
    3094            1 :                 break;
    3095          215 :             case ObjType::Qualify:
    3096          215 :                 evaluateQualify(state, variablePointer);
    3097          215 :                 break;
    3098            0 :             case ObjType::Invalid:
    3099            0 :                 ShowWarningError(state, format("UtilityCost variable not defined: {}", econVar(variablePointer).name));
    3100            0 :                 ShowContinueError(state, format("   In tariff: {}", tariff(econVar(variablePointer).tariffIndx).tariffName));
    3101            0 :                 ShowContinueError(state, "   This may be the result of a misspelled variable name in the UtilityCost:Computation object.");
    3102            0 :                 ShowContinueError(state, "   All zero values will be assumed for this variable.");
    3103            0 :                 break;
    3104         6171 :             case ObjType::Variable:
    3105              :             case ObjType::Category:
    3106              :             case ObjType::Native:
    3107              :             case ObjType::AssignCompute:
    3108              :             case ObjType::Tariff:
    3109              :             case ObjType::Computation:
    3110              :                 // do nothing
    3111         6171 :                 break;
    3112            0 :             default:
    3113            0 :                 ShowWarningError(state,
    3114            0 :                                  format("UtilityCost Debugging issue. Invalid kind of variable used (pushStack). {} in tariff: {}",
    3115            0 :                                         econVar(variablePointer).kindOfObj,
    3116            0 :                                         tariff(econVar(variablePointer).tariffIndx).tariffName));
    3117              :             }
    3118              :             // if the serviceCharges are being evaluated add in the monthly charges
    3119         8249 :             if (econVar(variablePointer).kindOfObj == ObjType::Category && econVar(variablePointer).specific == (int)Cat::ServiceCharges) {
    3120          298 :                 addMonthlyCharge(state, variablePointer);
    3121              :             }
    3122              :             // get the results of performing the evaluation - should have been
    3123              :             // put into the econVar values
    3124         8249 :             curMonthlyArray = econVar(variablePointer).values;
    3125              :         }
    3126              :     }
    3127              :     // now assign
    3128        11643 :     stack(s_econ->topOfStack).values = curMonthlyArray;
    3129        11643 : }
    3130              : 
    3131         7298 : void popStack(EnergyPlusData &state, Array1A<Real64> monthlyArray, int &variablePointer)
    3132              : {
    3133              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3134              :     //    DATE WRITTEN   July 2004
    3135              : 
    3136              :     //    A stack is used in the evaluation of the tariff since
    3137              :     //    the variables and operators are in a reverse polish
    3138              :     //    notation order. The stack operates on a last-in
    3139              :     //    first out basis. The stack consists of both a pointer
    3140              :     //    to the variable and the twelve monthly values.
    3141              :     //    This routine returns the item on the top of the stack
    3142              :     //    and removes it from the stack.
    3143              : 
    3144         7298 :     monthlyArray.dim(NumMonths);
    3145              : 
    3146         7298 :     auto &s_econ = state.dataEconTariff;
    3147         7298 :     auto const &stack = s_econ->stack;
    3148              : 
    3149         7298 :     if (s_econ->topOfStack >= 1) {
    3150         7298 :         variablePointer = stack(s_econ->topOfStack).varPt;
    3151         7298 :         monthlyArray = stack(s_econ->topOfStack).values;
    3152              :     } else {
    3153            0 :         ShowWarningError(
    3154              :             state,
    3155            0 :             format("UtilityCost:Tariff: stack underflow in calculation of utility bills. On variable: {}", s_econ->econVar(variablePointer).name));
    3156            0 :         variablePointer = 0;
    3157            0 :         monthlyArray = {0.0};
    3158            0 :         s_econ->topOfStack = 0;
    3159              :     }
    3160         7298 :     --s_econ->topOfStack;
    3161         7298 : }
    3162              : 
    3163         1585 : void evaluateChargeSimple(EnergyPlusData &state, int const usingVariable)
    3164              : {
    3165              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3166              :     //    DATE WRITTEN   July 2004
    3167              : 
    3168         1585 :     Array1D<Real64> sourceVals(NumMonths);
    3169         1585 :     Array1D<Real64> costPer(NumMonths);
    3170         1585 :     Array1D<Real64> resultChg(NumMonths);
    3171         1585 :     Array1D<Real64> seasonMask(NumMonths);
    3172              : 
    3173         1585 :     auto &s_econ = state.dataEconTariff;
    3174         1585 :     int curTariff = s_econ->econVar(usingVariable).tariffIndx;
    3175         1585 :     auto const &tariff = s_econ->tariff(curTariff);
    3176         1585 :     int indexInChg = s_econ->econVar(usingVariable).index;
    3177         1585 :     auto const &chargeSimple = s_econ->chargeSimple(indexInChg);
    3178              : 
    3179              :     // check the tariff - make sure they match
    3180         1585 :     if (chargeSimple.namePt != usingVariable) {
    3181            0 :         ShowWarningError(state, "UtilityCost:Tariff Debugging issue. ChargeSimple index does not match variable pointer.");
    3182            0 :         ShowContinueError(state, format("   Between: {}", s_econ->econVar(usingVariable).name));
    3183            0 :         ShowContinueError(state, format("       And: {}", s_econ->econVar(chargeSimple.namePt).name));
    3184              :     }
    3185         1585 :     if (chargeSimple.tariffIndx != curTariff) {
    3186            0 :         ShowWarningError(state, "UtilityCost:Tariff Debugging issue. ChargeSimple index does not match tariff index.");
    3187            0 :         ShowContinueError(state, format("   Between: {}", tariff.tariffName));
    3188            0 :         ShowContinueError(state, format("       And: {}", s_econ->tariff(chargeSimple.tariffIndx).tariffName));
    3189              :     }
    3190              :     // data from the Charge:Simple
    3191         1585 :     sourceVals = s_econ->econVar(chargeSimple.sourcePt).values;
    3192              :     // determine if costPer should be based on variable or value
    3193         1585 :     if (chargeSimple.costPerPt != 0) {
    3194           84 :         costPer = s_econ->econVar(chargeSimple.costPerPt).values;
    3195              :     } else {
    3196         1501 :         costPer = chargeSimple.costPerVal;
    3197              :     }
    3198              :     // find proper season mask
    3199         1585 :     if (chargeSimple.season == Season::Summer) {
    3200           87 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values;
    3201         1498 :     } else if (chargeSimple.season == Season::Winter) {
    3202           57 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values;
    3203         1441 :     } else if (chargeSimple.season == Season::Spring) {
    3204            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values;
    3205         1441 :     } else if (chargeSimple.season == Season::Fall) {
    3206            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values;
    3207         1441 :     } else if (chargeSimple.season == Season::Annual) {
    3208         1441 :         seasonMask = 1.0; // all months are 1
    3209              :     }
    3210              : 
    3211              :     // finally perform calculations
    3212         1585 :     resultChg = sourceVals * costPer * seasonMask;
    3213              :     // store the cost in the name of the variable
    3214         1585 :     s_econ->econVar(usingVariable).values = resultChg;
    3215              :     // set the flag that it has been evaluated so it won't be evaluated multiple times
    3216         1585 :     s_econ->econVar(usingVariable).isEvaluated = true;
    3217         1585 : }
    3218              : 
    3219          277 : void evaluateChargeBlock(EnergyPlusData &state, int const usingVariable)
    3220              : {
    3221              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3222              :     //    DATE WRITTEN   July 2004
    3223              : 
    3224          277 :     Array1D<Real64> sourceVals(NumMonths);
    3225          277 :     Array1D<Real64> blkSzMult(NumMonths);
    3226          277 :     Array1D<Real64> remainVals(NumMonths);
    3227          277 :     Array1D<Real64> resultChg(NumMonths);
    3228          277 :     Array1D<Real64> amountForBlk(NumMonths);
    3229          277 :     Array1D<Real64> curBlkSz(NumMonths);
    3230          277 :     Array1D<Real64> curBlkCost(NumMonths);
    3231          277 :     Array1D<Real64> seasonMask(NumMonths);
    3232              : 
    3233          277 :     auto &s_econ = state.dataEconTariff;
    3234          277 :     int curTariff = s_econ->econVar(usingVariable).tariffIndx;
    3235          277 :     auto const &tariff = s_econ->tariff(curTariff);
    3236          277 :     int indexInChg = s_econ->econVar(usingVariable).index;
    3237          277 :     auto const &chargeBlock = s_econ->chargeBlock(indexInChg);
    3238              : 
    3239              :     // check the tariff - make sure they match
    3240          277 :     if (chargeBlock.namePt != usingVariable) {
    3241            0 :         ShowWarningError(state, "UtilityCost:Tariff Debugging issue. chargeBlock index does not match variable pointer.");
    3242            0 :         ShowContinueError(state, format("   Between: {}", s_econ->econVar(usingVariable).name));
    3243            0 :         ShowContinueError(state, format("       And: {}", s_econ->econVar(chargeBlock.namePt).name));
    3244              :     }
    3245          277 :     if (chargeBlock.tariffIndx != curTariff) {
    3246            0 :         ShowWarningError(state, "UtilityCost:Tariff Debugging issue. chargeBlock index does not match tariff index.");
    3247            0 :         ShowContinueError(state, format("   Between: {}", tariff.tariffName));
    3248            0 :         ShowContinueError(state, format("       And: {}", s_econ->tariff(chargeBlock.tariffIndx).tariffName));
    3249              :     }
    3250              :     // data from the chargeBlock
    3251          277 :     sourceVals = s_econ->econVar(chargeBlock.sourcePt).values;
    3252              :     // find proper season mask
    3253              : 
    3254          277 :     if (chargeBlock.season == Season::Summer) {
    3255           16 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values;
    3256          261 :     } else if (chargeBlock.season == Season::Winter) {
    3257            6 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values;
    3258          255 :     } else if (chargeBlock.season == Season::Spring) {
    3259            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values;
    3260          255 :     } else if (chargeBlock.season == Season::Fall) {
    3261            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values;
    3262          255 :     } else if (chargeBlock.season == Season::Annual) {
    3263          255 :         seasonMask = 1.0; // all months are 1
    3264              :     }
    3265              :     // get block size multiplier
    3266          277 :     if (chargeBlock.blkSzMultPt != 0) {
    3267           89 :         blkSzMult = s_econ->econVar(chargeBlock.blkSzMultPt).values;
    3268              :     } else {
    3269          188 :         blkSzMult = chargeBlock.blkSzMultVal;
    3270              :     }
    3271              :     // initially set the remaining energy or demand to the source
    3272          277 :     remainVals = sourceVals;
    3273              :     // initially set the result (cost) to zero
    3274          277 :     resultChg = 0.0;
    3275              :     // loop through the blocks performing calculations
    3276         1200 :     for (int iBlk = 1; iBlk <= chargeBlock.numBlk; ++iBlk) {
    3277          923 :         if (chargeBlock.blkSzPt(iBlk) != 0) {
    3278            0 :             curBlkSz = s_econ->econVar(chargeBlock.blkSzPt(iBlk)).values;
    3279              :         } else {
    3280          923 :             curBlkSz = chargeBlock.blkSzVal(iBlk);
    3281              :         }
    3282          923 :         if (chargeBlock.blkCostPt(iBlk) != 0) {
    3283            0 :             curBlkCost = s_econ->econVar(chargeBlock.blkCostPt(iBlk)).values;
    3284              :         } else {
    3285          923 :             curBlkCost = chargeBlock.blkCostVal(iBlk);
    3286              :         }
    3287              :         // loop through the months
    3288        11999 :         for (int jMonth = 1; jMonth <= NumMonths; ++jMonth) {
    3289        11076 :             if (seasonMask(jMonth) == 1) {
    3290              :                 // IF ((curBlkSz(jMonth) * blkSzMult(jMonth)) .GT. remainVals(jMonth)) THEN - CR 6547
    3291        10392 :                 if (blkSzMult(jMonth) != 0) {
    3292         7716 :                     if (curBlkSz(jMonth) > (remainVals(jMonth) / blkSzMult(jMonth))) {
    3293         7715 :                         amountForBlk(jMonth) = remainVals(jMonth);
    3294              :                     } else {
    3295            1 :                         amountForBlk(jMonth) = curBlkSz(jMonth) * blkSzMult(jMonth);
    3296              :                     }
    3297              :                 } else {
    3298         2676 :                     amountForBlk(jMonth) = 0.0;
    3299              :                 }
    3300        10392 :                 resultChg(jMonth) += amountForBlk(jMonth) * curBlkCost(jMonth);
    3301        10392 :                 remainVals(jMonth) -= amountForBlk(jMonth);
    3302              :             }
    3303              :         }
    3304              :     }
    3305              :     // store the amount remaining if a variable is specified
    3306          277 :     if (chargeBlock.remainingPt != 0) {
    3307            1 :         s_econ->econVar(chargeBlock.remainingPt).values = remainVals;
    3308              :     } else {
    3309          276 :         bool flagAllZero = true;
    3310         3588 :         for (int jMonth = 1; jMonth <= NumMonths; ++jMonth) {
    3311         3312 :             if (seasonMask(jMonth) == 1) {
    3312         3048 :                 if (remainVals(jMonth) != 0) {
    3313            0 :                     flagAllZero = false;
    3314              :                 }
    3315              :             }
    3316              :         }
    3317          276 :         if (!flagAllZero) {
    3318            0 :             ShowWarningError(
    3319              :                 state,
    3320            0 :                 format("UtilityCost:Tariff Not all energy or demand was assigned in the block charge: {}", s_econ->econVar(usingVariable).name));
    3321              :         }
    3322              :     }
    3323              :     // store the cost in the name of the variable
    3324          277 :     s_econ->econVar(usingVariable).values = resultChg;
    3325              :     // set the flag that it has been evaluated so it won't be evaluated multiple times
    3326          277 :     s_econ->econVar(usingVariable).isEvaluated = true;
    3327          277 : }
    3328              : 
    3329            1 : void evaluateRatchet(EnergyPlusData &state, int const usingVariable)
    3330              : {
    3331              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3332              :     //    DATE WRITTEN   July 2004
    3333              : 
    3334            1 :     Array1D<Real64> baselineVals(NumMonths);
    3335            1 :     Array1D<Real64> adjustmentVals(NumMonths);
    3336            1 :     Array1D<Real64> multiplierVals(NumMonths);
    3337            1 :     Array1D<Real64> offsetVals(NumMonths);
    3338            1 :     Array1D<Real64> seasonFromMask(NumMonths);
    3339            1 :     Array1D<Real64> seasonToMask(NumMonths);
    3340            1 :     Array1D<Real64> adjSeasonal(NumMonths);
    3341            1 :     Array1D<Real64> adjPeak(NumMonths);
    3342            1 :     Array1D<Real64> maxAdjBase(NumMonths);
    3343            1 :     Array1D<Real64> finalResult(NumMonths);
    3344              : 
    3345            1 :     auto &s_econ = state.dataEconTariff;
    3346            1 :     int curTariff = s_econ->econVar(usingVariable).tariffIndx;
    3347            1 :     auto const &tariff = s_econ->tariff(curTariff);
    3348            1 :     int indexInChg = s_econ->econVar(usingVariable).index;
    3349            1 :     auto const &ratchet = s_econ->ratchet(indexInChg);
    3350            1 :     bool isMonthly = false;
    3351              : 
    3352              :     // check the tariff - make sure they match
    3353            1 :     if (ratchet.namePt != usingVariable) {
    3354            0 :         ShowWarningError(state, "UtilityCost:Tariff Debugging issue. Ratchet index does not match variable pointer.");
    3355            0 :         ShowContinueError(state, format("   Between: {}", s_econ->econVar(usingVariable).name));
    3356            0 :         ShowContinueError(state, format("       And: {}", s_econ->econVar(ratchet.namePt).name));
    3357              :     }
    3358            1 :     if (ratchet.tariffIndx != curTariff) {
    3359            0 :         ShowWarningError(state, "UtilityCost:Tariff Debugging issue. Ratchet index does not match tariff index.");
    3360            0 :         ShowContinueError(state, format("   Between: {}", tariff.tariffName));
    3361            0 :         ShowContinueError(state, format("       And: {}", s_econ->tariff(ratchet.tariffIndx).tariffName));
    3362              :     }
    3363              :     // data from the Ratchet
    3364            1 :     baselineVals = s_econ->econVar(ratchet.baselinePt).values;
    3365            1 :     adjustmentVals = s_econ->econVar(ratchet.adjustmentPt).values;
    3366              :     // determine if multiplier should be based on variable or value
    3367            1 :     if (ratchet.multiplierPt != 0) {
    3368            0 :         multiplierVals = s_econ->econVar(ratchet.multiplierPt).values;
    3369              :     } else {
    3370            1 :         multiplierVals = ratchet.multiplierVal;
    3371              :     }
    3372              :     // determine if offset should be based on variable or value
    3373            1 :     if (ratchet.offsetPt != 0) {
    3374            0 :         offsetVals = s_econ->econVar(ratchet.offsetPt).values;
    3375              :     } else {
    3376            1 :         offsetVals = ratchet.offsetVal;
    3377              :     }
    3378              :     // find proper season from mask
    3379            1 :     if (ratchet.seasonFrom == Season::Summer) {
    3380            1 :         seasonFromMask = s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values;
    3381            1 :         isMonthly = false;
    3382            0 :     } else if (ratchet.seasonFrom == Season::Winter) {
    3383            0 :         seasonFromMask = s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values;
    3384            0 :         isMonthly = false;
    3385            0 :     } else if (ratchet.seasonFrom == Season::Spring) {
    3386            0 :         seasonFromMask = s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values;
    3387            0 :         isMonthly = false;
    3388            0 :     } else if (ratchet.seasonFrom == Season::Fall) {
    3389            0 :         seasonFromMask = s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values;
    3390            0 :         isMonthly = false;
    3391            0 :     } else if (ratchet.seasonFrom == Season::Annual) {
    3392            0 :         seasonFromMask = 1.0; // all months are 1
    3393            0 :         isMonthly = false;
    3394            0 :     } else if (ratchet.seasonFrom == Season::Monthly) {
    3395            0 :         seasonFromMask = 1.0; // all months are 1
    3396            0 :         isMonthly = true;
    3397              :     } else {
    3398            0 :         assert(false);
    3399              :     }
    3400              : 
    3401              :     // find proper season to mask
    3402            1 :     if (ratchet.seasonTo == Season::Summer) {
    3403            0 :         seasonToMask = s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values;
    3404            1 :     } else if (ratchet.seasonTo == Season::Winter) {
    3405            0 :         seasonToMask = s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values;
    3406            1 :     } else if (ratchet.seasonTo == Season::Spring) {
    3407            0 :         seasonToMask = s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values;
    3408            1 :     } else if (ratchet.seasonTo == Season::Fall) {
    3409            0 :         seasonToMask = s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values;
    3410            1 :     } else if (ratchet.seasonTo == Season::Annual) {
    3411            1 :         seasonToMask = 1.0; // all months are 1
    3412              :     }
    3413              :     // finally perform calculations
    3414            1 :     if (isMonthly) {
    3415            0 :         adjSeasonal = adjustmentVals;
    3416              :     } else {
    3417            1 :         Real64 maximumVal = -HUGE_(Real64());
    3418           13 :         for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3419           12 :             if (seasonFromMask(iMonth) == 1) {
    3420            0 :                 if (adjustmentVals(iMonth) > maximumVal) {
    3421            0 :                     maximumVal = adjustmentVals(iMonth);
    3422              :                 }
    3423              :             }
    3424              :         }
    3425            1 :         adjSeasonal = maximumVal;
    3426              :     }
    3427           13 :     for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3428              :         // calculate adjusted peak value after offset and multiplier
    3429           12 :         adjPeak(iMonth) = (adjSeasonal(iMonth) + offsetVals(iMonth)) * multiplierVals(iMonth);
    3430              :         // the maximum of the adjustment and the baseline
    3431           12 :         if (adjPeak(iMonth) > baselineVals(iMonth)) {
    3432            0 :             maxAdjBase(iMonth) = adjPeak(iMonth);
    3433              :         } else {
    3434           12 :             maxAdjBase(iMonth) = baselineVals(iMonth);
    3435              :         }
    3436              :     }
    3437           13 :     for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3438           12 :         if (seasonToMask(iMonth) == 1) {
    3439           12 :             finalResult(iMonth) = maxAdjBase(iMonth);
    3440              :         } else {
    3441            0 :             finalResult(iMonth) = baselineVals(iMonth);
    3442              :         }
    3443              :     }
    3444              :     // store the cost in the name of the variable
    3445            1 :     s_econ->econVar(usingVariable).values = finalResult;
    3446              :     // set the flag that it has been evaluated so it won't be evaluated multiple times
    3447            1 :     s_econ->econVar(usingVariable).isEvaluated = true;
    3448            1 : }
    3449              : 
    3450          215 : void evaluateQualify(EnergyPlusData &state, int const usingVariable)
    3451              : {
    3452              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3453              :     //    DATE WRITTEN   July 2004
    3454              : 
    3455          215 :     Array1D<Real64> sourceVals(NumMonths);
    3456          215 :     Array1D<Real64> thresholdVals(NumMonths);
    3457          215 :     Array1D_int monthsQualify(NumMonths);
    3458          215 :     Array1D<Real64> seasonMask(NumMonths);
    3459              :     int adjNumberOfMonths;
    3460              :     bool isQualified;
    3461              : 
    3462          215 :     auto &s_econ = state.dataEconTariff;
    3463          215 :     auto &econVar = s_econ->econVar(usingVariable);
    3464              : 
    3465          215 :     int curTariff = econVar.tariffIndx;
    3466          215 :     auto &tariff = s_econ->tariff(curTariff);
    3467          215 :     int indexInQual = econVar.index;
    3468          215 :     auto const &qualify = s_econ->qualify(indexInQual);
    3469              :     // check the tariff - make sure they match
    3470          215 :     if (qualify.namePt != usingVariable) {
    3471            0 :         ShowWarningError(state, "UtilityCost:Tariff Debugging issue. Qualify index does not match variable pointer.");
    3472            0 :         ShowContinueError(state, format("   Between: {}", econVar.name));
    3473            0 :         ShowContinueError(state, format("       And: {}", s_econ->econVar(qualify.namePt).name));
    3474              :     }
    3475          215 :     if (qualify.tariffIndx != curTariff) {
    3476            0 :         ShowWarningError(state, "UtilityCost:Tariff Debugging issue. Qualify index does not match tariff index.");
    3477            0 :         ShowContinueError(state, format("   Between: {}", tariff.tariffName));
    3478            0 :         ShowContinueError(state, format("       And: {}", s_econ->tariff(qualify.tariffIndx).tariffName));
    3479              :     }
    3480              :     // data from the Qualify
    3481          215 :     sourceVals = s_econ->econVar(qualify.sourcePt).values;
    3482          215 :     bool curIsMaximum = qualify.isMaximum;
    3483          215 :     bool curIsConsecutive = qualify.isConsecutive;
    3484          215 :     int curNumberOfMonths = qualify.numberOfMonths;
    3485              :     // determine if threshold should be based on variable or value
    3486          215 :     if (qualify.thresholdPt != 0) {
    3487            0 :         thresholdVals = s_econ->econVar(qualify.thresholdPt).values;
    3488              :     } else {
    3489          215 :         thresholdVals = qualify.thresholdVal;
    3490              :     }
    3491              :     // find proper season mask
    3492              : 
    3493          215 :     if (qualify.season == Season::Summer) {
    3494            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values;
    3495          215 :     } else if (qualify.season == Season::Winter) {
    3496            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values;
    3497          215 :     } else if (qualify.season == Season::Spring) {
    3498            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values;
    3499          215 :     } else if (qualify.season == Season::Fall) {
    3500            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values;
    3501          215 :     } else if (qualify.season == Season::Annual) {
    3502          215 :         seasonMask = 1.0; // all months are 1
    3503              :     }
    3504              : 
    3505              :     // any months with no energy use are excluded from the qualification process
    3506         2795 :     for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3507         2580 :         if (s_econ->econVar(tariff.natives[(int)Native::TotalEnergy]).values(iMonth) == 0) {
    3508         2580 :             seasonMask(iMonth) = 0.0;
    3509              :         }
    3510              :     }
    3511              :     // finally perform calculations
    3512              :     // loop through the months
    3513          215 :     int monthsInSeason = 0;
    3514         2795 :     for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3515         2580 :         if (seasonMask(iMonth) == 1) {
    3516            0 :             ++monthsInSeason;
    3517              :             // use threshold as maximum or minimum
    3518            0 :             if (curIsMaximum) {
    3519            0 :                 if (sourceVals(iMonth) > thresholdVals(iMonth)) {
    3520            0 :                     monthsQualify(iMonth) = 0; // greater than maximum threshold so it is not qualified
    3521              :                 } else {
    3522            0 :                     monthsQualify(iMonth) = 1; // less than maximum threshold so it is qualified
    3523              :                 }
    3524              :             } else {
    3525            0 :                 if (sourceVals(iMonth) < thresholdVals(iMonth)) {
    3526            0 :                     monthsQualify(iMonth) = 0; // less than minimum threshold so it is not qualified
    3527              :                 } else {
    3528            0 :                     monthsQualify(iMonth) = 1; // greater than minimum threshold so it is qualified
    3529              :                 }
    3530              :             }
    3531              :         } else {
    3532         2580 :             monthsQualify(iMonth) = -1; // flag that indicates not part of the season
    3533              :         }
    3534              :     }
    3535              :     // see if the number of months is longer then the number of months and adjust
    3536          215 :     if (curNumberOfMonths > monthsInSeason) {
    3537          215 :         adjNumberOfMonths = monthsInSeason;
    3538              :     } else {
    3539            0 :         adjNumberOfMonths = curNumberOfMonths;
    3540              :     }
    3541              :     // now that each month is qualified or not, depending on the type of test see if the entire qualify pass or not
    3542          215 :     int cntAllQualMonths = 0;
    3543          215 :     int cntConsecQualMonths = 0;
    3544          215 :     int maxConsecQualMonths = 0;
    3545         2795 :     for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3546              :         {
    3547         2580 :             int const SELECT_CASE_var(monthsQualify(iMonth));
    3548         2580 :             if (SELECT_CASE_var == 1) { // qualified
    3549            0 :                 ++cntAllQualMonths;
    3550            0 :                 ++cntConsecQualMonths;
    3551              :                 // see if the count is greater then the previous count and if it is make it the new count
    3552            0 :                 if (cntConsecQualMonths > maxConsecQualMonths) {
    3553            0 :                     maxConsecQualMonths = cntConsecQualMonths;
    3554              :                 }
    3555         2580 :             } else if (SELECT_CASE_var == 0) { // not qualified
    3556              :                 // reset the counter on consecutive months
    3557            0 :                 cntConsecQualMonths = 0;
    3558              :             }
    3559              :         }
    3560              :     }
    3561              :     // if test is for consecutive months
    3562          215 :     if (curIsConsecutive) {
    3563            0 :         if (maxConsecQualMonths >= adjNumberOfMonths) {
    3564            0 :             isQualified = true;
    3565              :         } else {
    3566            0 :             isQualified = false;
    3567              :         }
    3568              :     } else { // count not consecutive
    3569          215 :         if (cntAllQualMonths >= adjNumberOfMonths) {
    3570          215 :             isQualified = true;
    3571              :         } else {
    3572            0 :             isQualified = false;
    3573              :         }
    3574              :     }
    3575              :     // now update the tariff level qualifier - only update if the tariff is still qualified
    3576              :     // and the current qualifier fails.
    3577          215 :     if (tariff.isQualified) {
    3578          215 :         if (!isQualified) {
    3579            0 :             tariff.isQualified = false;
    3580            0 :             tariff.ptDisqualifier = usingVariable;
    3581              :         }
    3582              :     }
    3583              :     // store the cost in the name of the variable
    3584          215 :     econVar.values = monthsQualify;
    3585              :     // set the flag that it has been evaluated so it won't be evaluated multiple times
    3586          215 :     econVar.isEvaluated = true;
    3587          215 : }
    3588              : 
    3589          298 : void addMonthlyCharge(EnergyPlusData &state, int const usingVariable)
    3590              : {
    3591              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3592              :     //    DATE WRITTEN   July 2004
    3593              : 
    3594              :     //    Include the monthly charges in the calculations
    3595              : 
    3596          298 :     auto &s_econ = state.dataEconTariff;
    3597          298 :     int curTariff = s_econ->econVar(usingVariable).tariffIndx;
    3598          298 :     auto const &tariff = s_econ->tariff(curTariff);
    3599              :     // check the tariff - make sure they match
    3600          298 :     if (tariff.cats[(int)Cat::ServiceCharges] != usingVariable) {
    3601            0 :         ShowWarningError(state, "UtilityCost:Tariff Debugging issue. Tariff index for service charge does not match variable pointer.");
    3602            0 :         ShowContinueError(state, format("   Between: {}", tariff.tariffName));
    3603            0 :         ShowContinueError(state, format("       And: {}", s_econ->tariff(tariff.cats[(int)Cat::ServiceCharges]).tariffName));
    3604              :     }
    3605          298 :     if (tariff.monthChgPt != 0) {
    3606            1 :         s_econ->econVar(usingVariable).values += s_econ->econVar(tariff.monthChgPt).values;
    3607              :     } else {
    3608          297 :         s_econ->econVar(usingVariable).values += tariff.monthChgVal;
    3609              :     }
    3610              :     // zero out months with no energy consumption
    3611              :     // curTotalEnergy = tariff.nativeTotalEnergy
    3612              :     // DO iMonth = 1, NumMonths
    3613              :     //  IF (s_econ->econVar(curTotalEnergy)%values(iMonth) .EQ. 0) THEN
    3614              :     //    s_econ->econVar(usingVariable)%values(iMonth) = 0
    3615              :     //  END IF
    3616              :     // END DO
    3617          298 : }
    3618              : 
    3619          298 : void checkMinimumMonthlyCharge(EnergyPlusData &state, int const curTariff)
    3620              : {
    3621              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3622              :     //    DATE WRITTEN   August 2008
    3623              : 
    3624              :     //    Check if the total is as big as the minimum monthly charge
    3625              : 
    3626          298 :     auto &s_econ = state.dataEconTariff;
    3627          298 :     auto const &tariff = s_econ->tariff(curTariff);
    3628              : 
    3629          298 :     int totalVar = tariff.cats[(int)Cat::Total];
    3630          298 :     int minMonVar = tariff.minMonthChgPt;
    3631              :     // if a variable is defined use that
    3632          298 :     if (minMonVar != 0) {
    3633            0 :         for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3634            0 :             if (s_econ->econVar(totalVar).values(iMonth) < s_econ->econVar(minMonVar).values(iMonth)) {
    3635            0 :                 s_econ->econVar(totalVar).values(iMonth) = s_econ->econVar(minMonVar).values(iMonth);
    3636              :             }
    3637              :         }
    3638              :     } else { // use the constant value
    3639         3874 :         for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3640         3576 :             if (s_econ->econVar(totalVar).values(iMonth) < tariff.minMonthChgVal) {
    3641           24 :                 s_econ->econVar(totalVar).values(iMonth) = tariff.minMonthChgVal;
    3642              :             }
    3643              :         }
    3644              :     }
    3645          298 : }
    3646              : 
    3647          100 : void setNativeVariables(EnergyPlusData &state)
    3648              : {
    3649              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3650              :     //    DATE WRITTEN   July 2004
    3651              : 
    3652              :     //    Set up the "built in" i.e. native variables that hold
    3653              :     //    the energy and demand from the simulation.
    3654              : 
    3655          100 :     auto &s_econ = state.dataEconTariff;
    3656              : 
    3657          100 :     Array1D<Real64> monthVal(NumMonths);
    3658          100 :     Real64 bigNumber(0.0); // Autodesk Value not used but suppresses warning about HUGE_() call
    3659              : 
    3660          100 :     bigNumber = HUGE_(bigNumber);
    3661          398 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    3662          298 :         auto &tariff = s_econ->tariff(iTariff);
    3663              :         // nativeTotalEnergy
    3664          298 :         monthVal = 0.0;
    3665         3874 :         for (int kMonth = 1; kMonth <= NumMonths; ++kMonth) {
    3666        21456 :             for (int jPeriod = 0; jPeriod < (int)Period::Num; ++jPeriod) {
    3667        17880 :                 monthVal(kMonth) += tariff.gatherEnergy(kMonth)[jPeriod];
    3668              :             }
    3669              :         }
    3670          298 :         s_econ->econVar(tariff.natives[(int)Native::TotalEnergy]).values = monthVal;
    3671              :         // nativeTotalDemand
    3672          298 :         monthVal = -bigNumber;
    3673         3874 :         for (int kMonth = 1; kMonth <= NumMonths; ++kMonth) {
    3674        21456 :             for (int jPeriod = 0; jPeriod < (int)Period::Num; ++jPeriod) {
    3675        17880 :                 if (tariff.gatherDemand(kMonth)[jPeriod] > monthVal(kMonth)) {
    3676         3588 :                     monthVal(kMonth) = tariff.gatherDemand(kMonth)[jPeriod];
    3677              :                 }
    3678              :             }
    3679              :         }
    3680              :         // if no maximum was set just set to zero
    3681         3874 :         for (int kMonth = 1; kMonth <= NumMonths; ++kMonth) {
    3682         3576 :             if (monthVal(kMonth) == -bigNumber) {
    3683            0 :                 monthVal(kMonth) = 0.0;
    3684              :             }
    3685              :         }
    3686          298 :         s_econ->econVar(tariff.natives[(int)Native::TotalDemand]).values = monthVal;
    3687         3874 :         for (int kMonth = 1; kMonth <= NumMonths; ++kMonth) {
    3688              :             // nativePeakEnergy
    3689         3576 :             s_econ->econVar(tariff.natives[(int)Native::PeakEnergy]).values(kMonth) = tariff.gatherEnergy(kMonth)[(int)Period::Peak];
    3690              :             // nativePeakDemand
    3691         3576 :             s_econ->econVar(tariff.natives[(int)Native::PeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3692              :             // nativeShoulderEnergy
    3693         3576 :             s_econ->econVar(tariff.natives[(int)Native::ShoulderEnergy]).values(kMonth) = tariff.gatherEnergy(kMonth)[(int)Period::Shoulder];
    3694              :             // nativeShoulderDemand
    3695         3576 :             s_econ->econVar(tariff.natives[(int)Native::ShoulderDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Shoulder];
    3696              :             // nativeOffPeakEnergy
    3697         3576 :             s_econ->econVar(tariff.natives[(int)Native::OffPeakEnergy]).values(kMonth) = tariff.gatherEnergy(kMonth)[(int)Period::OffPeak];
    3698              :             // nativeOffPeakDemand
    3699         3576 :             s_econ->econVar(tariff.natives[(int)Native::OffPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::OffPeak];
    3700              :             // nativeMidPeakEnergy
    3701         3576 :             s_econ->econVar(tariff.natives[(int)Native::MidPeakEnergy]).values(kMonth) = tariff.gatherEnergy(kMonth)[(int)Period::MidPeak];
    3702              :             // nativeMidPeakDemand
    3703         3576 :             s_econ->econVar(tariff.natives[(int)Native::MidPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::MidPeak];
    3704              :             // nativePeakExceedsOffPeak
    3705         3576 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak] - tariff.gatherDemand(kMonth)[(int)Period::OffPeak];
    3706         3576 :             if (monthVal(kMonth) > 0) {
    3707           12 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsOffPeak]).values(kMonth) = monthVal(kMonth);
    3708              :             } else {
    3709         3564 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsOffPeak]).values(kMonth) = 0.0;
    3710              :             }
    3711              :             // nativeOffPeakExceedsPeak
    3712         3576 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::OffPeak] - tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3713         3576 :             if (monthVal(kMonth) > 0) {
    3714            0 :                 s_econ->econVar(tariff.natives[(int)Native::OffPeakExceedsPeak]).values(kMonth) = monthVal(kMonth);
    3715              :             } else {
    3716         3576 :                 s_econ->econVar(tariff.natives[(int)Native::OffPeakExceedsPeak]).values(kMonth) = 0.0;
    3717              :             }
    3718              :             // nativePeakExceedsMidPeak
    3719         3576 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak] - tariff.gatherDemand(kMonth)[(int)Period::MidPeak];
    3720         3576 :             if (monthVal(kMonth) > 0) {
    3721           12 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsMidPeak]).values(kMonth) = monthVal(kMonth);
    3722              :             } else {
    3723         3564 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsOffPeak]).values(kMonth) = 0.0;
    3724              :             }
    3725              :             // nativeMidPeakExceedsPeak
    3726         3576 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::MidPeak] - tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3727         3576 :             if (monthVal(kMonth) > 0) {
    3728            0 :                 s_econ->econVar(tariff.natives[(int)Native::MidPeakExceedsPeak]).values(kMonth) = monthVal(kMonth);
    3729              :             } else {
    3730         3576 :                 s_econ->econVar(tariff.natives[(int)Native::MidPeakExceedsPeak]).values(kMonth) = 0.0;
    3731              :             }
    3732              :             // nativePeakExceedsShoulder
    3733         3576 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak] - tariff.gatherDemand(kMonth)[(int)Period::Shoulder];
    3734         3576 :             if (monthVal(kMonth) > 0) {
    3735           12 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsShoulder]).values(kMonth) = monthVal(kMonth);
    3736              :             } else {
    3737         3564 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsShoulder]).values(kMonth) = 0.0;
    3738              :             }
    3739              :             // nativeShoulderExceedsPeak
    3740         3576 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Shoulder] - tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3741         3576 :             if (monthVal(kMonth) > 0) {
    3742            0 :                 s_econ->econVar(tariff.natives[(int)Native::ShoulderExceedsPeak]).values(kMonth) = monthVal(kMonth);
    3743              :             } else {
    3744         3576 :                 s_econ->econVar(tariff.natives[(int)Native::ShoulderExceedsPeak]).values(kMonth) = 0.0;
    3745              :             }
    3746              :             // nativeIsWinter
    3747              :             // nativeIsNotWinter
    3748         3576 :             if (tariff.seasonForMonth(kMonth) == Season::Winter) {
    3749           12 :                 s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values(kMonth) = 1.0;
    3750           12 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotWinter]).values(kMonth) = 0.0;
    3751              :             } else {
    3752         3564 :                 s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values(kMonth) = 0.0;
    3753         3564 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotWinter]).values(kMonth) = 1.0;
    3754              :             }
    3755              :             // nativeIsSpring
    3756              :             // nativeIsNotSpring
    3757         3576 :             if (tariff.seasonForMonth(kMonth) == Season::Spring) {
    3758            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values(kMonth) = 1.0;
    3759            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotSpring]).values(kMonth) = 0.0;
    3760              :             } else {
    3761         3576 :                 s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values(kMonth) = 0.0;
    3762         3576 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotSpring]).values(kMonth) = 1.0;
    3763              :             }
    3764              :             // nativeIsSummer
    3765              :             // nativeIsNotSummer
    3766         3576 :             if (tariff.seasonForMonth(kMonth) == Season::Summer) {
    3767            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values(kMonth) = 1.0;
    3768            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotSummer]).values(kMonth) = 0.0;
    3769              :             } else {
    3770         3576 :                 s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values(kMonth) = 0.0;
    3771         3576 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotSummer]).values(kMonth) = 1.0;
    3772              :             }
    3773              :             // nativeIsAutumn
    3774              :             // nativeIsNotAutumn
    3775         3576 :             if (tariff.seasonForMonth(kMonth) == Season::Fall) {
    3776            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values(kMonth) = 1.0;
    3777            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotAutumn]).values(kMonth) = 0.0;
    3778              :             } else {
    3779         3576 :                 s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values(kMonth) = 0.0;
    3780         3576 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotAutumn]).values(kMonth) = 1.0;
    3781              :             }
    3782              :             // nativePeakAndShoulderEnergy
    3783         3576 :             s_econ->econVar(tariff.natives[(int)Native::PeakAndShoulderEnergy]).values(kMonth) =
    3784         3576 :                 tariff.gatherEnergy(kMonth)[(int)Period::Peak] + tariff.gatherEnergy(kMonth)[(int)Period::Shoulder];
    3785              :             // nativePeakAndShoulderDemand
    3786         3576 :             if (tariff.gatherDemand(kMonth)[(int)Period::Peak] > tariff.gatherDemand(kMonth)[(int)Period::Shoulder]) {
    3787           12 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndShoulderDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3788              :             } else {
    3789         3564 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndShoulderDemand]).values(kMonth) =
    3790         3564 :                     tariff.gatherDemand(kMonth)[(int)Period::Shoulder];
    3791              :             }
    3792              :             // nativePeakAndMidPeakEnergy
    3793         3576 :             s_econ->econVar(tariff.natives[(int)Native::PeakAndMidPeakEnergy]).values(kMonth) =
    3794         3576 :                 tariff.gatherEnergy(kMonth)[(int)Period::Peak] + tariff.gatherEnergy(kMonth)[(int)Period::MidPeak];
    3795              :             // nativePeakAndMidPeakDemand
    3796         3576 :             if (tariff.gatherDemand(kMonth)[(int)Period::Peak] > tariff.gatherDemand(kMonth)[(int)Period::MidPeak]) {
    3797           12 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndMidPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3798              :             } else {
    3799         3564 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndMidPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::MidPeak];
    3800              :             }
    3801              :             // nativeShoulderAndOffPeakEnergy
    3802         3576 :             s_econ->econVar(tariff.natives[(int)Native::ShoulderAndOffPeakEnergy]).values(kMonth) =
    3803         3576 :                 tariff.gatherEnergy(kMonth)[(int)Period::Shoulder] + tariff.gatherEnergy(kMonth)[(int)Period::OffPeak];
    3804              :             // nativeShoulderAndOffPeakDemand
    3805         3576 :             if (tariff.gatherDemand(kMonth)[(int)Period::Shoulder] > tariff.gatherDemand(kMonth)[(int)Period::OffPeak]) {
    3806            0 :                 s_econ->econVar(tariff.natives[(int)Native::ShoulderAndOffPeakDemand]).values(kMonth) =
    3807            0 :                     tariff.gatherDemand(kMonth)[(int)Period::Shoulder];
    3808              :             } else {
    3809         3576 :                 s_econ->econVar(tariff.natives[(int)Native::ShoulderAndOffPeakDemand]).values(kMonth) =
    3810         3576 :                     tariff.gatherDemand(kMonth)[(int)Period::OffPeak];
    3811              :             }
    3812              :             // nativePeakAndOffPeakEnergy
    3813         3576 :             s_econ->econVar(tariff.natives[(int)Native::PeakAndOffPeakEnergy]).values(kMonth) =
    3814         3576 :                 tariff.gatherEnergy(kMonth)[(int)Period::Peak] + tariff.gatherEnergy(kMonth)[(int)Period::OffPeak];
    3815              :             // nativePeakAndOffPeakDemand
    3816         3576 :             if (tariff.gatherDemand(kMonth)[(int)Period::Peak] > tariff.gatherDemand(kMonth)[(int)Period::OffPeak]) {
    3817           12 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndOffPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3818              :             } else {
    3819         3564 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndOffPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::OffPeak];
    3820              :             }
    3821              :             // nativeRealTimePriceCosts
    3822         3576 :             s_econ->econVar(tariff.natives[(int)Native::RealTimePriceCosts]).values(kMonth) = tariff.RTPcost(kMonth);
    3823              :             // nativeAboveCustomerBaseCosts
    3824         3576 :             s_econ->econVar(tariff.natives[(int)Native::AboveCustomerBaseCosts]).values(kMonth) = tariff.RTPaboveBaseCost(kMonth);
    3825              :             // nativeBelowCustomerBaseCosts
    3826         3576 :             s_econ->econVar(tariff.natives[(int)Native::BelowCustomerBaseCosts]).values(kMonth) = tariff.RTPbelowBaseCost(kMonth);
    3827              :             // nativeAboveCustomerBaseEnergy
    3828         3576 :             s_econ->econVar(tariff.natives[(int)Native::AboveCustomerBaseEnergy]).values(kMonth) = tariff.RTPaboveBaseEnergy(kMonth);
    3829              :             // nativeBelowCustomerBaseEnergy
    3830         3576 :             s_econ->econVar(tariff.natives[(int)Native::BelowCustomerBaseEnergy]).values(kMonth) = tariff.RTPbelowBaseEnergy(kMonth);
    3831              :         }
    3832              :     }
    3833          100 : }
    3834              : 
    3835          100 : void LEEDtariffReporting(EnergyPlusData &state)
    3836              : {
    3837              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3838              :     //    DATE WRITTEN   October 2012
    3839              : 
    3840              :     //    Write the economic results for LEED reporting
    3841              : 
    3842              :     Real64 elecTotalEne;
    3843              :     Real64 gasTotalEne;
    3844              :     Real64 distCoolTotalEne;
    3845              :     Real64 distHeatWaterTotalEne;
    3846              :     Real64 distHeatSteamTotalEne;
    3847              :     Real64 otherTotalEne;
    3848              :     Real64 elecTotalCost;
    3849              :     Real64 gasTotalCost;
    3850              :     Real64 otherTotalCost;
    3851              :     Real64 distCoolTotalCost;
    3852              :     Real64 distHeatWaterTotalCost;
    3853              :     Real64 distHeatSteamTotalCost;
    3854              :     Real64 allTotalCost;
    3855              :     EconConv elecUnits;
    3856              :     EconConv gasUnits;
    3857              :     EconConv distCoolUnits;
    3858              :     EconConv distHeatWaterUnits;
    3859              :     EconConv distHeatSteamUnits;
    3860              :     EconConv othrUnits;
    3861              :     DemandWindow gasDemWindowUnits;
    3862              :     DemandWindow distCoolDemWindowUnits;
    3863              :     DemandWindow distHeatWaterDemWindowUnits;
    3864              :     DemandWindow distHeatSteamDemWindowUnits;
    3865              :     DemandWindow othrDemWindowUnits;
    3866              : 
    3867          100 :     auto &s_orp = state.dataOutRptPredefined;
    3868              : 
    3869          100 :     auto &s_econ = state.dataEconTariff;
    3870              : 
    3871          100 :     if (s_econ->numTariff > 0) {
    3872          200 :         int distCoolFacilMeter = GetMeterIndex(state, "DISTRICTCOOLING:FACILITY");
    3873          200 :         int distHeatWaterFacilMeter = GetMeterIndex(state, "DISTRICTHEATINGWATER:FACILITY");
    3874          100 :         int distHeatSteamFacilMeter = GetMeterIndex(state, "DISTRICTHEATINGSTEAM:FACILITY");
    3875          100 :         elecTotalEne = 0.0;
    3876          100 :         gasTotalEne = 0.0;
    3877          100 :         distCoolTotalEne = 0.0;
    3878          100 :         distHeatWaterTotalEne = 0.0;
    3879          100 :         distHeatSteamTotalEne = 0.0;
    3880          100 :         otherTotalEne = 0.0;
    3881          100 :         elecTotalCost = 0.0;
    3882          100 :         gasTotalCost = 0.0;
    3883          100 :         distCoolTotalCost = 0.0;
    3884          100 :         distHeatWaterTotalCost = 0.0;
    3885          100 :         distHeatSteamTotalCost = 0.0;
    3886          100 :         otherTotalCost = 0.0;
    3887          100 :         allTotalCost = 0.0;
    3888          100 :         elecUnits = EconConv::USERDEF;
    3889          100 :         gasUnits = EconConv::USERDEF;
    3890          100 :         distCoolUnits = EconConv::USERDEF;
    3891          100 :         distHeatWaterUnits = EconConv::USERDEF;
    3892          100 :         distHeatSteamUnits = EconConv::USERDEF;
    3893          100 :         othrUnits = EconConv::USERDEF;
    3894          100 :         gasDemWindowUnits = DemandWindow::Invalid;
    3895          100 :         othrDemWindowUnits = DemandWindow::Invalid;
    3896          200 :         std::string elecTariffNames = "";
    3897          200 :         std::string gasTariffNames = "";
    3898          200 :         std::string distCoolTariffNames = "";
    3899          200 :         std::string distHeatWaterTariffNames = "";
    3900          200 :         std::string distHeatSteamTariffNames = "";
    3901          100 :         std::string othrTariffNames = "";
    3902          398 :         for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    3903          298 :             auto &tariff = s_econ->tariff(iTariff);
    3904          298 :             if (tariff.isSelected) {
    3905          187 :                 allTotalCost += tariff.totalAnnualCost;
    3906          187 :                 if (tariff.kindMtr == MeterType::ElecSimple || tariff.kindMtr == MeterType::ElecProduced ||
    3907           91 :                     tariff.kindMtr == MeterType::ElecPurchased || tariff.kindMtr == MeterType::ElecSurplusSold ||
    3908           89 :                     tariff.kindMtr == MeterType::ElecNet) {
    3909          101 :                     if (tariff.totalAnnualEnergy > elecTotalEne) {
    3910            1 :                         elecTotalEne = tariff.totalAnnualEnergy;
    3911              :                     }
    3912          101 :                     elecTotalCost += tariff.totalAnnualCost;
    3913          101 :                     elecTariffNames += ' ' + tariff.tariffName;
    3914          101 :                     elecUnits = tariff.convChoice;
    3915           86 :                 } else if (tariff.kindMtr == MeterType::Gas) {
    3916           84 :                     if (tariff.totalAnnualEnergy > gasTotalEne) {
    3917            0 :                         gasTotalEne = tariff.totalAnnualEnergy;
    3918              :                     }
    3919           84 :                     gasTotalCost += tariff.totalAnnualCost;
    3920           84 :                     gasTariffNames += ' ' + tariff.tariffName;
    3921           84 :                     gasUnits = tariff.convChoice;
    3922           84 :                     gasDemWindowUnits = tariff.demandWindow;
    3923            2 :                 } else if (tariff.reportMeterIndx == distCoolFacilMeter) {
    3924            1 :                     if (tariff.totalAnnualEnergy > distCoolTotalEne) {
    3925            0 :                         distCoolTotalEne = tariff.totalAnnualEnergy;
    3926              :                     }
    3927            1 :                     distCoolTotalCost += tariff.totalAnnualCost;
    3928            1 :                     distCoolTariffNames += ' ' + tariff.tariffName;
    3929            1 :                     distCoolUnits = tariff.convChoice;
    3930            1 :                     distCoolDemWindowUnits = tariff.demandWindow;
    3931            1 :                 } else if (tariff.reportMeterIndx == distHeatWaterFacilMeter) {
    3932            0 :                     if (tariff.totalAnnualEnergy > distHeatWaterTotalEne) {
    3933            0 :                         distHeatWaterTotalEne = tariff.totalAnnualEnergy;
    3934              :                     }
    3935            0 :                     distHeatWaterTotalCost += tariff.totalAnnualCost;
    3936            0 :                     distHeatWaterTariffNames += ' ' + tariff.tariffName;
    3937            0 :                     distHeatWaterUnits = tariff.convChoice;
    3938            0 :                     distHeatWaterDemWindowUnits = tariff.demandWindow;
    3939            1 :                 } else if (tariff.reportMeterIndx == distHeatSteamFacilMeter) {
    3940            0 :                     if (tariff.totalAnnualEnergy > distHeatSteamTotalEne) {
    3941            0 :                         distHeatSteamTotalEne = tariff.totalAnnualEnergy;
    3942              :                     }
    3943            0 :                     distHeatSteamTotalCost += tariff.totalAnnualCost;
    3944            0 :                     distHeatSteamTariffNames += ' ' + tariff.tariffName;
    3945            0 :                     distHeatSteamUnits = tariff.convChoice;
    3946            0 :                     distHeatSteamDemWindowUnits = tariff.demandWindow;
    3947            1 :                 } else if (tariff.kindMtr != MeterType::Water) {
    3948            0 :                     if (tariff.totalAnnualEnergy > otherTotalEne) {
    3949            0 :                         otherTotalEne = tariff.totalAnnualEnergy;
    3950              :                     }
    3951            0 :                     otherTotalCost += tariff.totalAnnualCost;
    3952            0 :                     othrTariffNames += ' ' + tariff.tariffName;
    3953            0 :                     othrUnits = tariff.convChoice;
    3954            0 :                     othrDemWindowUnits = tariff.demandWindow;
    3955              :                 } else {
    3956              :                 }
    3957              :             }
    3958              :         }
    3959              :         // names of the rates
    3960          100 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "Electricity", elecTariffNames);
    3961          100 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "Natural Gas", gasTariffNames);
    3962          100 :         if (distCoolTotalEne != 0) {
    3963            0 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "District Cooling", distCoolTariffNames);
    3964              :         }
    3965          100 :         if (distHeatWaterTotalEne != 0) {
    3966            0 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "District Heating Water", distHeatWaterTariffNames);
    3967              :         }
    3968          100 :         if (distHeatSteamTotalEne != 0) {
    3969            0 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "District Heating Steam", distHeatSteamTariffNames);
    3970              :         }
    3971          100 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "Other", othrTariffNames);
    3972              :         // virtual rate
    3973          100 :         if (elecTotalEne != 0) {
    3974            1 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsVirt, "Electricity", elecTotalCost / elecTotalEne, 3);
    3975              :         }
    3976          100 :         if (gasTotalEne != 0) {
    3977            0 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsVirt, "Natural Gas", gasTotalCost / gasTotalEne, 3);
    3978              :         }
    3979          100 :         if (otherTotalEne != 0) {
    3980            0 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsVirt, "Other", otherTotalCost / otherTotalEne, 3);
    3981              :         }
    3982              :         // units
    3983          100 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsEneUnt, "Electricity", format("{}", convEnergyStrings[(int)elecUnits]));
    3984          100 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsEneUnt, "Natural Gas", format("{}", convEnergyStrings[(int)gasUnits]));
    3985          100 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsEneUnt, "Other", format("{}", convEnergyStrings[(int)othrUnits]));
    3986          100 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsDemUnt, "Electricity", format("{}", convDemandStrings[(int)elecUnits]));
    3987          200 :         OutputReportPredefined::PreDefTableEntry(
    3988              :             state,
    3989          100 :             s_orp->pdchLeedEtsDemUnt,
    3990              :             "Natural Gas",
    3991          200 :             format("{}{}",
    3992          100 :                    convDemandStrings[(int)gasUnits],
    3993          100 :                    (gasDemWindowUnits == DemandWindow::Invalid) ? "" : demandWindowStrings[(int)gasDemWindowUnits]));
    3994          200 :         OutputReportPredefined::PreDefTableEntry(
    3995              :             state,
    3996          100 :             s_orp->pdchLeedEtsDemUnt,
    3997              :             "Other",
    3998          200 :             format("{}{}",
    3999          100 :                    convDemandStrings[(int)othrUnits],
    4000          100 :                    (othrDemWindowUnits == DemandWindow::Invalid) ? "" : demandWindowStrings[(int)othrDemWindowUnits]));
    4001              : 
    4002              :         // total cost
    4003          100 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEcsTotal, "Electricity", elecTotalCost, 2);
    4004          100 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEcsTotal, "Natural Gas", gasTotalCost, 2);
    4005          100 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEcsTotal, "Other", otherTotalCost, 2);
    4006              :         // show district energy if used
    4007          100 :         if (distCoolTotalEne != 0) {
    4008            0 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsVirt, "District Cooling", distCoolTotalCost / distCoolTotalEne, 3);
    4009            0 :             OutputReportPredefined::PreDefTableEntry(
    4010            0 :                 state, s_orp->pdchLeedEtsEneUnt, "District Cooling", format("{}", convEnergyStrings[(int)distCoolUnits]));
    4011            0 :             OutputReportPredefined::PreDefTableEntry(
    4012              :                 state,
    4013            0 :                 s_orp->pdchLeedEtsDemUnt,
    4014              :                 "District Cooling",
    4015            0 :                 format("{}{}",
    4016            0 :                        convDemandStrings[(int)distCoolUnits],
    4017            0 :                        (distCoolDemWindowUnits == DemandWindow::Invalid) ? "" : demandWindowStrings[(int)distCoolDemWindowUnits]));
    4018            0 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEcsTotal, "District Cooling", distCoolTotalCost, 2);
    4019              :         }
    4020          100 :         if (distHeatWaterTotalEne != 0) {
    4021            0 :             OutputReportPredefined::PreDefTableEntry(
    4022            0 :                 state, s_orp->pdchLeedEtsVirt, "District Heating Water", distHeatWaterTotalCost / distHeatWaterTotalEne, 3);
    4023            0 :             OutputReportPredefined::PreDefTableEntry(
    4024            0 :                 state, s_orp->pdchLeedEtsEneUnt, "District Heating Water", format("{}", convEnergyStrings[(int)distHeatWaterUnits]));
    4025            0 :             OutputReportPredefined::PreDefTableEntry(
    4026              :                 state,
    4027            0 :                 s_orp->pdchLeedEtsDemUnt,
    4028              :                 "District Heating Water",
    4029            0 :                 format("{}{}",
    4030            0 :                        convDemandStrings[(int)distHeatWaterUnits],
    4031            0 :                        (distHeatWaterDemWindowUnits == DemandWindow::Invalid) ? "" : demandWindowStrings[(int)distHeatWaterDemWindowUnits]));
    4032            0 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEcsTotal, "District Heating Water", distHeatWaterTotalCost, 2);
    4033              :         }
    4034          100 :         if (distHeatSteamTotalEne != 0) {
    4035            0 :             OutputReportPredefined::PreDefTableEntry(
    4036            0 :                 state, s_orp->pdchLeedEtsVirt, "District Heating Steam", distHeatSteamTotalCost / distHeatSteamTotalEne, 3);
    4037            0 :             OutputReportPredefined::PreDefTableEntry(
    4038            0 :                 state, s_orp->pdchLeedEtsEneUnt, "District Heating Steam", format("{}", convEnergyStrings[(int)distHeatSteamUnits]));
    4039            0 :             OutputReportPredefined::PreDefTableEntry(
    4040              :                 state,
    4041            0 :                 s_orp->pdchLeedEtsDemUnt,
    4042              :                 "District Heating Steam",
    4043            0 :                 format("{}{}",
    4044            0 :                        convDemandStrings[(int)distHeatSteamUnits],
    4045            0 :                        (distHeatSteamDemWindowUnits == DemandWindow::Invalid) ? "" : demandWindowStrings[(int)distHeatSteamDemWindowUnits]));
    4046            0 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEcsTotal, "District Heating Steam", distHeatSteamTotalCost, 2);
    4047              :         }
    4048              :         // save the total costs for later to compute process fraction
    4049          100 :         s_orp->LEEDelecCostTotal = elecTotalCost;
    4050          100 :         s_orp->LEEDgasCostTotal = gasTotalCost;
    4051          100 :         s_orp->LEEDothrCostTotal = distCoolTotalCost + distHeatWaterTotalCost + distHeatSteamTotalCost + otherTotalCost;
    4052          100 :         OutputReportPredefined::PreDefTableEntry(state,
    4053          100 :                                                  s_orp->pdchLeedEcsTotal,
    4054              :                                                  "Total",
    4055          100 :                                                  elecTotalCost + gasTotalCost + distCoolTotalCost + distHeatWaterTotalCost + distHeatSteamTotalCost +
    4056              :                                                      otherTotalCost,
    4057          100 :                                                  2);
    4058          100 :     }
    4059          100 : }
    4060              : 
    4061          799 : void WriteTabularTariffReports(EnergyPlusData &state)
    4062              : {
    4063              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    4064              :     //    DATE WRITTEN   July 2004
    4065              :     //    MODIFIED       January 2010, Kyle Benne
    4066              :     //                   Added SQLite output
    4067              : 
    4068              :     // all arrays are in the format: (row, column)
    4069          799 :     Array1D_string columnHead;
    4070          799 :     Array1D_int columnWidth;
    4071          799 :     Array1D_string rowHead;
    4072          799 :     Array2D_string tableBody;
    4073              :     // other local variables
    4074              :     Real64 elecTotalCost;
    4075              :     Real64 gasTotalCost;
    4076              :     Real64 otherTotalCost;
    4077              :     Real64 allTotalCost;
    4078          799 :     Real64 perAreaUnitConv(0.0);
    4079              : 
    4080          799 :     auto &s_econ = state.dataEconTariff;
    4081              : 
    4082              :     // Here to it is ready to assign ort->unitStyle_SQLite (not in SQLiteProcedures.cc)
    4083              :     // when ort->unitsStyle inputs should have been concretely processed and assigned.
    4084              :     // Included this here to make sure the units specifications are correctly updated.
    4085          799 :     if (state.dataOutRptTab->unitsStyle_SQLite == OutputReportTabular::UnitsStyle::NotFound) {
    4086            0 :         state.dataOutRptTab->unitsStyle_SQLite = state.dataOutRptTab->unitsStyle; // This is the default UseOutputControlTableStyles
    4087              :     }
    4088              : 
    4089              :     // compute floor area if no ABUPS
    4090          799 :     if (state.dataOutRptTab->buildingConditionedFloorArea == 0.0) {
    4091          123 :         OutputReportTabular::DetermineBuildingFloorArea(state);
    4092              :     }
    4093              : 
    4094          799 :     if (s_econ->numTariff > 0) {
    4095          101 :         auto &econVar = s_econ->econVar;
    4096              : 
    4097          101 :         if (state.dataOutRptTab->displayEconomicResultSummary) {
    4098           32 :             DisplayString(state, "Writing Tariff Reports");
    4099         6732 :             for (auto &e : econVar) {
    4100         6700 :                 e.isReported = false;
    4101              :             }
    4102           32 :             showWarningsBasedOnTotal(state);
    4103              :             //---------------------------------
    4104              :             // Economics Results Summary Report
    4105              :             //---------------------------------
    4106           96 :             OutputReportTabular::WriteReportHeaders(
    4107              :                 state, "Economics Results Summary Report", "Entire Facility", OutputProcessor::StoreType::Average);
    4108              : 
    4109           64 :             for (int iUnitSystem = 0; iUnitSystem <= 1; iUnitSystem++) {
    4110           64 :                 OutputReportTabular::UnitsStyle unitsStyle_cur = state.dataOutRptTab->unitsStyle;
    4111           64 :                 bool produceTabular = true;
    4112           64 :                 bool produceSQLite = false;
    4113           64 :                 if (produceDualUnitsFlags(iUnitSystem,
    4114           64 :                                           state.dataOutRptTab->unitsStyle,
    4115           64 :                                           state.dataOutRptTab->unitsStyle_SQLite,
    4116              :                                           unitsStyle_cur,
    4117              :                                           produceTabular,
    4118              :                                           produceSQLite)) {
    4119           32 :                     break;
    4120              :                 }
    4121              : 
    4122              :                 // do unit conversions if necessary
    4123           32 :                 std::string perAreaUnitName;
    4124           32 :                 if ((unitsStyle_cur == OutputReportTabular::UnitsStyle::InchPound) ||
    4125           32 :                     (unitsStyle_cur == OutputReportTabular::UnitsStyle::InchPoundExceptElectricity)) {
    4126            0 :                     int unitConvIndex = 0;
    4127            0 :                     std::string SIunit = "[~~$~~/m2]";
    4128            0 :                     OutputReportTabular::LookupSItoIP(state, SIunit, unitConvIndex, perAreaUnitName);
    4129            0 :                     perAreaUnitConv = OutputReportTabular::ConvertIP(state, unitConvIndex, 1.0);
    4130            0 :                 } else {
    4131           32 :                     perAreaUnitName = "[~~$~~/m2]";
    4132           32 :                     perAreaUnitConv = 1.0;
    4133              :                 }
    4134              : 
    4135              :                 //---- Annual Summary
    4136           32 :                 rowHead.allocate(3);
    4137           32 :                 columnHead.allocate(4);
    4138           32 :                 columnWidth.allocate(4);
    4139           32 :                 tableBody.allocate(4, 3);
    4140           32 :                 tableBody = "";
    4141           32 :                 columnHead(1) = "Electricity";
    4142           32 :                 columnHead(2) = "Natural Gas";
    4143           32 :                 columnHead(3) = "Other";
    4144           32 :                 columnHead(4) = "Total";
    4145           32 :                 rowHead(1) = "Cost [~~$~~]";
    4146           32 :                 rowHead(2) = "Cost per Total Building Area " + perAreaUnitName;
    4147           32 :                 rowHead(3) = "Cost per Net Conditioned Building Area " + perAreaUnitName;
    4148           32 :                 elecTotalCost = 0.0;
    4149           32 :                 gasTotalCost = 0.0;
    4150           32 :                 otherTotalCost = 0.0;
    4151           32 :                 allTotalCost = 0.0;
    4152          126 :                 for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4153           94 :                     auto const &tariff = s_econ->tariff(iTariff);
    4154           94 :                     if (tariff.isSelected) {
    4155           52 :                         allTotalCost += tariff.totalAnnualCost;
    4156           52 :                         if (tariff.kindMtr == MeterType::ElecSimple || tariff.kindMtr == MeterType::ElecProduced ||
    4157           24 :                             tariff.kindMtr == MeterType::ElecPurchased || tariff.kindMtr == MeterType::ElecSurplusSold ||
    4158           22 :                             tariff.kindMtr == MeterType::ElecNet) {
    4159           33 :                             elecTotalCost += tariff.totalAnnualCost;
    4160           19 :                         } else if (tariff.kindMtr == MeterType::Gas) {
    4161           18 :                             gasTotalCost += tariff.totalAnnualCost;
    4162            1 :                         } else if (tariff.kindMtr != MeterType::Water) {
    4163            0 :                             otherTotalCost += tariff.totalAnnualCost;
    4164              :                             // removed because this was confusing        columnHead(3) = tariff.reportMeter
    4165              :                         }
    4166              :                     }
    4167              :                 }
    4168           32 :                 tableBody(1, 1) = OutputReportTabular::RealToStr(elecTotalCost, 2);
    4169           32 :                 tableBody(2, 1) = OutputReportTabular::RealToStr(gasTotalCost, 2);
    4170           32 :                 tableBody(3, 1) = OutputReportTabular::RealToStr(otherTotalCost, 2);
    4171           32 :                 tableBody(4, 1) = OutputReportTabular::RealToStr(allTotalCost, 2);
    4172           32 :                 if (state.dataOutRptTab->buildingGrossFloorArea > 0.0) {
    4173           32 :                     tableBody(1, 2) =
    4174           64 :                         OutputReportTabular::RealToStr((elecTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
    4175           32 :                     tableBody(2, 2) =
    4176           64 :                         OutputReportTabular::RealToStr((gasTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
    4177           32 :                     tableBody(3, 2) =
    4178           64 :                         OutputReportTabular::RealToStr((otherTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
    4179           32 :                     tableBody(4, 2) =
    4180           64 :                         OutputReportTabular::RealToStr((allTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
    4181              :                 }
    4182           32 :                 if (state.dataOutRptTab->buildingConditionedFloorArea > 0.0) {
    4183           32 :                     tableBody(1, 3) =
    4184           64 :                         OutputReportTabular::RealToStr((elecTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
    4185           32 :                     tableBody(2, 3) =
    4186           64 :                         OutputReportTabular::RealToStr((gasTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
    4187           32 :                     tableBody(3, 3) =
    4188           64 :                         OutputReportTabular::RealToStr((otherTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
    4189           32 :                     tableBody(4, 3) =
    4190           64 :                         OutputReportTabular::RealToStr((allTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
    4191              :                 }
    4192           32 :                 columnWidth = 14; // array assignment - same for all columns
    4193           32 :                 if (produceTabular) {
    4194           32 :                     OutputReportTabular::WriteSubtitle(state, "Annual Cost");
    4195           32 :                     OutputReportTabular::WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    4196              :                 }
    4197           32 :                 if (produceSQLite) {
    4198           32 :                     if (state.dataSQLiteProcedures->sqlite) {
    4199           10 :                         state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    4200              :                             tableBody, rowHead, columnHead, "Economics Results Summary Report", "Entire Facility", "Annual Cost");
    4201              :                     }
    4202              :                 }
    4203           32 :                 if (produceTabular) {
    4204           32 :                     if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    4205            0 :                         state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    4206              :                             tableBody, rowHead, columnHead, "Economics Results Summary Report", "Entire Facility", "Annual Cost");
    4207              :                     }
    4208              :                 }
    4209           32 :                 columnHead.deallocate();
    4210           32 :                 rowHead.deallocate();
    4211           32 :                 columnWidth.deallocate();
    4212           32 :                 tableBody.deallocate();
    4213           32 :             }
    4214              :             //---- Tariff Summary
    4215           32 :             rowHead.allocate(s_econ->numTariff);
    4216           32 :             columnHead.allocate(6);
    4217           32 :             columnWidth.allocate(6);
    4218           32 :             tableBody.allocate(6, s_econ->numTariff);
    4219           32 :             tableBody = "";
    4220           32 :             columnHead(1) = "Selected";
    4221           32 :             columnHead(2) = "Qualified";
    4222           32 :             columnHead(3) = "Meter";
    4223           32 :             columnHead(4) = "Buy or Sell";
    4224           32 :             columnHead(5) = "Group";
    4225           32 :             columnHead(6) = "Annual Cost (~~$~~)";
    4226          126 :             for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4227           94 :                 auto const &tariff = s_econ->tariff(iTariff);
    4228           94 :                 rowHead(iTariff) = tariff.tariffName;
    4229           94 :                 tableBody(1, iTariff) = yesNoNames[(int)tariff.isSelected];
    4230           94 :                 tableBody(2, iTariff) = yesNoNames[(int)tariff.isQualified];
    4231              : 
    4232           94 :                 tableBody(3, iTariff) = tariff.reportMeter;
    4233              : 
    4234           94 :                 if (tariff.buyOrSell == BuySell::BuyFromUtility) {
    4235           92 :                     tableBody(4, iTariff) = "Buy";
    4236            2 :                 } else if (tariff.buyOrSell == BuySell::SellToUtility) {
    4237            1 :                     tableBody(4, iTariff) = "Sell";
    4238            1 :                 } else if (tariff.buyOrSell == BuySell::NetMetering) {
    4239            1 :                     tableBody(4, iTariff) = "Net";
    4240              :                 }
    4241              : 
    4242           94 :                 if (tariff.groupName == "") {
    4243           22 :                     tableBody(5, iTariff) = "(none)";
    4244              :                 } else {
    4245           72 :                     tableBody(5, iTariff) = tariff.groupName;
    4246              :                 }
    4247           94 :                 tableBody(6, iTariff) = OutputReportTabular::RealToStr(tariff.totalAnnualCost, 2);
    4248              :             }
    4249           32 :             columnWidth = 14; // array assignment - same for all columns
    4250           32 :             OutputReportTabular::WriteSubtitle(state, "Tariff Summary");
    4251           32 :             OutputReportTabular::WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    4252           32 :             if (state.dataSQLiteProcedures->sqlite) {
    4253           10 :                 state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    4254              :                     tableBody, rowHead, columnHead, "Economics Results Summary Report", "Entire Facility", "Tariff Summary");
    4255              :             }
    4256           32 :             if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    4257            0 :                 state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    4258              :                     tableBody, rowHead, columnHead, "Economics Results Summary Report", "Entire Facility", "Tariff Summary");
    4259              :             }
    4260           32 :             columnHead.deallocate();
    4261           32 :             rowHead.deallocate();
    4262           32 :             columnWidth.deallocate();
    4263           32 :             tableBody.deallocate();
    4264              :         }
    4265              :         //---------------------------------
    4266              :         // Tariff Report
    4267              :         //---------------------------------
    4268          101 :         if (state.dataOutRptTab->displayTariffReport) {
    4269          126 :             for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4270           94 :                 auto const &tariff = s_econ->tariff(iTariff);
    4271           94 :                 auto const &computation = s_econ->computation(iTariff);
    4272          188 :                 OutputReportTabular::WriteReportHeaders(state, "Tariff Report", tariff.tariffName, OutputProcessor::StoreType::Average);
    4273           94 :                 rowHead.allocate(7);
    4274           94 :                 columnHead.allocate(1);
    4275           94 :                 columnWidth.allocate(1);
    4276           94 :                 tableBody.allocate(1, 7);
    4277           94 :                 tableBody = "";
    4278           94 :                 columnHead(1) = "Parameter";
    4279           94 :                 rowHead(1) = "Meter";
    4280           94 :                 rowHead(2) = "Selected";
    4281           94 :                 rowHead(3) = "Group";
    4282           94 :                 rowHead(4) = "Qualified";
    4283           94 :                 rowHead(5) = "Disqualifier";
    4284           94 :                 rowHead(6) = "Computation";
    4285           94 :                 rowHead(7) = "Units";
    4286           94 :                 tableBody(1, 1) = tariff.reportMeter;
    4287           94 :                 if (tariff.isSelected) {
    4288           52 :                     tableBody(1, 2) = "Yes";
    4289              :                 } else {
    4290           42 :                     tableBody(1, 2) = "No";
    4291              :                 }
    4292           94 :                 if (tariff.groupName == "") {
    4293           22 :                     tableBody(1, 3) = "(none)";
    4294              :                 } else {
    4295           72 :                     tableBody(1, 3) = tariff.groupName;
    4296              :                 }
    4297           94 :                 if (tariff.isQualified) {
    4298           94 :                     tableBody(1, 4) = "Yes";
    4299              :                 } else {
    4300            0 :                     tableBody(1, 4) = "No";
    4301              :                 }
    4302           94 :                 if (tariff.isQualified) {
    4303           94 :                     tableBody(1, 5) = "n/a";
    4304              :                 } else {
    4305            0 :                     tableBody(1, 5) = econVar(tariff.ptDisqualifier).name;
    4306              :                 }
    4307           94 :                 if (computation.isUserDef) {
    4308            1 :                     tableBody(1, 6) = computation.computeName;
    4309              :                 } else {
    4310           93 :                     tableBody(1, 6) = "automatic";
    4311              :                 }
    4312           94 :                 switch (tariff.convChoice) {
    4313            1 :                 case EconConv::USERDEF: {
    4314            1 :                     tableBody(1, 7) = "User Defined";
    4315            1 :                 } break;
    4316           75 :                 case EconConv::KWH: {
    4317           75 :                     tableBody(1, 7) = "kWh";
    4318           75 :                 } break;
    4319            1 :                 case EconConv::THERM: {
    4320            1 :                     tableBody(1, 7) = "Therm";
    4321            1 :                 } break;
    4322            0 :                 case EconConv::MMBTU: {
    4323            0 :                     tableBody(1, 7) = "MMBtu";
    4324            0 :                 } break;
    4325            0 :                 case EconConv::MJ: {
    4326            0 :                     tableBody(1, 7) = "MJ";
    4327            0 :                 } break;
    4328            0 :                 case EconConv::KBTU: {
    4329            0 :                     tableBody(1, 7) = "kBtu";
    4330            0 :                 } break;
    4331           17 :                 case EconConv::MCF: {
    4332           17 :                     tableBody(1, 7) = "MCF";
    4333           17 :                 } break;
    4334            0 :                 case EconConv::CCF: {
    4335            0 :                     tableBody(1, 7) = "CCF";
    4336            0 :                 } break;
    4337            0 :                 default:
    4338            0 :                     break;
    4339              :                 }
    4340           94 :                 columnWidth = 14; // array assignment - same for all columns
    4341           94 :                 OutputReportTabular::WriteSubtitle(state, "General");
    4342           94 :                 OutputReportTabular::WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    4343           94 :                 if (state.dataSQLiteProcedures->sqlite) {
    4344           28 :                     state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    4345              :                         tableBody, rowHead, columnHead, "Tariff Report", tariff.tariffName, "General");
    4346              :                 }
    4347           94 :                 if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    4348            0 :                     state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    4349            0 :                         tableBody, rowHead, columnHead, "Tariff Report", tariff.tariffName, "General");
    4350              :                 }
    4351           94 :                 columnHead.deallocate();
    4352           94 :                 rowHead.deallocate();
    4353           94 :                 columnWidth.deallocate();
    4354           94 :                 tableBody.deallocate();
    4355              :                 //---- Categories
    4356        29994 :                 for (auto &e : econVar) {
    4357        29900 :                     e.activeNow = false;
    4358              :                 }
    4359           94 :                 econVar(tariff.cats[(int)Cat::EnergyCharges]).activeNow = true;
    4360           94 :                 econVar(tariff.cats[(int)Cat::DemandCharges]).activeNow = true;
    4361           94 :                 econVar(tariff.cats[(int)Cat::ServiceCharges]).activeNow = true;
    4362           94 :                 econVar(tariff.cats[(int)Cat::Basis]).activeNow = true;
    4363           94 :                 econVar(tariff.cats[(int)Cat::Adjustment]).activeNow = true;
    4364           94 :                 econVar(tariff.cats[(int)Cat::Surcharge]).activeNow = true;
    4365           94 :                 econVar(tariff.cats[(int)Cat::Subtotal]).activeNow = true;
    4366           94 :                 econVar(tariff.cats[(int)Cat::Taxes]).activeNow = true;
    4367           94 :                 econVar(tariff.cats[(int)Cat::Total]).activeNow = true;
    4368          188 :                 ReportEconomicVariable(state, "Categories", false, true, tariff.tariffName);
    4369              :                 //---- Charges
    4370        29994 :                 for (auto &e : econVar) {
    4371        29900 :                     e.activeNow = false;
    4372              :                 }
    4373        24878 :                 for (int kVar = 1; kVar <= s_econ->numEconVar; ++kVar) {
    4374        24784 :                     if (econVar(kVar).tariffIndx == iTariff) {
    4375         4950 :                         if ((econVar(kVar).kindOfObj == ObjType::ChargeSimple) || (econVar(kVar).kindOfObj == ObjType::ChargeBlock)) {
    4376          433 :                             econVar(kVar).activeNow = true;
    4377              :                         }
    4378              :                     }
    4379              :                 }
    4380          188 :                 ReportEconomicVariable(state, "Charges", true, true, tariff.tariffName);
    4381              :                 //---- Sources for Charges
    4382        29994 :                 for (auto &e : econVar) {
    4383        29900 :                     e.activeNow = false;
    4384              :                 }
    4385        24878 :                 for (int kVar = 1; kVar <= s_econ->numEconVar; ++kVar) {
    4386        24784 :                     if (econVar(kVar).tariffIndx == iTariff) {
    4387         4950 :                         int indexInChg = econVar(kVar).index;
    4388         4950 :                         if (econVar(kVar).kindOfObj == ObjType::ChargeSimple) {
    4389          352 :                             auto &chargeSimple = s_econ->chargeSimple(indexInChg);
    4390          352 :                             if (chargeSimple.sourcePt > 0) {
    4391          352 :                                 econVar(chargeSimple.sourcePt).activeNow = true;
    4392              :                             }
    4393         4598 :                         } else if (econVar(kVar).kindOfObj == ObjType::ChargeBlock) {
    4394           81 :                             auto &chargeBlock = s_econ->chargeBlock(indexInChg);
    4395           81 :                             if (chargeBlock.sourcePt > 0) {
    4396           81 :                                 econVar(chargeBlock.sourcePt).activeNow = true;
    4397              :                             }
    4398              :                         }
    4399              :                     }
    4400              :                 }
    4401          188 :                 ReportEconomicVariable(state, "Corresponding Sources for Charges", false, false, tariff.tariffName);
    4402              :                 //---- Rachets
    4403        29994 :                 for (auto &e : econVar) {
    4404        29900 :                     e.activeNow = false;
    4405              :                 }
    4406        24878 :                 for (int kVar = 1; kVar <= s_econ->numEconVar; ++kVar) {
    4407        24784 :                     if (econVar(kVar).tariffIndx == iTariff) {
    4408         4950 :                         if (econVar(kVar).kindOfObj == ObjType::Ratchet) {
    4409            1 :                             econVar(kVar).activeNow = true;
    4410              :                         }
    4411              :                     }
    4412              :                 }
    4413          188 :                 ReportEconomicVariable(state, "Ratchets", false, false, tariff.tariffName);
    4414              :                 //---- Qualifies
    4415        29994 :                 for (auto &e : econVar) {
    4416        29900 :                     e.activeNow = false;
    4417              :                 }
    4418        24878 :                 for (int kVar = 1; kVar <= s_econ->numEconVar; ++kVar) {
    4419        24784 :                     if (econVar(kVar).tariffIndx == iTariff) {
    4420         4950 :                         if (econVar(kVar).kindOfObj == ObjType::Qualify) {
    4421           77 :                             econVar(kVar).activeNow = true;
    4422              :                         }
    4423              :                     }
    4424              :                 }
    4425          188 :                 ReportEconomicVariable(state, "Qualifies", false, false, tariff.tariffName);
    4426              :                 //---- Native Variables
    4427        29994 :                 for (auto &e : econVar) {
    4428        29900 :                     e.activeNow = false;
    4429              :                 }
    4430         3572 :                 for (int kVar = tariff.firstNative; kVar <= tariff.lastNative; ++kVar) {
    4431         3478 :                     econVar(kVar).activeNow = true;
    4432              :                 }
    4433          188 :                 ReportEconomicVariable(state, "Native Variables", false, false, tariff.tariffName);
    4434              :                 //---- Other Variables
    4435        29994 :                 for (auto &e : econVar) {
    4436        29900 :                     e.activeNow = false;
    4437              :                 }
    4438        24878 :                 for (int kVar = 1; kVar <= s_econ->numEconVar; ++kVar) {
    4439        24784 :                     if (econVar(kVar).tariffIndx == iTariff) {
    4440         4950 :                         if (!econVar(kVar).isReported) {
    4441          114 :                             econVar(kVar).activeNow = true;
    4442              :                         }
    4443              :                     }
    4444              :                 }
    4445          188 :                 ReportEconomicVariable(state, "Other Variables", false, false, tariff.tariffName);
    4446              :                 //---- Computation
    4447           94 :                 if (computation.isUserDef) {
    4448            2 :                     OutputReportTabular::WriteTextLine(state, "Computation -  User Defined", true);
    4449              :                 } else {
    4450          186 :                     OutputReportTabular::WriteTextLine(state, "Computation -  Automatic", true);
    4451              :                 }
    4452          188 :                 std::string outString = "";
    4453         4858 :                 for (int lStep = computation.firstStep; lStep <= computation.lastStep; ++lStep) {
    4454         4764 :                     auto &step = s_econ->steps(lStep);
    4455              : 
    4456         4764 :                     if (step.type == StepType::EOL) {
    4457          997 :                         OutputReportTabular::WriteTextLine(state, rstrip(outString));
    4458          997 :                         outString = "";
    4459         3767 :                     } else if (step.type == StepType::Var) {
    4460         2770 :                         outString = econVar(step.varNum).name + ' ' + outString;
    4461          997 :                     } else if (step.type == StepType::Op) {
    4462          997 :                         outString = format("{} {}", opNamesUC[(int)step.op], outString);
    4463              :                     }
    4464              :                 }
    4465              :             }
    4466              :         }
    4467              :     }
    4468          799 : }
    4469              : 
    4470           32 : void showWarningsBasedOnTotal(EnergyPlusData &state)
    4471              : {
    4472              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    4473              :     //    DATE WRITTEN   July 2004
    4474              : 
    4475              :     //    Get the annual maximum and sum for the econVariable.
    4476              : 
    4477           32 :     auto &s_econ = state.dataEconTariff;
    4478          126 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4479           94 :         auto const &tariff = s_econ->tariff(iTariff);
    4480           94 :         if (tariff.buyOrSell == BuySell::BuyFromUtility) {
    4481           92 :             if (tariff.totalAnnualCost < 0) {
    4482            0 :                 ShowWarningError(state, "UtilityCost:Tariff: A negative annual total cost when buying electricity from a utility is unusual. ");
    4483            0 :                 ShowContinueError(state, format("  In UtilityCost:Tariff named {}", tariff.tariffName));
    4484              :             }
    4485            2 :         } else if (tariff.buyOrSell == BuySell::SellToUtility) {
    4486            1 :             if (tariff.totalAnnualCost > 0) {
    4487            0 :                 ShowWarningError(state, "UtilityCost:Tariff: A positive annual total cost when selling electricity to a utility is unusual. ");
    4488            0 :                 ShowContinueError(state, format("  In UtilityCost:Tariff named {}", tariff.tariffName));
    4489              :             }
    4490              :         }
    4491              :     }
    4492           32 : }
    4493              : 
    4494         5197 : void getMaxAndSum(EnergyPlusData &state, int const varPointer, Real64 &sumResult, Real64 &maxResult)
    4495              : {
    4496              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    4497              :     //    DATE WRITTEN   July 2004
    4498              : 
    4499              :     //    Get the annual maximum and sum for the econVariable.
    4500              : 
    4501         5197 :     Real64 maximumVal(0.0); // Autodesk Value not used but suppresses warning about HUGE_() call
    4502              : 
    4503         5197 :     auto const &s_econ = state.dataEconTariff;
    4504         5197 :     auto const &econVar = s_econ->econVar(varPointer);
    4505              : 
    4506         5197 :     Real64 sumVal = 0.0;
    4507         5197 :     maximumVal = -HUGE_(maximumVal);
    4508        67561 :     for (int jMonth = 1; jMonth <= 12; ++jMonth) { // note not all months get printed out if more than 12 are used.- need to fix this later
    4509        62364 :         Real64 curVal = econVar.values(jMonth);
    4510        62364 :         sumVal += curVal;
    4511        62364 :         if (curVal > maximumVal) {
    4512         5429 :             maximumVal = curVal;
    4513              :         }
    4514              :     }
    4515         5197 :     sumResult = sumVal;
    4516         5197 :     maxResult = maximumVal;
    4517         5197 : }
    4518              : 
    4519          658 : void ReportEconomicVariable(
    4520              :     EnergyPlusData &state, std::string const &titleString, bool const includeCategory, bool const showCurrencySymbol, std::string const &forString)
    4521              : {
    4522              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    4523              :     //    DATE WRITTEN   July 2004
    4524              :     //    MODIFIED       January 2010, Kyle Benne
    4525              :     //                   Added sqlite output
    4526              : 
    4527              :     //    Report all econVar that show as activeNow
    4528              : 
    4529              :     // all arrays are in the format: (row, column)
    4530          658 :     Array1D_string columnHead;
    4531          658 :     Array1D_int columnWidth;
    4532          658 :     Array1D_string rowHead;
    4533          658 :     Array2D_string tableBody;
    4534              :     Real64 sumVal;
    4535              :     Real64 maximumVal;
    4536              :     Real64 curVal;
    4537              :     int curIndex;
    4538              :     int curCatPt;
    4539              :     int curCategory;
    4540              : 
    4541              :     int iVar;
    4542              :     int jMonth;
    4543              :     int cntOfVar;
    4544              :     int nCntOfVar;
    4545              : 
    4546          658 :     auto const &s_econ = state.dataEconTariff;
    4547          658 :     auto const &econVar = s_econ->econVar;
    4548          658 :     auto const &chargeBlock = s_econ->chargeBlock;
    4549          658 :     auto const &chargeSimple = s_econ->chargeSimple;
    4550              : 
    4551          658 :     cntOfVar = 0;
    4552       174146 :     for (iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    4553       173488 :         if (econVar(iVar).activeNow) {
    4554         5197 :             ++cntOfVar;
    4555              :         }
    4556              :     }
    4557          658 :     if (includeCategory) {
    4558           94 :         rowHead.allocate(cntOfVar);
    4559           94 :         columnHead.allocate(15);
    4560           94 :         columnWidth.allocate(15);
    4561           94 :         tableBody.allocate(15, cntOfVar);
    4562              :     } else {
    4563          564 :         rowHead.allocate(cntOfVar);
    4564          564 :         columnHead.allocate(14);
    4565          564 :         columnWidth.allocate(14);
    4566          564 :         tableBody.allocate(14, cntOfVar);
    4567              :     }
    4568              :     // column names
    4569          658 :     columnHead(1) = "Jan";
    4570          658 :     columnHead(2) = "Feb";
    4571          658 :     columnHead(3) = "Mar";
    4572          658 :     columnHead(4) = "Apr";
    4573          658 :     columnHead(5) = "May";
    4574          658 :     columnHead(6) = "Jun";
    4575          658 :     columnHead(7) = "Jul";
    4576          658 :     columnHead(8) = "Aug";
    4577          658 :     columnHead(9) = "Sep";
    4578          658 :     columnHead(10) = "Oct";
    4579          658 :     columnHead(11) = "Nov";
    4580          658 :     columnHead(12) = "Dec";
    4581          658 :     columnHead(13) = "Sum";
    4582          658 :     columnHead(14) = "Max";
    4583          658 :     if (includeCategory) {
    4584           94 :         columnHead(15) = "Category";
    4585              :     }
    4586          658 :     nCntOfVar = 0;
    4587              :     // row names
    4588       174146 :     for (iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    4589       173488 :         if (econVar(iVar).activeNow) {
    4590         5197 :             ++nCntOfVar;
    4591         5197 :             if (showCurrencySymbol) {
    4592         1279 :                 rowHead(nCntOfVar) = econVar(iVar).name + " (~~$~~)";
    4593              :             } else {
    4594         3918 :                 rowHead(nCntOfVar) = econVar(iVar).name;
    4595              :             }
    4596              :         }
    4597              :     }
    4598              :     // fill the body
    4599          658 :     nCntOfVar = 0;
    4600       174146 :     for (iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    4601       173488 :         if (econVar(iVar).activeNow) {
    4602         5197 :             ++nCntOfVar;
    4603        67561 :             for (jMonth = 1; jMonth <= 12; ++jMonth) { // note not all months get printed out if more than 12 are used.- need to fix this later
    4604        62364 :                 curVal = econVar(iVar).values(jMonth);
    4605        62364 :                 if ((curVal > 0) && (curVal < 1)) {
    4606          480 :                     tableBody(jMonth, nCntOfVar) = OutputReportTabular::RealToStr(curVal, 4);
    4607              :                 } else {
    4608        61884 :                     tableBody(jMonth, nCntOfVar) = OutputReportTabular::RealToStr(curVal, 2);
    4609              :                 }
    4610              :             }
    4611         5197 :             getMaxAndSum(state, iVar, sumVal, maximumVal);
    4612         5197 :             tableBody(13, nCntOfVar) = OutputReportTabular::RealToStr(sumVal, 2);
    4613         5197 :             tableBody(14, nCntOfVar) = OutputReportTabular::RealToStr(maximumVal, 2);
    4614         5197 :             if (includeCategory) {
    4615              :                 // first find category
    4616          433 :                 curCategory = 0;
    4617          433 :                 curIndex = econVar(iVar).index;
    4618              : 
    4619          433 :                 switch (econVar(iVar).kindOfObj) {
    4620          352 :                 case ObjType::ChargeSimple:
    4621          352 :                     if ((curIndex >= 1) && (curIndex <= s_econ->numChargeSimple)) {
    4622          352 :                         curCatPt = chargeSimple(curIndex).categoryPt;
    4623              :                     }
    4624          352 :                     break;
    4625           81 :                 case ObjType::ChargeBlock:
    4626           81 :                     if ((curIndex >= 1) && (curIndex <= s_econ->numChargeBlock)) {
    4627           81 :                         curCatPt = chargeBlock(curIndex).categoryPt;
    4628              :                     }
    4629           81 :                     break;
    4630            0 :                 default:
    4631            0 :                     break;
    4632              :                 }
    4633              : 
    4634          433 :                 if ((curCatPt >= 1) && (curCatPt <= s_econ->numEconVar)) {
    4635          433 :                     curCategory = econVar(curCatPt).specific;
    4636              :                 }
    4637              : 
    4638              :                 // In this specific table, "NotIncluded" is written as "none" so need a special case for that
    4639          433 :                 tableBody(15, nCntOfVar) =
    4640          433 :                     (econVar(curCatPt).kindOfObj == ObjType::Category)
    4641          866 :                         ? ((econVar(curCatPt).specific == (int)Cat::NotIncluded) ? "none" : catNames[econVar(curCatPt).specific])
    4642          433 :                         : "none";
    4643              :             }
    4644         5197 :             s_econ->econVar(iVar).isReported = true;
    4645              :         }
    4646              :     }
    4647          658 :     columnWidth = 14; // array assignment - same for all columns
    4648          658 :     OutputReportTabular::WriteSubtitle(state, titleString);
    4649          658 :     OutputReportTabular::WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    4650          658 :     if (state.dataSQLiteProcedures->sqlite) {
    4651          196 :         state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(tableBody, rowHead, columnHead, "Tariff Report", forString, titleString);
    4652              :     }
    4653          658 :     if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    4654            0 :         state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    4655              :             tableBody, rowHead, columnHead, "Tariff Report", forString, titleString);
    4656              :     }
    4657          658 :     columnHead.deallocate();
    4658          658 :     rowHead.deallocate();
    4659          658 :     columnWidth.deallocate();
    4660          658 :     tableBody.deallocate();
    4661          658 : }
    4662              : 
    4663          100 : void selectTariff(EnergyPlusData &state)
    4664              : {
    4665              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    4666              :     //    DATE WRITTEN   July 2004
    4667              : 
    4668              :     //    To select tariffs for each combination of meter and
    4669              :     //    group.  If multiple tariffs have the same meter and
    4670              :     //    group, then select the one with the lowest cost.
    4671              :     //    For electric tariffs, since they may have buy, sell, or
    4672              :     //    netmetering, they need to be combined more carefully.
    4673              :     //    Multiple meters are used but buy + sell might be more or
    4674              :     //    less expensive than netmeter.
    4675              : 
    4676          100 :     Array1D_int groupIndex;     // index number (in tariff) for the group name
    4677          100 :     Array1D_int MinTariffIndex; // tariff index for the Minimum value
    4678              :     int curMinTariffIndex;
    4679              : 
    4680          100 :     auto const &s_econ = state.dataEconTariff;
    4681          100 :     auto const &econVar(s_econ->econVar);
    4682              : 
    4683          100 :     groupIndex.dimension(s_econ->numTariff, 0);
    4684          100 :     int groupCount = 0;
    4685          100 :     int numMins = 0;
    4686          100 :     MinTariffIndex.dimension(s_econ->numTariff, 0);
    4687          398 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4688          298 :         auto &tariff = s_econ->tariff(iTariff);
    4689              :         // compute the total annual cost of each tariff
    4690          298 :         int totalVarPt = tariff.cats[(int)Cat::Total];
    4691          298 :         int totEneVarPt = tariff.natives[(int)Native::TotalEnergy];
    4692          298 :         Real64 annualTotal = 0.0;
    4693          298 :         Real64 annEneTotal = 0.0;
    4694         3874 :         for (int jMonth = 1; jMonth <= NumMonths; ++jMonth) {
    4695         3576 :             annualTotal += econVar(totalVarPt).values(jMonth);
    4696         3576 :             annEneTotal += econVar(totEneVarPt).values(jMonth);
    4697              :         }
    4698          298 :         tariff.totalAnnualCost = annualTotal;
    4699          298 :         tariff.totalAnnualEnergy = annEneTotal;
    4700              :         // Set the groupIndex
    4701          298 :         if (groupIndex(iTariff) == 0) {
    4702              :             // set the current item to the tariff index
    4703          184 :             ++groupCount;
    4704          184 :             groupIndex(iTariff) = groupCount;
    4705              :             // set all remaining matching items to the same index
    4706          383 :             for (int kTariff = iTariff + 1; kTariff <= s_econ->numTariff; ++kTariff) {
    4707          199 :                 if (Util::SameString(s_econ->tariff(kTariff).groupName, tariff.groupName)) {
    4708          114 :                     groupIndex(kTariff) = groupCount;
    4709              :                 }
    4710              :             }
    4711              :         }
    4712              :     }
    4713              :     // First process the all tariff and identify the lowest cost for each type of meter and group.
    4714          398 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4715          298 :         auto &tariff = s_econ->tariff(iTariff);
    4716          298 :         if (tariff.isQualified) {
    4717          298 :             bool isFound = false;
    4718          523 :             for (int lMin = 1; lMin <= numMins; ++lMin) {
    4719          225 :                 curMinTariffIndex = MinTariffIndex(lMin);
    4720              :                 // find matching meter and group
    4721          225 :                 if (tariff.reportMeterIndx == s_econ->tariff(curMinTariffIndex).reportMeterIndx) {
    4722          110 :                     if (groupIndex(iTariff) == groupIndex(curMinTariffIndex)) {
    4723          110 :                         isFound = true;
    4724              :                         // found the matching mater and group now test if smaller Min is current tariff
    4725          110 :                         if (tariff.totalAnnualCost < s_econ->tariff(curMinTariffIndex).totalAnnualCost) {
    4726           98 :                             MinTariffIndex(lMin) = iTariff;
    4727              :                             // select the new Minimum tariff and deselect the one that was just exceeded
    4728           98 :                             s_econ->tariff(curMinTariffIndex).isSelected = false;
    4729           98 :                             tariff.isSelected = true;
    4730              :                         }
    4731              :                     }
    4732              :                 }
    4733              :             }
    4734          298 :             if (!isFound) {
    4735          188 :                 ++numMins;
    4736          188 :                 if (numMins > s_econ->numTariff) {
    4737            0 :                     ShowWarningError(state, "UtilityCost:Tariff Debugging error numMins greater than numTariff.");
    4738              :                 }
    4739          188 :                 MinTariffIndex(numMins) = iTariff;
    4740              :                 // tariff(numMins)%isSelected = .TRUE.  !original
    4741          188 :                 tariff.isSelected = true; // BTG changed 2/7/2005     CR6573
    4742              :             }
    4743              :         }
    4744              :     }
    4745              :     // Now select for the electric meters. If electric buying and selling and netmetering all are going
    4746              :     // on, need to determine which combination should be selected. Within each group select just one set
    4747              :     // of electric results.  The electric results can be either the buy rate only, the buy rate plus the
    4748              :     // sell rate, or the netmetering rate, whichever of these three is the lowest combination.
    4749              :     // (The kindElectricMtr was assigned in GetInputEconomicsTariff)
    4750          284 :     for (int mGroup = 1; mGroup <= groupCount; ++mGroup) {
    4751          184 :         int lowestSimpleTariff = 0;
    4752          184 :         int lowestPurchaseTariff = 0;
    4753          184 :         int lowestSurplusSoldTariff = 0;
    4754          184 :         int lowestNetMeterTariff = 0;
    4755          746 :         for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4756          562 :             auto &tariff = s_econ->tariff(iTariff);
    4757          562 :             if (tariff.isQualified) {
    4758          562 :                 if (tariff.isSelected) {
    4759          356 :                     if (groupIndex(iTariff) == mGroup) {
    4760          188 :                         if (tariff.kindMtr == MeterType::ElecSimple) {
    4761           96 :                             lowestSimpleTariff = iTariff;
    4762           92 :                         } else if (tariff.kindMtr == MeterType::ElecProduced) {
    4763              :                             // don't show electric produced rates as ever selected since surplus sold is more relevant
    4764            0 :                             tariff.isSelected = false;
    4765           92 :                         } else if (tariff.kindMtr == MeterType::ElecPurchased) {
    4766            1 :                             lowestPurchaseTariff = iTariff;
    4767           91 :                         } else if (tariff.kindMtr == MeterType::ElecSurplusSold) {
    4768            1 :                             lowestSurplusSoldTariff = iTariff;
    4769           90 :                         } else if (tariff.kindMtr == MeterType::ElecNet) {
    4770            4 :                             lowestNetMeterTariff = iTariff;
    4771              :                         }
    4772              :                     }
    4773              :                 }
    4774              :             }
    4775              :         }
    4776              :         // compare the simple and purchased metered tariffs
    4777          184 :         if ((lowestSimpleTariff > 0) && (lowestPurchaseTariff > 0)) {
    4778            0 :             if (s_econ->tariff(lowestSimpleTariff).totalAnnualCost < s_econ->tariff(lowestPurchaseTariff).totalAnnualCost) {
    4779            0 :                 s_econ->tariff(lowestPurchaseTariff).isSelected = false;
    4780            0 :                 lowestPurchaseTariff = 0;
    4781              :             } else {
    4782            0 :                 s_econ->tariff(lowestSimpleTariff).isSelected = false;
    4783            0 :                 lowestSimpleTariff = 0;
    4784              :             }
    4785              :         }
    4786              :         // if surplus sold is negative use it otherwise don't
    4787          184 :         if (lowestSurplusSoldTariff > 0) {
    4788            1 :             if (s_econ->tariff(lowestSurplusSoldTariff).totalAnnualCost > 0) {
    4789            0 :                 s_econ->tariff(lowestSurplusSoldTariff).isSelected = false;
    4790            0 :                 lowestSurplusSoldTariff = 0;
    4791              :             }
    4792              :         }
    4793              :         // if netmetering is used compare it to simple plus surplus
    4794          184 :         if (((lowestNetMeterTariff > 0) && (lowestSurplusSoldTariff > 0)) && (lowestSimpleTariff > 0)) {
    4795            0 :             if (s_econ->tariff(lowestNetMeterTariff).totalAnnualCost <
    4796            0 :                 (s_econ->tariff(lowestSimpleTariff).totalAnnualCost + s_econ->tariff(lowestSurplusSoldTariff).totalAnnualCost)) {
    4797            0 :                 s_econ->tariff(lowestSimpleTariff).isSelected = false;
    4798            0 :                 lowestSimpleTariff = 0;
    4799            0 :                 s_econ->tariff(lowestSurplusSoldTariff).isSelected = false;
    4800            0 :                 lowestSurplusSoldTariff = 0;
    4801              :             } else {
    4802            0 :                 s_econ->tariff(lowestNetMeterTariff).isSelected = false;
    4803            0 :                 lowestNetMeterTariff = 0;
    4804              :             }
    4805              :         }
    4806              :         // if netmetering is used compare it to purchased plus surplus
    4807          184 :         if (((lowestNetMeterTariff > 0) && (lowestSurplusSoldTariff > 0)) && (lowestPurchaseTariff > 0)) {
    4808            1 :             if (s_econ->tariff(lowestNetMeterTariff).totalAnnualCost <
    4809            1 :                 (s_econ->tariff(lowestPurchaseTariff).totalAnnualCost + s_econ->tariff(lowestSurplusSoldTariff).totalAnnualCost)) {
    4810            0 :                 s_econ->tariff(lowestPurchaseTariff).isSelected = false;
    4811            0 :                 lowestPurchaseTariff = 0;
    4812            0 :                 s_econ->tariff(lowestSurplusSoldTariff).isSelected = false;
    4813              :                 // lowestSurplusSoldTariff = 0; // not used after this point
    4814              :             } else {
    4815            1 :                 s_econ->tariff(lowestNetMeterTariff).isSelected = false;
    4816            1 :                 lowestNetMeterTariff = 0;
    4817              :             }
    4818              :         }
    4819              :         // if netmetering is used compare it to simple only
    4820          184 :         if ((lowestNetMeterTariff > 0) && (lowestSimpleTariff > 0)) {
    4821            0 :             if (s_econ->tariff(lowestNetMeterTariff).totalAnnualCost < s_econ->tariff(lowestSimpleTariff).totalAnnualCost) {
    4822            0 :                 s_econ->tariff(lowestSimpleTariff).isSelected = false;
    4823              :                 // lowestSimpleTariff = 0; // not used after this point
    4824              :             } else {
    4825            0 :                 s_econ->tariff(lowestNetMeterTariff).isSelected = false;
    4826            0 :                 lowestNetMeterTariff = 0;
    4827              :             }
    4828              :         }
    4829              :         // if netmetering is used compare it to purchased only
    4830          184 :         if ((lowestNetMeterTariff > 0) && (lowestPurchaseTariff > 0)) {
    4831            0 :             if (s_econ->tariff(lowestNetMeterTariff).totalAnnualCost < s_econ->tariff(lowestPurchaseTariff).totalAnnualCost) {
    4832            0 :                 s_econ->tariff(lowestPurchaseTariff).isSelected = false;
    4833              :                 // lowestPurchaseTariff = 0; // not used after this point
    4834              :             } else {
    4835            0 :                 s_econ->tariff(lowestNetMeterTariff).isSelected = false;
    4836              :                 // lowestNetMeterTariff = 0; // not used after this point
    4837              :             }
    4838              :         }
    4839              :     }
    4840          100 :     groupIndex.deallocate();
    4841          100 :     MinTariffIndex.deallocate();
    4842          100 : }
    4843              : 
    4844           96 : void GetMonthlyCostForResource(EnergyPlusData &state, Constant::eResource const inResourceNumber, Array1A<Real64> outMonthlyCosts)
    4845              : {
    4846              :     //       AUTHOR         Jason Glazer
    4847              :     //       DATE WRITTEN   May 2010
    4848              : 
    4849              :     //  Return the total annual cost for a given resource number.
    4850              : 
    4851              :     // Argument array dimensioning
    4852           96 :     auto const &s_econ = state.dataEconTariff;
    4853              : 
    4854           96 :     outMonthlyCosts.dim(12);
    4855              : 
    4856           96 :     outMonthlyCosts = 0.0;
    4857          816 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4858          720 :         auto const &tariff = s_econ->tariff(iTariff);
    4859          720 :         if (tariff.isSelected) {
    4860          192 :             if (tariff.resource == inResourceNumber) {
    4861            4 :                 auto const &econVar = s_econ->econVar(tariff.cats[(int)Cat::Total]);
    4862           52 :                 for (int jMonth = 1; jMonth <= 12; ++jMonth) { // use 12 because LCC assume 12 months
    4863           48 :                     outMonthlyCosts(jMonth) += econVar.values(jMonth);
    4864              :                 }
    4865              :             }
    4866              :         }
    4867              :     }
    4868           96 : }
    4869              : 
    4870              : } // namespace EnergyPlus::EconomicTariff
        

Generated by: LCOV version 2.0-1