LCOV - code coverage report
Current view: top level - EnergyPlus - EconomicTariff.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 2281 3094 73.7 %
Date: 2024-08-23 23:50:59 Functions: 43 43 100.0 %

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

Generated by: LCOV version 1.14