LCOV - code coverage report
Current view: top level - EnergyPlus - EconomicTariff.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 51.6 % 2819 1455
Test Date: 2025-06-02 12:03:30 Functions: 80.5 % 41 33

            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        18787 : 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        18787 :     auto &s_econ = state.dataEconTariff;
     227              : 
     228        18787 :     if (s_econ->Update_GetInput) {
     229           80 :         bool ErrorsFound = false;
     230              : 
     231           80 :         GetInputEconomicsTariff(state, ErrorsFound);
     232              :         // do rest of GetInput only if at least one tariff is defined.
     233           80 :         GetInputEconomicsCurrencyType(state, ErrorsFound);
     234           80 :         if (s_econ->numTariff >= 1) {
     235            7 :             if (!ErrorsFound && state.dataOutRptTab->displayEconomicResultSummary) {
     236            0 :                 OutputReportTabular::AddTOCEntry(state, "Economics Results Summary Report", "Entire Facility");
     237              :             }
     238            7 :             CreateCategoryNativeVariables(state);
     239            7 :             GetInputEconomicsQualify(state, ErrorsFound);
     240            7 :             GetInputEconomicsChargeSimple(state, ErrorsFound);
     241            7 :             GetInputEconomicsChargeBlock(state, ErrorsFound);
     242            7 :             GetInputEconomicsRatchet(state, ErrorsFound);
     243            7 :             GetInputEconomicsVariable(state, ErrorsFound);
     244            7 :             GetInputEconomicsComputation(state, ErrorsFound);
     245            7 :             CreateDefaultComputation(state);
     246              :         }
     247           80 :         s_econ->Update_GetInput = false;
     248           80 :         if (ErrorsFound) {
     249            0 :             ShowFatalError(state, "UpdateUtilityBills: Preceding errors cause termination.");
     250              :         }
     251              :     }
     252        18787 :     if (state.dataGlobal->DoOutputReporting && (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather)) {
     253            3 :         GatherForEconomics(state);
     254              :     }
     255        18787 : }
     256              : 
     257              : //======================================================================================================================
     258              : //======================================================================================================================
     259              : 
     260              : //    GET INPUT ROUTINES
     261              : 
     262              : //======================================================================================================================
     263              : //======================================================================================================================
     264              : 
     265           80 : 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           80 :     Constant::Units UnitsVar = Constant::Units::None; // Units sting, may be blank
     290           80 :     Array1D_string NamesOfKeys;                       // Specific key name
     291           80 :     Array1D_int IndexesForKeyVar;                     // Array index
     292              : 
     293           80 :     auto &s_ipsc = state.dataIPShortCut;
     294           80 :     auto &s_econ = state.dataEconTariff;
     295              : 
     296           80 :     std::string_view CurrentModuleObject = "UtilityCost:Tariff";
     297           80 :     s_econ->numTariff = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     298           80 :     s_econ->tariff.allocate(s_econ->numTariff);
     299           87 :     for (int iInObj = 1; iInObj <= s_econ->numTariff; ++iInObj) {
     300           14 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     301              :                                                                  CurrentModuleObject,
     302              :                                                                  iInObj,
     303            7 :                                                                  s_ipsc->cAlphaArgs,
     304              :                                                                  NumAlphas,
     305            7 :                                                                  s_ipsc->rNumericArgs,
     306              :                                                                  NumNums,
     307              :                                                                  IOStat,
     308            7 :                                                                  s_ipsc->lNumericFieldBlanks,
     309            7 :                                                                  s_ipsc->lAlphaFieldBlanks,
     310            7 :                                                                  s_ipsc->cAlphaFieldNames,
     311            7 :                                                                  s_ipsc->cNumericFieldNames);
     312              : 
     313            7 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     314            7 :         auto &tariff = s_econ->tariff(iInObj);
     315              : 
     316              :         // check to make sure none of the values are another economic object
     317           73 :         for (int jFld = 1; jFld <= NumAlphas; ++jFld) {
     318              :             //  args are always turned to upper case but this is okay...
     319           66 :             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            7 :         tariff.tariffName = s_ipsc->cAlphaArgs(1);
     326              :         // check if tariff name is unique
     327            7 :         int found = 0;
     328            7 :         for (int jObj = 1; jObj <= iInObj - 1; ++jObj) {
     329            0 :             if (tariff.tariffName == s_econ->tariff(jObj).tariffName) {
     330            0 :                 found = jObj;
     331            0 :                 break;
     332              :             }
     333              :         }
     334            7 :         if (found > 0) {
     335            0 :             ShowSevereDuplicateName(state, eoh);
     336            0 :             ErrorsFound = true;
     337              :         }
     338              :         // name of the report meter
     339            7 :         tariff.reportMeter = s_ipsc->cAlphaArgs(2);
     340              :         // call the key count function but only need count during this pass
     341            7 :         GetVariableKeyCountandType(state, tariff.reportMeter, KeyCount, TypeVar, AvgSumVar, StepTypeVar, UnitsVar);
     342              :         // if no meters found for that name
     343            7 :         if (KeyCount == 0) {
     344            3 :             ShowWarningError(state, format("{}{}=\"{}\" missing meter", RoutineName, CurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     345            6 :             ShowContinueError(
     346              :                 state,
     347            6 :                 format("Meter referenced is not present due to a lack of equipment that uses that energy source/meter:\"{}\".", tariff.reportMeter));
     348            3 :             tariff.reportMeterIndx = -1;
     349              :         } else {
     350            4 :             NamesOfKeys.allocate(KeyCount);
     351            4 :             IndexesForKeyVar.allocate(KeyCount);
     352            4 :             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            4 :             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            4 :             tariff.reportMeterIndx = IndexesForKeyVar(1);
     360              :             // get rid of the arrays used to get the variable number
     361            4 :             NamesOfKeys.deallocate();
     362            4 :             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            7 :         tariff.kindMtr = MeterType::Other;
     368              : 
     369              :         // Determine whether this meter is related to electricity, or water, or gas
     370            7 :         if (tariff.reportMeterIndx != -1) {
     371            4 :             switch (state.dataOutputProcessor->meters[tariff.reportMeterIndx]->resource) {
     372              :             // Various types of electricity meters
     373            1 :             case Constant::eResource::Electricity: {
     374            1 :                 tariff.kindMtr = MeterType::ElecSimple;
     375            1 :             } break;
     376            0 :             case Constant::eResource::ElectricityProduced: {
     377            0 :                 tariff.kindMtr = MeterType::ElecProduced;
     378            0 :             } break;
     379            0 :             case Constant::eResource::ElectricityPurchased: {
     380            0 :                 tariff.kindMtr = MeterType::ElecPurchased;
     381            0 :             } break;
     382            0 :             case Constant::eResource::ElectricitySurplusSold: {
     383            0 :                 tariff.kindMtr = MeterType::ElecSurplusSold;
     384            0 :             } break;
     385            0 :             case Constant::eResource::ElectricityNet: {
     386            0 :                 tariff.kindMtr = MeterType::ElecNet;
     387            0 :             } break;
     388              :             // Handle the case where its a water meter
     389            2 :             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            2 :                 tariff.kindMtr = MeterType::Water;
     396            2 :             } break;
     397              :             // Or a Natural Gas meter
     398            1 :             case Constant::eResource::NaturalGas: {
     399            1 :                 tariff.kindMtr = MeterType::Gas;
     400            1 :             } 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            7 :         switch (tariff.kindMtr) {
     412            2 :         case MeterType::Water: {
     413              :             // conversion factor
     414            2 :             tariff.convChoice = static_cast<EconConv>(getEnumValue(econConvNamesUC, s_ipsc->cAlphaArgs(3)));
     415            2 :             switch (tariff.convChoice) {
     416            0 :             case EconConv::USERDEF: {
     417            0 :                 tariff.energyConv = s_ipsc->rNumericArgs(1); // energy conversion factor
     418            0 :                 tariff.demandConv = s_ipsc->rNumericArgs(2); // demand conversion factor
     419            0 :             } break;
     420              : 
     421            0 :             case EconConv::M3: {
     422            0 :                 tariff.energyConv = 1.0;
     423            0 :                 tariff.demandConv = 3600.0;
     424            0 :             } break;
     425              : 
     426            1 :             case EconConv::CCF: {
     427            1 :                 tariff.energyConv = 0.35314666721488586;
     428            1 :                 tariff.demandConv = 0.35314666721488586 * 3600;
     429            1 :             } 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            1 :             default: { // ERROR: not a valid conversion, default to M3
     442            1 :                 tariff.convChoice = EconConv::M3;
     443            1 :                 tariff.energyConv = 1.0;
     444            1 :                 tariff.demandConv = 3600.0;
     445            1 :                 ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3), "M3");
     446            1 :             } break;
     447              :             } // switch (tariff.convChoice)
     448              : 
     449            2 :         } 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            1 :         case MeterType::ElecSimple:
     455              :         case MeterType::ElecProduced:
     456              :         case MeterType::ElecPurchased:
     457              :         case MeterType::ElecSurplusSold:
     458              :         case MeterType::ElecNet: {
     459            1 :             tariff.convChoice = static_cast<EconConv>(getEnumValue(econConvNamesUC, s_ipsc->cAlphaArgs(3)));
     460              : 
     461            1 :             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            0 :             case EconConv::KWH: {
     468            0 :                 tariff.energyConv = 0.0000002778;
     469            0 :                 tariff.demandConv = 0.001;
     470            0 :             } 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            1 :             default: {
     499            1 :                 tariff.convChoice = EconConv::KWH;
     500            1 :                 tariff.energyConv = 0.0000002778;
     501            1 :                 tariff.demandConv = 0.001;
     502            1 :                 ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3), "KWH");
     503            1 :             } break;
     504              :             } // switch (tariff.convChoice)
     505            1 :         } break;
     506              : 
     507              :             // If it's a gas meter
     508            1 :         case MeterType::Gas: {
     509            1 :             tariff.convChoice = static_cast<EconConv>(getEnumValue(econConvNamesUC, s_ipsc->cAlphaArgs(3)));
     510            1 :             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            0 :             case EconConv::THERM: {
     522            0 :                 tariff.energyConv = 9.4781712e-9;
     523            0 :                 tariff.demandConv = 0.00003412;
     524            0 :             } 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            0 :             case EconConv::MCF: {
     543            0 :                 tariff.energyConv = 9.4781712e-10;
     544            0 :                 tariff.demandConv = 0.000003412;
     545            0 :             } break;
     546              : 
     547            1 :             case EconConv::CCF: {
     548            1 :                 tariff.energyConv = 9.4781712e-9;
     549            1 :                 tariff.demandConv = 0.00003412;
     550            1 :             } 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            1 :         } 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            3 :         case MeterType::Other: {
     571            3 :             tariff.convChoice = static_cast<EconConv>(getEnumValue(econConvNamesUC, s_ipsc->cAlphaArgs(3)));
     572            3 :             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            3 :             case EconConv::KWH: {
     579            3 :                 tariff.energyConv = 0.0000002778;
     580            3 :                 tariff.demandConv = 0.001;
     581            3 :             } 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            0 :             default: {
     605            0 :                 tariff.convChoice = EconConv::KWH;
     606            0 :                 tariff.energyConv = 0.0000002778;
     607            0 :                 tariff.demandConv = 0.001;
     608            0 :                 ShowWarningInvalidKey(state, eoh, s_ipsc->cAlphaFieldNames(3), s_ipsc->cAlphaArgs(3), "KWH");
     609            0 :             } break;
     610              :             } // switch (tariff.convChoice)
     611            3 :         } 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            7 :         if (len(s_ipsc->cAlphaArgs(4)) > 0) {
     620            1 :             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            7 :         if (len(s_ipsc->cAlphaArgs(5)) > 0) {
     628            3 :             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            7 :         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            7 :         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            0 :                 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            0 :                 case 4:
     671              :                 case 12:
     672              :                 case 20:
     673              :                 case 60: {
     674            0 :                     tariff.demandWindow = DemandWindow::Quarter;
     675            0 :                     tariff.demWinTime = 0.25;
     676            0 :                 } break;
     677            0 :                 default: {
     678            0 :                     assert(false);
     679              :                 } break;
     680              :                 }
     681              :             }
     682            7 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(7), "HalfHour")) {
     683              :             {
     684            0 :                 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            0 :                 case 2:
     698              :                 case 4:
     699              :                 case 6:
     700              :                 case 10:
     701              :                 case 12:
     702              :                 case 20:
     703              :                 case 30:
     704              :                 case 60: {
     705            0 :                     tariff.demandWindow = DemandWindow::Half;
     706            0 :                     tariff.demWinTime = 0.50;
     707            0 :                 } break;
     708            0 :                 default: {
     709              :                     // assert(false); // EconomicTariff unit test gets here with NumOfTimeStepInHour == 0
     710            0 :                 } break;
     711              :                 }
     712              :             }
     713            7 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(7), "FullHour")) {
     714            0 :             tariff.demandWindow = DemandWindow::Hour;
     715            0 :             tariff.demWinTime = 1.00;
     716            7 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(7), "Day")) {
     717            0 :             tariff.demandWindow = DemandWindow::Day;
     718            0 :             tariff.demWinTime = 24.00;
     719            7 :         } 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            7 :                 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            0 :                 case 2:
     734              :                 case 6:
     735              :                 case 10:
     736              :                 case 30: {
     737            0 :                     tariff.demandWindow = DemandWindow::Half;
     738            0 :                     tariff.demWinTime = 0.50;
     739            0 :                 } break;
     740            7 :                 case 4:
     741              :                 case 12:
     742              :                 case 20:
     743              :                 case 60: {
     744            7 :                     tariff.demandWindow = DemandWindow::Quarter;
     745            7 :                     tariff.demWinTime = 0.25;
     746            7 :                 } 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            7 :         tariff.monthChgVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(8), isNotNumeric);
     755            7 :         tariff.monthChgPt =
     756            7 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(8), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, iInObj);
     757              :         // minimum monthly charge
     758            7 :         if (len(s_ipsc->cAlphaArgs(9)) > 0) {
     759            0 :             tariff.minMonthChgVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(9), isNotNumeric);
     760              :         } else {
     761            7 :             tariff.minMonthChgVal = -HUGE_(-1.0); // set to a very negative value
     762              :         }
     763            7 :         tariff.minMonthChgPt =
     764            7 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(9), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, iInObj);
     765              :         // real time pricing
     766            7 :         tariff.chargeSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(10));
     767            7 :         tariff.baseUseSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(11));
     768              :         // group name for separate distribution and transmission rates
     769            7 :         tariff.groupName = s_ipsc->cAlphaArgs(12);
     770              :         // buy or sell option
     771              : 
     772            7 :         if (s_ipsc->lAlphaFieldBlanks(13)) {
     773            5 :             tariff.buyOrSell = BuySell::BuyFromUtility;
     774            2 :         } 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            7 :         if (tariff.buyOrSell == BuySell::SellToUtility) {
     781            0 :             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            7 :         } else if (tariff.buyOrSell == BuySell::NetMetering) {
     787            2 :             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            5 :         } else if (tariff.buyOrSell == BuySell::BuyFromUtility) {
     793            5 :             if (hasi(tariff.reportMeter, "Elec")) { // test if electric meter
     794            3 :                 if (!(Util::SameString(tariff.reportMeter, "Electricity:Facility") ||
     795            3 :                       Util::SameString(tariff.reportMeter, "ElectricityPurchased:Facility"))) {
     796            0 :                     ShowWarningError(state, format("{}{}=\"{}\" atypical meter", RoutineName, CurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     797            0 :                     ShowContinueError(state,
     798            0 :                                       format("The meter chosen \"{}\" is not typically used with the buyFromUtility option.", tariff.reportMeter));
     799            0 :                     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           91 :         for (int kMonth = 1; kMonth <= NumMonths; ++kMonth) {
     808           84 :             tariff.seasonForMonth(kMonth) = Season::Invalid;
     809          504 :             for (int lPeriod = 0; lPeriod < (int)Period::Num; ++lPeriod) {
     810          420 :                 tariff.gatherEnergy(kMonth)[lPeriod] = 0.0;
     811          420 :                 tariff.gatherDemand(kMonth)[lPeriod] = 0.0;
     812              :             }
     813              :         }
     814              : 
     815              :         // assume that the tariff is qualified
     816            7 :         tariff.isQualified = true;
     817            7 :         tariff.ptDisqualifier = 0;
     818              :         // assume that the tariff is not selected
     819            7 :         tariff.isSelected = false;
     820            7 :         tariff.totalAnnualCost = 0.0;
     821              :         // now create the Table Of Contents entries for an HTML file
     822            7 :         if (state.dataOutRptTab->displayTariffReport) {
     823            0 :             OutputReportTabular::AddTOCEntry(state, "Tariff Report", tariff.tariffName);
     824              :         }
     825              :         // associate the resource number with each tariff
     826            7 :         if (tariff.reportMeterIndx != -1) {
     827            4 :             tariff.resource = state.dataOutputProcessor->meters[tariff.reportMeterIndx]->resource;
     828              :         }
     829              :     }
     830           80 : }
     831              : 
     832            7 : 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            7 :     auto &s_econ = state.dataEconTariff;
     850            7 :     auto &s_ipsc = state.dataIPShortCut;
     851              : 
     852            7 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Qualify";
     853            7 :     s_econ->numQualify = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     854            7 :     s_econ->qualify.allocate(s_econ->numQualify);
     855              : 
     856            8 :     for (iInObj = 1; iInObj <= s_econ->numQualify; ++iInObj) {
     857            2 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     858            1 :                                                                  s_ipsc->cCurrentModuleObject,
     859              :                                                                  iInObj,
     860            1 :                                                                  s_ipsc->cAlphaArgs,
     861              :                                                                  NumAlphas,
     862            1 :                                                                  s_ipsc->rNumericArgs,
     863              :                                                                  NumNums,
     864              :                                                                  IOStat,
     865            1 :                                                                  s_ipsc->lNumericFieldBlanks,
     866            1 :                                                                  s_ipsc->lAlphaFieldBlanks,
     867            1 :                                                                  s_ipsc->cAlphaFieldNames,
     868            1 :                                                                  s_ipsc->cNumericFieldNames);
     869              : 
     870            1 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     871              : 
     872            1 :         auto &qualify = s_econ->qualify(iInObj);
     873              : 
     874              :         // check to make sure none of the values are another economic object
     875            8 :         for (jFld = 1; jFld <= NumAlphas; ++jFld) {
     876            7 :             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            1 :         qualify.tariffIndx = FindTariffIndex(state, s_ipsc->cAlphaArgs(2), s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject);
     883            1 :         warnIfNativeVarname(state, s_ipsc->cAlphaArgs(1), qualify.tariffIndx, ErrorsFound, s_ipsc->cCurrentModuleObject);
     884            1 :         qualify.namePt =
     885            1 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(1), true, varIsAssigned, varNotYetDefined, ObjType::Qualify, iInObj, qualify.tariffIndx);
     886              :         // index of the variable in the variable array
     887            1 :         qualify.sourcePt =
     888            1 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(3), true, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, qualify.tariffIndx);
     889              :         // indicator if maximum test otherwise minimum
     890            1 :         if (s_ipsc->cAlphaArgs(4) == "MINIMUM") {
     891            1 :             qualify.isMaximum = false;
     892            0 :         } else if (s_ipsc->cAlphaArgs(4) == "MAXIMUM") {
     893            0 :             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            1 :         qualify.thresholdVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(5), isNotNumeric);
     900            1 :         qualify.thresholdPt =
     901            1 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(5), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, qualify.tariffIndx);
     902              :         // enumerated list of the kind of season
     903            1 :         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            1 :         if (s_ipsc->cAlphaArgs(7) == "COUNT") {
     910            1 :             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            1 :         qualify.numberOfMonths = s_ipsc->rNumericArgs(1);
     919              :     }
     920            7 : }
     921              : 
     922            7 : 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            7 :     auto &s_econ = state.dataEconTariff;
     937            7 :     auto &s_ipsc = state.dataIPShortCut;
     938            7 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Charge:Simple";
     939              : 
     940            7 :     s_econ->numChargeSimple = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     941            7 :     s_econ->chargeSimple.allocate(s_econ->numChargeSimple);
     942           15 :     for (int iInObj = 1; iInObj <= s_econ->numChargeSimple; ++iInObj) {
     943            8 :         auto &chargeSimple = s_econ->chargeSimple(iInObj);
     944           16 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     945            8 :                                                                  s_ipsc->cCurrentModuleObject,
     946              :                                                                  iInObj,
     947            8 :                                                                  s_ipsc->cAlphaArgs,
     948              :                                                                  NumAlphas,
     949            8 :                                                                  s_ipsc->rNumericArgs,
     950              :                                                                  NumNums,
     951              :                                                                  IOStat,
     952            8 :                                                                  s_ipsc->lNumericFieldBlanks,
     953            8 :                                                                  s_ipsc->lAlphaFieldBlanks,
     954            8 :                                                                  s_ipsc->cAlphaFieldNames,
     955            8 :                                                                  s_ipsc->cNumericFieldNames);
     956              : 
     957            8 :         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           56 :         for (int jFld = 1; jFld <= NumAlphas; ++jFld) {
     961           48 :             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            8 :         chargeSimple.tariffIndx = FindTariffIndex(state, s_ipsc->cAlphaArgs(2), s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject);
     968            8 :         warnIfNativeVarname(state, s_ipsc->cAlphaArgs(1), chargeSimple.tariffIndx, ErrorsFound, s_ipsc->cCurrentModuleObject);
     969            8 :         chargeSimple.namePt = AssignVariablePt(
     970            8 :             state, s_ipsc->cAlphaArgs(1), true, varIsAssigned, varNotYetDefined, ObjType::ChargeSimple, iInObj, chargeSimple.tariffIndx);
     971              :         // index of the variable in the variable array
     972            8 :         chargeSimple.sourcePt =
     973            8 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(3), true, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, chargeSimple.tariffIndx);
     974              :         // enumerated list of the kind of season
     975            8 :         chargeSimple.season = static_cast<Season>(getEnumValue(seasonNamesUC, s_ipsc->cAlphaArgs(4)));
     976            8 :         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            8 :         if (chargeSimple.season != Season::Annual) {
     983            7 :             if (chargeSimple.tariffIndx != 0) {
     984            7 :                 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            8 :         chargeSimple.categoryPt =
     994            8 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(5), true, varIsAssigned, varNotYetDefined, ObjType::Category, iInObj, chargeSimple.tariffIndx);
     995              :         // cost per unit value or variable
     996            8 :         chargeSimple.costPerVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(6), isNotNumeric);
     997            8 :         chargeSimple.costPerPt = AssignVariablePt(
     998            8 :             state, s_ipsc->cAlphaArgs(6), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, chargeSimple.tariffIndx);
     999              :     }
    1000            7 : }
    1001              : 
    1002            7 : 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            7 :     Real64 hugeNumber(0.0); // Autodesk Value not used but suppresses warning about HUGE_() call
    1018              : 
    1019            7 :     auto &s_econ = state.dataEconTariff;
    1020            7 :     auto &s_ipsc = state.dataIPShortCut;
    1021            7 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Charge:Block";
    1022              : 
    1023            7 :     hugeNumber = HUGE_(hugeNumber);
    1024            7 :     s_econ->numChargeBlock = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1025            7 :     s_econ->chargeBlock.allocate(s_econ->numChargeBlock);
    1026            8 :     for (int iInObj = 1; iInObj <= s_econ->numChargeBlock; ++iInObj) {
    1027            1 :         auto &chargeBlock = s_econ->chargeBlock(iInObj);
    1028            2 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1029            1 :                                                                  s_ipsc->cCurrentModuleObject,
    1030              :                                                                  iInObj,
    1031            1 :                                                                  s_ipsc->cAlphaArgs,
    1032              :                                                                  NumAlphas,
    1033            1 :                                                                  s_ipsc->rNumericArgs,
    1034              :                                                                  NumNums,
    1035              :                                                                  IOStat,
    1036            1 :                                                                  s_ipsc->lNumericFieldBlanks,
    1037            1 :                                                                  s_ipsc->lAlphaFieldBlanks,
    1038            1 :                                                                  s_ipsc->cAlphaFieldNames,
    1039            1 :                                                                  s_ipsc->cNumericFieldNames);
    1040              : 
    1041            1 :         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           14 :         for (int jFld = 1; jFld <= NumAlphas; ++jFld) {
    1045           13 :             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            1 :         chargeBlock.tariffIndx = FindTariffIndex(state, s_ipsc->cAlphaArgs(2), s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject);
    1052            1 :         warnIfNativeVarname(state, s_ipsc->cAlphaArgs(1), chargeBlock.tariffIndx, ErrorsFound, s_ipsc->cCurrentModuleObject);
    1053            1 :         chargeBlock.namePt = AssignVariablePt(
    1054            1 :             state, s_ipsc->cAlphaArgs(1), true, varIsAssigned, varNotYetDefined, ObjType::ChargeBlock, iInObj, chargeBlock.tariffIndx);
    1055              :         // index of the variable in the variable array
    1056            1 :         chargeBlock.sourcePt =
    1057            1 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(3), true, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, chargeBlock.tariffIndx);
    1058              :         // enumerated list of the kind of season
    1059            1 :         chargeBlock.season = static_cast<Season>(getEnumValue(seasonNamesUC, s_ipsc->cAlphaArgs(4)));
    1060            1 :         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            1 :         if (chargeBlock.season != Season::Annual) {
    1067            1 :             if (chargeBlock.tariffIndx != 0) {
    1068            1 :                 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            1 :         chargeBlock.categoryPt =
    1078            1 :             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            1 :         chargeBlock.remainingPt =
    1081            1 :             AssignVariablePt(state, s_ipsc->cAlphaArgs(6), true, varIsAssigned, varNotYetDefined, ObjType::Category, iInObj, chargeBlock.tariffIndx);
    1082              :         // block size multiplier
    1083            1 :         if (len(s_ipsc->cAlphaArgs(7)) == 0) { // if blank
    1084            1 :             chargeBlock.blkSzMultVal = 1.0;    // default is 1 if left blank
    1085            1 :             chargeBlock.blkSzMultPt = 0;
    1086              :         } else {
    1087            0 :             chargeBlock.blkSzMultVal = Util::ProcessNumber(s_ipsc->cAlphaArgs(7), isNotNumeric);
    1088            0 :             chargeBlock.blkSzMultPt = AssignVariablePt(
    1089            0 :                 state, s_ipsc->cAlphaArgs(7), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, chargeBlock.tariffIndx);
    1090              :         }
    1091              :         // number of blocks used
    1092            1 :         chargeBlock.numBlk = (NumAlphas - 7) / 2;
    1093            4 :         for (int jBlk = 1; jBlk <= chargeBlock.numBlk; ++jBlk) {
    1094            3 :             alphaOffset = 7 + (jBlk - 1) * 2;
    1095              :             // catch the "remaining" code word for the block size
    1096            3 :             if (Util::SameString(s_ipsc->cAlphaArgs(alphaOffset + 1), "REMAINING")) {
    1097            1 :                 chargeBlock.blkSzVal(jBlk) = hugeNumber / 1000000; // using small portion of largest possible value to prevent overflow
    1098            1 :                 chargeBlock.blkSzPt(jBlk) = 0;
    1099              :             } else {
    1100              :                 // array of block size
    1101            2 :                 chargeBlock.blkSzVal(jBlk) = Util::ProcessNumber(s_ipsc->cAlphaArgs(alphaOffset + 1), isNotNumeric);
    1102              : 
    1103            2 :                 chargeBlock.blkSzPt(jBlk) = AssignVariablePt(state,
    1104            2 :                                                              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            3 :             chargeBlock.blkCostVal(jBlk) = Util::ProcessNumber(s_ipsc->cAlphaArgs(alphaOffset + 2), isNotNumeric);
    1114            3 :             chargeBlock.blkCostPt(jBlk) = AssignVariablePt(state,
    1115            3 :                                                            s_ipsc->cAlphaArgs(alphaOffset + 2),
    1116              :                                                            isNotNumeric,
    1117              :                                                            varIsArgument,
    1118              :                                                            varNotYetDefined,
    1119              :                                                            ObjType::Invalid,
    1120              :                                                            0,
    1121              :                                                            chargeBlock.tariffIndx);
    1122              :         }
    1123              :     }
    1124            7 : }
    1125              : 
    1126            7 : 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            7 :     auto &s_econ = state.dataEconTariff;
    1142            7 :     auto &s_ipsc = state.dataIPShortCut;
    1143            7 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Ratchet";
    1144              : 
    1145            7 :     s_econ->numRatchet = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1146            7 :     s_econ->ratchet.allocate(s_econ->numRatchet);
    1147            8 :     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            7 : }
    1205              : 
    1206           11 : 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           11 :     auto &s_econ = state.dataEconTariff;
    1221           11 :     auto &s_ipsc = state.dataIPShortCut;
    1222              : 
    1223           11 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Variable";
    1224           11 :     int numEconVarObj = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1225           15 :     for (int iInObj = 1; iInObj <= numEconVarObj; ++iInObj) {
    1226            8 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1227            4 :                                                                  s_ipsc->cCurrentModuleObject,
    1228              :                                                                  iInObj,
    1229            4 :                                                                  s_ipsc->cAlphaArgs,
    1230              :                                                                  NumAlphas,
    1231            4 :                                                                  s_ipsc->rNumericArgs,
    1232              :                                                                  NumNums,
    1233              :                                                                  IOStat,
    1234            4 :                                                                  s_ipsc->lNumericFieldBlanks,
    1235            4 :                                                                  s_ipsc->lAlphaFieldBlanks,
    1236            4 :                                                                  s_ipsc->cAlphaFieldNames,
    1237            4 :                                                                  s_ipsc->cNumericFieldNames);
    1238              : 
    1239            4 :         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           16 :         for (int jFld = 1; jFld <= NumAlphas; ++jFld) {
    1243           12 :             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            4 :         int tariffPt = FindTariffIndex(state, s_ipsc->cAlphaArgs(2), s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject);
    1249            4 :         int variablePt = AssignVariablePt(state, s_ipsc->cAlphaArgs(1), true, varIsArgument, varUserDefined, ObjType::Variable, iInObj, tariffPt);
    1250            4 :         warnIfNativeVarname(state, s_ipsc->cAlphaArgs(1), tariffPt, ErrorsFound, s_ipsc->cCurrentModuleObject);
    1251            4 :         auto &econVar = s_econ->econVar(variablePt);
    1252              : 
    1253              :         // validate the kind of variable - not used internally except for validation
    1254            4 :         econVar.varUnitType = static_cast<VarUnitType>(getEnumValue(varUnitTypeNamesUC, s_ipsc->cAlphaArgs(3)));
    1255            4 :         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           52 :         for (int jVal = 1; jVal <= NumNums; ++jVal) {
    1263           48 :             econVar.values(jVal) = s_ipsc->rNumericArgs(jVal);
    1264              :         }
    1265              :         // fill the rest of the array with the last value entered
    1266            4 :         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           11 : }
    1273              : 
    1274            7 : 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            7 :     auto &s_econ = state.dataEconTariff;
    1289            7 :     auto &s_ipsc = state.dataIPShortCut;
    1290              : 
    1291            7 :     s_ipsc->cCurrentModuleObject = "UtilityCost:Computation";
    1292            7 :     s_econ->numComputation = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1293            7 :     s_econ->computation.allocate(s_econ->numTariff); // not the number of Computations but the number of tariffs
    1294              :     // set default values for computation
    1295           14 :     for (auto &e : s_econ->computation) {
    1296            7 :         e.computeName.clear();
    1297            7 :         e.firstStep = 0;
    1298            7 :         e.lastStep = -1;
    1299            7 :         e.isUserDef = false;
    1300            7 :     }
    1301            8 :     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            7 : }
    1352              : 
    1353           80 : 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           80 :     auto &s_ipsc = state.dataIPShortCut;
    1370           80 :     s_ipsc->cCurrentModuleObject = "CurrencyType";
    1371              : 
    1372           80 :     initializeMonetaryUnit(state);
    1373           80 :     NumCurrencyType = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
    1374           80 :     state.dataCostEstimateManager->selectedMonetaryUnit = 0; // invalid
    1375           80 :     if (NumCurrencyType == 0) {
    1376           80 :         state.dataCostEstimateManager->selectedMonetaryUnit = 1; // USD - U.S. Dollar
    1377            0 :     } else if (NumCurrencyType == 1) {
    1378            0 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1379            0 :                                                                  s_ipsc->cCurrentModuleObject,
    1380              :                                                                  1,
    1381            0 :                                                                  s_ipsc->cAlphaArgs,
    1382              :                                                                  NumAlphas,
    1383            0 :                                                                  s_ipsc->rNumericArgs,
    1384              :                                                                  NumNums,
    1385              :                                                                  IOStat,
    1386            0 :                                                                  s_ipsc->lNumericFieldBlanks,
    1387            0 :                                                                  s_ipsc->lAlphaFieldBlanks,
    1388            0 :                                                                  s_ipsc->cAlphaFieldNames,
    1389            0 :                                                                  s_ipsc->cNumericFieldNames);
    1390              :         // Monetary Unit
    1391            0 :         for (i = 1; i <= (int)state.dataCostEstimateManager->monetaryUnit.size(); ++i) {
    1392            0 :             if (Util::SameString(s_ipsc->cAlphaArgs(1), state.dataCostEstimateManager->monetaryUnit(i).code)) {
    1393            0 :                 state.dataCostEstimateManager->selectedMonetaryUnit = i;
    1394            0 :                 break;
    1395              :             }
    1396              :         }
    1397            0 :         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           80 : }
    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           80 : 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           80 :     int numMonetaryUnit = 111;
    1546           80 :     state.dataCostEstimateManager->monetaryUnit.allocate(numMonetaryUnit);
    1547           80 :     state.dataCostEstimateManager->monetaryUnit(1).code = "USD";
    1548           80 :     state.dataCostEstimateManager->monetaryUnit(2).code = "AFN";
    1549           80 :     state.dataCostEstimateManager->monetaryUnit(3).code = "ALL";
    1550           80 :     state.dataCostEstimateManager->monetaryUnit(4).code = "ANG";
    1551           80 :     state.dataCostEstimateManager->monetaryUnit(5).code = "ARS";
    1552           80 :     state.dataCostEstimateManager->monetaryUnit(6).code = "AUD";
    1553           80 :     state.dataCostEstimateManager->monetaryUnit(7).code = "AWG";
    1554           80 :     state.dataCostEstimateManager->monetaryUnit(8).code = "AZN";
    1555           80 :     state.dataCostEstimateManager->monetaryUnit(9).code = "BAM";
    1556           80 :     state.dataCostEstimateManager->monetaryUnit(10).code = "BBD";
    1557           80 :     state.dataCostEstimateManager->monetaryUnit(11).code = "BGN";
    1558           80 :     state.dataCostEstimateManager->monetaryUnit(12).code = "BMD";
    1559           80 :     state.dataCostEstimateManager->monetaryUnit(13).code = "BND";
    1560           80 :     state.dataCostEstimateManager->monetaryUnit(14).code = "BOB";
    1561           80 :     state.dataCostEstimateManager->monetaryUnit(15).code = "BRL";
    1562           80 :     state.dataCostEstimateManager->monetaryUnit(16).code = "BSD";
    1563           80 :     state.dataCostEstimateManager->monetaryUnit(17).code = "BWP";
    1564           80 :     state.dataCostEstimateManager->monetaryUnit(18).code = "BYR";
    1565           80 :     state.dataCostEstimateManager->monetaryUnit(19).code = "BZD";
    1566           80 :     state.dataCostEstimateManager->monetaryUnit(20).code = "CAD";
    1567           80 :     state.dataCostEstimateManager->monetaryUnit(21).code = "CHF";
    1568           80 :     state.dataCostEstimateManager->monetaryUnit(22).code = "CLP";
    1569           80 :     state.dataCostEstimateManager->monetaryUnit(23).code = "CNY";
    1570           80 :     state.dataCostEstimateManager->monetaryUnit(24).code = "COP";
    1571           80 :     state.dataCostEstimateManager->monetaryUnit(25).code = "CRC";
    1572           80 :     state.dataCostEstimateManager->monetaryUnit(26).code = "CUP";
    1573           80 :     state.dataCostEstimateManager->monetaryUnit(27).code = "CZK";
    1574           80 :     state.dataCostEstimateManager->monetaryUnit(28).code = "DKK";
    1575           80 :     state.dataCostEstimateManager->monetaryUnit(29).code = "DOP";
    1576           80 :     state.dataCostEstimateManager->monetaryUnit(30).code = "EEK";
    1577           80 :     state.dataCostEstimateManager->monetaryUnit(31).code = "EGP";
    1578           80 :     state.dataCostEstimateManager->monetaryUnit(32).code = "EUR";
    1579           80 :     state.dataCostEstimateManager->monetaryUnit(33).code = "FJD";
    1580           80 :     state.dataCostEstimateManager->monetaryUnit(34).code = "GBP";
    1581           80 :     state.dataCostEstimateManager->monetaryUnit(35).code = "GHC";
    1582           80 :     state.dataCostEstimateManager->monetaryUnit(36).code = "GIP";
    1583           80 :     state.dataCostEstimateManager->monetaryUnit(37).code = "GTQ";
    1584           80 :     state.dataCostEstimateManager->monetaryUnit(38).code = "GYD";
    1585           80 :     state.dataCostEstimateManager->monetaryUnit(39).code = "HKD";
    1586           80 :     state.dataCostEstimateManager->monetaryUnit(40).code = "HNL";
    1587           80 :     state.dataCostEstimateManager->monetaryUnit(41).code = "HRK";
    1588           80 :     state.dataCostEstimateManager->monetaryUnit(42).code = "HUF";
    1589           80 :     state.dataCostEstimateManager->monetaryUnit(43).code = "IDR";
    1590           80 :     state.dataCostEstimateManager->monetaryUnit(44).code = "ILS";
    1591           80 :     state.dataCostEstimateManager->monetaryUnit(45).code = "IMP";
    1592           80 :     state.dataCostEstimateManager->monetaryUnit(46).code = "INR";
    1593           80 :     state.dataCostEstimateManager->monetaryUnit(47).code = "IRR";
    1594           80 :     state.dataCostEstimateManager->monetaryUnit(48).code = "ISK";
    1595           80 :     state.dataCostEstimateManager->monetaryUnit(49).code = "JEP";
    1596           80 :     state.dataCostEstimateManager->monetaryUnit(50).code = "JMD";
    1597           80 :     state.dataCostEstimateManager->monetaryUnit(51).code = "JPY";
    1598           80 :     state.dataCostEstimateManager->monetaryUnit(52).code = "KGS";
    1599           80 :     state.dataCostEstimateManager->monetaryUnit(53).code = "KHR";
    1600           80 :     state.dataCostEstimateManager->monetaryUnit(54).code = "KPW";
    1601           80 :     state.dataCostEstimateManager->monetaryUnit(55).code = "KRW";
    1602           80 :     state.dataCostEstimateManager->monetaryUnit(56).code = "KYD";
    1603           80 :     state.dataCostEstimateManager->monetaryUnit(57).code = "KZT";
    1604           80 :     state.dataCostEstimateManager->monetaryUnit(58).code = "LAK";
    1605           80 :     state.dataCostEstimateManager->monetaryUnit(59).code = "LBP";
    1606           80 :     state.dataCostEstimateManager->monetaryUnit(60).code = "LKR";
    1607           80 :     state.dataCostEstimateManager->monetaryUnit(61).code = "LRD";
    1608           80 :     state.dataCostEstimateManager->monetaryUnit(62).code = "LTL";
    1609           80 :     state.dataCostEstimateManager->monetaryUnit(63).code = "LVL";
    1610           80 :     state.dataCostEstimateManager->monetaryUnit(64).code = "MKD";
    1611           80 :     state.dataCostEstimateManager->monetaryUnit(65).code = "MNT";
    1612           80 :     state.dataCostEstimateManager->monetaryUnit(66).code = "MUR";
    1613           80 :     state.dataCostEstimateManager->monetaryUnit(67).code = "MXN";
    1614           80 :     state.dataCostEstimateManager->monetaryUnit(68).code = "MYR";
    1615           80 :     state.dataCostEstimateManager->monetaryUnit(69).code = "MZN";
    1616           80 :     state.dataCostEstimateManager->monetaryUnit(70).code = "NAD";
    1617           80 :     state.dataCostEstimateManager->monetaryUnit(71).code = "NGN";
    1618           80 :     state.dataCostEstimateManager->monetaryUnit(72).code = "NIO";
    1619           80 :     state.dataCostEstimateManager->monetaryUnit(73).code = "NOK";
    1620           80 :     state.dataCostEstimateManager->monetaryUnit(74).code = "NPR";
    1621           80 :     state.dataCostEstimateManager->monetaryUnit(75).code = "NZD";
    1622           80 :     state.dataCostEstimateManager->monetaryUnit(76).code = "OMR";
    1623           80 :     state.dataCostEstimateManager->monetaryUnit(77).code = "PAB";
    1624           80 :     state.dataCostEstimateManager->monetaryUnit(78).code = "PEN";
    1625           80 :     state.dataCostEstimateManager->monetaryUnit(79).code = "PHP";
    1626           80 :     state.dataCostEstimateManager->monetaryUnit(80).code = "PKR";
    1627           80 :     state.dataCostEstimateManager->monetaryUnit(81).code = "PLN";
    1628           80 :     state.dataCostEstimateManager->monetaryUnit(82).code = "PYG";
    1629           80 :     state.dataCostEstimateManager->monetaryUnit(83).code = "QAR";
    1630           80 :     state.dataCostEstimateManager->monetaryUnit(84).code = "RON";
    1631           80 :     state.dataCostEstimateManager->monetaryUnit(85).code = "RSD";
    1632           80 :     state.dataCostEstimateManager->monetaryUnit(86).code = "RUB";
    1633           80 :     state.dataCostEstimateManager->monetaryUnit(87).code = "SAR";
    1634           80 :     state.dataCostEstimateManager->monetaryUnit(88).code = "SBD";
    1635           80 :     state.dataCostEstimateManager->monetaryUnit(89).code = "SCR";
    1636           80 :     state.dataCostEstimateManager->monetaryUnit(90).code = "SEK";
    1637           80 :     state.dataCostEstimateManager->monetaryUnit(91).code = "SGD";
    1638           80 :     state.dataCostEstimateManager->monetaryUnit(92).code = "SHP";
    1639           80 :     state.dataCostEstimateManager->monetaryUnit(93).code = "SOS";
    1640           80 :     state.dataCostEstimateManager->monetaryUnit(94).code = "SRD";
    1641           80 :     state.dataCostEstimateManager->monetaryUnit(95).code = "SVC";
    1642           80 :     state.dataCostEstimateManager->monetaryUnit(96).code = "SYP";
    1643           80 :     state.dataCostEstimateManager->monetaryUnit(97).code = "THB";
    1644           80 :     state.dataCostEstimateManager->monetaryUnit(98).code = "TRL";
    1645           80 :     state.dataCostEstimateManager->monetaryUnit(99).code = "TRY";
    1646           80 :     state.dataCostEstimateManager->monetaryUnit(100).code = "TTD";
    1647           80 :     state.dataCostEstimateManager->monetaryUnit(101).code = "TVD";
    1648           80 :     state.dataCostEstimateManager->monetaryUnit(102).code = "TWD";
    1649           80 :     state.dataCostEstimateManager->monetaryUnit(103).code = "UAH";
    1650           80 :     state.dataCostEstimateManager->monetaryUnit(104).code = "UYU";
    1651           80 :     state.dataCostEstimateManager->monetaryUnit(105).code = "UZS";
    1652           80 :     state.dataCostEstimateManager->monetaryUnit(106).code = "VEF";
    1653           80 :     state.dataCostEstimateManager->monetaryUnit(107).code = "VND";
    1654           80 :     state.dataCostEstimateManager->monetaryUnit(108).code = "XCD";
    1655           80 :     state.dataCostEstimateManager->monetaryUnit(109).code = "YER";
    1656           80 :     state.dataCostEstimateManager->monetaryUnit(110).code = "ZAR";
    1657           80 :     state.dataCostEstimateManager->monetaryUnit(111).code = "ZWD";
    1658              : 
    1659           80 :     state.dataCostEstimateManager->monetaryUnit(1).txt = "$";
    1660           80 :     state.dataCostEstimateManager->monetaryUnit(2).txt = "AFN";
    1661           80 :     state.dataCostEstimateManager->monetaryUnit(3).txt = "Lek";
    1662           80 :     state.dataCostEstimateManager->monetaryUnit(4).txt = "ANG";
    1663           80 :     state.dataCostEstimateManager->monetaryUnit(5).txt = "$";
    1664           80 :     state.dataCostEstimateManager->monetaryUnit(6).txt = "$";
    1665           80 :     state.dataCostEstimateManager->monetaryUnit(7).txt = "AWG";
    1666           80 :     state.dataCostEstimateManager->monetaryUnit(8).txt = "AZN";
    1667           80 :     state.dataCostEstimateManager->monetaryUnit(9).txt = "KM";
    1668           80 :     state.dataCostEstimateManager->monetaryUnit(10).txt = "$";
    1669           80 :     state.dataCostEstimateManager->monetaryUnit(11).txt = "BGN";
    1670           80 :     state.dataCostEstimateManager->monetaryUnit(12).txt = "$";
    1671           80 :     state.dataCostEstimateManager->monetaryUnit(13).txt = "$";
    1672           80 :     state.dataCostEstimateManager->monetaryUnit(14).txt = "$b";
    1673           80 :     state.dataCostEstimateManager->monetaryUnit(15).txt = "R$";
    1674           80 :     state.dataCostEstimateManager->monetaryUnit(16).txt = "$";
    1675           80 :     state.dataCostEstimateManager->monetaryUnit(17).txt = "P";
    1676           80 :     state.dataCostEstimateManager->monetaryUnit(18).txt = "p.";
    1677           80 :     state.dataCostEstimateManager->monetaryUnit(19).txt = "BZ$";
    1678           80 :     state.dataCostEstimateManager->monetaryUnit(20).txt = "$";
    1679           80 :     state.dataCostEstimateManager->monetaryUnit(21).txt = "CHF";
    1680           80 :     state.dataCostEstimateManager->monetaryUnit(22).txt = "$";
    1681           80 :     state.dataCostEstimateManager->monetaryUnit(23).txt = "CNY";
    1682           80 :     state.dataCostEstimateManager->monetaryUnit(24).txt = "$";
    1683           80 :     state.dataCostEstimateManager->monetaryUnit(25).txt = "CRC";
    1684           80 :     state.dataCostEstimateManager->monetaryUnit(26).txt = "CUP";
    1685           80 :     state.dataCostEstimateManager->monetaryUnit(27).txt = "CZK";
    1686           80 :     state.dataCostEstimateManager->monetaryUnit(28).txt = "kr";
    1687           80 :     state.dataCostEstimateManager->monetaryUnit(29).txt = "RD$";
    1688           80 :     state.dataCostEstimateManager->monetaryUnit(30).txt = "kr";
    1689           80 :     state.dataCostEstimateManager->monetaryUnit(31).txt = "£";
    1690           80 :     state.dataCostEstimateManager->monetaryUnit(32).txt = "EUR";
    1691           80 :     state.dataCostEstimateManager->monetaryUnit(33).txt = "$";
    1692           80 :     state.dataCostEstimateManager->monetaryUnit(34).txt = "£";
    1693           80 :     state.dataCostEstimateManager->monetaryUnit(35).txt = "¢";
    1694           80 :     state.dataCostEstimateManager->monetaryUnit(36).txt = "£";
    1695           80 :     state.dataCostEstimateManager->monetaryUnit(37).txt = "Q";
    1696           80 :     state.dataCostEstimateManager->monetaryUnit(38).txt = "$";
    1697           80 :     state.dataCostEstimateManager->monetaryUnit(39).txt = "HK$";
    1698           80 :     state.dataCostEstimateManager->monetaryUnit(40).txt = "L";
    1699           80 :     state.dataCostEstimateManager->monetaryUnit(41).txt = "kn";
    1700           80 :     state.dataCostEstimateManager->monetaryUnit(42).txt = "Ft";
    1701           80 :     state.dataCostEstimateManager->monetaryUnit(43).txt = "Rp";
    1702           80 :     state.dataCostEstimateManager->monetaryUnit(44).txt = "ILS";
    1703           80 :     state.dataCostEstimateManager->monetaryUnit(45).txt = "£";
    1704           80 :     state.dataCostEstimateManager->monetaryUnit(46).txt = "INR";
    1705           80 :     state.dataCostEstimateManager->monetaryUnit(47).txt = "IRR";
    1706           80 :     state.dataCostEstimateManager->monetaryUnit(48).txt = "kr";
    1707           80 :     state.dataCostEstimateManager->monetaryUnit(49).txt = "£";
    1708           80 :     state.dataCostEstimateManager->monetaryUnit(50).txt = "J$";
    1709           80 :     state.dataCostEstimateManager->monetaryUnit(51).txt = "Â¥";
    1710           80 :     state.dataCostEstimateManager->monetaryUnit(52).txt = "KGS";
    1711           80 :     state.dataCostEstimateManager->monetaryUnit(53).txt = "KHR";
    1712           80 :     state.dataCostEstimateManager->monetaryUnit(54).txt = "KPW";
    1713           80 :     state.dataCostEstimateManager->monetaryUnit(55).txt = "KRW";
    1714           80 :     state.dataCostEstimateManager->monetaryUnit(56).txt = "$";
    1715           80 :     state.dataCostEstimateManager->monetaryUnit(57).txt = "KZT";
    1716           80 :     state.dataCostEstimateManager->monetaryUnit(58).txt = "LAK";
    1717           80 :     state.dataCostEstimateManager->monetaryUnit(59).txt = "£";
    1718           80 :     state.dataCostEstimateManager->monetaryUnit(60).txt = "LKR";
    1719           80 :     state.dataCostEstimateManager->monetaryUnit(61).txt = "$";
    1720           80 :     state.dataCostEstimateManager->monetaryUnit(62).txt = "Lt";
    1721           80 :     state.dataCostEstimateManager->monetaryUnit(63).txt = "Ls";
    1722           80 :     state.dataCostEstimateManager->monetaryUnit(64).txt = "MKD";
    1723           80 :     state.dataCostEstimateManager->monetaryUnit(65).txt = "MNT";
    1724           80 :     state.dataCostEstimateManager->monetaryUnit(66).txt = "MUR";
    1725           80 :     state.dataCostEstimateManager->monetaryUnit(67).txt = "$";
    1726           80 :     state.dataCostEstimateManager->monetaryUnit(68).txt = "RM";
    1727           80 :     state.dataCostEstimateManager->monetaryUnit(69).txt = "MT";
    1728           80 :     state.dataCostEstimateManager->monetaryUnit(70).txt = "$";
    1729           80 :     state.dataCostEstimateManager->monetaryUnit(71).txt = "NGN";
    1730           80 :     state.dataCostEstimateManager->monetaryUnit(72).txt = "C$";
    1731           80 :     state.dataCostEstimateManager->monetaryUnit(73).txt = "kr";
    1732           80 :     state.dataCostEstimateManager->monetaryUnit(74).txt = "NPR";
    1733           80 :     state.dataCostEstimateManager->monetaryUnit(75).txt = "$";
    1734           80 :     state.dataCostEstimateManager->monetaryUnit(76).txt = "OMR";
    1735           80 :     state.dataCostEstimateManager->monetaryUnit(77).txt = "B/.";
    1736           80 :     state.dataCostEstimateManager->monetaryUnit(78).txt = "S/.";
    1737           80 :     state.dataCostEstimateManager->monetaryUnit(79).txt = "Php";
    1738           80 :     state.dataCostEstimateManager->monetaryUnit(80).txt = "PKR";
    1739           80 :     state.dataCostEstimateManager->monetaryUnit(81).txt = "PLN";
    1740           80 :     state.dataCostEstimateManager->monetaryUnit(82).txt = "Gs";
    1741           80 :     state.dataCostEstimateManager->monetaryUnit(83).txt = "QAR";
    1742           80 :     state.dataCostEstimateManager->monetaryUnit(84).txt = "lei";
    1743           80 :     state.dataCostEstimateManager->monetaryUnit(85).txt = "RSD";
    1744           80 :     state.dataCostEstimateManager->monetaryUnit(86).txt = "RUB";
    1745           80 :     state.dataCostEstimateManager->monetaryUnit(87).txt = "SAR";
    1746           80 :     state.dataCostEstimateManager->monetaryUnit(88).txt = "$";
    1747           80 :     state.dataCostEstimateManager->monetaryUnit(89).txt = "SCR";
    1748           80 :     state.dataCostEstimateManager->monetaryUnit(90).txt = "kr";
    1749           80 :     state.dataCostEstimateManager->monetaryUnit(91).txt = "$";
    1750           80 :     state.dataCostEstimateManager->monetaryUnit(92).txt = "£";
    1751           80 :     state.dataCostEstimateManager->monetaryUnit(93).txt = "S";
    1752           80 :     state.dataCostEstimateManager->monetaryUnit(94).txt = "$";
    1753           80 :     state.dataCostEstimateManager->monetaryUnit(95).txt = "$";
    1754           80 :     state.dataCostEstimateManager->monetaryUnit(96).txt = "£";
    1755           80 :     state.dataCostEstimateManager->monetaryUnit(97).txt = "THB";
    1756           80 :     state.dataCostEstimateManager->monetaryUnit(98).txt = "TRL";
    1757           80 :     state.dataCostEstimateManager->monetaryUnit(99).txt = "YTL";
    1758           80 :     state.dataCostEstimateManager->monetaryUnit(100).txt = "TT$";
    1759           80 :     state.dataCostEstimateManager->monetaryUnit(101).txt = "$";
    1760           80 :     state.dataCostEstimateManager->monetaryUnit(102).txt = "NT$";
    1761           80 :     state.dataCostEstimateManager->monetaryUnit(103).txt = "UAH";
    1762           80 :     state.dataCostEstimateManager->monetaryUnit(104).txt = "$U";
    1763           80 :     state.dataCostEstimateManager->monetaryUnit(105).txt = "UZS";
    1764           80 :     state.dataCostEstimateManager->monetaryUnit(106).txt = "Bs";
    1765           80 :     state.dataCostEstimateManager->monetaryUnit(107).txt = "VND";
    1766           80 :     state.dataCostEstimateManager->monetaryUnit(108).txt = "$";
    1767           80 :     state.dataCostEstimateManager->monetaryUnit(109).txt = "YER";
    1768           80 :     state.dataCostEstimateManager->monetaryUnit(110).txt = "R";
    1769           80 :     state.dataCostEstimateManager->monetaryUnit(111).txt = "Z$";
    1770              : 
    1771           80 :     state.dataCostEstimateManager->monetaryUnit(1).html = "$";
    1772           80 :     state.dataCostEstimateManager->monetaryUnit(2).html = "&#x060b;";
    1773           80 :     state.dataCostEstimateManager->monetaryUnit(3).html = "Lek";
    1774           80 :     state.dataCostEstimateManager->monetaryUnit(4).html = "&#x0192;";
    1775           80 :     state.dataCostEstimateManager->monetaryUnit(5).html = "$";
    1776           80 :     state.dataCostEstimateManager->monetaryUnit(6).html = "$";
    1777           80 :     state.dataCostEstimateManager->monetaryUnit(7).html = "&#x0192;";
    1778           80 :     state.dataCostEstimateManager->monetaryUnit(8).html = "&#x043c;&#x0430;&#x043d;";
    1779           80 :     state.dataCostEstimateManager->monetaryUnit(9).html = "KM";
    1780           80 :     state.dataCostEstimateManager->monetaryUnit(10).html = "$";
    1781           80 :     state.dataCostEstimateManager->monetaryUnit(11).html = "&#x043b;&#x0432;";
    1782           80 :     state.dataCostEstimateManager->monetaryUnit(12).html = "$";
    1783           80 :     state.dataCostEstimateManager->monetaryUnit(13).html = "$";
    1784           80 :     state.dataCostEstimateManager->monetaryUnit(14).html = "$b";
    1785           80 :     state.dataCostEstimateManager->monetaryUnit(15).html = "R$";
    1786           80 :     state.dataCostEstimateManager->monetaryUnit(16).html = "$";
    1787           80 :     state.dataCostEstimateManager->monetaryUnit(17).html = "P";
    1788           80 :     state.dataCostEstimateManager->monetaryUnit(18).html = "p.";
    1789           80 :     state.dataCostEstimateManager->monetaryUnit(19).html = "BZ$";
    1790           80 :     state.dataCostEstimateManager->monetaryUnit(20).html = "$";
    1791           80 :     state.dataCostEstimateManager->monetaryUnit(21).html = "CHF";
    1792           80 :     state.dataCostEstimateManager->monetaryUnit(22).html = "$";
    1793           80 :     state.dataCostEstimateManager->monetaryUnit(23).html = "&#x5143;";
    1794           80 :     state.dataCostEstimateManager->monetaryUnit(24).html = "$";
    1795           80 :     state.dataCostEstimateManager->monetaryUnit(25).html = "&#x20a1;";
    1796           80 :     state.dataCostEstimateManager->monetaryUnit(26).html = "&#x20b1;";
    1797           80 :     state.dataCostEstimateManager->monetaryUnit(27).html = "&#x004b;&#x010d;";
    1798           80 :     state.dataCostEstimateManager->monetaryUnit(28).html = "kr";
    1799           80 :     state.dataCostEstimateManager->monetaryUnit(29).html = "RD$";
    1800           80 :     state.dataCostEstimateManager->monetaryUnit(30).html = "kr";
    1801           80 :     state.dataCostEstimateManager->monetaryUnit(31).html = "£";
    1802           80 :     state.dataCostEstimateManager->monetaryUnit(32).html = "&#x20ac;";
    1803           80 :     state.dataCostEstimateManager->monetaryUnit(33).html = "$";
    1804           80 :     state.dataCostEstimateManager->monetaryUnit(34).html = "£";
    1805           80 :     state.dataCostEstimateManager->monetaryUnit(35).html = "¢";
    1806           80 :     state.dataCostEstimateManager->monetaryUnit(36).html = "£";
    1807           80 :     state.dataCostEstimateManager->monetaryUnit(37).html = "Q";
    1808           80 :     state.dataCostEstimateManager->monetaryUnit(38).html = "$";
    1809           80 :     state.dataCostEstimateManager->monetaryUnit(39).html = "HK$";
    1810           80 :     state.dataCostEstimateManager->monetaryUnit(40).html = "L";
    1811           80 :     state.dataCostEstimateManager->monetaryUnit(41).html = "kn";
    1812           80 :     state.dataCostEstimateManager->monetaryUnit(42).html = "Ft";
    1813           80 :     state.dataCostEstimateManager->monetaryUnit(43).html = "Rp";
    1814           80 :     state.dataCostEstimateManager->monetaryUnit(44).html = "&#x20aa;";
    1815           80 :     state.dataCostEstimateManager->monetaryUnit(45).html = "£";
    1816           80 :     state.dataCostEstimateManager->monetaryUnit(46).html = "&#x20a8;";
    1817           80 :     state.dataCostEstimateManager->monetaryUnit(47).html = "&#xfdfc;";
    1818           80 :     state.dataCostEstimateManager->monetaryUnit(48).html = "kr";
    1819           80 :     state.dataCostEstimateManager->monetaryUnit(49).html = "£";
    1820           80 :     state.dataCostEstimateManager->monetaryUnit(50).html = "J$";
    1821           80 :     state.dataCostEstimateManager->monetaryUnit(51).html = "Â¥";
    1822           80 :     state.dataCostEstimateManager->monetaryUnit(52).html = "&#x043b;&#x0432;";
    1823           80 :     state.dataCostEstimateManager->monetaryUnit(53).html = "&#x17db;";
    1824           80 :     state.dataCostEstimateManager->monetaryUnit(54).html = "&#x20a9;";
    1825           80 :     state.dataCostEstimateManager->monetaryUnit(55).html = "&#x20a9;";
    1826           80 :     state.dataCostEstimateManager->monetaryUnit(56).html = "$";
    1827           80 :     state.dataCostEstimateManager->monetaryUnit(57).html = "&#x043b;&#x0432;";
    1828           80 :     state.dataCostEstimateManager->monetaryUnit(58).html = "&#x20ad;";
    1829           80 :     state.dataCostEstimateManager->monetaryUnit(59).html = "£";
    1830           80 :     state.dataCostEstimateManager->monetaryUnit(60).html = "&#x20a8;";
    1831           80 :     state.dataCostEstimateManager->monetaryUnit(61).html = "$";
    1832           80 :     state.dataCostEstimateManager->monetaryUnit(62).html = "Lt";
    1833           80 :     state.dataCostEstimateManager->monetaryUnit(63).html = "Ls";
    1834           80 :     state.dataCostEstimateManager->monetaryUnit(64).html = "&#x0434;&#x0435;&#x043d;";
    1835           80 :     state.dataCostEstimateManager->monetaryUnit(65).html = "&#x20ae;";
    1836           80 :     state.dataCostEstimateManager->monetaryUnit(66).html = "&#x20a8;";
    1837           80 :     state.dataCostEstimateManager->monetaryUnit(67).html = "$";
    1838           80 :     state.dataCostEstimateManager->monetaryUnit(68).html = "RM";
    1839           80 :     state.dataCostEstimateManager->monetaryUnit(69).html = "MT";
    1840           80 :     state.dataCostEstimateManager->monetaryUnit(70).html = "$";
    1841           80 :     state.dataCostEstimateManager->monetaryUnit(71).html = "&#x20a6;";
    1842           80 :     state.dataCostEstimateManager->monetaryUnit(72).html = "C$";
    1843           80 :     state.dataCostEstimateManager->monetaryUnit(73).html = "kr";
    1844           80 :     state.dataCostEstimateManager->monetaryUnit(74).html = "&#x20a8;";
    1845           80 :     state.dataCostEstimateManager->monetaryUnit(75).html = "$";
    1846           80 :     state.dataCostEstimateManager->monetaryUnit(76).html = "&#xfdfc;";
    1847           80 :     state.dataCostEstimateManager->monetaryUnit(77).html = "B/.";
    1848           80 :     state.dataCostEstimateManager->monetaryUnit(78).html = "S/.";
    1849           80 :     state.dataCostEstimateManager->monetaryUnit(79).html = "Php";
    1850           80 :     state.dataCostEstimateManager->monetaryUnit(80).html = "&#x20a8;";
    1851           80 :     state.dataCostEstimateManager->monetaryUnit(81).html = "&#x007a;&#x0142;";
    1852           80 :     state.dataCostEstimateManager->monetaryUnit(82).html = "Gs";
    1853           80 :     state.dataCostEstimateManager->monetaryUnit(83).html = "&#xfdfc;";
    1854           80 :     state.dataCostEstimateManager->monetaryUnit(84).html = "lei";
    1855           80 :     state.dataCostEstimateManager->monetaryUnit(85).html = "&#x0414;&#x0438;&#x043d;&#x002e;";
    1856           80 :     state.dataCostEstimateManager->monetaryUnit(86).html = "&#x0440;&#x0443;&#x0431;";
    1857           80 :     state.dataCostEstimateManager->monetaryUnit(87).html = "&#xfdfc;";
    1858           80 :     state.dataCostEstimateManager->monetaryUnit(88).html = "$";
    1859           80 :     state.dataCostEstimateManager->monetaryUnit(89).html = "&#x20a8;";
    1860           80 :     state.dataCostEstimateManager->monetaryUnit(90).html = "kr";
    1861           80 :     state.dataCostEstimateManager->monetaryUnit(91).html = "$";
    1862           80 :     state.dataCostEstimateManager->monetaryUnit(92).html = "£";
    1863           80 :     state.dataCostEstimateManager->monetaryUnit(93).html = "S";
    1864           80 :     state.dataCostEstimateManager->monetaryUnit(94).html = "$";
    1865           80 :     state.dataCostEstimateManager->monetaryUnit(95).html = "$";
    1866           80 :     state.dataCostEstimateManager->monetaryUnit(96).html = "£";
    1867           80 :     state.dataCostEstimateManager->monetaryUnit(97).html = "&#x0e3f;";
    1868           80 :     state.dataCostEstimateManager->monetaryUnit(98).html = "&#x20a4;";
    1869           80 :     state.dataCostEstimateManager->monetaryUnit(99).html = "YTL";
    1870           80 :     state.dataCostEstimateManager->monetaryUnit(100).html = "TT$";
    1871           80 :     state.dataCostEstimateManager->monetaryUnit(101).html = "$";
    1872           80 :     state.dataCostEstimateManager->monetaryUnit(102).html = "NT$";
    1873           80 :     state.dataCostEstimateManager->monetaryUnit(103).html = "&#x20b4;";
    1874           80 :     state.dataCostEstimateManager->monetaryUnit(104).html = "$U";
    1875           80 :     state.dataCostEstimateManager->monetaryUnit(105).html = "&#x043b;&#x0432;";
    1876           80 :     state.dataCostEstimateManager->monetaryUnit(106).html = "Bs";
    1877           80 :     state.dataCostEstimateManager->monetaryUnit(107).html = "&#x20ab;";
    1878           80 :     state.dataCostEstimateManager->monetaryUnit(108).html = "$";
    1879           80 :     state.dataCostEstimateManager->monetaryUnit(109).html = "&#xfdfc;";
    1880           80 :     state.dataCostEstimateManager->monetaryUnit(110).html = "R";
    1881           80 :     state.dataCostEstimateManager->monetaryUnit(111).html = "Z$";
    1882           80 : }
    1883              : 
    1884           16 : 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           16 :     auto &s_econ = state.dataEconTariff;
    1894              : 
    1895              :     int FindTariffIndex;
    1896           16 :     int found = 0;
    1897              : 
    1898           16 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    1899           12 :         if (Util::SameString(nameOfTariff, s_econ->tariff(iTariff).tariffName)) {
    1900           12 :             found = iTariff;
    1901           12 :             break;
    1902              :         }
    1903              :     }
    1904           16 :     if (found > 0) {
    1905           12 :         FindTariffIndex = found;
    1906              :     } else {
    1907            4 :         ShowSevereError(state, format("{}=\"{}\" invalid tariff referenced", nameOfCurObj, nameOfReferingObj));
    1908            4 :         ShowContinueError(state, format("not found UtilityCost:Tariff=\"{}\".", nameOfTariff));
    1909            4 :         ErrorsFound = true;
    1910            4 :         FindTariffIndex = 0;
    1911              :     }
    1912           16 :     return FindTariffIndex;
    1913              : }
    1914              : 
    1915           16 : 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           16 :     auto &s_econ = state.dataEconTariff;
    1924              : 
    1925           16 :     bool throwError = false;
    1926           16 :     if (getEnumValue(nativeNamesUC, objName) != -1) {
    1927            0 :         throwError = true;
    1928           16 :     } else if (getEnumValue(catNamesUC, objName) != -1) {
    1929            0 :         throwError = true;
    1930              :     }
    1931              : 
    1932           16 :     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           16 : }
    1942              : 
    1943          416 : 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          416 :     auto &s_econ = state.dataEconTariff;
    1961              :     int AssignVariablePt;
    1962              : 
    1963          416 :     if (flagIfNotNumeric && (len(stringIn) >= 1)) {
    1964          385 :         std::string inNoSpaces = RemoveSpaces(state, stringIn);
    1965          385 :         int found = 0;
    1966          385 :         if (allocated(s_econ->econVar)) {
    1967         9071 :             for (int iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    1968         8736 :                 if (s_econ->econVar(iVar).tariffIndx == tariffPt) {
    1969         8736 :                     if (Util::SameString(s_econ->econVar(iVar).name, inNoSpaces)) {
    1970           39 :                         found = iVar;
    1971           39 :                         break;
    1972              :                     }
    1973              :                 }
    1974              :             }
    1975              :         }
    1976          385 :         if (found > 0) {
    1977           39 :             AssignVariablePt = found;
    1978           39 :             if (s_econ->econVar(found).kindOfObj == ObjType::Invalid) {
    1979            0 :                 s_econ->econVar(found).kindOfObj = econObjKind;
    1980            0 :                 if (s_econ->econVar(found).index == 0) {
    1981            0 :                     s_econ->econVar(found).index = objIndex;
    1982              :                 }
    1983              :             }
    1984              :         } else {
    1985          346 :             incrementEconVar(state);
    1986          346 :             s_econ->econVar(s_econ->numEconVar).name = inNoSpaces;
    1987          346 :             s_econ->econVar(s_econ->numEconVar).kindOfObj = econObjKind;
    1988          346 :             s_econ->econVar(s_econ->numEconVar).index = objIndex;
    1989          346 :             AssignVariablePt = s_econ->numEconVar;
    1990              :         }
    1991              :         // now set the flag for the type of usage the variable has
    1992          385 :         if (useOfVar == varIsArgument) {
    1993          289 :             s_econ->econVar(AssignVariablePt).isArgument = true;
    1994           96 :         } else if (useOfVar == varIsAssigned) {
    1995           96 :             s_econ->econVar(AssignVariablePt).isAssigned = true;
    1996              :         }
    1997          385 :         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          437 :         if ((varSpecific != varNotYetDefined) ||
    2004           52 :             (s_econ->econVar(AssignVariablePt).kindOfObj != ObjType::Category && s_econ->econVar(AssignVariablePt).kindOfObj != ObjType::Native)) {
    2005          352 :             s_econ->econVar(AssignVariablePt).specific = varSpecific;
    2006              :         }
    2007          385 :     } else { // if the string was numeric return a zero
    2008           31 :         AssignVariablePt = 0;
    2009              :     }
    2010          416 :     return AssignVariablePt;
    2011              : }
    2012              : 
    2013          346 : 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          346 :     int constexpr sizeIncrement(100);
    2021          346 :     auto &s_econ = state.dataEconTariff;
    2022              : 
    2023          346 :     if (!allocated(s_econ->econVar)) {
    2024           11 :         s_econ->econVar.allocate(sizeIncrement);
    2025           11 :         s_econ->sizeEconVar = sizeIncrement;
    2026           11 :         s_econ->numEconVar = 1;
    2027              :     } else {
    2028          335 :         ++s_econ->numEconVar;
    2029              :         // if larger than current size grow the array
    2030          335 :         if (s_econ->numEconVar > s_econ->sizeEconVar) {
    2031            0 :             s_econ->econVar.redimension(s_econ->sizeEconVar += sizeIncrement);
    2032              :         }
    2033              :     }
    2034          346 :     auto &econVar = s_econ->econVar(s_econ->numEconVar);
    2035              : 
    2036              :     // initialize new record) //Autodesk Most of these match default initialization so not needed
    2037          346 :     econVar.name = "";
    2038          346 :     econVar.tariffIndx = 0;
    2039          346 :     econVar.kindOfObj = ObjType::Invalid;
    2040          346 :     econVar.index = 0;
    2041          346 :     std::fill(econVar.values.begin(), econVar.values.end(), 0.0);
    2042          346 :     econVar.isArgument = false;
    2043          346 :     econVar.isAssigned = false;
    2044          346 :     econVar.specific = varNotYetDefined;
    2045              :     //        econVar( numEconVar ).values = 0.0; //Autodesk Already initialized above
    2046              :     // Autodesk Don't initialize cntMeDependOn
    2047          346 :     econVar.Operator = Op::Invalid;
    2048          346 :     econVar.firstOperand = 1; // Autodesk Default initialization sets this to 0
    2049          346 :     econVar.lastOperand = 0;
    2050          346 :     econVar.activeNow = false;
    2051          346 :     econVar.isEvaluated = false;
    2052              :     // Autodesk Don't initialize isReported
    2053              :     // Autodesk Don't initialize varUnitType
    2054          346 : }
    2055              : 
    2056          168 : 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          168 :     auto &s_econ = state.dataEconTariff;
    2065          168 :     int constexpr sizeIncrement(100);
    2066              : 
    2067          168 :     if (!allocated(s_econ->steps)) {
    2068            7 :         s_econ->steps.allocate(sizeIncrement);
    2069            7 :         s_econ->sizeSteps = sizeIncrement;
    2070            7 :         s_econ->numSteps = 1;
    2071              :     } else {
    2072          161 :         ++s_econ->numSteps;
    2073              :         // if larger than current size grow the array
    2074          161 :         if (s_econ->numSteps > s_econ->sizeSteps) {
    2075            0 :             s_econ->steps.redimension(s_econ->sizeSteps += sizeIncrement);
    2076              :         }
    2077              :     }
    2078              :     // initialize new record
    2079          168 :     s_econ->steps(s_econ->numSteps).type = StepType::EOL;
    2080          168 : }
    2081              : 
    2082          385 : 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          385 :     std::string StringOut;
    2090          385 :     bool foundSpaces = false;
    2091         5884 :     for (std::string::size_type iString = 0; iString < len(StringIn); ++iString) {
    2092         5499 :         if (StringIn[iString] != ' ') {
    2093         5499 :             StringOut += StringIn[iString];
    2094              :         } else {
    2095            0 :             foundSpaces = true;
    2096              :         }
    2097              :     }
    2098          385 :     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          385 :     return StringOut;
    2103            0 : }
    2104              : 
    2105            7 : 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            7 :     auto &s_econ = state.dataEconTariff;
    2114           14 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    2115            7 :         auto &tariff = s_econ->tariff(iTariff);
    2116              : 
    2117              :         // category variables first
    2118           77 :         for (int iCat = 0; iCat < (int)Cat::Num; ++iCat) {
    2119           70 :             tariff.cats[iCat] = AssignVariablePt(state, catNames[iCat], true, varIsAssigned, iCat, ObjType::Category, 0, iTariff);
    2120              :         }
    2121              : 
    2122            7 :         tariff.firstCategory = tariff.cats[(int)Cat::EnergyCharges];
    2123            7 :         tariff.lastCategory = tariff.cats[(int)Cat::NotIncluded];
    2124              : 
    2125              :         // category variables first
    2126              : 
    2127          266 :         for (int iNative = 0; iNative < (int)Native::Num; ++iNative) {
    2128          259 :             tariff.natives[iNative] = AssignVariablePt(state, nativeNames[iNative], true, varIsArgument, iNative, ObjType::Native, 0, iTariff);
    2129              :         }
    2130            7 :         tariff.firstNative = tariff.natives[(int)Native::TotalEnergy];
    2131            7 :         tariff.lastNative = tariff.natives[(int)Native::BelowCustomerBaseEnergy];
    2132              :     }
    2133            7 : }
    2134              : 
    2135              : //======================================================================================================================
    2136              : //======================================================================================================================
    2137              : 
    2138              : //    DEFAULT COMPUTATION RELATED ROUTINES
    2139              : 
    2140              : //======================================================================================================================
    2141              : //======================================================================================================================
    2142              : 
    2143            7 : 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            7 :     auto &s_econ = state.dataEconTariff;
    2200              : 
    2201              :     // for each tariff that does not have a UtilityCost:Computation object go through the variables
    2202           14 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    2203            7 :         auto &tariff = s_econ->tariff(iTariff);
    2204            7 :         auto &computation = s_econ->computation(iTariff);
    2205            7 :         if (!computation.isUserDef) {
    2206              :             // clear all variables so that they are not active
    2207          293 :             for (int jVar = 1; jVar <= s_econ->numEconVar; ++jVar) {
    2208          287 :                 s_econ->econVar(jVar).activeNow = false;
    2209              :             }
    2210              :             // make all native variables active
    2211          228 :             for (int jVar = tariff.firstNative; jVar <= tariff.lastNative; ++jVar) {
    2212          222 :                 s_econ->econVar(jVar).activeNow = true;
    2213              :             }
    2214              :             //"clear" the dependOn array
    2215            6 :             s_econ->numOperand = 0;
    2216              :             // Define the preset equations (category summation)
    2217            6 :             int curTotal = tariff.cats[(int)Cat::Total];
    2218            6 :             int curSubtotal = tariff.cats[(int)Cat::Subtotal];
    2219            6 :             int curBasis = tariff.cats[(int)Cat::Basis];
    2220              :             // total SUM subtotal taxes
    2221            6 :             s_econ->econVar(curTotal).Operator = Op::SUM;
    2222            6 :             s_econ->econVar(curTotal).activeNow = true;
    2223            6 :             addOperand(state, curTotal, curSubtotal);
    2224            6 :             addOperand(state, curTotal, tariff.cats[(int)Cat::Taxes]);
    2225              :             // subtotal SUM basis adjustments surcharges
    2226            6 :             s_econ->econVar(curSubtotal).Operator = Op::SUM;
    2227            6 :             s_econ->econVar(curSubtotal).activeNow = true;
    2228            6 :             addOperand(state, curSubtotal, curBasis);
    2229            6 :             addOperand(state, curSubtotal, tariff.cats[(int)Cat::Adjustment]);
    2230            6 :             addOperand(state, curSubtotal, tariff.cats[(int)Cat::Surcharge]);
    2231              :             // basis SUM EnergyCharges DemandCharges ServiceCharges
    2232            6 :             s_econ->econVar(curBasis).Operator = Op::SUM;
    2233            6 :             s_econ->econVar(curBasis).activeNow = true;
    2234            6 :             addOperand(state, curBasis, tariff.cats[(int)Cat::EnergyCharges]);
    2235            6 :             addOperand(state, curBasis, tariff.cats[(int)Cat::DemandCharges]);
    2236            6 :             addOperand(state, curBasis, tariff.cats[(int)Cat::ServiceCharges]);
    2237              :             // set up the equations for other objects
    2238            6 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::EnergyCharges]);
    2239            6 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::DemandCharges]);
    2240            6 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::ServiceCharges]);
    2241            6 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::Adjustment]);
    2242            6 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::Surcharge]);
    2243            6 :             addChargesToOperand(state, iTariff, tariff.cats[(int)Cat::Taxes]);
    2244              :             // add the real time pricing to the energy charges
    2245            6 :             if (tariff.chargeSched != nullptr) {
    2246            0 :                 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            6 :             for (int kObj = 1; kObj <= s_econ->numQualify; ++kObj) {
    2252            0 :                 auto const &qualify = s_econ->qualify(kObj);
    2253            0 :                 if (qualify.tariffIndx == iTariff) {
    2254            0 :                     int curObject = qualify.namePt;
    2255            0 :                     s_econ->econVar(curObject).Operator = Op::NOOP;
    2256            0 :                     s_econ->econVar(curObject).activeNow = true;
    2257            0 :                     addOperand(state, curObject, qualify.sourcePt);
    2258            0 :                     addOperand(state, curObject, qualify.thresholdPt);
    2259              :                 }
    2260              :             }
    2261              :             // Ratchet
    2262            6 :             for (int kObj = 1; kObj <= s_econ->numRatchet; ++kObj) {
    2263            0 :                 auto const &ratchet = s_econ->ratchet(kObj);
    2264            0 :                 if (ratchet.tariffIndx == iTariff) {
    2265            0 :                     int curObject = ratchet.namePt;
    2266            0 :                     s_econ->econVar(curObject).Operator = Op::NOOP;
    2267            0 :                     s_econ->econVar(curObject).activeNow = true;
    2268            0 :                     addOperand(state, curObject, ratchet.baselinePt);
    2269            0 :                     addOperand(state, curObject, ratchet.adjustmentPt);
    2270            0 :                     addOperand(state, curObject, ratchet.multiplierPt);
    2271            0 :                     addOperand(state, curObject, ratchet.offsetPt);
    2272              :                 }
    2273              :             }
    2274              :             // ChargeSimple
    2275           11 :             for (int kObj = 1; kObj <= s_econ->numChargeSimple; ++kObj) {
    2276            5 :                 auto const &chargeSimple = s_econ->chargeSimple(kObj);
    2277            5 :                 if (chargeSimple.tariffIndx == iTariff) {
    2278            5 :                     int curObject = chargeSimple.namePt;
    2279            5 :                     s_econ->econVar(curObject).Operator = Op::NOOP;
    2280            5 :                     s_econ->econVar(curObject).activeNow = true;
    2281            5 :                     addOperand(state, curObject, chargeSimple.sourcePt);
    2282            5 :                     addOperand(state, curObject, chargeSimple.costPerPt);
    2283              :                 }
    2284              :             }
    2285              :             // ChargeBlock
    2286            6 :             for (int kObj = 1; kObj <= s_econ->numChargeBlock; ++kObj) {
    2287            0 :                 auto const &chargeBlock = s_econ->chargeBlock(kObj);
    2288            0 :                 if (chargeBlock.tariffIndx == iTariff) {
    2289            0 :                     int curObject = chargeBlock.namePt;
    2290            0 :                     s_econ->econVar(curObject).Operator = Op::NOOP;
    2291            0 :                     s_econ->econVar(curObject).activeNow = true;
    2292            0 :                     addOperand(state, curObject, chargeBlock.sourcePt);
    2293            0 :                     addOperand(state, curObject, chargeBlock.blkSzMultPt);
    2294            0 :                     for (int mBlock = 1; mBlock <= chargeBlock.numBlk; ++mBlock) {
    2295            0 :                         addOperand(state, curObject, chargeBlock.blkSzPt(mBlock));
    2296            0 :                         addOperand(state, curObject, chargeBlock.blkCostPt(mBlock));
    2297              :                     }
    2298              :                     // now add a new "equation" for dependency of remainingPt on namePt
    2299            0 :                     int remainPt = chargeBlock.remainingPt;
    2300            0 :                     if (remainPt > 0) {
    2301            0 :                         s_econ->econVar(remainPt).Operator = Op::NOOP;
    2302            0 :                         s_econ->econVar(remainPt).activeNow = true;
    2303            0 :                         addOperand(state, remainPt, curObject);
    2304              :                     }
    2305              :                 }
    2306              :             }
    2307              :             // Economic:Variable
    2308              :             // make all of the user defined variables as active
    2309          293 :             for (int iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    2310          287 :                 if (s_econ->econVar(iVar).tariffIndx == iTariff) {
    2311          287 :                     if (s_econ->econVar(iVar).kindOfObj == ObjType::Variable) {
    2312            0 :                         s_econ->econVar(iVar).activeNow = true;
    2313              :                     }
    2314              :                 }
    2315              :             }
    2316              :             // make sure no computation is already user defined
    2317            6 :             if (computation.firstStep != 0) {
    2318            0 :                 ShowWarningError(state, format("In UtilityCost:Tariff: Overwriting user defined tariff {}", tariff.tariffName));
    2319              :             }
    2320              :             // initialize the computation
    2321            6 :             computation.computeName = "Autogenerated - " + tariff.tariffName;
    2322            6 :             computation.firstStep = s_econ->numSteps + 1;
    2323            6 :             computation.lastStep = -1; // this will be incremented by addStep
    2324            6 :             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          293 :             for (int jVar = 1; jVar <= s_econ->numEconVar; ++jVar) {
    2330          287 :                 s_econ->econVar(jVar).cntMeDependOn = 0;
    2331              :             }
    2332              :             // Second, add up the number of dependencies on each variable
    2333          293 :             for (int iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    2334          287 :                 if (s_econ->econVar(iVar).activeNow) {
    2335          281 :                     if (s_econ->econVar(iVar).lastOperand >= s_econ->econVar(iVar).firstOperand) {
    2336           26 :                         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            6 :             int numNoDepend = -1;
    2343            6 :             int loopCount = 0;
    2344           21 :             while ((numNoDepend != 0) || (loopCount > 100000)) {
    2345           15 :                 numNoDepend = 0;
    2346          735 :                 for (int iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    2347          720 :                     if (s_econ->econVar(iVar).activeNow) {
    2348              :                         // find a variable that has no more dangling dependencies
    2349          293 :                         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          281 :                             if ((s_econ->econVar(iVar).kindOfObj != ObjType::Native) && (s_econ->econVar(iVar).kindOfObj != ObjType::Variable)) {
    2353           59 :                                 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           84 :                                     for (int kOperand = s_econ->econVar(iVar).lastOperand; kOperand >= s_econ->econVar(iVar).firstOperand;
    2357              :                                          --kOperand) {
    2358           58 :                                         incrementSteps(state);
    2359           58 :                                         s_econ->steps(s_econ->numSteps) = s_econ->operands(kOperand);
    2360              :                                     }
    2361              :                                     // append the operator (either SUM or NOOP)
    2362           26 :                                     incrementSteps(state);
    2363           26 :                                     s_econ->steps(s_econ->numSteps).type = StepType::Op;
    2364           26 :                                     s_econ->steps(s_econ->numSteps).op = s_econ->econVar(iVar).Operator;
    2365              :                                     // append the variable itself
    2366           26 :                                     incrementSteps(state);
    2367           26 :                                     s_econ->steps(s_econ->numSteps).type = StepType::Var;
    2368           26 :                                     s_econ->steps(s_econ->numSteps).varNum = iVar;
    2369              :                                     // at the end of the line show a zero to clear the stack
    2370           26 :                                     incrementSteps(state);
    2371           26 :                                     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        13727 :                             for (int jVar = 1; jVar <= s_econ->numEconVar; ++jVar) {
    2377        13446 :                                 if (s_econ->econVar(jVar).activeNow) {
    2378         8434 :                                     for (int kOperand = s_econ->econVar(jVar).firstOperand; kOperand <= s_econ->econVar(jVar).lastOperand;
    2379              :                                          ++kOperand) {
    2380         1711 :                                         int referVar = s_econ->operands(kOperand).varNum;
    2381         1711 :                                         if (iVar == referVar) {
    2382           58 :                                             --s_econ->econVar(jVar).cntMeDependOn;
    2383              :                                             // for each variable that has been decremented to zero increment the counter
    2384           58 :                                             if (s_econ->econVar(jVar).cntMeDependOn <= 0) {
    2385           26 :                                                 ++numNoDepend;
    2386              :                                             }
    2387              :                                         }
    2388              :                                     }
    2389              :                                 }
    2390              :                             }
    2391              :                             // make the variable inactive
    2392          281 :                             s_econ->econVar(iVar).activeNow = false;
    2393              :                         }
    2394              :                     }
    2395              :                 }
    2396           15 :                 ++loopCount;
    2397              :             }
    2398            6 :             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            6 :             bool remainingVarFlag = false;
    2404          293 :             for (int iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    2405          287 :                 if (s_econ->econVar(iVar).activeNow) {
    2406            0 :                     remainingVarFlag = true;
    2407              :                 }
    2408              :             }
    2409            6 :             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            6 :             computation.lastStep = s_econ->numSteps;
    2427            6 :             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            7 : }
    2438              : 
    2439           63 : 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           63 :     int constexpr sizeIncrement(100);
    2448           63 :     auto &s_econ = state.dataEconTariff;
    2449              : 
    2450           63 :     if (varOperand != 0) {
    2451              :         // increment the numOperand and allocate/reallocate the array
    2452              :         // if necessary
    2453           58 :         if (!allocated(s_econ->operands)) {
    2454            6 :             s_econ->operands.allocate(sizeIncrement);
    2455            6 :             s_econ->sizeOperand = sizeIncrement;
    2456            6 :             s_econ->numOperand = 1;
    2457              :         } else {
    2458           52 :             ++s_econ->numOperand;
    2459              :             // if larger than current size grow the array
    2460           52 :             if (s_econ->numOperand > s_econ->sizeOperand) {
    2461            0 :                 s_econ->operands.redimension(s_econ->sizeOperand += sizeIncrement);
    2462              :             }
    2463              :         }
    2464           58 :         auto &econVar = s_econ->econVar(varMe);
    2465              : 
    2466              :         // now add the dependency relationship
    2467           58 :         s_econ->operands(s_econ->numOperand).type = StepType::Var;
    2468           58 :         s_econ->operands(s_econ->numOperand).varNum = varOperand;
    2469           58 :         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           58 :         if (varMe != s_econ->addOperand_prevVarMe) {
    2473           26 :             econVar.firstOperand = s_econ->numOperand;
    2474           26 :             s_econ->addOperand_prevVarMe = varMe;
    2475              :         }
    2476              :     }
    2477           63 : }
    2478              : 
    2479           36 : 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           36 :     auto const &s_econ = state.dataEconTariff;
    2489           36 :     auto const &chargeSimple = s_econ->chargeSimple;
    2490           36 :     auto const &chargeBlock = s_econ->chargeBlock;
    2491              : 
    2492           36 :     s_econ->econVar(curPointer).Operator = Op::SUM;
    2493           36 :     s_econ->econVar(curPointer).activeNow = true;
    2494           66 :     for (int kObj = 1; kObj <= s_econ->numChargeSimple; ++kObj) {
    2495           30 :         if (chargeSimple(kObj).tariffIndx == curTariff) {
    2496           30 :             if (chargeSimple(kObj).categoryPt == curPointer) {
    2497            5 :                 addOperand(state, curPointer, chargeSimple(kObj).namePt);
    2498              :             }
    2499              :         }
    2500              :     }
    2501           36 :     for (int kObj = 1; kObj <= s_econ->numChargeBlock; ++kObj) {
    2502            0 :         if (chargeBlock(kObj).tariffIndx == curTariff) {
    2503            0 :             if (chargeBlock(kObj).categoryPt == curPointer) {
    2504            0 :                 addOperand(state, curPointer, chargeBlock(kObj).namePt);
    2505              :             }
    2506              :         }
    2507              :     }
    2508           36 : }
    2509              : 
    2510              : //======================================================================================================================
    2511              : //======================================================================================================================
    2512              : 
    2513              : //    GATHER TIMESTEP VALUES ROUTINE
    2514              : 
    2515              : //======================================================================================================================
    2516              : //======================================================================================================================
    2517              : 
    2518            4 : 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            4 :     auto &s_econ = state.dataEconTariff;
    2536              : 
    2537            4 :     if (s_econ->numTariff >= 1) {
    2538            8 :         for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    2539            4 :             auto &tariff = s_econ->tariff(iTariff);
    2540              :             // if the meter is defined get the value
    2541            4 :             if (tariff.reportMeterIndx != -1) {
    2542            1 :                 curInstantValue = GetCurrentMeterValue(state, tariff.reportMeterIndx);
    2543              :             } else {
    2544            3 :                 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            4 :             tariff.collectEnergy += curInstantValue;
    2549            4 :             tariff.collectTime += state.dataGlobal->TimeStepZoneSec;
    2550              :             // added *SecInHour when adding RTP support August 2008
    2551            4 :             if (tariff.collectTime >= tariff.demWinTime * Constant::rSecsInHour) {
    2552              :                 // get current value that has been converted into desired units
    2553            4 :                 curDemand = tariff.demandConv * tariff.collectEnergy / tariff.collectTime;
    2554            4 :                 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            4 :                 Season curSeason = (tariff.seasonSched != nullptr) ? static_cast<Season>(tariff.seasonSched->getCurrentVal()) : Season::Winter;
    2559            4 :                 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            7 :                         (((state.dataGlobal->HourOfDay + state.dataEnvrn->DSTIndicator) <= Constant::iHoursInDay) ? state.dataEnvrn->Month
    2566           11 :                                                                                                                   : state.dataEnvrn->MonthTomorrow);
    2567              : 
    2568            4 :                 bool isGood = false;
    2569            4 :                 if (curSeason == Season::Winter || curSeason == Season::Spring || curSeason == Season::Summer || curSeason == Season::Fall ||
    2570              :                     curSeason == Season::Annual) {
    2571            4 :                     if (isWithinRange(state, curPeriod, 1, 4)) {
    2572            4 :                         if (isWithinRange(state, curMonth, 1, 12)) {
    2573            4 :                             isGood = true;
    2574              :                         }
    2575              :                     }
    2576              :                 }
    2577            4 :                 if (isGood) {
    2578            4 :                     tariff.seasonForMonth(curMonth) = curSeason;
    2579            4 :                     tariff.gatherEnergy(curMonth)[(int)curPeriod] += curEnergy;
    2580            4 :                     if (tariff.gatherDemand(curMonth)[(int)curPeriod] < curDemand) {
    2581            0 :                         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            4 :                 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            4 :                 tariff.collectEnergy = 0.0;
    2614            4 :                 tariff.collectTime = 0.0;
    2615              :             }
    2616              :         }
    2617              :     }
    2618            4 : }
    2619              : 
    2620            9 : 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            9 :     if (maxThreshold < minThreshold) {
    2631            0 :         ShowWarningError(state, "UtilityCost: Invalid thresholds in IsWithinRange routine.");
    2632              :     }
    2633            9 :     if ((testVal <= maxThreshold) && (testVal >= minThreshold)) {
    2634            9 :         isWithinRange = true;
    2635              :     } else {
    2636            0 :         isWithinRange = false;
    2637              :     }
    2638            9 :     return isWithinRange;
    2639              : }
    2640              : 
    2641              : //======================================================================================================================
    2642              : //======================================================================================================================
    2643              : 
    2644              : //    COMPUTE THE UTILITY BILLS AND CREATE REPORTS
    2645              : 
    2646              : //======================================================================================================================
    2647              : //======================================================================================================================
    2648              : 
    2649           73 : 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           73 :     auto &s_econ = state.dataEconTariff;
    2660              : 
    2661              :     // values used in specific operations
    2662           73 :     Array1D<Real64> a(NumMonths);
    2663           73 :     Array1D<Real64> b(NumMonths);
    2664           73 :     Array1D<Real64> c(NumMonths);
    2665           73 :     Array1D<Real64> d(NumMonths);
    2666              : 
    2667           73 :     int constexpr noVar(0);
    2668              : 
    2669              :     Real64 annualAggregate;
    2670              : 
    2671           73 :     if (!state.files.outputControl.writeTabular(state)) {
    2672            0 :         state.dataOutRptTab->WriteTabularFiles = false;
    2673            0 :         return;
    2674              :     }
    2675              : 
    2676           73 :     Real64 hugeValue = HUGE_(Real64());
    2677              :     //  Clear the isEvaluated flags for all economics variables.
    2678           73 :     for (int nVar = 1; nVar <= s_econ->numEconVar; ++nVar) {
    2679            0 :         s_econ->econVar(nVar).isEvaluated = false;
    2680              :     }
    2681              : 
    2682           73 :     if (s_econ->numTariff == 0) {
    2683           73 :         return;
    2684              :     }
    2685              : 
    2686            0 :     state.dataOutRptTab->WriteTabularFiles = true;
    2687            0 :     setNativeVariables(state);
    2688              :     int aPt;
    2689              :     int bPt;
    2690              :     int cPt;
    2691            0 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    2692            0 :         for (int jStep = s_econ->computation(iTariff).firstStep; jStep <= s_econ->computation(iTariff).lastStep; ++jStep) {
    2693            0 :             auto const &step = s_econ->steps(jStep);
    2694            0 :             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            0 :             if (step.type == StepType::EOL) {
    2701            0 :                 if (s_econ->topOfStack >= 2) {
    2702            0 :                     popStack(state, b, bPt); // pop the variable pointer
    2703            0 :                     popStack(state, a, aPt); // pop the values
    2704            0 :                     if (isWithinRange(state, bPt, 1, s_econ->numEconVar)) {
    2705            0 :                         s_econ->econVar(bPt).values = a;
    2706              :                     }
    2707              :                 }
    2708            0 :                 s_econ->topOfStack = 0;
    2709              : 
    2710              :                 // Variable
    2711            0 :             } else if (step.type == StepType::Var) {
    2712            0 :                 pushStack(state, s_econ->econVar(step.varNum).values, step.varNum);
    2713              : 
    2714              :                 // Operator
    2715            0 :             } else if (step.type == StepType::Op) {
    2716            0 :                 switch (step.op) {
    2717              : 
    2718            0 :                 case Op::SUM: {
    2719            0 :                     a = 0.0;
    2720            0 :                     for (int kStack = 1, kStack_end = s_econ->topOfStack; kStack <= kStack_end; ++kStack) { // popStack modifies topOfStack
    2721            0 :                         popStack(state, b, bPt);
    2722            0 :                         a += b;
    2723              :                     }
    2724            0 :                     pushStack(state, a, noVar);
    2725            0 :                 } 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            0 :                 case Op::NOOP: {
    3026              :                     // do nothing but clear the stack
    3027            0 :                     s_econ->topOfStack = 0;
    3028              :                     // No longer pushing a zero to fix bug
    3029              :                     // and push zero
    3030              :                     // a = 0
    3031            0 :                 } break;
    3032              : 
    3033            0 :                 default: {
    3034            0 :                 } break;
    3035              :                 }
    3036              :             }
    3037              :         }
    3038            0 :         checkMinimumMonthlyCharge(state, iTariff);
    3039              :     }
    3040            0 :     selectTariff(state);
    3041            0 :     LEEDtariffReporting(state);
    3042          292 : }
    3043              : 
    3044            3 : 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            3 :     monthlyArray.dim(NumMonths);
    3057              : 
    3058            3 :     Array1D<Real64> curMonthlyArray(NumMonths);
    3059            3 :     int constexpr sizeIncrement(50);
    3060              : 
    3061            3 :     auto &s_econ = state.dataEconTariff;
    3062            3 :     auto &stack = s_econ->stack;
    3063            3 :     auto const &econVar = s_econ->econVar;
    3064            3 :     auto const &tariff = s_econ->tariff;
    3065              : 
    3066            3 :     curMonthlyArray = monthlyArray;
    3067            3 :     if (!allocated(stack)) {
    3068            1 :         stack.allocate(sizeIncrement);
    3069            1 :         s_econ->sizeStack = sizeIncrement;
    3070            1 :         s_econ->topOfStack = 1;
    3071              :     } else {
    3072            2 :         ++s_econ->topOfStack;
    3073              :         // if larger than current size grow the array
    3074            2 :         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            3 :     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            3 :     if (variablePointer != 0) {
    3083            1 :         if (!econVar(variablePointer).isEvaluated) {
    3084              : 
    3085            1 :             switch (econVar(variablePointer).kindOfObj) {
    3086            0 :             case ObjType::ChargeSimple:
    3087            0 :                 evaluateChargeSimple(state, variablePointer);
    3088            0 :                 break;
    3089            0 :             case ObjType::ChargeBlock:
    3090            0 :                 evaluateChargeBlock(state, variablePointer);
    3091            0 :                 break;
    3092            0 :             case ObjType::Ratchet:
    3093            0 :                 evaluateRatchet(state, variablePointer);
    3094            0 :                 break;
    3095            0 :             case ObjType::Qualify:
    3096            0 :                 evaluateQualify(state, variablePointer);
    3097            0 :                 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            1 :             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            1 :                 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            1 :             if (econVar(variablePointer).kindOfObj == ObjType::Category && econVar(variablePointer).specific == (int)Cat::ServiceCharges) {
    3120            0 :                 addMonthlyCharge(state, variablePointer);
    3121              :             }
    3122              :             // get the results of performing the evaluation - should have been
    3123              :             // put into the econVar values
    3124            1 :             curMonthlyArray = econVar(variablePointer).values;
    3125              :         }
    3126              :     }
    3127              :     // now assign
    3128            3 :     stack(s_econ->topOfStack).values = curMonthlyArray;
    3129            3 : }
    3130              : 
    3131            3 : 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            3 :     monthlyArray.dim(NumMonths);
    3145              : 
    3146            3 :     auto &s_econ = state.dataEconTariff;
    3147            3 :     auto const &stack = s_econ->stack;
    3148              : 
    3149            3 :     if (s_econ->topOfStack >= 1) {
    3150            3 :         variablePointer = stack(s_econ->topOfStack).varPt;
    3151            3 :         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            3 :     --s_econ->topOfStack;
    3161            3 : }
    3162              : 
    3163            3 : void evaluateChargeSimple(EnergyPlusData &state, int const usingVariable)
    3164              : {
    3165              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3166              :     //    DATE WRITTEN   July 2004
    3167              : 
    3168            3 :     Array1D<Real64> sourceVals(NumMonths);
    3169            3 :     Array1D<Real64> costPer(NumMonths);
    3170            3 :     Array1D<Real64> resultChg(NumMonths);
    3171            3 :     Array1D<Real64> seasonMask(NumMonths);
    3172              : 
    3173            3 :     auto &s_econ = state.dataEconTariff;
    3174            3 :     int curTariff = s_econ->econVar(usingVariable).tariffIndx;
    3175            3 :     auto const &tariff = s_econ->tariff(curTariff);
    3176            3 :     int indexInChg = s_econ->econVar(usingVariable).index;
    3177            3 :     auto const &chargeSimple = s_econ->chargeSimple(indexInChg);
    3178              : 
    3179              :     // check the tariff - make sure they match
    3180            3 :     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            3 :     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            3 :     sourceVals = s_econ->econVar(chargeSimple.sourcePt).values;
    3192              :     // determine if costPer should be based on variable or value
    3193            3 :     if (chargeSimple.costPerPt != 0) {
    3194            1 :         costPer = s_econ->econVar(chargeSimple.costPerPt).values;
    3195              :     } else {
    3196            2 :         costPer = chargeSimple.costPerVal;
    3197              :     }
    3198              :     // find proper season mask
    3199            3 :     if (chargeSimple.season == Season::Summer) {
    3200            1 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values;
    3201            2 :     } else if (chargeSimple.season == Season::Winter) {
    3202            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values;
    3203            2 :     } else if (chargeSimple.season == Season::Spring) {
    3204            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values;
    3205            2 :     } else if (chargeSimple.season == Season::Fall) {
    3206            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values;
    3207            2 :     } else if (chargeSimple.season == Season::Annual) {
    3208            2 :         seasonMask = 1.0; // all months are 1
    3209              :     }
    3210              : 
    3211              :     // finally perform calculations
    3212            3 :     resultChg = sourceVals * costPer * seasonMask;
    3213              :     // store the cost in the name of the variable
    3214            3 :     s_econ->econVar(usingVariable).values = resultChg;
    3215              :     // set the flag that it has been evaluated so it won't be evaluated multiple times
    3216            3 :     s_econ->econVar(usingVariable).isEvaluated = true;
    3217            3 : }
    3218              : 
    3219            1 : void evaluateChargeBlock(EnergyPlusData &state, int const usingVariable)
    3220              : {
    3221              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3222              :     //    DATE WRITTEN   July 2004
    3223              : 
    3224            1 :     Array1D<Real64> sourceVals(NumMonths);
    3225            1 :     Array1D<Real64> blkSzMult(NumMonths);
    3226            1 :     Array1D<Real64> remainVals(NumMonths);
    3227            1 :     Array1D<Real64> resultChg(NumMonths);
    3228            1 :     Array1D<Real64> amountForBlk(NumMonths);
    3229            1 :     Array1D<Real64> curBlkSz(NumMonths);
    3230            1 :     Array1D<Real64> curBlkCost(NumMonths);
    3231            1 :     Array1D<Real64> seasonMask(NumMonths);
    3232              : 
    3233            1 :     auto &s_econ = state.dataEconTariff;
    3234            1 :     int curTariff = s_econ->econVar(usingVariable).tariffIndx;
    3235            1 :     auto const &tariff = s_econ->tariff(curTariff);
    3236            1 :     int indexInChg = s_econ->econVar(usingVariable).index;
    3237            1 :     auto const &chargeBlock = s_econ->chargeBlock(indexInChg);
    3238              : 
    3239              :     // check the tariff - make sure they match
    3240            1 :     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            1 :     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            1 :     sourceVals = s_econ->econVar(chargeBlock.sourcePt).values;
    3252              :     // find proper season mask
    3253              : 
    3254            1 :     if (chargeBlock.season == Season::Summer) {
    3255            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values;
    3256            1 :     } else if (chargeBlock.season == Season::Winter) {
    3257            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values;
    3258            1 :     } else if (chargeBlock.season == Season::Spring) {
    3259            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values;
    3260            1 :     } else if (chargeBlock.season == Season::Fall) {
    3261            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values;
    3262            1 :     } else if (chargeBlock.season == Season::Annual) {
    3263            1 :         seasonMask = 1.0; // all months are 1
    3264              :     }
    3265              :     // get block size multiplier
    3266            1 :     if (chargeBlock.blkSzMultPt != 0) {
    3267            0 :         blkSzMult = s_econ->econVar(chargeBlock.blkSzMultPt).values;
    3268              :     } else {
    3269            1 :         blkSzMult = chargeBlock.blkSzMultVal;
    3270              :     }
    3271              :     // initially set the remaining energy or demand to the source
    3272            1 :     remainVals = sourceVals;
    3273              :     // initially set the result (cost) to zero
    3274            1 :     resultChg = 0.0;
    3275              :     // loop through the blocks performing calculations
    3276            4 :     for (int iBlk = 1; iBlk <= chargeBlock.numBlk; ++iBlk) {
    3277            3 :         if (chargeBlock.blkSzPt(iBlk) != 0) {
    3278            0 :             curBlkSz = s_econ->econVar(chargeBlock.blkSzPt(iBlk)).values;
    3279              :         } else {
    3280            3 :             curBlkSz = chargeBlock.blkSzVal(iBlk);
    3281              :         }
    3282            3 :         if (chargeBlock.blkCostPt(iBlk) != 0) {
    3283            0 :             curBlkCost = s_econ->econVar(chargeBlock.blkCostPt(iBlk)).values;
    3284              :         } else {
    3285            3 :             curBlkCost = chargeBlock.blkCostVal(iBlk);
    3286              :         }
    3287              :         // loop through the months
    3288           39 :         for (int jMonth = 1; jMonth <= NumMonths; ++jMonth) {
    3289           36 :             if (seasonMask(jMonth) == 1) {
    3290              :                 // IF ((curBlkSz(jMonth) * blkSzMult(jMonth)) .GT. remainVals(jMonth)) THEN - CR 6547
    3291           36 :                 if (blkSzMult(jMonth) != 0) {
    3292           36 :                     if (curBlkSz(jMonth) > (remainVals(jMonth) / blkSzMult(jMonth))) {
    3293           21 :                         amountForBlk(jMonth) = remainVals(jMonth);
    3294              :                     } else {
    3295           15 :                         amountForBlk(jMonth) = curBlkSz(jMonth) * blkSzMult(jMonth);
    3296              :                     }
    3297              :                 } else {
    3298            0 :                     amountForBlk(jMonth) = 0.0;
    3299              :                 }
    3300           36 :                 resultChg(jMonth) += amountForBlk(jMonth) * curBlkCost(jMonth);
    3301           36 :                 remainVals(jMonth) -= amountForBlk(jMonth);
    3302              :             }
    3303              :         }
    3304              :     }
    3305              :     // store the amount remaining if a variable is specified
    3306            1 :     if (chargeBlock.remainingPt != 0) {
    3307            0 :         s_econ->econVar(chargeBlock.remainingPt).values = remainVals;
    3308              :     } else {
    3309            1 :         bool flagAllZero = true;
    3310           13 :         for (int jMonth = 1; jMonth <= NumMonths; ++jMonth) {
    3311           12 :             if (seasonMask(jMonth) == 1) {
    3312           12 :                 if (remainVals(jMonth) != 0) {
    3313            0 :                     flagAllZero = false;
    3314              :                 }
    3315              :             }
    3316              :         }
    3317            1 :         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            1 :     s_econ->econVar(usingVariable).values = resultChg;
    3325              :     // set the flag that it has been evaluated so it won't be evaluated multiple times
    3326            1 :     s_econ->econVar(usingVariable).isEvaluated = true;
    3327            1 : }
    3328              : 
    3329            0 : void evaluateRatchet(EnergyPlusData &state, int const usingVariable)
    3330              : {
    3331              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3332              :     //    DATE WRITTEN   July 2004
    3333              : 
    3334            0 :     Array1D<Real64> baselineVals(NumMonths);
    3335            0 :     Array1D<Real64> adjustmentVals(NumMonths);
    3336            0 :     Array1D<Real64> multiplierVals(NumMonths);
    3337            0 :     Array1D<Real64> offsetVals(NumMonths);
    3338            0 :     Array1D<Real64> seasonFromMask(NumMonths);
    3339            0 :     Array1D<Real64> seasonToMask(NumMonths);
    3340            0 :     Array1D<Real64> adjSeasonal(NumMonths);
    3341            0 :     Array1D<Real64> adjPeak(NumMonths);
    3342            0 :     Array1D<Real64> maxAdjBase(NumMonths);
    3343            0 :     Array1D<Real64> finalResult(NumMonths);
    3344              : 
    3345            0 :     auto &s_econ = state.dataEconTariff;
    3346            0 :     int curTariff = s_econ->econVar(usingVariable).tariffIndx;
    3347            0 :     auto const &tariff = s_econ->tariff(curTariff);
    3348            0 :     int indexInChg = s_econ->econVar(usingVariable).index;
    3349            0 :     auto const &ratchet = s_econ->ratchet(indexInChg);
    3350            0 :     bool isMonthly = false;
    3351              : 
    3352              :     // check the tariff - make sure they match
    3353            0 :     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            0 :     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            0 :     baselineVals = s_econ->econVar(ratchet.baselinePt).values;
    3365            0 :     adjustmentVals = s_econ->econVar(ratchet.adjustmentPt).values;
    3366              :     // determine if multiplier should be based on variable or value
    3367            0 :     if (ratchet.multiplierPt != 0) {
    3368            0 :         multiplierVals = s_econ->econVar(ratchet.multiplierPt).values;
    3369              :     } else {
    3370            0 :         multiplierVals = ratchet.multiplierVal;
    3371              :     }
    3372              :     // determine if offset should be based on variable or value
    3373            0 :     if (ratchet.offsetPt != 0) {
    3374            0 :         offsetVals = s_econ->econVar(ratchet.offsetPt).values;
    3375              :     } else {
    3376            0 :         offsetVals = ratchet.offsetVal;
    3377              :     }
    3378              :     // find proper season from mask
    3379            0 :     if (ratchet.seasonFrom == Season::Summer) {
    3380            0 :         seasonFromMask = s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values;
    3381            0 :         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            0 :     if (ratchet.seasonTo == Season::Summer) {
    3403            0 :         seasonToMask = s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values;
    3404            0 :     } else if (ratchet.seasonTo == Season::Winter) {
    3405            0 :         seasonToMask = s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values;
    3406            0 :     } else if (ratchet.seasonTo == Season::Spring) {
    3407            0 :         seasonToMask = s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values;
    3408            0 :     } else if (ratchet.seasonTo == Season::Fall) {
    3409            0 :         seasonToMask = s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values;
    3410            0 :     } else if (ratchet.seasonTo == Season::Annual) {
    3411            0 :         seasonToMask = 1.0; // all months are 1
    3412              :     }
    3413              :     // finally perform calculations
    3414            0 :     if (isMonthly) {
    3415            0 :         adjSeasonal = adjustmentVals;
    3416              :     } else {
    3417            0 :         Real64 maximumVal = -HUGE_(Real64());
    3418            0 :         for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3419            0 :             if (seasonFromMask(iMonth) == 1) {
    3420            0 :                 if (adjustmentVals(iMonth) > maximumVal) {
    3421            0 :                     maximumVal = adjustmentVals(iMonth);
    3422              :                 }
    3423              :             }
    3424              :         }
    3425            0 :         adjSeasonal = maximumVal;
    3426              :     }
    3427            0 :     for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3428              :         // calculate adjusted peak value after offset and multiplier
    3429            0 :         adjPeak(iMonth) = (adjSeasonal(iMonth) + offsetVals(iMonth)) * multiplierVals(iMonth);
    3430              :         // the maximum of the adjustment and the baseline
    3431            0 :         if (adjPeak(iMonth) > baselineVals(iMonth)) {
    3432            0 :             maxAdjBase(iMonth) = adjPeak(iMonth);
    3433              :         } else {
    3434            0 :             maxAdjBase(iMonth) = baselineVals(iMonth);
    3435              :         }
    3436              :     }
    3437            0 :     for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3438            0 :         if (seasonToMask(iMonth) == 1) {
    3439            0 :             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            0 :     s_econ->econVar(usingVariable).values = finalResult;
    3446              :     // set the flag that it has been evaluated so it won't be evaluated multiple times
    3447            0 :     s_econ->econVar(usingVariable).isEvaluated = true;
    3448            0 : }
    3449              : 
    3450            0 : void evaluateQualify(EnergyPlusData &state, int const usingVariable)
    3451              : {
    3452              :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    3453              :     //    DATE WRITTEN   July 2004
    3454              : 
    3455            0 :     Array1D<Real64> sourceVals(NumMonths);
    3456            0 :     Array1D<Real64> thresholdVals(NumMonths);
    3457            0 :     Array1D_int monthsQualify(NumMonths);
    3458            0 :     Array1D<Real64> seasonMask(NumMonths);
    3459              :     int adjNumberOfMonths;
    3460              :     bool isQualified;
    3461              : 
    3462            0 :     auto &s_econ = state.dataEconTariff;
    3463            0 :     auto &econVar = s_econ->econVar(usingVariable);
    3464              : 
    3465            0 :     int curTariff = econVar.tariffIndx;
    3466            0 :     auto &tariff = s_econ->tariff(curTariff);
    3467            0 :     int indexInQual = econVar.index;
    3468            0 :     auto const &qualify = s_econ->qualify(indexInQual);
    3469              :     // check the tariff - make sure they match
    3470            0 :     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            0 :     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            0 :     sourceVals = s_econ->econVar(qualify.sourcePt).values;
    3482            0 :     bool curIsMaximum = qualify.isMaximum;
    3483            0 :     bool curIsConsecutive = qualify.isConsecutive;
    3484            0 :     int curNumberOfMonths = qualify.numberOfMonths;
    3485              :     // determine if threshold should be based on variable or value
    3486            0 :     if (qualify.thresholdPt != 0) {
    3487            0 :         thresholdVals = s_econ->econVar(qualify.thresholdPt).values;
    3488              :     } else {
    3489            0 :         thresholdVals = qualify.thresholdVal;
    3490              :     }
    3491              :     // find proper season mask
    3492              : 
    3493            0 :     if (qualify.season == Season::Summer) {
    3494            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values;
    3495            0 :     } else if (qualify.season == Season::Winter) {
    3496            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values;
    3497            0 :     } else if (qualify.season == Season::Spring) {
    3498            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values;
    3499            0 :     } else if (qualify.season == Season::Fall) {
    3500            0 :         seasonMask = s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values;
    3501            0 :     } else if (qualify.season == Season::Annual) {
    3502            0 :         seasonMask = 1.0; // all months are 1
    3503              :     }
    3504              : 
    3505              :     // any months with no energy use are excluded from the qualification process
    3506            0 :     for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3507            0 :         if (s_econ->econVar(tariff.natives[(int)Native::TotalEnergy]).values(iMonth) == 0) {
    3508            0 :             seasonMask(iMonth) = 0.0;
    3509              :         }
    3510              :     }
    3511              :     // finally perform calculations
    3512              :     // loop through the months
    3513            0 :     int monthsInSeason = 0;
    3514            0 :     for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3515            0 :         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            0 :             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            0 :     if (curNumberOfMonths > monthsInSeason) {
    3537            0 :         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            0 :     int cntAllQualMonths = 0;
    3543            0 :     int cntConsecQualMonths = 0;
    3544            0 :     int maxConsecQualMonths = 0;
    3545            0 :     for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3546              :         {
    3547            0 :             int const SELECT_CASE_var(monthsQualify(iMonth));
    3548            0 :             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            0 :             } 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            0 :     if (curIsConsecutive) {
    3563            0 :         if (maxConsecQualMonths >= adjNumberOfMonths) {
    3564            0 :             isQualified = true;
    3565              :         } else {
    3566            0 :             isQualified = false;
    3567              :         }
    3568              :     } else { // count not consecutive
    3569            0 :         if (cntAllQualMonths >= adjNumberOfMonths) {
    3570            0 :             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            0 :     if (tariff.isQualified) {
    3578            0 :         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            0 :     econVar.values = monthsQualify;
    3585              :     // set the flag that it has been evaluated so it won't be evaluated multiple times
    3586            0 :     econVar.isEvaluated = true;
    3587            0 : }
    3588              : 
    3589            0 : 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            0 :     auto &s_econ = state.dataEconTariff;
    3597            0 :     int curTariff = s_econ->econVar(usingVariable).tariffIndx;
    3598            0 :     auto const &tariff = s_econ->tariff(curTariff);
    3599              :     // check the tariff - make sure they match
    3600            0 :     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            0 :     if (tariff.monthChgPt != 0) {
    3606            0 :         s_econ->econVar(usingVariable).values += s_econ->econVar(tariff.monthChgPt).values;
    3607              :     } else {
    3608            0 :         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            0 : }
    3618              : 
    3619            0 : 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            0 :     auto &s_econ = state.dataEconTariff;
    3627            0 :     auto const &tariff = s_econ->tariff(curTariff);
    3628              : 
    3629            0 :     int totalVar = tariff.cats[(int)Cat::Total];
    3630            0 :     int minMonVar = tariff.minMonthChgPt;
    3631              :     // if a variable is defined use that
    3632            0 :     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            0 :         for (int iMonth = 1; iMonth <= NumMonths; ++iMonth) {
    3640            0 :             if (s_econ->econVar(totalVar).values(iMonth) < tariff.minMonthChgVal) {
    3641            0 :                 s_econ->econVar(totalVar).values(iMonth) = tariff.minMonthChgVal;
    3642              :             }
    3643              :         }
    3644              :     }
    3645            0 : }
    3646              : 
    3647            0 : 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            0 :     auto &s_econ = state.dataEconTariff;
    3656              : 
    3657            0 :     Array1D<Real64> monthVal(NumMonths);
    3658            0 :     Real64 bigNumber(0.0); // Autodesk Value not used but suppresses warning about HUGE_() call
    3659              : 
    3660            0 :     bigNumber = HUGE_(bigNumber);
    3661            0 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    3662            0 :         auto &tariff = s_econ->tariff(iTariff);
    3663              :         // nativeTotalEnergy
    3664            0 :         monthVal = 0.0;
    3665            0 :         for (int kMonth = 1; kMonth <= NumMonths; ++kMonth) {
    3666            0 :             for (int jPeriod = 0; jPeriod < (int)Period::Num; ++jPeriod) {
    3667            0 :                 monthVal(kMonth) += tariff.gatherEnergy(kMonth)[jPeriod];
    3668              :             }
    3669              :         }
    3670            0 :         s_econ->econVar(tariff.natives[(int)Native::TotalEnergy]).values = monthVal;
    3671              :         // nativeTotalDemand
    3672            0 :         monthVal = -bigNumber;
    3673            0 :         for (int kMonth = 1; kMonth <= NumMonths; ++kMonth) {
    3674            0 :             for (int jPeriod = 0; jPeriod < (int)Period::Num; ++jPeriod) {
    3675            0 :                 if (tariff.gatherDemand(kMonth)[jPeriod] > monthVal(kMonth)) {
    3676            0 :                     monthVal(kMonth) = tariff.gatherDemand(kMonth)[jPeriod];
    3677              :                 }
    3678              :             }
    3679              :         }
    3680              :         // if no maximum was set just set to zero
    3681            0 :         for (int kMonth = 1; kMonth <= NumMonths; ++kMonth) {
    3682            0 :             if (monthVal(kMonth) == -bigNumber) {
    3683            0 :                 monthVal(kMonth) = 0.0;
    3684              :             }
    3685              :         }
    3686            0 :         s_econ->econVar(tariff.natives[(int)Native::TotalDemand]).values = monthVal;
    3687            0 :         for (int kMonth = 1; kMonth <= NumMonths; ++kMonth) {
    3688              :             // nativePeakEnergy
    3689            0 :             s_econ->econVar(tariff.natives[(int)Native::PeakEnergy]).values(kMonth) = tariff.gatherEnergy(kMonth)[(int)Period::Peak];
    3690              :             // nativePeakDemand
    3691            0 :             s_econ->econVar(tariff.natives[(int)Native::PeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3692              :             // nativeShoulderEnergy
    3693            0 :             s_econ->econVar(tariff.natives[(int)Native::ShoulderEnergy]).values(kMonth) = tariff.gatherEnergy(kMonth)[(int)Period::Shoulder];
    3694              :             // nativeShoulderDemand
    3695            0 :             s_econ->econVar(tariff.natives[(int)Native::ShoulderDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Shoulder];
    3696              :             // nativeOffPeakEnergy
    3697            0 :             s_econ->econVar(tariff.natives[(int)Native::OffPeakEnergy]).values(kMonth) = tariff.gatherEnergy(kMonth)[(int)Period::OffPeak];
    3698              :             // nativeOffPeakDemand
    3699            0 :             s_econ->econVar(tariff.natives[(int)Native::OffPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::OffPeak];
    3700              :             // nativeMidPeakEnergy
    3701            0 :             s_econ->econVar(tariff.natives[(int)Native::MidPeakEnergy]).values(kMonth) = tariff.gatherEnergy(kMonth)[(int)Period::MidPeak];
    3702              :             // nativeMidPeakDemand
    3703            0 :             s_econ->econVar(tariff.natives[(int)Native::MidPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::MidPeak];
    3704              :             // nativePeakExceedsOffPeak
    3705            0 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak] - tariff.gatherDemand(kMonth)[(int)Period::OffPeak];
    3706            0 :             if (monthVal(kMonth) > 0) {
    3707            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsOffPeak]).values(kMonth) = monthVal(kMonth);
    3708              :             } else {
    3709            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsOffPeak]).values(kMonth) = 0.0;
    3710              :             }
    3711              :             // nativeOffPeakExceedsPeak
    3712            0 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::OffPeak] - tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3713            0 :             if (monthVal(kMonth) > 0) {
    3714            0 :                 s_econ->econVar(tariff.natives[(int)Native::OffPeakExceedsPeak]).values(kMonth) = monthVal(kMonth);
    3715              :             } else {
    3716            0 :                 s_econ->econVar(tariff.natives[(int)Native::OffPeakExceedsPeak]).values(kMonth) = 0.0;
    3717              :             }
    3718              :             // nativePeakExceedsMidPeak
    3719            0 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak] - tariff.gatherDemand(kMonth)[(int)Period::MidPeak];
    3720            0 :             if (monthVal(kMonth) > 0) {
    3721            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsMidPeak]).values(kMonth) = monthVal(kMonth);
    3722              :             } else {
    3723            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsOffPeak]).values(kMonth) = 0.0;
    3724              :             }
    3725              :             // nativeMidPeakExceedsPeak
    3726            0 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::MidPeak] - tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3727            0 :             if (monthVal(kMonth) > 0) {
    3728            0 :                 s_econ->econVar(tariff.natives[(int)Native::MidPeakExceedsPeak]).values(kMonth) = monthVal(kMonth);
    3729              :             } else {
    3730            0 :                 s_econ->econVar(tariff.natives[(int)Native::MidPeakExceedsPeak]).values(kMonth) = 0.0;
    3731              :             }
    3732              :             // nativePeakExceedsShoulder
    3733            0 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak] - tariff.gatherDemand(kMonth)[(int)Period::Shoulder];
    3734            0 :             if (monthVal(kMonth) > 0) {
    3735            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsShoulder]).values(kMonth) = monthVal(kMonth);
    3736              :             } else {
    3737            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakExceedsShoulder]).values(kMonth) = 0.0;
    3738              :             }
    3739              :             // nativeShoulderExceedsPeak
    3740            0 :             monthVal(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Shoulder] - tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3741            0 :             if (monthVal(kMonth) > 0) {
    3742            0 :                 s_econ->econVar(tariff.natives[(int)Native::ShoulderExceedsPeak]).values(kMonth) = monthVal(kMonth);
    3743              :             } else {
    3744            0 :                 s_econ->econVar(tariff.natives[(int)Native::ShoulderExceedsPeak]).values(kMonth) = 0.0;
    3745              :             }
    3746              :             // nativeIsWinter
    3747              :             // nativeIsNotWinter
    3748            0 :             if (tariff.seasonForMonth(kMonth) == Season::Winter) {
    3749            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values(kMonth) = 1.0;
    3750            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotWinter]).values(kMonth) = 0.0;
    3751              :             } else {
    3752            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsWinter]).values(kMonth) = 0.0;
    3753            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotWinter]).values(kMonth) = 1.0;
    3754              :             }
    3755              :             // nativeIsSpring
    3756              :             // nativeIsNotSpring
    3757            0 :             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            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsSpring]).values(kMonth) = 0.0;
    3762            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotSpring]).values(kMonth) = 1.0;
    3763              :             }
    3764              :             // nativeIsSummer
    3765              :             // nativeIsNotSummer
    3766            0 :             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            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsSummer]).values(kMonth) = 0.0;
    3771            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotSummer]).values(kMonth) = 1.0;
    3772              :             }
    3773              :             // nativeIsAutumn
    3774              :             // nativeIsNotAutumn
    3775            0 :             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            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsAutumn]).values(kMonth) = 0.0;
    3780            0 :                 s_econ->econVar(tariff.natives[(int)Native::IsNotAutumn]).values(kMonth) = 1.0;
    3781              :             }
    3782              :             // nativePeakAndShoulderEnergy
    3783            0 :             s_econ->econVar(tariff.natives[(int)Native::PeakAndShoulderEnergy]).values(kMonth) =
    3784            0 :                 tariff.gatherEnergy(kMonth)[(int)Period::Peak] + tariff.gatherEnergy(kMonth)[(int)Period::Shoulder];
    3785              :             // nativePeakAndShoulderDemand
    3786            0 :             if (tariff.gatherDemand(kMonth)[(int)Period::Peak] > tariff.gatherDemand(kMonth)[(int)Period::Shoulder]) {
    3787            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndShoulderDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3788              :             } else {
    3789            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndShoulderDemand]).values(kMonth) =
    3790            0 :                     tariff.gatherDemand(kMonth)[(int)Period::Shoulder];
    3791              :             }
    3792              :             // nativePeakAndMidPeakEnergy
    3793            0 :             s_econ->econVar(tariff.natives[(int)Native::PeakAndMidPeakEnergy]).values(kMonth) =
    3794            0 :                 tariff.gatherEnergy(kMonth)[(int)Period::Peak] + tariff.gatherEnergy(kMonth)[(int)Period::MidPeak];
    3795              :             // nativePeakAndMidPeakDemand
    3796            0 :             if (tariff.gatherDemand(kMonth)[(int)Period::Peak] > tariff.gatherDemand(kMonth)[(int)Period::MidPeak]) {
    3797            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndMidPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3798              :             } else {
    3799            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndMidPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::MidPeak];
    3800              :             }
    3801              :             // nativeShoulderAndOffPeakEnergy
    3802            0 :             s_econ->econVar(tariff.natives[(int)Native::ShoulderAndOffPeakEnergy]).values(kMonth) =
    3803            0 :                 tariff.gatherEnergy(kMonth)[(int)Period::Shoulder] + tariff.gatherEnergy(kMonth)[(int)Period::OffPeak];
    3804              :             // nativeShoulderAndOffPeakDemand
    3805            0 :             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            0 :                 s_econ->econVar(tariff.natives[(int)Native::ShoulderAndOffPeakDemand]).values(kMonth) =
    3810            0 :                     tariff.gatherDemand(kMonth)[(int)Period::OffPeak];
    3811              :             }
    3812              :             // nativePeakAndOffPeakEnergy
    3813            0 :             s_econ->econVar(tariff.natives[(int)Native::PeakAndOffPeakEnergy]).values(kMonth) =
    3814            0 :                 tariff.gatherEnergy(kMonth)[(int)Period::Peak] + tariff.gatherEnergy(kMonth)[(int)Period::OffPeak];
    3815              :             // nativePeakAndOffPeakDemand
    3816            0 :             if (tariff.gatherDemand(kMonth)[(int)Period::Peak] > tariff.gatherDemand(kMonth)[(int)Period::OffPeak]) {
    3817            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndOffPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::Peak];
    3818              :             } else {
    3819            0 :                 s_econ->econVar(tariff.natives[(int)Native::PeakAndOffPeakDemand]).values(kMonth) = tariff.gatherDemand(kMonth)[(int)Period::OffPeak];
    3820              :             }
    3821              :             // nativeRealTimePriceCosts
    3822            0 :             s_econ->econVar(tariff.natives[(int)Native::RealTimePriceCosts]).values(kMonth) = tariff.RTPcost(kMonth);
    3823              :             // nativeAboveCustomerBaseCosts
    3824            0 :             s_econ->econVar(tariff.natives[(int)Native::AboveCustomerBaseCosts]).values(kMonth) = tariff.RTPaboveBaseCost(kMonth);
    3825              :             // nativeBelowCustomerBaseCosts
    3826            0 :             s_econ->econVar(tariff.natives[(int)Native::BelowCustomerBaseCosts]).values(kMonth) = tariff.RTPbelowBaseCost(kMonth);
    3827              :             // nativeAboveCustomerBaseEnergy
    3828            0 :             s_econ->econVar(tariff.natives[(int)Native::AboveCustomerBaseEnergy]).values(kMonth) = tariff.RTPaboveBaseEnergy(kMonth);
    3829              :             // nativeBelowCustomerBaseEnergy
    3830            0 :             s_econ->econVar(tariff.natives[(int)Native::BelowCustomerBaseEnergy]).values(kMonth) = tariff.RTPbelowBaseEnergy(kMonth);
    3831              :         }
    3832              :     }
    3833            0 : }
    3834              : 
    3835            2 : 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            2 :     auto &s_orp = state.dataOutRptPredefined;
    3868              : 
    3869            2 :     auto &s_econ = state.dataEconTariff;
    3870              : 
    3871            2 :     if (s_econ->numTariff > 0) {
    3872            4 :         int distCoolFacilMeter = GetMeterIndex(state, "DISTRICTCOOLING:FACILITY");
    3873            4 :         int distHeatWaterFacilMeter = GetMeterIndex(state, "DISTRICTHEATINGWATER:FACILITY");
    3874            2 :         int distHeatSteamFacilMeter = GetMeterIndex(state, "DISTRICTHEATINGSTEAM:FACILITY");
    3875            2 :         elecTotalEne = 0.0;
    3876            2 :         gasTotalEne = 0.0;
    3877            2 :         distCoolTotalEne = 0.0;
    3878            2 :         distHeatWaterTotalEne = 0.0;
    3879            2 :         distHeatSteamTotalEne = 0.0;
    3880            2 :         otherTotalEne = 0.0;
    3881            2 :         elecTotalCost = 0.0;
    3882            2 :         gasTotalCost = 0.0;
    3883            2 :         distCoolTotalCost = 0.0;
    3884            2 :         distHeatWaterTotalCost = 0.0;
    3885            2 :         distHeatSteamTotalCost = 0.0;
    3886            2 :         otherTotalCost = 0.0;
    3887            2 :         allTotalCost = 0.0;
    3888            2 :         elecUnits = EconConv::USERDEF;
    3889            2 :         gasUnits = EconConv::USERDEF;
    3890            2 :         distCoolUnits = EconConv::USERDEF;
    3891            2 :         distHeatWaterUnits = EconConv::USERDEF;
    3892            2 :         distHeatSteamUnits = EconConv::USERDEF;
    3893            2 :         othrUnits = EconConv::USERDEF;
    3894            2 :         gasDemWindowUnits = DemandWindow::Invalid;
    3895            2 :         othrDemWindowUnits = DemandWindow::Invalid;
    3896            4 :         std::string elecTariffNames = "";
    3897            4 :         std::string gasTariffNames = "";
    3898            4 :         std::string distCoolTariffNames = "";
    3899            4 :         std::string distHeatWaterTariffNames = "";
    3900            4 :         std::string distHeatSteamTariffNames = "";
    3901            2 :         std::string othrTariffNames = "";
    3902           13 :         for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    3903           11 :             auto &tariff = s_econ->tariff(iTariff);
    3904           11 :             if (tariff.isSelected) {
    3905           11 :                 allTotalCost += tariff.totalAnnualCost;
    3906           11 :                 if (tariff.kindMtr == MeterType::ElecSimple || tariff.kindMtr == MeterType::ElecProduced ||
    3907           11 :                     tariff.kindMtr == MeterType::ElecPurchased || tariff.kindMtr == MeterType::ElecSurplusSold ||
    3908            8 :                     tariff.kindMtr == MeterType::ElecNet) {
    3909            3 :                     if (tariff.totalAnnualEnergy > elecTotalEne) {
    3910            2 :                         elecTotalEne = tariff.totalAnnualEnergy;
    3911              :                     }
    3912            3 :                     elecTotalCost += tariff.totalAnnualCost;
    3913            3 :                     elecTariffNames += ' ' + tariff.tariffName;
    3914            3 :                     elecUnits = tariff.convChoice;
    3915            8 :                 } else if (tariff.kindMtr == MeterType::Gas) {
    3916            3 :                     if (tariff.totalAnnualEnergy > gasTotalEne) {
    3917            1 :                         gasTotalEne = tariff.totalAnnualEnergy;
    3918              :                     }
    3919            3 :                     gasTotalCost += tariff.totalAnnualCost;
    3920            3 :                     gasTariffNames += ' ' + tariff.tariffName;
    3921            3 :                     gasUnits = tariff.convChoice;
    3922            3 :                     gasDemWindowUnits = tariff.demandWindow;
    3923            5 :                 } else if (tariff.reportMeterIndx == distCoolFacilMeter) {
    3924            2 :                     if (tariff.totalAnnualEnergy > distCoolTotalEne) {
    3925            2 :                         distCoolTotalEne = tariff.totalAnnualEnergy;
    3926              :                     }
    3927            2 :                     distCoolTotalCost += tariff.totalAnnualCost;
    3928            2 :                     distCoolTariffNames += ' ' + tariff.tariffName;
    3929            2 :                     distCoolUnits = tariff.convChoice;
    3930            2 :                     distCoolDemWindowUnits = tariff.demandWindow;
    3931            3 :                 } else if (tariff.reportMeterIndx == distHeatWaterFacilMeter) {
    3932            2 :                     if (tariff.totalAnnualEnergy > distHeatWaterTotalEne) {
    3933            2 :                         distHeatWaterTotalEne = tariff.totalAnnualEnergy;
    3934              :                     }
    3935            2 :                     distHeatWaterTotalCost += tariff.totalAnnualCost;
    3936            2 :                     distHeatWaterTariffNames += ' ' + tariff.tariffName;
    3937            2 :                     distHeatWaterUnits = tariff.convChoice;
    3938            2 :                     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            2 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "Electricity", elecTariffNames);
    3961            2 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "Natural Gas", gasTariffNames);
    3962            2 :         if (distCoolTotalEne != 0) {
    3963            2 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "District Cooling", distCoolTariffNames);
    3964              :         }
    3965            2 :         if (distHeatWaterTotalEne != 0) {
    3966            2 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "District Heating Water", distHeatWaterTariffNames);
    3967              :         }
    3968            2 :         if (distHeatSteamTotalEne != 0) {
    3969            0 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "District Heating Steam", distHeatSteamTariffNames);
    3970              :         }
    3971            2 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsRtNm, "Other", othrTariffNames);
    3972              :         // virtual rate
    3973            2 :         if (elecTotalEne != 0) {
    3974            2 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsVirt, "Electricity", elecTotalCost / elecTotalEne, 3);
    3975              :         }
    3976            2 :         if (gasTotalEne != 0) {
    3977            1 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsVirt, "Natural Gas", gasTotalCost / gasTotalEne, 3);
    3978              :         }
    3979            2 :         if (otherTotalEne != 0) {
    3980            0 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsVirt, "Other", otherTotalCost / otherTotalEne, 3);
    3981              :         }
    3982              :         // units
    3983            2 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsEneUnt, "Electricity", format("{}", convEnergyStrings[(int)elecUnits]));
    3984            2 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsEneUnt, "Natural Gas", format("{}", convEnergyStrings[(int)gasUnits]));
    3985            2 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsEneUnt, "Other", format("{}", convEnergyStrings[(int)othrUnits]));
    3986            2 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsDemUnt, "Electricity", format("{}", convDemandStrings[(int)elecUnits]));
    3987            4 :         OutputReportPredefined::PreDefTableEntry(
    3988              :             state,
    3989            2 :             s_orp->pdchLeedEtsDemUnt,
    3990              :             "Natural Gas",
    3991            4 :             format("{}{}",
    3992            2 :                    convDemandStrings[(int)gasUnits],
    3993            2 :                    (gasDemWindowUnits == DemandWindow::Invalid) ? "" : demandWindowStrings[(int)gasDemWindowUnits]));
    3994            4 :         OutputReportPredefined::PreDefTableEntry(
    3995              :             state,
    3996            2 :             s_orp->pdchLeedEtsDemUnt,
    3997              :             "Other",
    3998            4 :             format("{}{}",
    3999            2 :                    convDemandStrings[(int)othrUnits],
    4000            2 :                    (othrDemWindowUnits == DemandWindow::Invalid) ? "" : demandWindowStrings[(int)othrDemWindowUnits]));
    4001              : 
    4002              :         // total cost
    4003            2 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEcsTotal, "Electricity", elecTotalCost, 2);
    4004            2 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEcsTotal, "Natural Gas", gasTotalCost, 2);
    4005            2 :         OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEcsTotal, "Other", otherTotalCost, 2);
    4006              :         // show district energy if used
    4007            2 :         if (distCoolTotalEne != 0) {
    4008            2 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEtsVirt, "District Cooling", distCoolTotalCost / distCoolTotalEne, 3);
    4009            4 :             OutputReportPredefined::PreDefTableEntry(
    4010            6 :                 state, s_orp->pdchLeedEtsEneUnt, "District Cooling", format("{}", convEnergyStrings[(int)distCoolUnits]));
    4011            4 :             OutputReportPredefined::PreDefTableEntry(
    4012              :                 state,
    4013            2 :                 s_orp->pdchLeedEtsDemUnt,
    4014              :                 "District Cooling",
    4015            4 :                 format("{}{}",
    4016            2 :                        convDemandStrings[(int)distCoolUnits],
    4017            2 :                        (distCoolDemWindowUnits == DemandWindow::Invalid) ? "" : demandWindowStrings[(int)distCoolDemWindowUnits]));
    4018            2 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEcsTotal, "District Cooling", distCoolTotalCost, 2);
    4019              :         }
    4020            2 :         if (distHeatWaterTotalEne != 0) {
    4021            4 :             OutputReportPredefined::PreDefTableEntry(
    4022            4 :                 state, s_orp->pdchLeedEtsVirt, "District Heating Water", distHeatWaterTotalCost / distHeatWaterTotalEne, 3);
    4023            4 :             OutputReportPredefined::PreDefTableEntry(
    4024            6 :                 state, s_orp->pdchLeedEtsEneUnt, "District Heating Water", format("{}", convEnergyStrings[(int)distHeatWaterUnits]));
    4025            4 :             OutputReportPredefined::PreDefTableEntry(
    4026              :                 state,
    4027            2 :                 s_orp->pdchLeedEtsDemUnt,
    4028              :                 "District Heating Water",
    4029            4 :                 format("{}{}",
    4030            2 :                        convDemandStrings[(int)distHeatWaterUnits],
    4031            2 :                        (distHeatWaterDemWindowUnits == DemandWindow::Invalid) ? "" : demandWindowStrings[(int)distHeatWaterDemWindowUnits]));
    4032            2 :             OutputReportPredefined::PreDefTableEntry(state, s_orp->pdchLeedEcsTotal, "District Heating Water", distHeatWaterTotalCost, 2);
    4033              :         }
    4034            2 :         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            2 :         s_orp->LEEDelecCostTotal = elecTotalCost;
    4050            2 :         s_orp->LEEDgasCostTotal = gasTotalCost;
    4051            2 :         s_orp->LEEDothrCostTotal = distCoolTotalCost + distHeatWaterTotalCost + distHeatSteamTotalCost + otherTotalCost;
    4052            2 :         OutputReportPredefined::PreDefTableEntry(state,
    4053            2 :                                                  s_orp->pdchLeedEcsTotal,
    4054              :                                                  "Total",
    4055            2 :                                                  elecTotalCost + gasTotalCost + distCoolTotalCost + distHeatWaterTotalCost + distHeatSteamTotalCost +
    4056              :                                                      otherTotalCost,
    4057            2 :                                                  2);
    4058            2 :     }
    4059            2 : }
    4060              : 
    4061           75 : 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           75 :     Array1D_string columnHead;
    4070           75 :     Array1D_int columnWidth;
    4071           75 :     Array1D_string rowHead;
    4072           75 :     Array2D_string tableBody;
    4073              :     // other local variables
    4074              :     Real64 elecTotalCost;
    4075              :     Real64 gasTotalCost;
    4076              :     Real64 otherTotalCost;
    4077              :     Real64 allTotalCost;
    4078           75 :     Real64 perAreaUnitConv(0.0);
    4079              : 
    4080           75 :     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           75 :     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           75 :     if (state.dataOutRptTab->buildingConditionedFloorArea == 0.0) {
    4091           59 :         OutputReportTabular::DetermineBuildingFloorArea(state);
    4092              :     }
    4093              : 
    4094           75 :     if (s_econ->numTariff > 0) {
    4095            2 :         auto &econVar = s_econ->econVar;
    4096              : 
    4097            2 :         if (state.dataOutRptTab->displayEconomicResultSummary) {
    4098            2 :             DisplayString(state, "Writing Tariff Reports");
    4099          202 :             for (auto &e : econVar) {
    4100          200 :                 e.isReported = false;
    4101              :             }
    4102            2 :             showWarningsBasedOnTotal(state);
    4103              :             //---------------------------------
    4104              :             // Economics Results Summary Report
    4105              :             //---------------------------------
    4106            6 :             OutputReportTabular::WriteReportHeaders(
    4107              :                 state, "Economics Results Summary Report", "Entire Facility", OutputProcessor::StoreType::Average);
    4108              : 
    4109            5 :             for (int iUnitSystem = 0; iUnitSystem <= 1; iUnitSystem++) {
    4110            4 :                 OutputReportTabular::UnitsStyle unitsStyle_cur = state.dataOutRptTab->unitsStyle;
    4111            4 :                 bool produceTabular = true;
    4112            4 :                 bool produceSQLite = false;
    4113            4 :                 if (produceDualUnitsFlags(iUnitSystem,
    4114            4 :                                           state.dataOutRptTab->unitsStyle,
    4115            4 :                                           state.dataOutRptTab->unitsStyle_SQLite,
    4116              :                                           unitsStyle_cur,
    4117              :                                           produceTabular,
    4118              :                                           produceSQLite)) {
    4119            1 :                     break;
    4120              :                 }
    4121              : 
    4122              :                 // do unit conversions if necessary
    4123            3 :                 std::string perAreaUnitName;
    4124            3 :                 if ((unitsStyle_cur == OutputReportTabular::UnitsStyle::InchPound) ||
    4125            2 :                     (unitsStyle_cur == OutputReportTabular::UnitsStyle::InchPoundExceptElectricity)) {
    4126            1 :                     int unitConvIndex = 0;
    4127            1 :                     std::string SIunit = "[~~$~~/m2]";
    4128            1 :                     OutputReportTabular::LookupSItoIP(state, SIunit, unitConvIndex, perAreaUnitName);
    4129            1 :                     perAreaUnitConv = OutputReportTabular::ConvertIP(state, unitConvIndex, 1.0);
    4130            1 :                 } else {
    4131            2 :                     perAreaUnitName = "[~~$~~/m2]";
    4132            2 :                     perAreaUnitConv = 1.0;
    4133              :                 }
    4134              : 
    4135              :                 //---- Annual Summary
    4136            3 :                 rowHead.allocate(3);
    4137            3 :                 columnHead.allocate(4);
    4138            3 :                 columnWidth.allocate(4);
    4139            3 :                 tableBody.allocate(4, 3);
    4140            3 :                 tableBody = "";
    4141            3 :                 columnHead(1) = "Electricity";
    4142            3 :                 columnHead(2) = "Natural Gas";
    4143            3 :                 columnHead(3) = "Other";
    4144            3 :                 columnHead(4) = "Total";
    4145            3 :                 rowHead(1) = "Cost [~~$~~]";
    4146            3 :                 rowHead(2) = "Cost per Total Building Area " + perAreaUnitName;
    4147            3 :                 rowHead(3) = "Cost per Net Conditioned Building Area " + perAreaUnitName;
    4148            3 :                 elecTotalCost = 0.0;
    4149            3 :                 gasTotalCost = 0.0;
    4150            3 :                 otherTotalCost = 0.0;
    4151            3 :                 allTotalCost = 0.0;
    4152            6 :                 for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4153            3 :                     auto const &tariff = s_econ->tariff(iTariff);
    4154            3 :                     if (tariff.isSelected) {
    4155            3 :                         allTotalCost += tariff.totalAnnualCost;
    4156            3 :                         if (tariff.kindMtr == MeterType::ElecSimple || tariff.kindMtr == MeterType::ElecProduced ||
    4157            3 :                             tariff.kindMtr == MeterType::ElecPurchased || tariff.kindMtr == MeterType::ElecSurplusSold ||
    4158            3 :                             tariff.kindMtr == MeterType::ElecNet) {
    4159            0 :                             elecTotalCost += tariff.totalAnnualCost;
    4160            3 :                         } else if (tariff.kindMtr == MeterType::Gas) {
    4161            0 :                             gasTotalCost += tariff.totalAnnualCost;
    4162            3 :                         } else if (tariff.kindMtr != MeterType::Water) {
    4163            3 :                             otherTotalCost += tariff.totalAnnualCost;
    4164              :                             // removed because this was confusing        columnHead(3) = tariff.reportMeter
    4165              :                         }
    4166              :                     }
    4167              :                 }
    4168            3 :                 tableBody(1, 1) = OutputReportTabular::RealToStr(elecTotalCost, 2);
    4169            3 :                 tableBody(2, 1) = OutputReportTabular::RealToStr(gasTotalCost, 2);
    4170            3 :                 tableBody(3, 1) = OutputReportTabular::RealToStr(otherTotalCost, 2);
    4171            3 :                 tableBody(4, 1) = OutputReportTabular::RealToStr(allTotalCost, 2);
    4172            3 :                 if (state.dataOutRptTab->buildingGrossFloorArea > 0.0) {
    4173            3 :                     tableBody(1, 2) =
    4174            6 :                         OutputReportTabular::RealToStr((elecTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
    4175            3 :                     tableBody(2, 2) =
    4176            6 :                         OutputReportTabular::RealToStr((gasTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
    4177            3 :                     tableBody(3, 2) =
    4178            6 :                         OutputReportTabular::RealToStr((otherTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
    4179            3 :                     tableBody(4, 2) =
    4180            6 :                         OutputReportTabular::RealToStr((allTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
    4181              :                 }
    4182            3 :                 if (state.dataOutRptTab->buildingConditionedFloorArea > 0.0) {
    4183            3 :                     tableBody(1, 3) =
    4184            6 :                         OutputReportTabular::RealToStr((elecTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
    4185            3 :                     tableBody(2, 3) =
    4186            6 :                         OutputReportTabular::RealToStr((gasTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
    4187            3 :                     tableBody(3, 3) =
    4188            6 :                         OutputReportTabular::RealToStr((otherTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
    4189            3 :                     tableBody(4, 3) =
    4190            6 :                         OutputReportTabular::RealToStr((allTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
    4191              :                 }
    4192            3 :                 columnWidth = 14; // array assignment - same for all columns
    4193            3 :                 if (produceTabular) {
    4194            2 :                     OutputReportTabular::WriteSubtitle(state, "Annual Cost");
    4195            2 :                     OutputReportTabular::WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    4196              :                 }
    4197            3 :                 if (produceSQLite) {
    4198            2 :                     if (state.dataSQLiteProcedures->sqlite) {
    4199            2 :                         state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    4200              :                             tableBody, rowHead, columnHead, "Economics Results Summary Report", "Entire Facility", "Annual Cost");
    4201              :                     }
    4202              :                 }
    4203            3 :                 if (produceTabular) {
    4204            2 :                     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            3 :                 columnHead.deallocate();
    4210            3 :                 rowHead.deallocate();
    4211            3 :                 columnWidth.deallocate();
    4212            3 :                 tableBody.deallocate();
    4213            3 :             }
    4214              :             //---- Tariff Summary
    4215            2 :             rowHead.allocate(s_econ->numTariff);
    4216            2 :             columnHead.allocate(6);
    4217            2 :             columnWidth.allocate(6);
    4218            2 :             tableBody.allocate(6, s_econ->numTariff);
    4219            2 :             tableBody = "";
    4220            2 :             columnHead(1) = "Selected";
    4221            2 :             columnHead(2) = "Qualified";
    4222            2 :             columnHead(3) = "Meter";
    4223            2 :             columnHead(4) = "Buy or Sell";
    4224            2 :             columnHead(5) = "Group";
    4225            2 :             columnHead(6) = "Annual Cost (~~$~~)";
    4226            4 :             for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4227            2 :                 auto const &tariff = s_econ->tariff(iTariff);
    4228            2 :                 rowHead(iTariff) = tariff.tariffName;
    4229            2 :                 tableBody(1, iTariff) = yesNoNames[(int)tariff.isSelected];
    4230            2 :                 tableBody(2, iTariff) = yesNoNames[(int)tariff.isQualified];
    4231              : 
    4232            2 :                 tableBody(3, iTariff) = tariff.reportMeter;
    4233              : 
    4234            2 :                 if (tariff.buyOrSell == BuySell::BuyFromUtility) {
    4235            0 :                     tableBody(4, iTariff) = "Buy";
    4236            2 :                 } else if (tariff.buyOrSell == BuySell::SellToUtility) {
    4237            0 :                     tableBody(4, iTariff) = "Sell";
    4238            2 :                 } else if (tariff.buyOrSell == BuySell::NetMetering) {
    4239            2 :                     tableBody(4, iTariff) = "Net";
    4240              :                 }
    4241              : 
    4242            2 :                 if (tariff.groupName == "") {
    4243            2 :                     tableBody(5, iTariff) = "(none)";
    4244              :                 } else {
    4245            0 :                     tableBody(5, iTariff) = tariff.groupName;
    4246              :                 }
    4247            2 :                 tableBody(6, iTariff) = OutputReportTabular::RealToStr(tariff.totalAnnualCost, 2);
    4248              :             }
    4249            2 :             columnWidth = 14; // array assignment - same for all columns
    4250            2 :             OutputReportTabular::WriteSubtitle(state, "Tariff Summary");
    4251            2 :             OutputReportTabular::WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    4252            2 :             if (state.dataSQLiteProcedures->sqlite) {
    4253            2 :                 state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    4254              :                     tableBody, rowHead, columnHead, "Economics Results Summary Report", "Entire Facility", "Tariff Summary");
    4255              :             }
    4256            2 :             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            2 :             columnHead.deallocate();
    4261            2 :             rowHead.deallocate();
    4262            2 :             columnWidth.deallocate();
    4263            2 :             tableBody.deallocate();
    4264              :         }
    4265              :         //---------------------------------
    4266              :         // Tariff Report
    4267              :         //---------------------------------
    4268            2 :         if (state.dataOutRptTab->displayTariffReport) {
    4269            0 :             for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4270            0 :                 auto const &tariff = s_econ->tariff(iTariff);
    4271            0 :                 auto const &computation = s_econ->computation(iTariff);
    4272            0 :                 OutputReportTabular::WriteReportHeaders(state, "Tariff Report", tariff.tariffName, OutputProcessor::StoreType::Average);
    4273            0 :                 rowHead.allocate(7);
    4274            0 :                 columnHead.allocate(1);
    4275            0 :                 columnWidth.allocate(1);
    4276            0 :                 tableBody.allocate(1, 7);
    4277            0 :                 tableBody = "";
    4278            0 :                 columnHead(1) = "Parameter";
    4279            0 :                 rowHead(1) = "Meter";
    4280            0 :                 rowHead(2) = "Selected";
    4281            0 :                 rowHead(3) = "Group";
    4282            0 :                 rowHead(4) = "Qualified";
    4283            0 :                 rowHead(5) = "Disqualifier";
    4284            0 :                 rowHead(6) = "Computation";
    4285            0 :                 rowHead(7) = "Units";
    4286            0 :                 tableBody(1, 1) = tariff.reportMeter;
    4287            0 :                 if (tariff.isSelected) {
    4288            0 :                     tableBody(1, 2) = "Yes";
    4289              :                 } else {
    4290            0 :                     tableBody(1, 2) = "No";
    4291              :                 }
    4292            0 :                 if (tariff.groupName == "") {
    4293            0 :                     tableBody(1, 3) = "(none)";
    4294              :                 } else {
    4295            0 :                     tableBody(1, 3) = tariff.groupName;
    4296              :                 }
    4297            0 :                 if (tariff.isQualified) {
    4298            0 :                     tableBody(1, 4) = "Yes";
    4299              :                 } else {
    4300            0 :                     tableBody(1, 4) = "No";
    4301              :                 }
    4302            0 :                 if (tariff.isQualified) {
    4303            0 :                     tableBody(1, 5) = "n/a";
    4304              :                 } else {
    4305            0 :                     tableBody(1, 5) = econVar(tariff.ptDisqualifier).name;
    4306              :                 }
    4307            0 :                 if (computation.isUserDef) {
    4308            0 :                     tableBody(1, 6) = computation.computeName;
    4309              :                 } else {
    4310            0 :                     tableBody(1, 6) = "automatic";
    4311              :                 }
    4312            0 :                 switch (tariff.convChoice) {
    4313            0 :                 case EconConv::USERDEF: {
    4314            0 :                     tableBody(1, 7) = "User Defined";
    4315            0 :                 } break;
    4316            0 :                 case EconConv::KWH: {
    4317            0 :                     tableBody(1, 7) = "kWh";
    4318            0 :                 } break;
    4319            0 :                 case EconConv::THERM: {
    4320            0 :                     tableBody(1, 7) = "Therm";
    4321            0 :                 } 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            0 :                 case EconConv::MCF: {
    4332            0 :                     tableBody(1, 7) = "MCF";
    4333            0 :                 } break;
    4334            0 :                 case EconConv::CCF: {
    4335            0 :                     tableBody(1, 7) = "CCF";
    4336            0 :                 } break;
    4337            0 :                 default:
    4338            0 :                     break;
    4339              :                 }
    4340            0 :                 columnWidth = 14; // array assignment - same for all columns
    4341            0 :                 OutputReportTabular::WriteSubtitle(state, "General");
    4342            0 :                 OutputReportTabular::WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    4343            0 :                 if (state.dataSQLiteProcedures->sqlite) {
    4344            0 :                     state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    4345              :                         tableBody, rowHead, columnHead, "Tariff Report", tariff.tariffName, "General");
    4346              :                 }
    4347            0 :                 if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    4348            0 :                     state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    4349            0 :                         tableBody, rowHead, columnHead, "Tariff Report", tariff.tariffName, "General");
    4350              :                 }
    4351            0 :                 columnHead.deallocate();
    4352            0 :                 rowHead.deallocate();
    4353            0 :                 columnWidth.deallocate();
    4354            0 :                 tableBody.deallocate();
    4355              :                 //---- Categories
    4356            0 :                 for (auto &e : econVar) {
    4357            0 :                     e.activeNow = false;
    4358              :                 }
    4359            0 :                 econVar(tariff.cats[(int)Cat::EnergyCharges]).activeNow = true;
    4360            0 :                 econVar(tariff.cats[(int)Cat::DemandCharges]).activeNow = true;
    4361            0 :                 econVar(tariff.cats[(int)Cat::ServiceCharges]).activeNow = true;
    4362            0 :                 econVar(tariff.cats[(int)Cat::Basis]).activeNow = true;
    4363            0 :                 econVar(tariff.cats[(int)Cat::Adjustment]).activeNow = true;
    4364            0 :                 econVar(tariff.cats[(int)Cat::Surcharge]).activeNow = true;
    4365            0 :                 econVar(tariff.cats[(int)Cat::Subtotal]).activeNow = true;
    4366            0 :                 econVar(tariff.cats[(int)Cat::Taxes]).activeNow = true;
    4367            0 :                 econVar(tariff.cats[(int)Cat::Total]).activeNow = true;
    4368            0 :                 ReportEconomicVariable(state, "Categories", false, true, tariff.tariffName);
    4369              :                 //---- Charges
    4370            0 :                 for (auto &e : econVar) {
    4371            0 :                     e.activeNow = false;
    4372              :                 }
    4373            0 :                 for (int kVar = 1; kVar <= s_econ->numEconVar; ++kVar) {
    4374            0 :                     if (econVar(kVar).tariffIndx == iTariff) {
    4375            0 :                         if ((econVar(kVar).kindOfObj == ObjType::ChargeSimple) || (econVar(kVar).kindOfObj == ObjType::ChargeBlock)) {
    4376            0 :                             econVar(kVar).activeNow = true;
    4377              :                         }
    4378              :                     }
    4379              :                 }
    4380            0 :                 ReportEconomicVariable(state, "Charges", true, true, tariff.tariffName);
    4381              :                 //---- Sources for Charges
    4382            0 :                 for (auto &e : econVar) {
    4383            0 :                     e.activeNow = false;
    4384              :                 }
    4385            0 :                 for (int kVar = 1; kVar <= s_econ->numEconVar; ++kVar) {
    4386            0 :                     if (econVar(kVar).tariffIndx == iTariff) {
    4387            0 :                         int indexInChg = econVar(kVar).index;
    4388            0 :                         if (econVar(kVar).kindOfObj == ObjType::ChargeSimple) {
    4389            0 :                             auto &chargeSimple = s_econ->chargeSimple(indexInChg);
    4390            0 :                             if (chargeSimple.sourcePt > 0) {
    4391            0 :                                 econVar(chargeSimple.sourcePt).activeNow = true;
    4392              :                             }
    4393            0 :                         } else if (econVar(kVar).kindOfObj == ObjType::ChargeBlock) {
    4394            0 :                             auto &chargeBlock = s_econ->chargeBlock(indexInChg);
    4395            0 :                             if (chargeBlock.sourcePt > 0) {
    4396            0 :                                 econVar(chargeBlock.sourcePt).activeNow = true;
    4397              :                             }
    4398              :                         }
    4399              :                     }
    4400              :                 }
    4401            0 :                 ReportEconomicVariable(state, "Corresponding Sources for Charges", false, false, tariff.tariffName);
    4402              :                 //---- Rachets
    4403            0 :                 for (auto &e : econVar) {
    4404            0 :                     e.activeNow = false;
    4405              :                 }
    4406            0 :                 for (int kVar = 1; kVar <= s_econ->numEconVar; ++kVar) {
    4407            0 :                     if (econVar(kVar).tariffIndx == iTariff) {
    4408            0 :                         if (econVar(kVar).kindOfObj == ObjType::Ratchet) {
    4409            0 :                             econVar(kVar).activeNow = true;
    4410              :                         }
    4411              :                     }
    4412              :                 }
    4413            0 :                 ReportEconomicVariable(state, "Ratchets", false, false, tariff.tariffName);
    4414              :                 //---- Qualifies
    4415            0 :                 for (auto &e : econVar) {
    4416            0 :                     e.activeNow = false;
    4417              :                 }
    4418            0 :                 for (int kVar = 1; kVar <= s_econ->numEconVar; ++kVar) {
    4419            0 :                     if (econVar(kVar).tariffIndx == iTariff) {
    4420            0 :                         if (econVar(kVar).kindOfObj == ObjType::Qualify) {
    4421            0 :                             econVar(kVar).activeNow = true;
    4422              :                         }
    4423              :                     }
    4424              :                 }
    4425            0 :                 ReportEconomicVariable(state, "Qualifies", false, false, tariff.tariffName);
    4426              :                 //---- Native Variables
    4427            0 :                 for (auto &e : econVar) {
    4428            0 :                     e.activeNow = false;
    4429              :                 }
    4430            0 :                 for (int kVar = tariff.firstNative; kVar <= tariff.lastNative; ++kVar) {
    4431            0 :                     econVar(kVar).activeNow = true;
    4432              :                 }
    4433            0 :                 ReportEconomicVariable(state, "Native Variables", false, false, tariff.tariffName);
    4434              :                 //---- Other Variables
    4435            0 :                 for (auto &e : econVar) {
    4436            0 :                     e.activeNow = false;
    4437              :                 }
    4438            0 :                 for (int kVar = 1; kVar <= s_econ->numEconVar; ++kVar) {
    4439            0 :                     if (econVar(kVar).tariffIndx == iTariff) {
    4440            0 :                         if (!econVar(kVar).isReported) {
    4441            0 :                             econVar(kVar).activeNow = true;
    4442              :                         }
    4443              :                     }
    4444              :                 }
    4445            0 :                 ReportEconomicVariable(state, "Other Variables", false, false, tariff.tariffName);
    4446              :                 //---- Computation
    4447            0 :                 if (computation.isUserDef) {
    4448            0 :                     OutputReportTabular::WriteTextLine(state, "Computation -  User Defined", true);
    4449              :                 } else {
    4450            0 :                     OutputReportTabular::WriteTextLine(state, "Computation -  Automatic", true);
    4451              :                 }
    4452            0 :                 std::string outString = "";
    4453            0 :                 for (int lStep = computation.firstStep; lStep <= computation.lastStep; ++lStep) {
    4454            0 :                     auto &step = s_econ->steps(lStep);
    4455              : 
    4456            0 :                     if (step.type == StepType::EOL) {
    4457            0 :                         OutputReportTabular::WriteTextLine(state, rstrip(outString));
    4458            0 :                         outString = "";
    4459            0 :                     } else if (step.type == StepType::Var) {
    4460            0 :                         outString = econVar(step.varNum).name + ' ' + outString;
    4461            0 :                     } else if (step.type == StepType::Op) {
    4462            0 :                         outString = format("{} {}", opNamesUC[(int)step.op], outString);
    4463              :                     }
    4464              :                 }
    4465              :             }
    4466              :         }
    4467              :     }
    4468           75 : }
    4469              : 
    4470            2 : 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            2 :     auto &s_econ = state.dataEconTariff;
    4478            4 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4479            2 :         auto const &tariff = s_econ->tariff(iTariff);
    4480            2 :         if (tariff.buyOrSell == BuySell::BuyFromUtility) {
    4481            0 :             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            0 :             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            2 : }
    4493              : 
    4494            0 : 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            0 :     Real64 maximumVal(0.0); // Autodesk Value not used but suppresses warning about HUGE_() call
    4502              : 
    4503            0 :     auto const &s_econ = state.dataEconTariff;
    4504            0 :     auto const &econVar = s_econ->econVar(varPointer);
    4505              : 
    4506            0 :     Real64 sumVal = 0.0;
    4507            0 :     maximumVal = -HUGE_(maximumVal);
    4508            0 :     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            0 :         Real64 curVal = econVar.values(jMonth);
    4510            0 :         sumVal += curVal;
    4511            0 :         if (curVal > maximumVal) {
    4512            0 :             maximumVal = curVal;
    4513              :         }
    4514              :     }
    4515            0 :     sumResult = sumVal;
    4516            0 :     maxResult = maximumVal;
    4517            0 : }
    4518              : 
    4519            0 : 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            0 :     Array1D_string columnHead;
    4531            0 :     Array1D_int columnWidth;
    4532            0 :     Array1D_string rowHead;
    4533            0 :     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            0 :     auto const &s_econ = state.dataEconTariff;
    4547            0 :     auto const &econVar = s_econ->econVar;
    4548            0 :     auto const &chargeBlock = s_econ->chargeBlock;
    4549            0 :     auto const &chargeSimple = s_econ->chargeSimple;
    4550              : 
    4551            0 :     cntOfVar = 0;
    4552            0 :     for (iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    4553            0 :         if (econVar(iVar).activeNow) {
    4554            0 :             ++cntOfVar;
    4555              :         }
    4556              :     }
    4557            0 :     if (includeCategory) {
    4558            0 :         rowHead.allocate(cntOfVar);
    4559            0 :         columnHead.allocate(15);
    4560            0 :         columnWidth.allocate(15);
    4561            0 :         tableBody.allocate(15, cntOfVar);
    4562              :     } else {
    4563            0 :         rowHead.allocate(cntOfVar);
    4564            0 :         columnHead.allocate(14);
    4565            0 :         columnWidth.allocate(14);
    4566            0 :         tableBody.allocate(14, cntOfVar);
    4567              :     }
    4568              :     // column names
    4569            0 :     columnHead(1) = "Jan";
    4570            0 :     columnHead(2) = "Feb";
    4571            0 :     columnHead(3) = "Mar";
    4572            0 :     columnHead(4) = "Apr";
    4573            0 :     columnHead(5) = "May";
    4574            0 :     columnHead(6) = "Jun";
    4575            0 :     columnHead(7) = "Jul";
    4576            0 :     columnHead(8) = "Aug";
    4577            0 :     columnHead(9) = "Sep";
    4578            0 :     columnHead(10) = "Oct";
    4579            0 :     columnHead(11) = "Nov";
    4580            0 :     columnHead(12) = "Dec";
    4581            0 :     columnHead(13) = "Sum";
    4582            0 :     columnHead(14) = "Max";
    4583            0 :     if (includeCategory) {
    4584            0 :         columnHead(15) = "Category";
    4585              :     }
    4586            0 :     nCntOfVar = 0;
    4587              :     // row names
    4588            0 :     for (iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    4589            0 :         if (econVar(iVar).activeNow) {
    4590            0 :             ++nCntOfVar;
    4591            0 :             if (showCurrencySymbol) {
    4592            0 :                 rowHead(nCntOfVar) = econVar(iVar).name + " (~~$~~)";
    4593              :             } else {
    4594            0 :                 rowHead(nCntOfVar) = econVar(iVar).name;
    4595              :             }
    4596              :         }
    4597              :     }
    4598              :     // fill the body
    4599            0 :     nCntOfVar = 0;
    4600            0 :     for (iVar = 1; iVar <= s_econ->numEconVar; ++iVar) {
    4601            0 :         if (econVar(iVar).activeNow) {
    4602            0 :             ++nCntOfVar;
    4603            0 :             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            0 :                 curVal = econVar(iVar).values(jMonth);
    4605            0 :                 if ((curVal > 0) && (curVal < 1)) {
    4606            0 :                     tableBody(jMonth, nCntOfVar) = OutputReportTabular::RealToStr(curVal, 4);
    4607              :                 } else {
    4608            0 :                     tableBody(jMonth, nCntOfVar) = OutputReportTabular::RealToStr(curVal, 2);
    4609              :                 }
    4610              :             }
    4611            0 :             getMaxAndSum(state, iVar, sumVal, maximumVal);
    4612            0 :             tableBody(13, nCntOfVar) = OutputReportTabular::RealToStr(sumVal, 2);
    4613            0 :             tableBody(14, nCntOfVar) = OutputReportTabular::RealToStr(maximumVal, 2);
    4614            0 :             if (includeCategory) {
    4615              :                 // first find category
    4616            0 :                 curCategory = 0;
    4617            0 :                 curIndex = econVar(iVar).index;
    4618              : 
    4619            0 :                 switch (econVar(iVar).kindOfObj) {
    4620            0 :                 case ObjType::ChargeSimple:
    4621            0 :                     if ((curIndex >= 1) && (curIndex <= s_econ->numChargeSimple)) {
    4622            0 :                         curCatPt = chargeSimple(curIndex).categoryPt;
    4623              :                     }
    4624            0 :                     break;
    4625            0 :                 case ObjType::ChargeBlock:
    4626            0 :                     if ((curIndex >= 1) && (curIndex <= s_econ->numChargeBlock)) {
    4627            0 :                         curCatPt = chargeBlock(curIndex).categoryPt;
    4628              :                     }
    4629            0 :                     break;
    4630            0 :                 default:
    4631            0 :                     break;
    4632              :                 }
    4633              : 
    4634            0 :                 if ((curCatPt >= 1) && (curCatPt <= s_econ->numEconVar)) {
    4635            0 :                     curCategory = econVar(curCatPt).specific;
    4636              :                 }
    4637              : 
    4638              :                 // In this specific table, "NotIncluded" is written as "none" so need a special case for that
    4639            0 :                 tableBody(15, nCntOfVar) =
    4640            0 :                     (econVar(curCatPt).kindOfObj == ObjType::Category)
    4641            0 :                         ? ((econVar(curCatPt).specific == (int)Cat::NotIncluded) ? "none" : catNames[econVar(curCatPt).specific])
    4642            0 :                         : "none";
    4643              :             }
    4644            0 :             s_econ->econVar(iVar).isReported = true;
    4645              :         }
    4646              :     }
    4647            0 :     columnWidth = 14; // array assignment - same for all columns
    4648            0 :     OutputReportTabular::WriteSubtitle(state, titleString);
    4649            0 :     OutputReportTabular::WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    4650            0 :     if (state.dataSQLiteProcedures->sqlite) {
    4651            0 :         state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(tableBody, rowHead, columnHead, "Tariff Report", forString, titleString);
    4652              :     }
    4653            0 :     if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    4654            0 :         state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    4655              :             tableBody, rowHead, columnHead, "Tariff Report", forString, titleString);
    4656              :     }
    4657            0 :     columnHead.deallocate();
    4658            0 :     rowHead.deallocate();
    4659            0 :     columnWidth.deallocate();
    4660            0 :     tableBody.deallocate();
    4661            0 : }
    4662              : 
    4663            0 : 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            0 :     Array1D_int groupIndex;     // index number (in tariff) for the group name
    4677            0 :     Array1D_int MinTariffIndex; // tariff index for the Minimum value
    4678              :     int curMinTariffIndex;
    4679              : 
    4680            0 :     auto const &s_econ = state.dataEconTariff;
    4681            0 :     auto const &econVar(s_econ->econVar);
    4682              : 
    4683            0 :     groupIndex.dimension(s_econ->numTariff, 0);
    4684            0 :     int groupCount = 0;
    4685            0 :     int numMins = 0;
    4686            0 :     MinTariffIndex.dimension(s_econ->numTariff, 0);
    4687            0 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4688            0 :         auto &tariff = s_econ->tariff(iTariff);
    4689              :         // compute the total annual cost of each tariff
    4690            0 :         int totalVarPt = tariff.cats[(int)Cat::Total];
    4691            0 :         int totEneVarPt = tariff.natives[(int)Native::TotalEnergy];
    4692            0 :         Real64 annualTotal = 0.0;
    4693            0 :         Real64 annEneTotal = 0.0;
    4694            0 :         for (int jMonth = 1; jMonth <= NumMonths; ++jMonth) {
    4695            0 :             annualTotal += econVar(totalVarPt).values(jMonth);
    4696            0 :             annEneTotal += econVar(totEneVarPt).values(jMonth);
    4697              :         }
    4698            0 :         tariff.totalAnnualCost = annualTotal;
    4699            0 :         tariff.totalAnnualEnergy = annEneTotal;
    4700              :         // Set the groupIndex
    4701            0 :         if (groupIndex(iTariff) == 0) {
    4702              :             // set the current item to the tariff index
    4703            0 :             ++groupCount;
    4704            0 :             groupIndex(iTariff) = groupCount;
    4705              :             // set all remaining matching items to the same index
    4706            0 :             for (int kTariff = iTariff + 1; kTariff <= s_econ->numTariff; ++kTariff) {
    4707            0 :                 if (Util::SameString(s_econ->tariff(kTariff).groupName, tariff.groupName)) {
    4708            0 :                     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            0 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4715            0 :         auto &tariff = s_econ->tariff(iTariff);
    4716            0 :         if (tariff.isQualified) {
    4717            0 :             bool isFound = false;
    4718            0 :             for (int lMin = 1; lMin <= numMins; ++lMin) {
    4719            0 :                 curMinTariffIndex = MinTariffIndex(lMin);
    4720              :                 // find matching meter and group
    4721            0 :                 if (tariff.reportMeterIndx == s_econ->tariff(curMinTariffIndex).reportMeterIndx) {
    4722            0 :                     if (groupIndex(iTariff) == groupIndex(curMinTariffIndex)) {
    4723            0 :                         isFound = true;
    4724              :                         // found the matching mater and group now test if smaller Min is current tariff
    4725            0 :                         if (tariff.totalAnnualCost < s_econ->tariff(curMinTariffIndex).totalAnnualCost) {
    4726            0 :                             MinTariffIndex(lMin) = iTariff;
    4727              :                             // select the new Minimum tariff and deselect the one that was just exceeded
    4728            0 :                             s_econ->tariff(curMinTariffIndex).isSelected = false;
    4729            0 :                             tariff.isSelected = true;
    4730              :                         }
    4731              :                     }
    4732              :                 }
    4733              :             }
    4734            0 :             if (!isFound) {
    4735            0 :                 ++numMins;
    4736            0 :                 if (numMins > s_econ->numTariff) {
    4737            0 :                     ShowWarningError(state, "UtilityCost:Tariff Debugging error numMins greater than numTariff.");
    4738              :                 }
    4739            0 :                 MinTariffIndex(numMins) = iTariff;
    4740              :                 // tariff(numMins)%isSelected = .TRUE.  !original
    4741            0 :                 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            0 :     for (int mGroup = 1; mGroup <= groupCount; ++mGroup) {
    4751            0 :         int lowestSimpleTariff = 0;
    4752            0 :         int lowestPurchaseTariff = 0;
    4753            0 :         int lowestSurplusSoldTariff = 0;
    4754            0 :         int lowestNetMeterTariff = 0;
    4755            0 :         for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4756            0 :             auto &tariff = s_econ->tariff(iTariff);
    4757            0 :             if (tariff.isQualified) {
    4758            0 :                 if (tariff.isSelected) {
    4759            0 :                     if (groupIndex(iTariff) == mGroup) {
    4760            0 :                         if (tariff.kindMtr == MeterType::ElecSimple) {
    4761            0 :                             lowestSimpleTariff = iTariff;
    4762            0 :                         } 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            0 :                         } else if (tariff.kindMtr == MeterType::ElecPurchased) {
    4766            0 :                             lowestPurchaseTariff = iTariff;
    4767            0 :                         } else if (tariff.kindMtr == MeterType::ElecSurplusSold) {
    4768            0 :                             lowestSurplusSoldTariff = iTariff;
    4769            0 :                         } else if (tariff.kindMtr == MeterType::ElecNet) {
    4770            0 :                             lowestNetMeterTariff = iTariff;
    4771              :                         }
    4772              :                     }
    4773              :                 }
    4774              :             }
    4775              :         }
    4776              :         // compare the simple and purchased metered tariffs
    4777            0 :         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            0 :         if (lowestSurplusSoldTariff > 0) {
    4788            0 :             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            0 :         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            0 :         if (((lowestNetMeterTariff > 0) && (lowestSurplusSoldTariff > 0)) && (lowestPurchaseTariff > 0)) {
    4808            0 :             if (s_econ->tariff(lowestNetMeterTariff).totalAnnualCost <
    4809            0 :                 (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            0 :                 s_econ->tariff(lowestNetMeterTariff).isSelected = false;
    4816            0 :                 lowestNetMeterTariff = 0;
    4817              :             }
    4818              :         }
    4819              :         // if netmetering is used compare it to simple only
    4820            0 :         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            0 :         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            0 :     groupIndex.deallocate();
    4841            0 :     MinTariffIndex.deallocate();
    4842            0 : }
    4843              : 
    4844           48 : 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           48 :     auto const &s_econ = state.dataEconTariff;
    4853              : 
    4854           48 :     outMonthlyCosts.dim(12);
    4855              : 
    4856           48 :     outMonthlyCosts = 0.0;
    4857           96 :     for (int iTariff = 1; iTariff <= s_econ->numTariff; ++iTariff) {
    4858           48 :         auto const &tariff = s_econ->tariff(iTariff);
    4859           48 :         if (tariff.isSelected) {
    4860           48 :             if (tariff.resource == inResourceNumber) {
    4861            1 :                 auto const &econVar = s_econ->econVar(tariff.cats[(int)Cat::Total]);
    4862           13 :                 for (int jMonth = 1; jMonth <= 12; ++jMonth) { // use 12 because LCC assume 12 months
    4863           12 :                     outMonthlyCosts(jMonth) += econVar.values(jMonth);
    4864              :                 }
    4865              :             }
    4866              :         }
    4867              :     }
    4868           48 : }
    4869              : 
    4870              : } // namespace EnergyPlus::EconomicTariff
        

Generated by: LCOV version 2.0-1