LCOV - code coverage report
Current view: top level - EnergyPlus - EconomicLifeCycleCost.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 870 1137 76.5 %
Date: 2023-01-17 19:17:23 Functions: 14 14 100.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, 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 <cmath>
      50             : 
      51             : // ObjexxFCL Headers
      52             : #include <ObjexxFCL/Fmath.hh>
      53             : #include <ObjexxFCL/string.functions.hh>
      54             : 
      55             : // EnergyPlus Headers
      56             : #include <EnergyPlus/CostEstimateManager.hh>
      57             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      58             : #include <EnergyPlus/DataGlobalConstants.hh>
      59             : #include <EnergyPlus/DataIPShortCuts.hh>
      60             : #include <EnergyPlus/DisplayRoutines.hh>
      61             : #include <EnergyPlus/EconomicLifeCycleCost.hh>
      62             : #include <EnergyPlus/EconomicTariff.hh>
      63             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      64             : #include <EnergyPlus/OutputReportTabular.hh>
      65             : #include <EnergyPlus/ResultsFramework.hh>
      66             : #include <EnergyPlus/SQLiteProcedures.hh>
      67             : #include <EnergyPlus/UtilityRoutines.hh>
      68             : 
      69             : namespace EnergyPlus::EconomicLifeCycleCost {
      70             : 
      71             : // Module containing the routines dealing with the EconomicLifeCycleCost
      72             : 
      73             : // MODULE INFORMATION:
      74             : //       AUTHOR         Jason Glazer of GARD Analytics, Inc.
      75             : //       DATE WRITTEN   May 2010
      76             : //       MODIFIED       na
      77             : //       RE-ENGINEERED  na
      78             : 
      79             : // PURPOSE OF THIS MODULE:
      80             : //   To compute life-cycle cost measures such as present value based
      81             : //   on input provided by the user as well as calculated energy costs.
      82             : 
      83             : // METHODOLOGY EMPLOYED:
      84             : //   Uses NIST Handbook 135 "Life-Cycle Costing Manual for the Federal
      85             : //   Energy Management Program" for most computations.
      86             : 
      87             : // REFERENCES:
      88             : //   To compute the net present value for all costs entered in the
      89             : //   LifeCycleCosts objects, the algorithms from NIST Handbook 135
      90             : //   "Life-Cycle Costing Manual for the Federal Energy Management
      91             : //   Program" will be used as the primary source. Supplemental sources
      92             : //   of algorithms will be derived from ASTM E833-09a "Standard
      93             : //   Terminology of Building Economics", ASTM E917-05 "Standard
      94             : //   Practice for Measuring Life-Cycle Cost of Buildings and Building
      95             : //   Systems", and "Engineering Economic Analysis, Ninth Edition", by
      96             : //   Donald Newnan, Ted Eschenback, and Jerome Lavelle.
      97             : 
      98             : // OTHER NOTES:
      99             : // na
     100             : 
     101             : // Using/Aliasing
     102             : using namespace DataGlobalConstants;
     103             : 
     104             : // Functions
     105             : 
     106         769 : void GetInputForLifeCycleCost(EnergyPlusData &state)
     107             : {
     108             :     // SUBROUTINE INFORMATION:
     109             :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
     110             :     //    DATE WRITTEN   May 2010
     111             :     //    MODIFIED       na
     112             :     //    RE-ENGINEERED  na
     113             : 
     114             :     // PURPOSE OF THIS SUBROUTINE:
     115             :     //    Read the input file for "LifeCycleCost:Parameters" object.
     116             : 
     117             :     // Using/Aliasing
     118             :     using OutputReportTabular::AddTOCEntry;
     119             : 
     120         769 :     auto &elcc(state.dataEconLifeCycleCost);
     121             : 
     122         769 :     if (elcc->GetInput_GetLifeCycleCostInput) {
     123         769 :         GetInputLifeCycleCostParameters(state);
     124         769 :         GetInputLifeCycleCostRecurringCosts(state);
     125         769 :         GetInputLifeCycleCostNonrecurringCost(state);
     126         769 :         GetInputLifeCycleCostUsePriceEscalation(state);
     127         769 :         GetInputLifeCycleCostUseAdjustment(state);
     128         769 :         elcc->GetInput_GetLifeCycleCostInput = false;
     129             :     }
     130         769 : }
     131             : 
     132         769 : void ComputeLifeCycleCostAndReport(EnergyPlusData &state)
     133             : {
     134             :     // SUBROUTINE INFORMATION:
     135             :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
     136             :     //    DATE WRITTEN   May 2010
     137             :     //    MODIFIED       na
     138             :     //    RE-ENGINEERED  na
     139             : 
     140             :     // PURPOSE OF THIS SUBROUTINE:
     141             :     //    Perform the life cycle cost computations and write report.
     142             : 
     143         769 :     if (state.dataEconLifeCycleCost->LCCparamPresent) {
     144           1 :         DisplayString(state, "Computing Life Cycle Costs and Reporting");
     145           1 :         ExpressAsCashFlows(state);
     146           1 :         ComputePresentValue(state);
     147           1 :         ComputeEscalatedEnergyCosts(state);
     148           1 :         ComputeTaxAndDepreciation(state);
     149           1 :         WriteTabularLifeCycleCostReport(state);
     150             :     }
     151         769 : }
     152             : 
     153             : //======================================================================================================================
     154             : //======================================================================================================================
     155             : 
     156             : //    GET INPUT ROUTINES
     157             : 
     158             : //======================================================================================================================
     159             : //======================================================================================================================
     160             : 
     161         769 : void GetInputLifeCycleCostParameters(EnergyPlusData &state)
     162             : {
     163             :     // SUBROUTINE INFORMATION:
     164             :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
     165             :     //    DATE WRITTEN   May 2010
     166             : 
     167             :     // PURPOSE OF THIS SUBROUTINE:
     168             :     //    Read the input file for "LifeCycleCost:Parameters" object.
     169             : 
     170             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     171             : 
     172             :     int jFld;                        // loop counter
     173             :     int NumFields;                   // Total number of elements
     174             :     int NumAlphas;                   // Number of elements in the alpha array
     175             :     int NumNums;                     // Number of elements in the numeric array
     176        1538 :     Array1D_string AlphaArray;       // character string data
     177        1538 :     Array1D<Real64> NumArray;        // numeric data
     178             :     int IOStat;                      // IO Status when calling get input subroutine
     179        1538 :     std::string CurrentModuleObject; // for ease in renaming.
     180             :     int NumObj;                      // count of objects
     181             : 
     182         769 :     CurrentModuleObject = "LifeCycleCost:Parameters";
     183         769 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNums);
     184         769 :     NumArray.allocate(NumNums);
     185         769 :     AlphaArray.allocate(NumAlphas);
     186         769 :     NumObj = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     187             : 
     188         769 :     auto &elcc(state.dataEconLifeCycleCost);
     189             : 
     190         769 :     if (NumObj == 0) {
     191         768 :         elcc->LCCparamPresent = false;
     192           1 :     } else if (NumObj == 1) {
     193           1 :         elcc->LCCparamPresent = true;
     194           5 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     195             :                                                                  CurrentModuleObject,
     196             :                                                                  1,
     197             :                                                                  AlphaArray,
     198             :                                                                  NumAlphas,
     199             :                                                                  NumArray,
     200             :                                                                  NumNums,
     201             :                                                                  IOStat,
     202           1 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     203           1 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     204           1 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     205           1 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     206             :         // check to make sure none of the values are another life cycle cost object
     207           7 :         for (jFld = 1; jFld <= NumAlphas; ++jFld) {
     208           6 :             if (hasi(AlphaArray(jFld), "LifeCycleCost:")) {
     209           0 :                 ShowWarningError(state,
     210           0 :                                  "In " + CurrentModuleObject + " named " + AlphaArray(1) +
     211             :                                      " a field was found containing LifeCycleCost: which may indicate a missing comma.");
     212             :             }
     213             :         }
     214             :         // start to extract values from input array into appropriate fields
     215             :         //  A1,  \field Name
     216             :         //       \required-field
     217             :         //       \type alpha
     218           1 :         elcc->LCCname = AlphaArray(1);
     219             :         //  A2, \field Discounting Convention
     220             :         //      \type choice
     221             :         //      \key EndOfYear
     222             :         //      \key MidYear
     223             :         //      \key BeginningOfYear
     224             :         //      \default EndOfYear
     225           1 :         elcc->discountConvention = static_cast<DiscConv>(getEnumerationValue(DiscConvNamesUC, UtilityRoutines::MakeUPPERCase(AlphaArray(2))));
     226           1 :         if (elcc->discountConvention == DiscConv::Invalid) {
     227           0 :             elcc->discountConvention = DiscConv::EndOfYear;
     228           0 :             ShowWarningError(state,
     229           0 :                              CurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + AlphaArray(2) +
     230             :                                  "\". EndOfYear will be used.");
     231             :         }
     232             :         // A3,  \field Inflation Approach
     233             :         //      \type choice
     234             :         //      \key ConstantDollar
     235             :         //      \key CurrentDollar
     236             :         //      \default ConstantDollar
     237           1 :         elcc->inflationApproach = static_cast<InflAppr>(getEnumerationValue(InflApprNamesUC, UtilityRoutines::MakeUPPERCase(AlphaArray(3))));
     238           1 :         if (elcc->inflationApproach == InflAppr::Invalid) {
     239           0 :             elcc->inflationApproach = InflAppr::ConstantDollar;
     240           0 :             ShowWarningError(state,
     241           0 :                              CurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + AlphaArray(3) +
     242             :                                  "\". ConstantDollar will be used.");
     243             :         }
     244             :         // N1,  \field Real Discount Rate
     245             :         //      \type real
     246           1 :         elcc->realDiscountRate = NumArray(1);
     247           1 :         if ((elcc->inflationApproach == InflAppr::ConstantDollar) && state.dataIPShortCut->lNumericFieldBlanks(1)) {
     248           0 :             ShowWarningError(state,
     249           0 :                              CurrentModuleObject + ": Invalid for field " + state.dataIPShortCut->cNumericFieldNames(1) +
     250             :                                  " to be blank when ConstantDollar analysis is be used.");
     251             :         }
     252           1 :         if ((elcc->realDiscountRate > 0.30) || (elcc->realDiscountRate < -0.30)) {
     253           0 :             ShowWarningError(state,
     254           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(1) +
     255             :                                  ".  This value is the decimal value not a percentage so most values are between 0.02 and 0.15. ");
     256             :         }
     257             :         // N2,  \field Nominal Discount Rate
     258             :         //      \type real
     259           1 :         elcc->nominalDiscountRate = NumArray(2);
     260           1 :         if ((elcc->inflationApproach == InflAppr::CurrentDollar) && state.dataIPShortCut->lNumericFieldBlanks(2)) {
     261           0 :             ShowWarningError(state,
     262           0 :                              CurrentModuleObject + ": Invalid for field " + state.dataIPShortCut->cNumericFieldNames(2) +
     263             :                                  " to be blank when CurrentDollar analysis is be used.");
     264             :         }
     265           1 :         if ((elcc->nominalDiscountRate > 0.30) || (elcc->nominalDiscountRate < -0.30)) {
     266           0 :             ShowWarningError(state,
     267           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(2) +
     268             :                                  ".  This value is the decimal value not a percentage so most values are between 0.02 and 0.15. ");
     269             :         }
     270             :         // N3,  \field Inflation
     271             :         //      \type real
     272           1 :         elcc->inflation = NumArray(3);
     273           1 :         if ((elcc->inflationApproach == InflAppr::ConstantDollar) && (!state.dataIPShortCut->lNumericFieldBlanks(3))) {
     274           0 :             ShowWarningError(state,
     275           0 :                              CurrentModuleObject + ": Invalid for field " + state.dataIPShortCut->cNumericFieldNames(3) +
     276             :                                  " contain a value when ConstantDollar analysis is be used.");
     277             :         }
     278           1 :         if ((elcc->inflation > 0.30) || (elcc->inflation < -0.30)) {
     279           0 :             ShowWarningError(state,
     280           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(3) +
     281             :                                  ".  This value is the decimal value not a percentage so most values are between 0.02 and 0.15. ");
     282             :         }
     283             :         // A4,  \field Base Date Month
     284             :         //      \type choice
     285             :         //      \key January
     286             :         //      \key February
     287             :         //      \key March
     288             :         //      \key April
     289             :         //      \key May
     290             :         //      \key June
     291             :         //      \key July
     292             :         //      \key August
     293             :         //      \key September
     294             :         //      \key October
     295             :         //      \key November
     296             :         //      \key December
     297             :         //      \default January
     298           1 :         elcc->baseDateMonth = getEnumerationValue(UtilityRoutines::MonthNamesUC, UtilityRoutines::MakeUPPERCase(AlphaArray(4)));
     299           1 :         if (elcc->baseDateMonth == -1) {
     300           0 :             elcc->baseDateMonth = 0;
     301           0 :             ShowWarningError(state,
     302           0 :                              CurrentModuleObject + ": Invalid month entered in field " + state.dataIPShortCut->cAlphaFieldNames(4) +
     303           0 :                                  ". Using January instead of \"" + AlphaArray(4) + "\"");
     304             :         }
     305             :         // N4,  \field Base Date Year
     306             :         //      \type integer
     307             :         //      \minimum 1900
     308             :         //      \maximum 2100
     309           1 :         elcc->baseDateYear = int(NumArray(4));
     310           1 :         if (elcc->baseDateYear > 2100) {
     311           0 :             ShowWarningError(state,
     312           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(4) +
     313             :                                  ".  Value greater than 2100 yet it is representing a year. ");
     314             :         }
     315           1 :         if (elcc->baseDateYear < 1900) {
     316           0 :             ShowWarningError(state,
     317           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(4) +
     318             :                                  ".  Value less than 1900 yet it is representing a year. ");
     319             :         }
     320             :         // A5,  \field Service Date Month
     321             :         //      \type choice
     322             :         //      \key January
     323             :         //      \key February
     324             :         //      \key March
     325             :         //      \key April
     326             :         //      \key May
     327             :         //      \key June
     328             :         //      \key July
     329             :         //      \key August
     330             :         //      \key September
     331             :         //      \key October
     332             :         //      \key November
     333             :         //      \key December
     334             :         //      \default January
     335           1 :         elcc->serviceDateMonth = getEnumerationValue(UtilityRoutines::MonthNamesUC, UtilityRoutines::MakeUPPERCase(AlphaArray(5)));
     336           1 :         if (elcc->serviceDateMonth == -1) {
     337           0 :             elcc->serviceDateMonth = 0;
     338           0 :             ShowWarningError(state,
     339           0 :                              CurrentModuleObject + ": Invalid month entered in field " + state.dataIPShortCut->cAlphaFieldNames(5) +
     340           0 :                                  ". Using January instead of \"" + AlphaArray(5) + "\"");
     341             :         }
     342             :         // N5,  \field Service Date Year
     343             :         //      \type integer
     344             :         //      \minimum 1900
     345             :         //      \maximum 2100
     346           1 :         elcc->serviceDateYear = int(NumArray(5));
     347           1 :         if (elcc->serviceDateYear > 2100) {
     348           0 :             ShowWarningError(state,
     349           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(5) +
     350             :                                  ".  Value greater than 2100 yet it is representing a year. ");
     351             :         }
     352           1 :         if (elcc->serviceDateYear < 1900) {
     353           0 :             ShowWarningError(state,
     354           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(5) +
     355             :                                  ".  Value less than 1900 yet it is representing a year. ");
     356             :         }
     357             :         // N6,  \field Length of Study Period in Years
     358             :         //      \type integer
     359             :         //      \minimum 1
     360             :         //      \maximum 100
     361           1 :         elcc->lengthStudyYears = int(NumArray(6));
     362           1 :         if (elcc->lengthStudyYears > 100) {
     363           0 :             ShowWarningError(state,
     364           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(6) +
     365             :                                  ".  A value greater than 100 is not reasonable for an economic evaluation. ");
     366             :         }
     367           1 :         if (elcc->lengthStudyYears < 1) {
     368           0 :             ShowWarningError(state,
     369           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(6) +
     370             :                                  ".  A value less than 1 is not reasonable for an economic evaluation. ");
     371             :         }
     372           1 :         elcc->lengthStudyTotalMonths = elcc->lengthStudyYears * 12;
     373             :         // N7, \field Tax rate
     374             :         //      \type real
     375             :         //      \minimum 0.0
     376           1 :         elcc->taxRate = NumArray(7);
     377           1 :         if (elcc->taxRate < 0.0 && (!state.dataIPShortCut->lNumericFieldBlanks(7))) {
     378           0 :             ShowWarningError(state,
     379           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(10) +
     380             :                                  ".  A value less than 0 is not reasonable for a tax rate. ");
     381             :         }
     382             :         // A6;  \field Depreciation Method
     383             :         //      \type choice
     384             :         //      \key ModifiedAcceleratedCostRecoverySystem-3year
     385             :         //      \key ModifiedAcceleratedCostRecoverySystem-5year
     386             :         //      \key ModifiedAcceleratedCostRecoverySystem-7year
     387             :         //      \key ModifiedAcceleratedCostRecoverySystem-10year
     388             :         //      \key ModifiedAcceleratedCostRecoverySystem-15year
     389             :         //      \key ModifiedAcceleratedCostRecoverySystem-20year
     390             :         //      \key StraightLine-27year
     391             :         //      \key StraightLine-31year
     392             :         //      \key StraightLine-39year
     393             :         //      \key StraightLine-40year
     394             :         //      \key None
     395             :         //      \default None
     396           1 :         elcc->depreciationMethod = static_cast<DeprMethod>(getEnumerationValue(DeprMethodNamesUC, UtilityRoutines::MakeUPPERCase(AlphaArray(6))));
     397           1 :         if (elcc->depreciationMethod == DeprMethod::Invalid) {
     398           0 :             elcc->depreciationMethod = DeprMethod::None;
     399           0 :             if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
     400           0 :                 ShowWarningError(state,
     401           0 :                                  CurrentModuleObject + ": The input field " + state.dataIPShortCut->cAlphaFieldNames(6) +
     402             :                                      "is blank. \"None\" will be used.");
     403             :             } else {
     404           0 :                 ShowWarningError(state,
     405           0 :                                  CurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(6) + "=\"" + AlphaArray(6) +
     406             :                                      R"(". "None" will be used.)");
     407             :             }
     408             :         }
     409             :         // compute derived variables
     410           1 :         elcc->lastDateYear = elcc->baseDateYear + elcc->lengthStudyYears - 1;
     411             :     } else {
     412           0 :         ShowWarningError(state, CurrentModuleObject + ": Only one instance of this object is allowed. No life-cycle cost reports will be generated.");
     413           0 :         elcc->LCCparamPresent = false;
     414             :     }
     415         769 : }
     416             : 
     417         769 : void GetInputLifeCycleCostRecurringCosts(EnergyPlusData &state)
     418             : {
     419             :     // SUBROUTINE INFORMATION:
     420             :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
     421             :     //    DATE WRITTEN   May 2010
     422             : 
     423             :     // PURPOSE OF THIS SUBROUTINE:
     424             :     //    Read the input file for "LifeCycleCost:RecurringCosts" object.
     425             : 
     426             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     427             : 
     428             :     int iInObj;                      // loop index variable for reading in objects
     429             :     int jFld;                        // loop counter
     430             :     int NumFields;                   // Total number of elements
     431             :     int NumAlphas;                   // Number of elements in the alpha array
     432             :     int NumNums;                     // Number of elements in the numeric array
     433         770 :     Array1D_string AlphaArray;       // character string data
     434         770 :     Array1D<Real64> NumArray;        // numeric data
     435             :     int IOStat;                      // IO Status when calling get input subroutine
     436         770 :     std::string CurrentModuleObject; // for ease in renaming.
     437             : 
     438         769 :     auto &elcc(state.dataEconLifeCycleCost);
     439             : 
     440         769 :     if (!elcc->LCCparamPresent) return;
     441           1 :     CurrentModuleObject = "LifeCycleCost:RecurringCosts";
     442           1 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNums);
     443           1 :     NumArray.allocate(NumNums);
     444           1 :     AlphaArray.allocate(NumAlphas);
     445           1 :     elcc->numRecurringCosts = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     446           1 :     elcc->RecurringCosts.resize(elcc->numRecurringCosts);
     447           2 :     for (iInObj = 0; iInObj < elcc->numRecurringCosts; ++iInObj) {
     448           5 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     449             :                                                                  CurrentModuleObject,
     450             :                                                                  iInObj + 1, // since this index needs to start from 1
     451             :                                                                  AlphaArray,
     452             :                                                                  NumAlphas,
     453             :                                                                  NumArray,
     454             :                                                                  NumNums,
     455             :                                                                  IOStat,
     456           1 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     457           1 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     458           1 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     459           1 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     460             :         // check to make sure none of the values are another life cycle cost object
     461           4 :         for (jFld = 1; jFld <= NumAlphas; ++jFld) {
     462           3 :             if (hasi(AlphaArray(jFld), "LifeCycleCost:")) {
     463           0 :                 ShowWarningError(state,
     464           0 :                                  "In " + CurrentModuleObject + " named " + AlphaArray(1) +
     465             :                                      " a field was found containing LifeCycleCost: which may indicate a missing comma.");
     466             :             }
     467             :         }
     468             :         // start to extract values from input array into appropriate fields
     469             :         //   A1,  \field Name
     470             :         //        \required-field
     471             :         //        \type alpha
     472           1 :         elcc->RecurringCosts[iInObj].name = AlphaArray(1);
     473             :         //   A2,  \field Category
     474             :         //        \type choice
     475             :         //        \key Maintenance
     476             :         //        \key Repair
     477             :         //        \key Operation
     478             :         //        \key Replacement
     479             :         //        \key MinorOverhaul
     480             :         //        \key MajorOverhaul
     481             :         //        \key OtherOperational
     482             :         //        \default Maintenance
     483           1 :         elcc->RecurringCosts[iInObj].category =
     484           2 :             static_cast<CostCategory>(getEnumerationValue(CostCategoryNamesUCNoSpace, UtilityRoutines::MakeUPPERCase(AlphaArray(2))));
     485           1 :         bool isNotRecurringCost = BITF_TEST_NONE(BITF(elcc->RecurringCosts[iInObj].category),
     486             :                                                  BITF(CostCategory::Maintenance) | BITF(CostCategory::Repair) | BITF(CostCategory::Operation) |
     487             :                                                      BITF(CostCategory::Replacement) | BITF(CostCategory::MinorOverhaul) |
     488             :                                                      BITF(CostCategory::MajorOverhaul) | BITF(CostCategory::OtherOperational));
     489           1 :         if (isNotRecurringCost) {
     490           0 :             elcc->RecurringCosts[iInObj].category = CostCategory::Maintenance;
     491           0 :             ShowWarningError(state,
     492           0 :                              CurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + AlphaArray(2) +
     493             :                                  "\". The category of Maintenance will be used.");
     494             :         }
     495             :         //   N1,  \field Cost
     496             :         //        \type real
     497           1 :         elcc->RecurringCosts[iInObj].cost = NumArray(1);
     498             :         //   A3,  \field Start of Costs
     499             :         //        \type choice
     500             :         //        \key ServicePeriod
     501             :         //        \key BasePeriod
     502             :         //        \default ServicePeriod
     503           1 :         elcc->RecurringCosts[iInObj].startOfCosts =
     504           2 :             static_cast<StartCosts>(getEnumerationValue(StartCostNamesUC, UtilityRoutines::MakeUPPERCase(AlphaArray(3))));
     505           1 :         if (elcc->RecurringCosts[iInObj].startOfCosts == StartCosts::Invalid) {
     506           0 :             elcc->RecurringCosts[iInObj].startOfCosts = StartCosts::ServicePeriod;
     507           0 :             ShowWarningError(state,
     508           0 :                              CurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + AlphaArray(3) +
     509             :                                  "\". The start of the service period will be used.");
     510             :         }
     511             :         //   N2,  \field Years from Start
     512             :         //        \type integer
     513             :         //        \minimum 0
     514             :         //        \maximum 100
     515           1 :         elcc->RecurringCosts[iInObj].yearsFromStart = int(NumArray(2));
     516           1 :         if (elcc->RecurringCosts[iInObj].yearsFromStart > 100) {
     517           0 :             ShowWarningError(
     518             :                 state,
     519           0 :                 CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(2) +
     520             :                     ".  This value is the number of years from the start so a value greater than 100 is not reasonable for an economic evaluation. ");
     521             :         }
     522           1 :         if (elcc->RecurringCosts[iInObj].yearsFromStart < 0) {
     523           0 :             ShowWarningError(
     524             :                 state,
     525           0 :                 CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(2) +
     526             :                     ".  This value is the number of years from the start so a value less than 0 is not reasonable for an economic evaluation. ");
     527             :         }
     528             :         //   N3,  \field Months from Start
     529             :         //        \type integer
     530             :         //        \minimum 0
     531             :         //        \maximum 1200
     532           1 :         elcc->RecurringCosts[iInObj].monthsFromStart = int(NumArray(3));
     533           1 :         if (elcc->RecurringCosts[iInObj].monthsFromStart > 1200) {
     534           0 :             ShowWarningError(state,
     535           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(3) +
     536             :                                  ".  This value is the number of months from the start so a value greater than 1200 is not reasonable for an "
     537             :                                  "economic evaluation. ");
     538             :         }
     539           1 :         if (elcc->RecurringCosts[iInObj].monthsFromStart < 0) {
     540           0 :             ShowWarningError(
     541             :                 state,
     542           0 :                 CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(3) +
     543             :                     ".  This value is the number of months from the start so a value less than 0 is not reasonable for an economic evaluation. ");
     544             :         }
     545             :         //   N4,  \field Repeat Period Years
     546             :         //        \type integer
     547             :         //        \minimum 1
     548             :         //        \maximum 100
     549           1 :         elcc->RecurringCosts[iInObj].repeatPeriodYears = int(NumArray(4));
     550           1 :         if (elcc->RecurringCosts[iInObj].repeatPeriodYears > 100) {
     551           0 :             ShowWarningError(state,
     552           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(4) +
     553             :                                  ".  This value is the number of years between occurrences of the cost so a value greater than 100 is not reasonable "
     554             :                                  "for an economic evaluation. ");
     555             :         }
     556           1 :         if (elcc->RecurringCosts[iInObj].repeatPeriodYears < 1) {
     557           0 :             ShowWarningError(state,
     558           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(4) +
     559             :                                  ".  This value is the number of years between occurrences of the cost so a value less than 1 is not reasonable for "
     560             :                                  "an economic evaluation. ");
     561             :         }
     562             :         //   N5,  \field Repeat Period Months
     563             :         //        \type integer
     564             :         //        \minimum 0
     565             :         //        \maximum 1200
     566           1 :         elcc->RecurringCosts[iInObj].repeatPeriodMonths = int(NumArray(5));
     567           1 :         if (elcc->RecurringCosts[iInObj].repeatPeriodMonths > 1200) {
     568           0 :             ShowWarningError(state,
     569           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(5) +
     570             :                                  ".  This value is the number of months between occurrences of the cost so a value greater than 1200 is not "
     571             :                                  "reasonable for an economic evaluation. ");
     572             :         }
     573           1 :         if (elcc->RecurringCosts[iInObj].repeatPeriodMonths < 0) {
     574           0 :             ShowWarningError(state,
     575           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(5) +
     576             :                                  ".  This value is the number of months between occurrences of the cost so a value less than 0 is not reasonable for "
     577             :                                  "an economic evaluation. ");
     578             :         }
     579           1 :         if ((elcc->RecurringCosts[iInObj].repeatPeriodMonths == 0) && (elcc->RecurringCosts[iInObj].repeatPeriodYears == 0)) {
     580           0 :             ShowWarningError(state,
     581           0 :                              CurrentModuleObject + ": Invalid value in fields " + state.dataIPShortCut->cNumericFieldNames(5) + " and " +
     582           0 :                                  state.dataIPShortCut->cNumericFieldNames(4) + ".  The repeat period must not be zero months and zero years. ");
     583             :         }
     584             :         //   N6;  \field Annual escalation rate
     585             :         //        \type real
     586           1 :         elcc->RecurringCosts[iInObj].annualEscalationRate = int(NumArray(6));
     587           1 :         if (elcc->RecurringCosts[iInObj].annualEscalationRate > 0.30) {
     588           0 :             ShowWarningError(state,
     589           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(6) +
     590             :                                  ".  This value is the decimal value for the annual escalation so most values are between 0.02 and 0.15. ");
     591             :         }
     592           1 :         if (elcc->RecurringCosts[iInObj].annualEscalationRate < -0.30) {
     593           0 :             ShowWarningError(state,
     594           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(6) +
     595             :                                  ".  This value is the decimal value for the annual escalation so most values are between 0.02 and 0.15. ");
     596             :         }
     597             :         // express the years and months fields in total months
     598           1 :         elcc->RecurringCosts[iInObj].totalMonthsFromStart =
     599           1 :             elcc->RecurringCosts[iInObj].yearsFromStart * 12 + elcc->RecurringCosts[iInObj].monthsFromStart;
     600           1 :         elcc->RecurringCosts[iInObj].totalRepeatPeriodMonths =
     601           1 :             elcc->RecurringCosts[iInObj].repeatPeriodYears * 12 + elcc->RecurringCosts[iInObj].repeatPeriodMonths;
     602             :     }
     603             : }
     604             : 
     605         769 : void GetInputLifeCycleCostNonrecurringCost(EnergyPlusData &state)
     606             : {
     607             :     // SUBROUTINE INFORMATION:
     608             :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
     609             :     //    DATE WRITTEN   May 2010
     610             : 
     611             :     // PURPOSE OF THIS SUBROUTINE:
     612             :     //    Read the input file for "LifeCycleCost:NonrecurringCost" object.
     613             : 
     614             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     615             : 
     616             :     int iInObj;                      // loop index variable for reading in objects
     617             :     int jFld;                        // loop counter
     618             :     int NumFields;                   // Total number of elements
     619             :     int NumAlphas;                   // Number of elements in the alpha array
     620             :     int NumNums;                     // Number of elements in the numeric array
     621         770 :     Array1D_string AlphaArray;       // character string data
     622         770 :     Array1D<Real64> NumArray;        // numeric data
     623             :     int IOStat;                      // IO Status when calling get input subroutine
     624         770 :     std::string CurrentModuleObject; // for ease in renaming.
     625             :     int numComponentCostLineItems;   // number of ComponentCost:LineItem objects
     626             : 
     627         769 :     auto &elcc(state.dataEconLifeCycleCost);
     628             : 
     629         769 :     if (!elcc->LCCparamPresent) return;
     630           1 :     CurrentModuleObject = "LifeCycleCost:NonrecurringCost";
     631           1 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNums);
     632           1 :     NumArray.allocate(NumNums);
     633           1 :     AlphaArray.allocate(NumAlphas);
     634           1 :     elcc->numNonrecurringCost = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     635           1 :     numComponentCostLineItems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ComponentCost:LineItem");
     636           1 :     if (numComponentCostLineItems > 0) {                              // leave room for component cost total
     637           0 :         elcc->NonrecurringCost.resize(elcc->numNonrecurringCost + 1); // add a place for CostEstimate total
     638             :     } else {
     639           1 :         elcc->NonrecurringCost.resize(elcc->numNonrecurringCost);
     640             :     }
     641           6 :     for (iInObj = 0; iInObj < elcc->numNonrecurringCost; ++iInObj) {
     642          25 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     643             :                                                                  CurrentModuleObject,
     644             :                                                                  iInObj + 1, // since this index needs to start from 1
     645             :                                                                  AlphaArray,
     646             :                                                                  NumAlphas,
     647             :                                                                  NumArray,
     648             :                                                                  NumNums,
     649             :                                                                  IOStat,
     650           5 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     651           5 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     652           5 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     653           5 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     654             :         // check to make sure none of the values are another life cycle cost object
     655          20 :         for (jFld = 1; jFld <= NumAlphas; ++jFld) {
     656          15 :             if (hasi(AlphaArray(jFld), "LifeCycleCost:")) {
     657           0 :                 ShowWarningError(state,
     658           0 :                                  "In " + CurrentModuleObject + " named " + AlphaArray(1) +
     659             :                                      " a field was found containing LifeCycleCost: which may indicate a missing comma.");
     660             :             }
     661             :         }
     662             :         // start to extract values from input array into appropriate fields
     663             :         // A1,  \field Name
     664             :         //      \required-field
     665             :         //      \type alpha
     666           5 :         elcc->NonrecurringCost[iInObj].name = AlphaArray(1);
     667             :         // A2,  \field Category
     668             :         //      \type choice
     669             :         //      \key Construction
     670             :         //      \key Salvage
     671             :         //      \key OtherCapital
     672             :         //      \default Construction
     673           5 :         elcc->NonrecurringCost[iInObj].category =
     674          10 :             static_cast<CostCategory>(getEnumerationValue(CostCategoryNamesUCNoSpace, UtilityRoutines::MakeUPPERCase(AlphaArray(2))));
     675             :         bool isNotNonRecurringCost =
     676           5 :             BITF_TEST_NONE(BITF(elcc->NonrecurringCost[iInObj].category),
     677             :                            BITF(CostCategory::Construction) | BITF(CostCategory::Salvage) | BITF(CostCategory::OtherCapital));
     678           5 :         if (isNotNonRecurringCost) {
     679           0 :             elcc->NonrecurringCost[iInObj].category = CostCategory::Construction;
     680           0 :             ShowWarningError(state,
     681           0 :                              CurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + AlphaArray(2) +
     682             :                                  "\". The category of Construction will be used.");
     683             :         }
     684             :         // N1,  \field Cost
     685             :         //      \type real
     686           5 :         elcc->NonrecurringCost[iInObj].cost = NumArray(1);
     687             :         // A3,  \field Start of Costs
     688             :         //      \type choice
     689             :         //      \key ServicePeriod
     690             :         //      \key BasePeriod
     691             :         //      \default ServicePeriod
     692           5 :         elcc->NonrecurringCost[iInObj].startOfCosts =
     693          10 :             static_cast<StartCosts>(getEnumerationValue(StartCostNamesUC, UtilityRoutines::MakeUPPERCase(AlphaArray(3))));
     694           5 :         if (elcc->NonrecurringCost[iInObj].startOfCosts == StartCosts::Invalid) {
     695           0 :             elcc->NonrecurringCost[iInObj].startOfCosts = StartCosts::ServicePeriod;
     696           0 :             ShowWarningError(state,
     697           0 :                              CurrentModuleObject + ": Invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + AlphaArray(3) +
     698             :                                  "\". The start of the service period will be used.");
     699             :         }
     700             :         // N2,  \field Years from Start
     701             :         //      \type integer
     702             :         //      \minimum 0
     703             :         //      \maximum 100
     704           5 :         elcc->NonrecurringCost[iInObj].yearsFromStart = int(NumArray(2));
     705           5 :         if (elcc->NonrecurringCost[iInObj].yearsFromStart > 100) {
     706           0 :             ShowWarningError(
     707             :                 state,
     708           0 :                 CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(2) +
     709             :                     ".  This value is the number of years from the start so a value greater than 100 is not reasonable for an economic evaluation. ");
     710             :         }
     711           5 :         if (elcc->NonrecurringCost[iInObj].yearsFromStart < 0) {
     712           0 :             ShowWarningError(
     713             :                 state,
     714           0 :                 CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(2) +
     715             :                     ".  This value is the number of years from the start so a value less than 0 is not reasonable for an economic evaluation. ");
     716             :         }
     717             :         //  N3;  \field Months from Start
     718             :         //       \type integer
     719             :         //       \minimum 0
     720             :         //       \maximum 11
     721           5 :         elcc->NonrecurringCost[iInObj].monthsFromStart = int(NumArray(3));
     722           5 :         if (elcc->NonrecurringCost[iInObj].monthsFromStart > 1200) {
     723           0 :             ShowWarningError(state,
     724           0 :                              CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(3) +
     725             :                                  ".  This value is the number of months from the start so a value greater than 1200 is not reasonable for an "
     726             :                                  "economic evaluation. ");
     727             :         }
     728           5 :         if (elcc->NonrecurringCost[iInObj].monthsFromStart < 0) {
     729           0 :             ShowWarningError(
     730             :                 state,
     731           0 :                 CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(3) +
     732             :                     ".  This value is the number of months from the start so a value less than 0 is not reasonable for an economic evaluation. ");
     733             :         }
     734             :         // express the years and months fields in total months
     735           5 :         elcc->NonrecurringCost[iInObj].totalMonthsFromStart =
     736           5 :             elcc->NonrecurringCost[iInObj].yearsFromStart * 12 + elcc->NonrecurringCost[iInObj].monthsFromStart;
     737             :     }
     738             : }
     739             : 
     740         769 : void GetInputLifeCycleCostUsePriceEscalation(EnergyPlusData &state)
     741             : {
     742             :     // SUBROUTINE INFORMATION:
     743             :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
     744             :     //    DATE WRITTEN   May 2010
     745             : 
     746             :     // PURPOSE OF THIS SUBROUTINE:
     747             :     //    Read the input file for "LifeCycleCost:UsePriceEscalation" object.
     748             : 
     749             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     750             : 
     751             :     int iInObj;                      // loop index variable for reading in objects
     752             :     int jFld;                        // loop counter
     753             :     int jYear;                       // loop counter
     754             :     int NumFields;                   // Total number of elements
     755             :     int NumAlphas;                   // Number of elements in the alpha array
     756             :     int NumNums;                     // Number of elements in the numeric array
     757         770 :     Array1D_string AlphaArray;       // character string data
     758         770 :     Array1D<Real64> NumArray;        // numeric data
     759             :     int IOStat;                      // IO Status when calling get input subroutine
     760         770 :     std::string CurrentModuleObject; // for ease in renaming.
     761             : 
     762         769 :     auto &elcc(state.dataEconLifeCycleCost);
     763             : 
     764         769 :     if (!elcc->LCCparamPresent) return;
     765           1 :     CurrentModuleObject = "LifeCycleCost:UsePriceEscalation";
     766           1 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNums);
     767           1 :     NumArray.allocate(NumNums);
     768           1 :     AlphaArray.allocate(NumAlphas);
     769           1 :     elcc->numUsePriceEscalation = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     770           1 :     elcc->UsePriceEscalation.allocate(elcc->numUsePriceEscalation);
     771           4 :     for (iInObj = 1; iInObj <= elcc->numUsePriceEscalation; ++iInObj) {
     772           3 :         elcc->UsePriceEscalation(iInObj).Escalation.allocate(elcc->lengthStudyYears);
     773             :     }
     774           1 :     if (elcc->numUsePriceEscalation > 0) {
     775           4 :         for (iInObj = 1; iInObj <= elcc->numUsePriceEscalation; ++iInObj) {
     776          15 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     777             :                                                                      CurrentModuleObject,
     778             :                                                                      iInObj,
     779             :                                                                      AlphaArray,
     780             :                                                                      NumAlphas,
     781             :                                                                      NumArray,
     782             :                                                                      NumNums,
     783             :                                                                      IOStat,
     784           3 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     785           3 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     786           3 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     787           3 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     788             :             // check to make sure none of the values are another life cycle cost object
     789          12 :             for (jFld = 1; jFld <= NumAlphas; ++jFld) {
     790           9 :                 if (hasi(AlphaArray(jFld), "LifeCycleCost:")) {
     791           0 :                     ShowWarningError(state,
     792           0 :                                      "In " + CurrentModuleObject + " named " + AlphaArray(1) +
     793             :                                          " a field was found containing LifeCycleCost: which may indicate a missing comma.");
     794             :                 }
     795             :             }
     796             :             // start to extract values from input array into appropriate fields
     797             :             // A1,  \field Name
     798             :             //      \required-field
     799             :             //      \type alpha
     800           3 :             elcc->UsePriceEscalation(iInObj).name = AlphaArray(1);
     801             :             //  A2,  \field Resource
     802             :             //       \required-field
     803             :             //       \type choice
     804             :             //       \key Electricity
     805             :             //       \key NaturalGas
     806             :             //       \key Steam
     807             :             //       \key Gasoline
     808             :             //       \key Diesel
     809             :             //       \key Coal
     810             :             //       \key FuelOilNo1
     811             :             //       \key FuelOilNo2
     812             :             //       \key Propane
     813             :             //       \key Water
     814             :             //       \key OtherFuel1
     815             :             //       \key OtherFuel2
     816           3 :             elcc->UsePriceEscalation(iInObj).resource = AssignResourceTypeNum(AlphaArray(2)); // use function from DataGlobalConstants
     817           3 :             if (NumAlphas > 3) {
     818           0 :                 ShowWarningError(state, "In " + CurrentModuleObject + " contains more alpha fields than expected.");
     819             :             }
     820             :             // N1,  \field Escalation Start Year
     821             :             //      \type integer
     822             :             //      \minimum 1900
     823             :             //      \maximum 2100
     824           3 :             elcc->UsePriceEscalation(iInObj).escalationStartYear = int(NumArray(1));
     825           3 :             if (elcc->UsePriceEscalation(iInObj).escalationStartYear > 2100) {
     826           0 :                 ShowWarningError(state,
     827           0 :                                  CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(1) +
     828             :                                      ".  Value greater than 2100 yet it is representing a year. ");
     829             :             }
     830           3 :             if (elcc->UsePriceEscalation(iInObj).escalationStartYear < 1900) {
     831           0 :                 ShowWarningError(state,
     832           0 :                                  CurrentModuleObject + ": Invalid value in field " + state.dataIPShortCut->cNumericFieldNames(1) +
     833             :                                      ".  Value less than 1900 yet it is representing a year. ");
     834             :             }
     835             :             // A3,  \field Escalation Start Month
     836             :             //      \type choice
     837             :             //      \key January
     838             :             //      \key February
     839             :             //      \key March
     840             :             //      \key April
     841             :             //      \key May
     842             :             //      \key June
     843             :             //      \key July
     844             :             //      \key August
     845             :             //      \key September
     846             :             //      \key October
     847             :             //      \key November
     848             :             //      \key December
     849             :             //      \default January
     850           3 :             elcc->UsePriceEscalation(iInObj).escalationStartMonth =
     851           6 :                 getEnumerationValue(UtilityRoutines::MonthNamesUC, UtilityRoutines::MakeUPPERCase(AlphaArray(3)));
     852           3 :             if (elcc->UsePriceEscalation(iInObj).escalationStartMonth == -1) {
     853           0 :                 elcc->UsePriceEscalation(iInObj).escalationStartMonth = 0;
     854           0 :                 ShowWarningError(state,
     855           0 :                                  CurrentModuleObject + ": Invalid month entered in field " + state.dataIPShortCut->cAlphaFieldNames(3) +
     856           0 :                                      ". Using January instead of \"" + AlphaArray(3) + "\"");
     857             :             }
     858             :             // N2,  \field Year 1 Escalation
     859             :             //      \type real
     860             :             //      \begin-extensible
     861             :             // The array is from the baseDateYear until baseDateYear + lengthStudyYears
     862             :             // Set the array to default to 1.0
     863          69 :             for (jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
     864          66 :                 elcc->UsePriceEscalation(iInObj).Escalation(jYear) = 1.0;
     865             :             }
     866             :             // Since the years in the UsePriceEscalation may not match up with the baseDateYear and
     867             :             // the lenghtStudyYears, need to make adjustments when reading in the values to align
     868             :             // with the baseDateYear (the first item in all yearly arrays)
     869           3 :             elcc->UsePriceEscalation_escStartYear = elcc->UsePriceEscalation(iInObj).escalationStartYear;
     870           3 :             elcc->UsePriceEscalation_escNumYears = NumNums - 1;
     871           3 :             elcc->UsePriceEscalation_escEndYear = elcc->UsePriceEscalation_escStartYear + elcc->UsePriceEscalation_escNumYears - 1;
     872           3 :             elcc->UsePriceEscalation_earlierEndYear = min(elcc->UsePriceEscalation_escEndYear, elcc->lastDateYear);   // pick the earlier ending date
     873           3 :             elcc->UsePriceEscalation_laterStartYear = max(elcc->UsePriceEscalation_escStartYear, elcc->baseDateYear); // pick the later starting date
     874          69 :             for (jYear = elcc->UsePriceEscalation_laterStartYear; jYear <= elcc->UsePriceEscalation_earlierEndYear; ++jYear) {
     875          66 :                 elcc->UsePriceEscalation_curFld = 2 + jYear - elcc->UsePriceEscalation_escStartYear;
     876          66 :                 elcc->UsePriceEscalation_curEsc = 1 + jYear - elcc->baseDateYear;
     877          66 :                 if ((elcc->UsePriceEscalation_curFld <= NumNums) && (elcc->UsePriceEscalation_curFld >= 1)) {
     878          66 :                     if ((elcc->UsePriceEscalation_curEsc <= elcc->lengthStudyYears) && (elcc->UsePriceEscalation_curEsc >= 1)) {
     879          66 :                         elcc->UsePriceEscalation(iInObj).Escalation(elcc->UsePriceEscalation_curEsc) = NumArray(elcc->UsePriceEscalation_curFld);
     880             :                     }
     881             :                 }
     882             :             }
     883             :         }
     884             :     }
     885             : }
     886             : 
     887         769 : void GetInputLifeCycleCostUseAdjustment(EnergyPlusData &state)
     888             : {
     889             :     // SUBROUTINE INFORMATION:
     890             :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
     891             :     //    DATE WRITTEN   May 2010
     892             : 
     893             :     // PURPOSE OF THIS SUBROUTINE:
     894             :     //    Read the input file for "LifeCycleCost:UseAdjustment" object.
     895             : 
     896             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     897             : 
     898             :     int iInObj;                      // loop index variable for reading in objects
     899             :     int jFld;                        // loop counter
     900             :     int jYear;                       // loop counter
     901             :     int NumFields;                   // Total number of elements
     902             :     int NumAlphas;                   // Number of elements in the alpha array
     903             :     int NumNums;                     // Number of elements in the numeric array
     904         770 :     Array1D_string AlphaArray;       // character string data
     905         770 :     Array1D<Real64> NumArray;        // numeric data
     906             :     int IOStat;                      // IO Status when calling get input subroutine
     907         770 :     std::string CurrentModuleObject; // for ease in renaming.
     908             :     int numFldsToUse;
     909             : 
     910         769 :     auto &elcc(state.dataEconLifeCycleCost);
     911             : 
     912         769 :     if (!elcc->LCCparamPresent) return;
     913           1 :     CurrentModuleObject = "LifeCycleCost:UseAdjustment";
     914           1 :     state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumFields, NumAlphas, NumNums);
     915           1 :     NumArray.allocate(NumNums);
     916           1 :     AlphaArray.allocate(NumAlphas);
     917           1 :     elcc->numUseAdjustment = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     918           1 :     elcc->UseAdjustment.allocate(elcc->numUseAdjustment);
     919           2 :     for (iInObj = 1; iInObj <= elcc->numUseAdjustment; ++iInObj) {
     920           1 :         elcc->UseAdjustment(iInObj).Adjustment.allocate(elcc->lengthStudyYears);
     921             :     }
     922           1 :     if (elcc->numUseAdjustment > 0) {
     923           2 :         for (iInObj = 1; iInObj <= elcc->numUseAdjustment; ++iInObj) {
     924           5 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     925             :                                                                      CurrentModuleObject,
     926             :                                                                      iInObj,
     927             :                                                                      AlphaArray,
     928             :                                                                      NumAlphas,
     929             :                                                                      NumArray,
     930             :                                                                      NumNums,
     931             :                                                                      IOStat,
     932           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     933           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     934           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     935           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     936             :             // check to make sure none of the values are another life cycle cost object
     937           3 :             for (jFld = 1; jFld <= NumAlphas; ++jFld) {
     938           2 :                 if (hasi(AlphaArray(jFld), "LifeCycleCost:")) {
     939           0 :                     ShowWarningError(state,
     940           0 :                                      "In " + CurrentModuleObject + " named " + AlphaArray(1) +
     941             :                                          " a field was found containing LifeCycleCost: which may indicate a missing comma.");
     942             :                 }
     943             :             }
     944             :             // start to extract values from input array into appropriate fields
     945             :             //  A1,  \field Name
     946             :             //       \required-field
     947             :             //       \type alpha
     948           1 :             elcc->UseAdjustment(iInObj).name = AlphaArray(1);
     949             :             //  A2,  \field Resource
     950             :             //       \required-field
     951             :             //       \type choice
     952             :             //       \key Electricity
     953             :             //       \key NaturalGas
     954             :             //       \key Steam
     955             :             //       \key Gasoline
     956             :             //       \key Diesel
     957             :             //       \key Coal
     958             :             //       \key FuelOilNo1
     959             :             //       \key FuelOilNo2
     960             :             //       \key Propane
     961             :             //       \key Water
     962             :             //       \key OtherFuel1
     963             :             //       \key OtherFuel2
     964           1 :             elcc->UseAdjustment(iInObj).resource = AssignResourceTypeNum(AlphaArray(2)); // use function from DataGlobalConstants
     965           1 :             if (NumAlphas > 2) {
     966           0 :                 ShowWarningError(state, "In " + CurrentModuleObject + " contains more alpha fields than expected.");
     967             :             }
     968             :             //  N1,  \field Year 1 Multiplier
     969             :             //       \type real
     970             :             //       \begin-extensible
     971             :             // Set the array to default to 1.0
     972          23 :             for (jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
     973          22 :                 elcc->UseAdjustment(iInObj).Adjustment(jYear) = 1.0;
     974             :             }
     975           1 :             numFldsToUse = min(NumNums, elcc->lengthStudyYears);
     976           2 :             for (jYear = 1; jYear <= numFldsToUse; ++jYear) {
     977           1 :                 elcc->UseAdjustment(iInObj).Adjustment(jYear) = NumArray(jYear);
     978             :             }
     979             :         }
     980             :     }
     981             : }
     982             : 
     983             : //======================================================================================================================
     984             : //======================================================================================================================
     985             : 
     986             : //    COMPUTATION ROUTINES
     987             : 
     988             : //======================================================================================================================
     989             : //======================================================================================================================
     990             : 
     991           1 : void ExpressAsCashFlows(EnergyPlusData &state)
     992             : {
     993             :     // SUBROUTINE INFORMATION:
     994             :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
     995             :     //    DATE WRITTEN   July 2010
     996             :     //    MODIFIED       na
     997             :     //    RE-ENGINEERED  na
     998             : 
     999             :     // PURPOSE OF THIS SUBROUTINE:
    1000             :     //    Convert all recurring and nonrecurring costs into cash flows
    1001             :     //    used in calculations and reporting.
    1002             : 
    1003             :     // METHODOLOGY EMPLOYED:
    1004             : 
    1005             :     // REFERENCES:
    1006             :     // na
    1007             : 
    1008             :     // USE STATEMENTS:
    1009             : 
    1010             :     // Using/Aliasing
    1011             :     using EconomicTariff::GetMonthlyCostForResource;
    1012             : 
    1013             :     // Locals
    1014             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    1015             :     // na
    1016             : 
    1017             :     // SUBROUTINE PARAMETER DEFINITIONS:
    1018             :     // na
    1019             : 
    1020             :     // INTERFACE BLOCK SPECIFICATIONS
    1021             :     // na
    1022             : 
    1023             :     // DERIVED TYPE DEFINITIONS
    1024             :     // na
    1025             : 
    1026             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1027             :     int iCashFlow;
    1028             :     int jCost;
    1029             :     int jAdj;
    1030             :     int kYear;
    1031             :     int offset;
    1032             :     int month; // number of months since base date
    1033             :     int firstMonth;
    1034             :     int monthsBaseToService;
    1035             : 
    1036           2 :     std::map<int, std::map<DataGlobalConstants::ResourceType, Real64>> resourceCosts;
    1037          13 :     for (int jMonth = 1; jMonth <= 12; ++jMonth) {
    1038          24 :         std::map<DataGlobalConstants::ResourceType, Real64> monthMap;
    1039         576 :         for (auto iResource : state.dataGlobalConst->AllResourceTypes) {
    1040         564 :             monthMap.insert(std::pair<DataGlobalConstants::ResourceType, Real64>(iResource, 0.0));
    1041             :         }
    1042          12 :         resourceCosts.insert(std::pair<int, std::map<DataGlobalConstants::ResourceType, Real64>>(jMonth, monthMap));
    1043             :     }
    1044             : 
    1045           2 :     Array1D<Real64> curResourceCosts(12);
    1046             : 
    1047           2 :     std::map<DataGlobalConstants::ResourceType, bool> resourceCostNotZero;
    1048          48 :     for (auto iResource : state.dataGlobalConst->AllResourceTypes) {
    1049          47 :         resourceCostNotZero.insert(std::pair<DataGlobalConstants::ResourceType, bool>(iResource, false));
    1050             :     }
    1051             : 
    1052           2 :     std::map<DataGlobalConstants::ResourceType, Real64> resourceCostAnnual;
    1053          48 :     for (auto iResource : state.dataGlobalConst->AllResourceTypes) {
    1054          47 :         resourceCostAnnual.insert(std::pair<DataGlobalConstants::ResourceType, Real64>(iResource, 0.0));
    1055             :     }
    1056             : 
    1057             :     Real64 annualCost;
    1058             :     int found;
    1059             :     CostCategory curCategory;
    1060           2 :     Array1D<Real64> monthlyInflationFactor;
    1061             :     Real64 inflationPerMonth;
    1062             :     int iLoop;
    1063             : 
    1064           1 :     auto &elcc(state.dataEconLifeCycleCost);
    1065             : 
    1066             :     // compute months from 1900 for base and service period
    1067           1 :     elcc->ExpressAsCashFlows_baseMonths1900 =
    1068           1 :         (elcc->baseDateYear - 1900) * 12 + (elcc->baseDateMonth + 1); // elcc->baseDateMonth + 1 to account for baseDateMonth starting at 0
    1069           1 :     elcc->ExpressAsCashFlows_serviceMonths1900 =
    1070           1 :         (elcc->serviceDateYear - 1900) * 12 + elcc->serviceDateMonth + 1; // elcc->serviceDateMonth + 1 to account for serviceDateMonth starting at 0
    1071           1 :     monthsBaseToService = elcc->ExpressAsCashFlows_serviceMonths1900 - elcc->ExpressAsCashFlows_baseMonths1900;
    1072             :     // if ComponentCost:LineItem exist, the grand total of all costs are another non-recurring cost
    1073           1 :     if (state.dataCostEstimateManager->CurntBldg.GrandTotal >
    1074             :         0.0) { // from DataCostEstimate and computed in WriteCompCostTable within OutputReportTabular
    1075           0 :         ++elcc->numNonrecurringCost;
    1076           0 :         elcc->NonrecurringCost[elcc->numNonrecurringCost].name = "Total of ComponentCost:*";
    1077           0 :         elcc->NonrecurringCost[elcc->numNonrecurringCost].lineItem = "";
    1078           0 :         elcc->NonrecurringCost[elcc->numNonrecurringCost].category = CostCategory::Construction;
    1079           0 :         elcc->NonrecurringCost[elcc->numNonrecurringCost].cost = state.dataCostEstimateManager->CurntBldg.GrandTotal;
    1080           0 :         elcc->NonrecurringCost[elcc->numNonrecurringCost].startOfCosts = StartCosts::BasePeriod;
    1081           0 :         elcc->NonrecurringCost[elcc->numNonrecurringCost].yearsFromStart = 0;
    1082           0 :         elcc->NonrecurringCost[elcc->numNonrecurringCost].monthsFromStart = 0;
    1083           0 :         elcc->NonrecurringCost[elcc->numNonrecurringCost].totalMonthsFromStart = 0;
    1084             :     }
    1085             : 
    1086             :     // gather costs from EconomicTariff for each end use
    1087           1 :     elcc->numResourcesUsed = 0;
    1088          48 :     for (auto iResource : state.dataGlobalConst->AllResourceTypes) {
    1089          47 :         GetMonthlyCostForResource(state, iResource, curResourceCosts);
    1090          47 :         annualCost = 0.0;
    1091         611 :         for (int jMonth = 1; jMonth <= 12; ++jMonth) {
    1092         564 :             resourceCosts.at(jMonth).at(iResource) = curResourceCosts(jMonth);
    1093         564 :             annualCost += resourceCosts.at(jMonth).at(iResource);
    1094             :         }
    1095          47 :         if (annualCost != 0.0) {
    1096           1 :             ++elcc->numResourcesUsed;
    1097           1 :             resourceCostNotZero.at(iResource) = true;
    1098             :         } else {
    1099          46 :             resourceCostNotZero.at(iResource) = false;
    1100             :         }
    1101          47 :         resourceCostAnnual.at(iResource) = annualCost;
    1102             :     }
    1103             :     // allocate the escalated energy cost arrays
    1104          23 :     for (int year = 1; year <= elcc->lengthStudyYears; ++year) {
    1105          44 :         std::map<DataGlobalConstants::ResourceType, Real64> yearMap;
    1106        1056 :         for (auto iResource : state.dataGlobalConst->AllResourceTypes) {
    1107        1034 :             yearMap.insert(std::pair<DataGlobalConstants::ResourceType, Real64>(iResource, 0.0));
    1108             :         }
    1109          22 :         elcc->EscalatedEnergy.insert(std::pair<int, std::map<DataGlobalConstants::ResourceType, Real64>>(year, yearMap));
    1110             :     }
    1111             : 
    1112           1 :     elcc->EscalatedTotEnergy.allocate(elcc->lengthStudyYears);
    1113           1 :     elcc->EscalatedTotEnergy = 0.0;
    1114             : 
    1115             :     // pre-compute the inflation factors for each year
    1116           1 :     monthlyInflationFactor.allocate(elcc->lengthStudyTotalMonths);
    1117           1 :     if (elcc->inflationApproach == InflAppr::ConstantDollar) {
    1118           1 :         monthlyInflationFactor = 1.0; // not really used but just in case
    1119           0 :     } else if (elcc->inflationApproach == InflAppr::CurrentDollar) {
    1120             :         // to allocate an interest rate (in this case inflation) cannot just use 1/12
    1121             :         // for the monthly value since it will be slightly wrong. Instead use inverse of
    1122             :         // formula from Newnan (4-32) which is r = m x (ia + 1)^(1/m) - 1)
    1123           0 :         inflationPerMonth = std::pow(elcc->inflation + 1.0, 1.0 / 12.0) - 1;
    1124           0 :         for (int jMonth = 1; jMonth <= elcc->lengthStudyTotalMonths; ++jMonth) {
    1125           0 :             monthlyInflationFactor(jMonth) = std::pow(1.0 + inflationPerMonth, jMonth - 1);
    1126             :         }
    1127             :     }
    1128             : 
    1129           1 :     elcc->numCashFlow = CostCategory::Num + elcc->numRecurringCosts + elcc->numNonrecurringCost + elcc->numResourcesUsed;
    1130             :     // Cashflow array order:
    1131             :     //   1 cost categories
    1132             :     //   2 recurring costs
    1133             :     //   3 nonrecurring costs
    1134             :     //   4 resource costs
    1135           1 :     elcc->CashFlow.resize(elcc->numCashFlow);
    1136          24 :     for (iCashFlow = 0; iCashFlow < elcc->numCashFlow; ++iCashFlow) {
    1137          23 :         elcc->CashFlow[iCashFlow].mnAmount.allocate(elcc->lengthStudyTotalMonths);
    1138          23 :         elcc->CashFlow[iCashFlow].yrAmount.allocate(elcc->lengthStudyYears);
    1139          23 :         elcc->CashFlow[iCashFlow].yrPresVal.allocate(elcc->lengthStudyYears);
    1140          23 :         elcc->CashFlow[iCashFlow].mnAmount = 0.0;  // zero all cash flow values
    1141          23 :         elcc->CashFlow[iCashFlow].yrAmount = 0.0;  // zero all cash flow values
    1142          23 :         elcc->CashFlow[iCashFlow].yrPresVal = 0.0; // zero all present values
    1143             :     }
    1144             :     // Put nonrecurring costs into cashflows
    1145           1 :     offset = CostCategory::Num + elcc->numRecurringCosts;
    1146           6 :     for (jCost = 0; jCost < elcc->numNonrecurringCost; ++jCost) {
    1147           5 :         elcc->CashFlow[offset + jCost].name = elcc->NonrecurringCost[jCost].name;
    1148           5 :         elcc->CashFlow[offset + jCost].SourceKind = SourceKindType::Nonrecurring;
    1149           5 :         elcc->CashFlow[offset + jCost].Category = elcc->NonrecurringCost[jCost].category;
    1150           5 :         elcc->CashFlow[offset + jCost].orginalCost = elcc->NonrecurringCost[jCost].cost;
    1151           5 :         elcc->CashFlow[offset + jCost].mnAmount = 0.0;
    1152           5 :         if (elcc->NonrecurringCost[jCost].startOfCosts == StartCosts::ServicePeriod) {
    1153           0 :             month = elcc->NonrecurringCost[jCost].totalMonthsFromStart + monthsBaseToService + 1;
    1154           5 :         } else if (elcc->NonrecurringCost[jCost].startOfCosts == StartCosts::BasePeriod) {
    1155           5 :             month = elcc->NonrecurringCost[jCost].totalMonthsFromStart + 1;
    1156             :         }
    1157           5 :         if ((month >= 1) && (month <= elcc->lengthStudyTotalMonths)) {
    1158           5 :             elcc->CashFlow[offset + jCost].mnAmount(month) = elcc->NonrecurringCost[jCost].cost * monthlyInflationFactor(month);
    1159             :         } else {
    1160           0 :             ShowWarningError(state,
    1161           0 :                              "For life cycle costing a nonrecurring cost named " + elcc->NonrecurringCost[jCost].name +
    1162             :                                  " contains a cost which is not within the study period.");
    1163             :         }
    1164             :     }
    1165             :     // Put recurring costs into cashflows
    1166           1 :     offset = CostCategory::Num;
    1167           2 :     for (jCost = 0; jCost < elcc->numRecurringCosts; ++jCost) {
    1168           1 :         elcc->CashFlow[offset + jCost].name = elcc->RecurringCosts[jCost].name;
    1169           1 :         elcc->CashFlow[offset + jCost].SourceKind = SourceKindType::Recurring;
    1170           1 :         elcc->CashFlow[offset + jCost].Category = elcc->RecurringCosts[jCost].category;
    1171           1 :         elcc->CashFlow[offset + jCost].orginalCost = elcc->RecurringCosts[jCost].cost;
    1172           1 :         if (elcc->RecurringCosts[jCost].startOfCosts == StartCosts::ServicePeriod) {
    1173           1 :             firstMonth = elcc->RecurringCosts[jCost].totalMonthsFromStart + monthsBaseToService + 1;
    1174           0 :         } else if (elcc->RecurringCosts[jCost].startOfCosts == StartCosts::BasePeriod) {
    1175           0 :             firstMonth = elcc->RecurringCosts[jCost].totalMonthsFromStart + 1;
    1176             :         }
    1177           1 :         if ((firstMonth >= 1) && (firstMonth <= elcc->lengthStudyTotalMonths)) {
    1178           1 :             month = firstMonth;
    1179           1 :             if (elcc->RecurringCosts[jCost].totalRepeatPeriodMonths >= 1) {
    1180          20 :                 for (iLoop = 0; iLoop < 10000; ++iLoop) { // add a limit to the loop to prevent runaway condition
    1181          20 :                     elcc->CashFlow[offset + jCost].mnAmount(month) = elcc->RecurringCosts[jCost].cost * monthlyInflationFactor(month);
    1182          20 :                     month += elcc->RecurringCosts[jCost].totalRepeatPeriodMonths;
    1183          20 :                     if (month > elcc->lengthStudyTotalMonths) break;
    1184             :                 }
    1185             :             }
    1186             :         } else {
    1187           0 :             ShowWarningError(state,
    1188           0 :                              "For life cycle costing the recurring cost named " + elcc->RecurringCosts[jCost].name +
    1189             :                                  " has the first year of the costs that is not within the study period.");
    1190             :         }
    1191             :     }
    1192             :     // Put resource costs into cashflows
    1193             :     // the first cash flow for resources should be after the categories, recurring and nonrecurring costs
    1194           1 :     int cashFlowCounter = CostCategory::Num + elcc->numRecurringCosts + elcc->numNonrecurringCost - 1; // Since CashFlow starts at 0
    1195          48 :     for (auto iResource : state.dataGlobalConst->AllResourceTypes) {
    1196          47 :         if (resourceCostNotZero.at(iResource)) {
    1197           1 :             ++cashFlowCounter;
    1198             : 
    1199           1 :             switch (iResource) {
    1200           0 :             case DataGlobalConstants::ResourceType::Water:
    1201             :             case DataGlobalConstants::ResourceType::OnSiteWater:
    1202             :             case DataGlobalConstants::ResourceType::MainsWater:
    1203             :             case DataGlobalConstants::ResourceType::RainWater:
    1204             :             case DataGlobalConstants::ResourceType::WellWater:
    1205             :             case DataGlobalConstants::ResourceType::Condensate:
    1206           0 :                 elcc->CashFlow[cashFlowCounter].Category = CostCategory::Water;
    1207           0 :                 break;
    1208           1 :             case DataGlobalConstants::ResourceType::Electricity:
    1209             :             case DataGlobalConstants::ResourceType::Natural_Gas:
    1210             :             case DataGlobalConstants::ResourceType::Gasoline:
    1211             :             case DataGlobalConstants::ResourceType::Diesel:
    1212             :             case DataGlobalConstants::ResourceType::Coal:
    1213             :             case DataGlobalConstants::ResourceType::FuelOil_1:
    1214             :             case DataGlobalConstants::ResourceType::FuelOil_2:
    1215             :             case DataGlobalConstants::ResourceType::Propane:
    1216             :             case DataGlobalConstants::ResourceType::EnergyTransfer:
    1217             :             case DataGlobalConstants::ResourceType::Steam:
    1218             :             case DataGlobalConstants::ResourceType::DistrictCooling:
    1219             :             case DataGlobalConstants::ResourceType::DistrictHeating:
    1220             :             case DataGlobalConstants::ResourceType::ElectricityProduced:
    1221             :             case DataGlobalConstants::ResourceType::ElectricityPurchased:
    1222             :             case DataGlobalConstants::ResourceType::ElectricityNet:
    1223             :             case DataGlobalConstants::ResourceType::SolarWater:
    1224             :             case DataGlobalConstants::ResourceType::SolarAir:
    1225           1 :                 elcc->CashFlow[cashFlowCounter].Category = CostCategory::Energy;
    1226           1 :                 break;
    1227           0 :             default:
    1228           0 :                 elcc->CashFlow[cashFlowCounter].Category = CostCategory::Operation;
    1229             :             }
    1230             : 
    1231           1 :             elcc->CashFlow[cashFlowCounter].Resource = iResource;
    1232           1 :             elcc->CashFlow[cashFlowCounter].SourceKind = SourceKindType::Resource;
    1233           1 :             elcc->CashFlow[cashFlowCounter].name = GetResourceTypeChar(iResource);
    1234           1 :             if (cashFlowCounter <= elcc->numCashFlow) {
    1235             :                 // put the monthly energy costs into the cashflow prior to adjustments
    1236             :                 // energy costs (a.k.a. resource costs) start at the start of service and repeat
    1237             :                 // until the end of the study total
    1238          13 :                 for (int jMonth = 1; jMonth <= 12; ++jMonth) {
    1239          12 :                     elcc->CashFlow[cashFlowCounter].mnAmount(monthsBaseToService + jMonth) = resourceCosts.at(jMonth).at(iResource);
    1240             :                 }
    1241           1 :                 elcc->CashFlow[cashFlowCounter].orginalCost = resourceCostAnnual.at(iResource);
    1242         229 :                 for (int jMonth = monthsBaseToService + 13; jMonth <= elcc->lengthStudyTotalMonths; ++jMonth) {
    1243             :                     // use the cost from a year earlier
    1244         228 :                     elcc->CashFlow[cashFlowCounter].mnAmount(jMonth) = elcc->CashFlow[cashFlowCounter].mnAmount(jMonth - 12);
    1245             :                 }
    1246             :                 // add in the impact of inflation
    1247         265 :                 for (int jMonth = 1; jMonth <= elcc->lengthStudyTotalMonths; ++jMonth) {
    1248         264 :                     elcc->CashFlow[cashFlowCounter].mnAmount(jMonth) *= monthlyInflationFactor(jMonth);
    1249             :                 }
    1250             :                 // now factor in adjustments
    1251             :                 // need to find the correct adjustment to use for the current resource
    1252           1 :                 found = 0;
    1253           2 :                 for (jAdj = 1; jAdj <= elcc->numUseAdjustment; ++jAdj) {
    1254           1 :                     if (elcc->UseAdjustment(jAdj).resource == iResource) {
    1255           0 :                         found = jAdj;
    1256           0 :                         break;
    1257             :                     }
    1258             :                 }
    1259             :                 // if any adjustments were found for that resource apply the multiplier
    1260           1 :                 if (found != 0) {
    1261           0 :                     for (kYear = 1; kYear <= elcc->lengthStudyYears;
    1262             :                          ++kYear) { // if service period is later than base period then this will go too far
    1263           0 :                         for (int jMonth = 1; jMonth <= 12; ++jMonth) {
    1264           0 :                             month = (kYear - 1) * 12 + jMonth;
    1265           0 :                             if (month > elcc->lengthStudyTotalMonths) break;
    1266           0 :                             elcc->CashFlow[cashFlowCounter].mnAmount(month) *= elcc->UseAdjustment(found).Adjustment(kYear);
    1267             :                         }
    1268             :                     }
    1269             :                 }
    1270             :             }
    1271             :         }
    1272             :     }
    1273             :     // put cashflows into categories
    1274          17 :     for (jCost = 0; jCost < CostCategory::Num; ++jCost) {
    1275          16 :         elcc->CashFlow[jCost].Category = static_cast<CostCategory>(jCost); // make each category the type indicated
    1276          16 :         elcc->CashFlow[jCost].SourceKind = SourceKindType::Sum;
    1277             :     }
    1278             :     // add the cashflows by category
    1279           9 :     for (jCost = CostCategory::Num - 1; jCost < elcc->numCashFlow; ++jCost) {
    1280           8 :         curCategory = elcc->CashFlow[jCost].Category;
    1281           8 :         if ((curCategory < CostCategory::Num) && (curCategory >= 0)) {
    1282        2120 :             for (int jMonth = 1; jMonth <= elcc->lengthStudyTotalMonths; ++jMonth) {
    1283        2112 :                 elcc->CashFlow[curCategory].mnAmount(jMonth) += elcc->CashFlow[jCost].mnAmount(jMonth);
    1284             :             }
    1285             :         }
    1286             :     }
    1287             :     // create total categories
    1288         265 :     for (int jMonth = 1; jMonth <= elcc->lengthStudyTotalMonths; ++jMonth) {
    1289         264 :         elcc->CashFlow[CostCategory::TotEnergy].mnAmount(jMonth) = elcc->CashFlow[CostCategory::Energy].mnAmount(jMonth);
    1290         264 :         elcc->CashFlow[CostCategory::TotOper].mnAmount(jMonth) =
    1291         528 :             elcc->CashFlow[CostCategory::Maintenance].mnAmount(jMonth) + elcc->CashFlow[CostCategory::Repair].mnAmount(jMonth) +
    1292         792 :             elcc->CashFlow[CostCategory::Operation].mnAmount(jMonth) + elcc->CashFlow[CostCategory::Replacement].mnAmount(jMonth) +
    1293         792 :             elcc->CashFlow[CostCategory::MinorOverhaul].mnAmount(jMonth) + elcc->CashFlow[CostCategory::MajorOverhaul].mnAmount(jMonth) +
    1294         792 :             elcc->CashFlow[CostCategory::OtherOperational].mnAmount(jMonth) + elcc->CashFlow[CostCategory::Water].mnAmount(jMonth) +
    1295         264 :             elcc->CashFlow[CostCategory::Energy].mnAmount(jMonth);
    1296         792 :         elcc->CashFlow[CostCategory::TotCaptl].mnAmount(jMonth) = elcc->CashFlow[CostCategory::Construction].mnAmount(jMonth) +
    1297         528 :                                                                   elcc->CashFlow[CostCategory::Salvage].mnAmount(jMonth) +
    1298         264 :                                                                   elcc->CashFlow[CostCategory::OtherCapital].mnAmount(jMonth);
    1299         264 :         elcc->CashFlow[CostCategory::TotGrand].mnAmount(jMonth) =
    1300         264 :             elcc->CashFlow[CostCategory::TotOper].mnAmount(jMonth) + elcc->CashFlow[CostCategory::TotCaptl].mnAmount(jMonth);
    1301             :     }
    1302             :     // convert all monthly cashflows into yearly cashflows
    1303          24 :     for (jCost = 0; jCost < elcc->numCashFlow; ++jCost) {
    1304         529 :         for (kYear = 1; kYear <= elcc->lengthStudyYears; ++kYear) {
    1305         506 :             annualCost = 0.0;
    1306        6578 :             for (int jMonth = 1; jMonth <= 12; ++jMonth) {
    1307        6072 :                 month = (kYear - 1) * 12 + jMonth;
    1308        6072 :                 if (month <= elcc->lengthStudyTotalMonths) {
    1309        6072 :                     annualCost += elcc->CashFlow[jCost].mnAmount(month);
    1310             :                 }
    1311             :             }
    1312         506 :             elcc->CashFlow[jCost].yrAmount(kYear) = annualCost;
    1313             :         }
    1314             :     }
    1315             :     // generate a warning if resource referenced was not used
    1316           4 :     for (int nUsePriceEsc = 1; nUsePriceEsc <= elcc->numUsePriceEscalation; ++nUsePriceEsc) {
    1317           3 :         auto curResource = elcc->UsePriceEscalation(nUsePriceEsc).resource;
    1318           3 :         if (!resourceCostNotZero.at(curResource) && state.dataGlobal->DoWeathSim) {
    1319           0 :             ShowWarningError(state,
    1320           0 :                              "The resource referenced by LifeCycleCost:UsePriceEscalation= \"" + elcc->UsePriceEscalation(nUsePriceEsc).name +
    1321             :                                  "\" has no energy cost. ");
    1322           0 :             ShowContinueError(state, "... It is likely that the wrong resource is used. The resource should match the meter used in Utility:Tariff.");
    1323             :         }
    1324             :     }
    1325           1 : }
    1326             : 
    1327           1 : void ComputeEscalatedEnergyCosts(EnergyPlusData &state)
    1328             : {
    1329             :     // J. Glazer - August 2019
    1330             :     int nUsePriceEsc;
    1331             : 
    1332           1 :     auto &elcc(state.dataEconLifeCycleCost);
    1333             : 
    1334          24 :     for (int iCashFlow = 0; iCashFlow < elcc->numCashFlow; ++iCashFlow) {
    1335          23 :         if (elcc->CashFlow[iCashFlow].pvKind == PrValKind::Energy) {
    1336             :             // make sure this is not water
    1337           1 :             auto curResource = elcc->CashFlow[iCashFlow].Resource;
    1338           2 :             if (elcc->CashFlow[iCashFlow].Resource == DataGlobalConstants::ResourceType::Water ||
    1339           1 :                 (elcc->CashFlow[iCashFlow].Resource >= DataGlobalConstants::ResourceType::OnSiteWater &&
    1340           0 :                  elcc->CashFlow[iCashFlow].Resource <= DataGlobalConstants::ResourceType::Condensate)) {
    1341           0 :                 continue;
    1342             :             }
    1343           1 :             if ((curResource != DataGlobalConstants::ResourceType::None)) {
    1344           1 :                 int found = 0;
    1345           3 :                 for (nUsePriceEsc = 1; nUsePriceEsc <= elcc->numUsePriceEscalation; ++nUsePriceEsc) {
    1346           3 :                     if (elcc->UsePriceEscalation(nUsePriceEsc).resource == curResource) {
    1347           1 :                         found = nUsePriceEsc;
    1348           1 :                         break;
    1349             :                     }
    1350             :                 }
    1351           1 :                 if (found > 0) {
    1352          23 :                     for (int jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
    1353          22 :                         elcc->EscalatedEnergy.at(jYear).at(curResource) =
    1354          22 :                             elcc->CashFlow[iCashFlow].yrAmount(jYear) * elcc->UsePriceEscalation(found).Escalation(jYear);
    1355             :                     }
    1356             :                 } else { // if no escalation than just store the original energy cost
    1357           0 :                     for (int jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
    1358           0 :                         elcc->EscalatedEnergy.at(jYear).at(curResource) = elcc->CashFlow[iCashFlow].yrAmount(jYear);
    1359             :                     }
    1360             :                 }
    1361             :             }
    1362             :         }
    1363             :     }
    1364          48 :     for (auto kResource : state.dataGlobalConst->AllResourceTypes) {
    1365        1081 :         for (int jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
    1366        1034 :             elcc->EscalatedTotEnergy(jYear) += elcc->EscalatedEnergy.at(jYear).at(kResource);
    1367             :         }
    1368             :     }
    1369           1 : }
    1370             : 
    1371           1 : void ComputePresentValue(EnergyPlusData &state)
    1372             : {
    1373             :     // SUBROUTINE INFORMATION:
    1374             :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1375             :     //    DATE WRITTEN   August 2010
    1376             :     //    MODIFIED       na
    1377             :     //    RE-ENGINEERED  na
    1378             : 
    1379             :     // PURPOSE OF THIS SUBROUTINE:
    1380             :     //    For each cashflow, compute the present value
    1381             : 
    1382             :     // METHODOLOGY EMPLOYED:
    1383             : 
    1384             :     // REFERENCES:
    1385             :     // na
    1386             : 
    1387             :     // USE STATEMENTS:
    1388             : 
    1389             :     // Locals
    1390             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    1391             :     // na
    1392             : 
    1393             :     // SUBROUTINE PARAMETER DEFINITIONS:
    1394             :     // na
    1395             : 
    1396             :     // INTERFACE BLOCK SPECIFICATIONS
    1397             :     // na
    1398             : 
    1399             :     // DERIVED TYPE DEFINITIONS
    1400             :     // na
    1401             : 
    1402             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1403             :     Real64 totalPV;
    1404             :     int curCategory;
    1405             :     Real64 curDiscountRate;
    1406             :     int iCashFlow;
    1407             :     int jYear;
    1408             :     int nUsePriceEsc;
    1409             :     Real64 effectiveYear;
    1410             : 
    1411           1 :     auto &elcc(state.dataEconLifeCycleCost);
    1412             : 
    1413             :     // identify how each cashflow should be treated
    1414          24 :     for (iCashFlow = 0; iCashFlow < elcc->numCashFlow; ++iCashFlow) {
    1415          23 :         switch (elcc->CashFlow[iCashFlow].SourceKind) {
    1416           1 :         case SourceKindType::Resource: {
    1417             :             // only for real fuels purchased such as electricity, natural gas, etc..
    1418           2 :             if ((elcc->CashFlow[iCashFlow].Resource >= DataGlobalConstants::ResourceType::Electricity) &&
    1419           1 :                 (elcc->CashFlow[iCashFlow].Resource <= DataGlobalConstants::ResourceType::ElectricitySurplusSold)) {
    1420           1 :                 elcc->CashFlow[iCashFlow].pvKind = PrValKind::Energy;
    1421             :             } else {
    1422           0 :                 elcc->CashFlow[iCashFlow].pvKind = PrValKind::NonEnergy;
    1423             :             }
    1424           1 :             break;
    1425             :         }
    1426           6 :         case SourceKindType::Recurring:
    1427             :         case SourceKindType::Nonrecurring: {
    1428           6 :             if (elcc->CashFlow[iCashFlow].Category == CostCategory::Energy) {
    1429           0 :                 elcc->CashFlow[iCashFlow].pvKind = PrValKind::Energy;
    1430             :             } else {
    1431           6 :                 elcc->CashFlow[iCashFlow].pvKind = PrValKind::NonEnergy;
    1432             :             }
    1433           6 :             break;
    1434             :         }
    1435          16 :         case SourceKindType::Sum:
    1436             :         default: {
    1437          16 :             elcc->CashFlow[iCashFlow].pvKind = PrValKind::NotComputed;
    1438          16 :             break;
    1439             :         }
    1440             :         }
    1441             :     }
    1442             :     // compute the Single Present Value factors based on the discount rate
    1443           1 :     elcc->SPV.allocate(elcc->lengthStudyYears);
    1444          23 :     for (int year = 1; year <= elcc->lengthStudyYears; ++year) {
    1445          44 :         std::map<DataGlobalConstants::ResourceType, Real64> yearMap;
    1446        1056 :         for (auto iResource : state.dataGlobalConst->AllResourceTypes) {
    1447        1034 :             yearMap.insert(std::pair<DataGlobalConstants::ResourceType, Real64>(iResource, 0.0));
    1448             :         }
    1449          22 :         elcc->energySPV.insert(std::pair<int, std::map<DataGlobalConstants::ResourceType, Real64>>(year, yearMap));
    1450             :     }
    1451             : 
    1452             :     // Depending if using Constant or Current Dollar analysis
    1453             :     // use the appropriate discount rate
    1454           1 :     if (elcc->inflationApproach == InflAppr::ConstantDollar) {
    1455           1 :         curDiscountRate = elcc->realDiscountRate;
    1456           0 :     } else if (elcc->inflationApproach == InflAppr::CurrentDollar) {
    1457           0 :         curDiscountRate = elcc->nominalDiscountRate;
    1458             :     }
    1459             :     // compute single present values based on real discount rates
    1460           1 :     constexpr std::array<Real64, static_cast<int>(DiscConv::Num)> DiscConv2EffectiveYearAdjustment = {1.0, 0.5, 0.0};
    1461          23 :     for (jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
    1462             :         // NIST 155 D.2.1.1 - Single Present Value (SPV) formula
    1463          22 :         effectiveYear = double(jYear) - DiscConv2EffectiveYearAdjustment[static_cast<int>(elcc->discountConvention)];
    1464          22 :         elcc->SPV(jYear) = 1.0 / std::pow(1.0 + curDiscountRate, effectiveYear);
    1465             :     }
    1466             :     // use SPV as default values for all energy types
    1467          23 :     for (jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
    1468        1056 :         for (auto kResource : state.dataGlobalConst->AllResourceTypes) {
    1469        1034 :             elcc->energySPV.at(jYear).at(kResource) = elcc->SPV(jYear);
    1470             :         }
    1471             :     }
    1472             :     // loop through the resources and if they match a UseEscalation use those values instead
    1473           4 :     for (nUsePriceEsc = 1; nUsePriceEsc <= elcc->numUsePriceEscalation; ++nUsePriceEsc) {
    1474           3 :         auto curResource = elcc->UsePriceEscalation(nUsePriceEsc).resource;
    1475           3 :         if (curResource != DataGlobalConstants::ResourceType::None) {
    1476          69 :             for (jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
    1477             :                 // the following is based on UPV* formula from NIST 135 supplement but is for a single year
    1478          66 :                 effectiveYear = double(jYear) - DiscConv2EffectiveYearAdjustment[static_cast<int>(elcc->discountConvention)];
    1479          66 :                 elcc->energySPV.at(jYear).at(curResource) =
    1480          66 :                     elcc->UsePriceEscalation(nUsePriceEsc).Escalation(jYear) / std::pow(1.0 + curDiscountRate, effectiveYear);
    1481             :             }
    1482             :         }
    1483             :     }
    1484          24 :     for (iCashFlow = 0; iCashFlow < elcc->numCashFlow; ++iCashFlow) {
    1485          23 :         switch (elcc->CashFlow[iCashFlow].pvKind) {
    1486           6 :         case PrValKind::NonEnergy: {
    1487           6 :             totalPV = 0.0;
    1488         138 :             for (jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
    1489         132 :                 elcc->CashFlow[iCashFlow].yrPresVal(jYear) = elcc->CashFlow[iCashFlow].yrAmount(jYear) * elcc->SPV(jYear);
    1490         132 :                 totalPV += elcc->CashFlow[iCashFlow].yrPresVal(jYear);
    1491             :             }
    1492           6 :             elcc->CashFlow[iCashFlow].presentValue = totalPV;
    1493           6 :             break;
    1494             :         }
    1495           1 :         case PrValKind::Energy: {
    1496           1 :             auto curResource = elcc->CashFlow[iCashFlow].Resource;
    1497           1 :             if (curResource != DataGlobalConstants::ResourceType::None) {
    1498           1 :                 totalPV = 0.0;
    1499          23 :                 for (jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
    1500          22 :                     elcc->CashFlow[iCashFlow].yrPresVal(jYear) =
    1501          22 :                         elcc->CashFlow[iCashFlow].yrAmount(jYear) * elcc->energySPV.at(jYear).at(curResource);
    1502          22 :                     totalPV += elcc->CashFlow[iCashFlow].yrPresVal(jYear);
    1503             :                 }
    1504           1 :                 elcc->CashFlow[iCashFlow].presentValue = totalPV;
    1505             :             }
    1506           1 :             break;
    1507             :         }
    1508             :             //            case iPrValKind::NotComputed: included in default
    1509          16 :         default:
    1510          16 :             break; // do nothing
    1511             :         }
    1512             :     }
    1513             :     // sum by category
    1514          17 :     for (int i = 0; i < CostCategory::Num; ++i) {
    1515          16 :         elcc->CashFlow[i].presentValue = 0; // initialize value to zero before summing in next for loop
    1516             :     }
    1517           8 :     for (iCashFlow = CostCategory::Num; iCashFlow < elcc->numCashFlow; ++iCashFlow) {
    1518           7 :         curCategory = elcc->CashFlow[iCashFlow].Category;
    1519           7 :         if ((curCategory < CostCategory::Num) && (curCategory >= 0)) {
    1520           7 :             elcc->CashFlow[curCategory].presentValue += elcc->CashFlow[iCashFlow].presentValue;
    1521         161 :             for (jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
    1522         154 :                 elcc->CashFlow[curCategory].yrPresVal(jYear) += elcc->CashFlow[iCashFlow].yrPresVal(jYear);
    1523             :             }
    1524             :         }
    1525             :     }
    1526             :     // create total categories
    1527           1 :     elcc->CashFlow[CostCategory::TotEnergy].presentValue = elcc->CashFlow[CostCategory::Energy].presentValue;
    1528           1 :     elcc->CashFlow[CostCategory::TotOper].presentValue =
    1529           2 :         elcc->CashFlow[CostCategory::Maintenance].presentValue + elcc->CashFlow[CostCategory::Repair].presentValue +
    1530           3 :         elcc->CashFlow[CostCategory::Operation].presentValue + elcc->CashFlow[CostCategory::Replacement].presentValue +
    1531           3 :         elcc->CashFlow[CostCategory::MinorOverhaul].presentValue + elcc->CashFlow[CostCategory::MajorOverhaul].presentValue +
    1532           3 :         elcc->CashFlow[CostCategory::OtherOperational].presentValue + elcc->CashFlow[CostCategory::Water].presentValue +
    1533           1 :         elcc->CashFlow[CostCategory::Energy].presentValue;
    1534           3 :     elcc->CashFlow[CostCategory::TotCaptl].presentValue = elcc->CashFlow[CostCategory::Construction].presentValue +
    1535           2 :                                                           elcc->CashFlow[CostCategory::Salvage].presentValue +
    1536           1 :                                                           elcc->CashFlow[CostCategory::OtherCapital].presentValue;
    1537           1 :     elcc->CashFlow[CostCategory::TotGrand].presentValue =
    1538           1 :         elcc->CashFlow[CostCategory::TotOper].presentValue + elcc->CashFlow[CostCategory::TotCaptl].presentValue;
    1539          23 :     for (jYear = 1; jYear <= elcc->lengthStudyYears; ++jYear) {
    1540          22 :         elcc->CashFlow[CostCategory::TotEnergy].yrPresVal(jYear) = elcc->CashFlow[CostCategory::Energy].yrPresVal(jYear);
    1541          22 :         elcc->CashFlow[CostCategory::TotOper].yrPresVal(jYear) =
    1542          44 :             elcc->CashFlow[CostCategory::Maintenance].yrPresVal(jYear) + elcc->CashFlow[CostCategory::Repair].yrPresVal(jYear) +
    1543          66 :             elcc->CashFlow[CostCategory::Operation].yrPresVal(jYear) + elcc->CashFlow[CostCategory::Replacement].yrPresVal(jYear) +
    1544          66 :             elcc->CashFlow[CostCategory::MinorOverhaul].yrPresVal(jYear) + elcc->CashFlow[CostCategory::MajorOverhaul].yrPresVal(jYear) +
    1545          66 :             elcc->CashFlow[CostCategory::OtherOperational].yrPresVal(jYear) + elcc->CashFlow[CostCategory::Water].yrPresVal(jYear) +
    1546          22 :             elcc->CashFlow[CostCategory::Energy].yrPresVal(jYear);
    1547          66 :         elcc->CashFlow[CostCategory::TotCaptl].yrPresVal(jYear) = elcc->CashFlow[CostCategory::Construction].yrPresVal(jYear) +
    1548          44 :                                                                   elcc->CashFlow[CostCategory::Salvage].yrPresVal(jYear) +
    1549          22 :                                                                   elcc->CashFlow[CostCategory::OtherCapital].yrPresVal(jYear);
    1550          22 :         elcc->CashFlow[CostCategory::TotGrand].yrPresVal(jYear) =
    1551          22 :             elcc->CashFlow[CostCategory::TotOper].yrPresVal(jYear) + elcc->CashFlow[CostCategory::TotCaptl].yrPresVal(jYear);
    1552             :     }
    1553           1 : }
    1554             : 
    1555           1 : void ComputeTaxAndDepreciation(EnergyPlusData &state)
    1556             : {
    1557             :     // SUBROUTINE INFORMATION:
    1558             :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1559             :     //    DATE WRITTEN   August 2010
    1560             :     //    MODIFIED       na
    1561             :     //    RE-ENGINEERED  na
    1562             : 
    1563             :     // PURPOSE OF THIS SUBROUTINE:
    1564             :     //    Compute the present value after factoring in taxes
    1565             :     //    and depreciation.
    1566             : 
    1567             :     // METHODOLOGY EMPLOYED:
    1568             : 
    1569             :     // REFERENCES:
    1570             :     // na
    1571             : 
    1572             :     // USE STATEMENTS:
    1573             : 
    1574             :     // Locals
    1575             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    1576             :     // na
    1577             : 
    1578             :     // SUBROUTINE PARAMETER DEFINITIONS:
    1579             : 
    1580             :     // INTERFACE BLOCK SPECIFICATIONS
    1581             :     // na
    1582             : 
    1583             :     // DERIVED TYPE DEFINITIONS
    1584             :     // na
    1585             : 
    1586             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1587             :     Real64 curCapital;
    1588             :     int curDepYear;
    1589             :     int iYear;
    1590             :     int jYear;
    1591             : 
    1592           1 :     auto &elcc(state.dataEconLifeCycleCost);
    1593             : 
    1594           1 :     elcc->DepreciatedCapital.allocate(elcc->lengthStudyYears);
    1595           1 :     elcc->TaxableIncome.allocate(elcc->lengthStudyYears);
    1596           1 :     elcc->Taxes.allocate(elcc->lengthStudyYears);
    1597           1 :     elcc->AfterTaxCashFlow.allocate(elcc->lengthStudyYears);
    1598           1 :     elcc->AfterTaxPresentValue.allocate(elcc->lengthStudyYears);
    1599             : 
    1600             :     // Depreciation factors are based on IRS Publication 946 for 2009 "How to Depreciate Property"
    1601             :     // The MACRS valus are based on Modified Accelerated Cost Recovery System GDS for 3, 5, 7, 10 year
    1602             :     // property are based on 200% depreciation method shown in Appendix A using half year. 15 and 20 are
    1603             :     // based on 150% (Chart 1). For Straight Line depreciation GDS is used for 27 years (actually 27.5)
    1604             :     // 31 years (actually 31.5 years) and 39 years using mid month. For 40 years ADS is used (chart 2)
    1605             :     // Table A-1 is used for 3, 4, 5, 10, 15 and 20 years. Table A-6 is for 27 years. Table A-7 for 31 years.
    1606             :     // Table A-7a for 39 years. Table A-13 for 40 years. These years are a classification of property
    1607             :     // and should not be confused with the length of the study. For 27 years, 31 years, 39 years and 40 years
    1608             :     // the June value was used.
    1609             : 
    1610             :     // convert construction costs (not salvage) into depreciation
    1611           1 :     elcc->DepreciatedCapital = 0.0; // set all years to zero
    1612          23 :     for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1613          22 :         curCapital = elcc->CashFlow[CostCategory::Construction].yrAmount(iYear) + elcc->CashFlow[CostCategory::OtherCapital].yrAmount(iYear);
    1614         924 :         for (jYear = 0; jYear < SizeDepr; ++jYear) {
    1615         902 :             curDepYear = iYear + jYear; // start depreciating with the year that the capital was shown and go to years following
    1616         902 :             if (curDepYear <= elcc->lengthStudyYears) {
    1617         253 :                 elcc->DepreciatedCapital(curDepYear) +=
    1618         253 :                     curCapital * (DepreciationPercentTable[static_cast<int>(elcc->depreciationMethod)][jYear] / 100);
    1619             :             }
    1620             :         }
    1621             :     }
    1622             :     // Using Newnan pg 3880
    1623             :     //   before-tax cash flow
    1624             :     //   depreciation
    1625             :     //   taxable income (before-tax cash flow - depreciation)
    1626             :     //   income taxes (taxable income x incremental tax rate)
    1627             :     //   after-tax cash flow (before-tax cash flow - income taxes)
    1628          23 :     for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1629          22 :         elcc->TaxableIncome(iYear) = elcc->CashFlow[CostCategory::TotGrand].yrAmount(iYear) - elcc->DepreciatedCapital(iYear);
    1630          22 :         elcc->Taxes(iYear) = elcc->TaxableIncome(iYear) * elcc->taxRate;
    1631          22 :         elcc->AfterTaxCashFlow(iYear) = elcc->CashFlow[CostCategory::TotGrand].yrAmount(iYear) - elcc->Taxes(iYear);
    1632             :         // the present value after taxes is pretax present value minus the present value of the taxes
    1633          22 :         elcc->AfterTaxPresentValue(iYear) = elcc->CashFlow[CostCategory::TotGrand].yrPresVal(iYear) - elcc->Taxes(iYear) * elcc->SPV(iYear);
    1634             :     }
    1635           1 : }
    1636             : 
    1637             : //======================================================================================================================
    1638             : //======================================================================================================================
    1639             : 
    1640             : //    OUTPUT ROUTINES
    1641             : 
    1642             : //======================================================================================================================
    1643             : //======================================================================================================================
    1644             : 
    1645           1 : void WriteTabularLifeCycleCostReport(EnergyPlusData &state)
    1646             : {
    1647             :     // SUBROUTINE INFORMATION:
    1648             :     //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
    1649             :     //    DATE WRITTEN   June 2010
    1650             :     //    MODIFIED       na
    1651             :     //    RE-ENGINEERED  na
    1652             : 
    1653             :     // PURPOSE OF THIS SUBROUTINE:
    1654             :     //    Write the output report related to life-cycle costing
    1655             :     //    to the tabular output file.
    1656             : 
    1657             :     // METHODOLOGY EMPLOYED:
    1658             : 
    1659             :     // REFERENCES:
    1660             :     // na
    1661             : 
    1662             :     // Using/Aliasing
    1663             :     using OutputReportTabular::RealToStr;
    1664             :     using OutputReportTabular::WriteReportHeaders;
    1665             :     using OutputReportTabular::WriteSubtitle;
    1666             :     using OutputReportTabular::WriteTable;
    1667             : 
    1668             :     // Locals
    1669             :     // SUBROUTINE ARGUMENT DEFINITIONS:
    1670             :     // na
    1671             : 
    1672             :     // SUBROUTINE PARAMETER DEFINITIONS:
    1673             :     // na
    1674             : 
    1675             :     // INTERFACE BLOCK SPECIFICATIONS
    1676             :     // na
    1677             : 
    1678             :     // DERIVED TYPE DEFINITIONS
    1679             :     // na
    1680             : 
    1681             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1682             :     // all arrays are in the format: (row, column)
    1683           2 :     Array1D_string columnHead;
    1684           2 :     Array1D_int columnWidth;
    1685           2 :     Array1D_string rowHead;
    1686           2 :     Array2D_string tableBody;
    1687             : 
    1688             :     int numColumns;
    1689             :     int iYear;
    1690             :     int jObj;
    1691             :     int kMonth;
    1692             :     int curCashFlow;
    1693             :     int numRows;
    1694             :     int offset;
    1695             :     int numYears;
    1696             :     Real64 totalPV;
    1697             : 
    1698           1 :     auto &elcc(state.dataEconLifeCycleCost);
    1699             : 
    1700           1 :     if (elcc->LCCparamPresent && state.dataOutRptTab->displayLifeCycleCostReport) {
    1701             :         //---------------------------------
    1702             :         // Life-Cycle Cost Verification and Results Report
    1703             :         //---------------------------------
    1704           1 :         WriteReportHeaders(state, "Life-Cycle Cost Report", "Entire Facility", OutputProcessor::StoreType::Averaged);
    1705             :         //---- Life-Cycle Cost Parameters
    1706           1 :         rowHead.allocate(11);
    1707           1 :         columnHead.allocate(1);
    1708           1 :         columnWidth.allocate(1);
    1709           1 :         tableBody.allocate(1, 11);
    1710           1 :         tableBody = "";
    1711           1 :         rowHead(1) = "Name";
    1712           1 :         rowHead(2) = "Discounting Convention";
    1713           1 :         rowHead(3) = "Inflation Approach";
    1714           1 :         rowHead(4) = "Real Discount Rate";
    1715           1 :         rowHead(5) = "Nominal Discount Rate";
    1716           1 :         rowHead(6) = "Inflation";
    1717           1 :         rowHead(7) = "Base Date";
    1718           1 :         rowHead(8) = "Service Date";
    1719           1 :         rowHead(9) = "Length of Study Period in Years";
    1720           1 :         rowHead(10) = "Tax rate";
    1721           1 :         rowHead(11) = "Depreciation Method";
    1722           1 :         columnHead(1) = "Value";
    1723             : 
    1724           1 :         tableBody(1, 1) = elcc->LCCname;
    1725           1 :         tableBody(1, 2) = DiscConvNames[static_cast<int>(elcc->discountConvention)];
    1726           1 :         tableBody(1, 3) = InflApprNames[static_cast<int>(elcc->inflationApproach)];
    1727           1 :         if (elcc->inflationApproach == InflAppr::ConstantDollar) {
    1728           1 :             tableBody(1, 4) = RealToStr(elcc->realDiscountRate, 4);
    1729             :         } else {
    1730           0 :             tableBody(1, 4) = "-- N/A --";
    1731             :         }
    1732           1 :         if (elcc->inflationApproach == InflAppr::CurrentDollar) {
    1733           0 :             tableBody(1, 5) = RealToStr(elcc->nominalDiscountRate, 4);
    1734             :         } else {
    1735           1 :             tableBody(1, 5) = "-- N/A --";
    1736             :         }
    1737           1 :         if (elcc->inflationApproach == InflAppr::CurrentDollar) {
    1738           0 :             tableBody(1, 6) = RealToStr(elcc->inflation, 4);
    1739             :         } else {
    1740           1 :             tableBody(1, 6) = "-- N/A --";
    1741             :         }
    1742           1 :         tableBody(1, 7) = format("{} {}", UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->baseDateMonth)], elcc->baseDateYear);
    1743           1 :         tableBody(1, 8) = format("{} {}", UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->serviceDateMonth)], elcc->serviceDateYear);
    1744           1 :         tableBody(1, 9) = fmt::to_string(elcc->lengthStudyYears);
    1745           1 :         tableBody(1, 10) = RealToStr(elcc->taxRate, 4);
    1746           1 :         tableBody(1, 11) = DeprMethodNames[static_cast<int>(elcc->depreciationMethod)];
    1747             : 
    1748           1 :         columnWidth = 14; // array assignment - same for all columns
    1749           1 :         WriteSubtitle(state, "Life-Cycle Cost Parameters");
    1750           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    1751           1 :         if (state.dataSQLiteProcedures->sqlite) {
    1752           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    1753             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Life-Cycle Cost Parameters");
    1754             :         }
    1755           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    1756           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    1757             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Life-Cycle Cost Parameters");
    1758             :         }
    1759             : 
    1760           1 :         columnHead.deallocate();
    1761           1 :         rowHead.deallocate();
    1762           1 :         columnWidth.deallocate();
    1763           1 :         tableBody.deallocate();
    1764             :         //---- Use Price Escalation
    1765           1 :         numColumns = max(1, elcc->numUsePriceEscalation);
    1766           1 :         rowHead.allocate(elcc->lengthStudyYears + 2);
    1767           1 :         columnHead.allocate(numColumns);
    1768           1 :         columnWidth.dimension(numColumns, 14); // array assignment - same for all columns
    1769           1 :         tableBody.allocate(numColumns, elcc->lengthStudyYears + 2);
    1770           1 :         tableBody = "";
    1771           1 :         columnHead = "none";
    1772           1 :         rowHead(1) = "Resource";
    1773           1 :         rowHead(2) = "Start Date";
    1774          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1775          22 :             rowHead(iYear + 2) = fmt::to_string(iYear);
    1776             :         }
    1777           4 :         for (jObj = 1; jObj <= elcc->numUsePriceEscalation; ++jObj) { // loop through objects not columns to add names
    1778           3 :             columnHead(jObj) = elcc->UsePriceEscalation(jObj).name;
    1779           3 :             tableBody(jObj, 1) = GetResourceTypeChar(elcc->UsePriceEscalation(jObj).resource);
    1780           6 :             tableBody(jObj, 2) = format("{} {}",
    1781           3 :                                         UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->UsePriceEscalation(jObj).escalationStartMonth)],
    1782           6 :                                         elcc->UsePriceEscalation(jObj).escalationStartYear);
    1783             :         }
    1784           4 :         for (jObj = 1; jObj <= elcc->numUsePriceEscalation; ++jObj) {
    1785          69 :             for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1786          66 :                 tableBody(jObj, iYear + 2) = RealToStr(elcc->UsePriceEscalation(jObj).Escalation(iYear), 6);
    1787             :             }
    1788             :         }
    1789           1 :         WriteSubtitle(state, "Use Price Escalation");
    1790           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    1791           1 :         if (state.dataSQLiteProcedures->sqlite) {
    1792           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    1793             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Use Price Escalation");
    1794             :         }
    1795           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    1796           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    1797             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Use Price Escalation");
    1798             :         }
    1799           1 :         columnHead.deallocate();
    1800           1 :         rowHead.deallocate();
    1801           1 :         columnWidth.deallocate();
    1802           1 :         tableBody.deallocate();
    1803             :         //---- Use Adjustment
    1804           1 :         if (elcc->numUseAdjustment >= 1) { // only create table if objects used
    1805           1 :             numColumns = max(1, elcc->numUseAdjustment);
    1806           1 :             numYears = elcc->lengthStudyYears - (elcc->serviceDateYear - elcc->baseDateYear);
    1807           1 :             rowHead.allocate(numYears + 1);
    1808           1 :             columnHead.allocate(numColumns);
    1809           1 :             columnWidth.dimension(numColumns, 14); // array assignment - same for all columns
    1810           1 :             tableBody.allocate(numColumns, numYears + 1);
    1811           1 :             tableBody = "";
    1812           1 :             columnHead = "none";
    1813           1 :             rowHead(1) = "";
    1814          21 :             for (iYear = 1; iYear <= numYears; ++iYear) {
    1815          20 :                 rowHead(iYear + 1) =
    1816          40 :                     format("{} {}", UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->serviceDateMonth)], elcc->serviceDateYear + iYear - 1);
    1817             :             }
    1818           2 :             for (jObj = 1; jObj <= elcc->numUseAdjustment; ++jObj) { // loop through objects not columns to add names
    1819           1 :                 columnHead(jObj) = elcc->UseAdjustment(jObj).name;
    1820           1 :                 tableBody(jObj, 1) = GetResourceTypeChar(elcc->UseAdjustment(jObj).resource);
    1821             :             }
    1822           2 :             for (jObj = 1; jObj <= elcc->numUseAdjustment; ++jObj) {
    1823          21 :                 for (iYear = 1; iYear <= numYears; ++iYear) {
    1824          20 :                     tableBody(jObj, iYear + 1) = RealToStr(elcc->UseAdjustment(jObj).Adjustment(iYear), 6);
    1825             :                 }
    1826             :             }
    1827           1 :             WriteSubtitle(state, "Use Adjustment");
    1828           1 :             WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    1829           1 :             if (state.dataSQLiteProcedures->sqlite) {
    1830           0 :                 state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    1831             :                     tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Use Adjustment");
    1832             :             }
    1833           1 :             if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    1834           0 :                 state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    1835             :                     tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Use Adjustment");
    1836             :             }
    1837           1 :             columnHead.deallocate();
    1838           1 :             rowHead.deallocate();
    1839           1 :             columnWidth.deallocate();
    1840           1 :             tableBody.deallocate();
    1841             :         }
    1842             :         //---- Cash Flow for Recurring and Nonrecurring Costs
    1843           1 :         numColumns = max(1, elcc->numRecurringCosts + elcc->numNonrecurringCost);
    1844           1 :         rowHead.allocate(elcc->lengthStudyYears + 1);
    1845           1 :         columnHead.allocate(numColumns);
    1846           1 :         columnWidth.dimension(numColumns, 14); // array assignment - same for all columns
    1847           1 :         tableBody.allocate(numColumns, elcc->lengthStudyYears + 1);
    1848           1 :         tableBody = "";
    1849           1 :         rowHead(1) = "";
    1850          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1851          22 :             rowHead(iYear + 1) =
    1852          44 :                 format("{} {}", UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->baseDateMonth)], elcc->baseDateYear + iYear - 1);
    1853             :         }
    1854           7 :         for (jObj = 0; jObj < (elcc->numRecurringCosts + elcc->numNonrecurringCost); ++jObj) {
    1855           6 :             curCashFlow = CostCategory::Num + jObj;
    1856           6 :             columnHead(jObj + 1) = elcc->CashFlow[curCashFlow].name;
    1857             : 
    1858           6 :             tableBody(jObj + 1, 1) = SourceKindTypeNames[static_cast<int>(elcc->CashFlow[curCashFlow].SourceKind)];
    1859             : 
    1860         138 :             for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1861         132 :                 tableBody(jObj + 1, iYear + 1) = RealToStr(elcc->CashFlow[curCashFlow].yrAmount(iYear), 2);
    1862             :             }
    1863             :         }
    1864           1 :         WriteSubtitle(state, "Cash Flow for Recurring and Nonrecurring Costs (Without Escalation)");
    1865           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    1866           1 :         if (state.dataSQLiteProcedures->sqlite) {
    1867           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(tableBody,
    1868             :                                                                                rowHead,
    1869             :                                                                                columnHead,
    1870             :                                                                                "Life-Cycle Cost Report",
    1871             :                                                                                "Entire Facility",
    1872             :                                                                                "Cash Flow for Recurring and Nonrecurring Costs (Without Escalation)");
    1873             :         }
    1874           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    1875           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    1876             :                 tableBody,
    1877             :                 rowHead,
    1878             :                 columnHead,
    1879             :                 "Life-Cycle Cost Report",
    1880             :                 "Entire Facility",
    1881             :                 "Cash Flow for Recurring and Nonrecurring Costs (Without Escalation)");
    1882             :         }
    1883           1 :         columnHead.deallocate();
    1884           1 :         rowHead.deallocate();
    1885           1 :         columnWidth.deallocate();
    1886           1 :         tableBody.deallocate();
    1887             :         //---- Energy and Water Cost Cash Flows (Without Escalation)
    1888           1 :         numColumns = max(1, elcc->numResourcesUsed + 1);
    1889           1 :         rowHead.allocate(elcc->lengthStudyYears);
    1890           1 :         columnHead.allocate(numColumns);
    1891           1 :         columnWidth.dimension(numColumns, 14); // array assignment - same for all columns
    1892           1 :         tableBody.allocate(numColumns, elcc->lengthStudyYears);
    1893           1 :         tableBody = "";
    1894          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1895          22 :             rowHead(iYear) = format("{} {}", UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->baseDateMonth)], elcc->baseDateYear + iYear - 1);
    1896             :         }
    1897           2 :         for (jObj = 0; jObj < elcc->numResourcesUsed; ++jObj) {
    1898           1 :             curCashFlow = CostCategory::Num + elcc->numRecurringCosts + elcc->numNonrecurringCost + jObj;
    1899           1 :             columnHead(jObj + 1) = elcc->CashFlow[curCashFlow].name;
    1900          23 :             for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1901          22 :                 tableBody(jObj + 1, iYear) = RealToStr(elcc->CashFlow[curCashFlow].yrAmount(iYear), 2);
    1902             :             }
    1903             :         }
    1904           1 :         columnHead(numColumns) = Total;
    1905          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1906          22 :             tableBody(jObj + 1, iYear) =
    1907          44 :                 RealToStr(elcc->CashFlow[CostCategory::TotEnergy].yrAmount(iYear) + elcc->CashFlow[CostCategory::Water].yrAmount(iYear), 2);
    1908             :         }
    1909           1 :         WriteSubtitle(state, "Energy and Water Cost Cash Flows (Without Escalation)");
    1910           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    1911           1 :         if (state.dataSQLiteProcedures->sqlite) {
    1912           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    1913             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Energy and Water Cost Cash Flows (Without Escalation)");
    1914             :         }
    1915           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    1916           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    1917             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Energy and Water Cost Cash Flows (Without Escalation)");
    1918             :         }
    1919           1 :         columnHead.deallocate();
    1920           1 :         rowHead.deallocate();
    1921           1 :         columnWidth.deallocate();
    1922           1 :         tableBody.deallocate();
    1923             :         //---- Energy and Water Cost Cash Flows (With Escalation)
    1924           1 :         numColumns = max(1, elcc->numResourcesUsed + 1);
    1925           1 :         rowHead.allocate(elcc->lengthStudyYears);
    1926           1 :         columnHead.allocate(numColumns);
    1927           1 :         columnWidth.dimension(numColumns, 14); // array assignment - same for all columns
    1928           1 :         tableBody.allocate(numColumns, elcc->lengthStudyYears);
    1929           1 :         tableBody = "";
    1930          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1931          22 :             rowHead(iYear) = format("{} {}", UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->baseDateMonth)], elcc->baseDateYear + iYear - 1);
    1932             :         }
    1933           2 :         for (jObj = 0; jObj < elcc->numResourcesUsed; ++jObj) {
    1934           1 :             curCashFlow = CostCategory::Num + elcc->numRecurringCosts + elcc->numNonrecurringCost + jObj;
    1935           1 :             columnHead(jObj + 1) = elcc->CashFlow[curCashFlow].name;
    1936           1 :             auto curResource = elcc->CashFlow[curCashFlow].Resource;
    1937           1 :             if (elcc->CashFlow[curCashFlow].Resource != DataGlobalConstants::ResourceType::Water) {
    1938          23 :                 for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1939          22 :                     tableBody(jObj + 1, iYear) = RealToStr(elcc->EscalatedEnergy.at(iYear).at(curResource), 2);
    1940             :                 }
    1941             :             } else { // for water just use the original cashflow since not involved in escalation
    1942           0 :                 for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1943           0 :                     tableBody(jObj + 1, iYear) = RealToStr(elcc->CashFlow[curCashFlow].yrAmount(iYear), 2);
    1944             :                 }
    1945             :             }
    1946             :         }
    1947           1 :         columnHead(numColumns) = Total;
    1948          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1949          22 :             tableBody(jObj + 1, iYear) = RealToStr(elcc->EscalatedTotEnergy(iYear) + elcc->CashFlow[CostCategory::Water].yrAmount(iYear), 2);
    1950             :         }
    1951           1 :         WriteSubtitle(state, "Energy and Water Cost Cash Flows (With Escalation)");
    1952           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    1953           1 :         if (state.dataSQLiteProcedures->sqlite) {
    1954           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    1955             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Energy and Water Cost Cash Flows (With Escalation)");
    1956             :         }
    1957           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    1958           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    1959             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Energy and Water Cost Cash Flows (With Escalation)");
    1960             :         }
    1961           1 :         columnHead.deallocate();
    1962           1 :         rowHead.deallocate();
    1963           1 :         columnWidth.deallocate();
    1964           1 :         tableBody.deallocate();
    1965             : 
    1966             :         //---- Capital Cash Flow by Category
    1967           1 :         rowHead.allocate(elcc->lengthStudyYears);
    1968           1 :         columnHead.allocate(4);
    1969           1 :         columnWidth.allocate(4);
    1970           1 :         columnWidth = 14; // array assignment - same for all columns
    1971           1 :         tableBody.allocate(4, elcc->lengthStudyYears);
    1972           1 :         tableBody = "";
    1973           4 :         for (int CostCategory = CostCategory::Construction, tableColumnIndex = 1; CostCategory <= CostCategory::OtherCapital;
    1974             :              ++tableColumnIndex, ++CostCategory) {
    1975           3 :             columnHead(tableColumnIndex) = CostCategoryNamesNoSpace[static_cast<int>(CostCategory)];
    1976             :         }
    1977           1 :         columnHead(4) = Total;
    1978          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    1979          22 :             rowHead(iYear) = format("{} {}", UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->baseDateMonth)], elcc->baseDateYear + iYear - 1);
    1980         110 :             for (int CostCategory = CostCategory::Construction, tableColumnIndex = 1; CostCategory <= CostCategory::TotCaptl;
    1981             :                  ++tableColumnIndex, ++CostCategory) {
    1982          88 :                 tableBody(tableColumnIndex, iYear) = RealToStr(elcc->CashFlow[CostCategory].yrAmount(iYear), 2);
    1983             :             }
    1984             :         }
    1985           1 :         WriteSubtitle(state, "Capital Cash Flow by Category (Without Escalation)");
    1986           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    1987           1 :         if (state.dataSQLiteProcedures->sqlite) {
    1988           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    1989             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Capital Cash Flow by Category (Without Escalation)");
    1990             :         }
    1991           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    1992           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    1993             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Capital Cash Flow by Category (Without Escalation)");
    1994             :         }
    1995           1 :         columnHead.deallocate();
    1996           1 :         rowHead.deallocate();
    1997           1 :         columnWidth.deallocate();
    1998           1 :         tableBody.deallocate();
    1999             :         //---- Operating Cash Flow by Category (Without Escalation)
    2000           1 :         rowHead.allocate(elcc->lengthStudyYears);
    2001           1 :         columnHead.allocate(10);
    2002           1 :         columnWidth.allocate(10);
    2003           1 :         columnWidth = 14; // array assignment - same for all columns
    2004           1 :         tableBody.allocate(10, elcc->lengthStudyYears);
    2005           1 :         tableBody = "";
    2006          10 :         for (int CostCategory = CostCategory::Maintenance, tableColumnIndex = 1; CostCategory <= CostCategory::Energy;
    2007             :              ++tableColumnIndex, ++CostCategory) {
    2008           9 :             columnHead(tableColumnIndex) = CostCategoryNamesNoSpace[CostCategory];
    2009             :         }
    2010           1 :         columnHead(10) = Total;
    2011             : 
    2012          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    2013          22 :             rowHead(iYear) = format("{} {}", UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->baseDateMonth)], elcc->baseDateYear + iYear - 1);
    2014         242 :             for (int CashFlowCostCategory = CostCategory::Maintenance; CashFlowCostCategory <= CostCategory::TotOper; ++CashFlowCostCategory) {
    2015         220 :                 tableBody(CashFlowCostCategory + 1, iYear) = RealToStr(elcc->CashFlow[CashFlowCostCategory].yrAmount(iYear), 2);
    2016             :             }
    2017             :         }
    2018           1 :         WriteSubtitle(state, "Operating Cash Flow by Category (Without Escalation)");
    2019           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    2020           1 :         if (state.dataSQLiteProcedures->sqlite) {
    2021           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    2022             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Operating Cash Flow by Category (Without Escalation)");
    2023             :         }
    2024           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    2025           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    2026             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Operating Cash Flow by Category (Without Escalation)");
    2027             :         }
    2028           1 :         columnHead.deallocate();
    2029           1 :         rowHead.deallocate();
    2030           1 :         columnWidth.deallocate();
    2031           1 :         tableBody.deallocate();
    2032             :         //---- Operating Cash Flow by Category (With Escalation)
    2033           1 :         rowHead.allocate(elcc->lengthStudyYears);
    2034           1 :         columnHead.allocate(10);
    2035           1 :         columnWidth.allocate(10);
    2036           1 :         columnWidth = 14; // array assignment - same for all columns
    2037           1 :         tableBody.allocate(10, elcc->lengthStudyYears);
    2038           1 :         tableBody = "";
    2039          10 :         for (int CostCategory = CostCategory::Maintenance, tableColumnIndex = 1; CostCategory <= CostCategory::Energy;
    2040             :              ++tableColumnIndex, ++CostCategory) {
    2041           9 :             columnHead(tableColumnIndex) = CostCategoryNamesNoSpace[CostCategory];
    2042             :         }
    2043           1 :         columnHead(10) = Total;
    2044             : 
    2045          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    2046          22 :             rowHead(iYear) = format("{} {}", UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->baseDateMonth)], elcc->baseDateYear + iYear - 1);
    2047         198 :             for (int CashFlowCostCategory = CostCategory::Maintenance; CashFlowCostCategory <= CostCategory::Water; ++CashFlowCostCategory) {
    2048         176 :                 tableBody(CashFlowCostCategory + 1, iYear) = RealToStr(elcc->CashFlow[CashFlowCostCategory].yrAmount(iYear), 2);
    2049             :             }
    2050          22 :             tableBody(9, iYear) = RealToStr(elcc->EscalatedTotEnergy(iYear), 2);
    2051          22 :             Real64 yearly_total_cost = elcc->CashFlow[CostCategory::TotOper].yrAmount(iYear) + elcc->EscalatedTotEnergy(iYear) -
    2052          22 :                                        elcc->CashFlow[CostCategory::TotEnergy].yrAmount(iYear);
    2053          22 :             tableBody(10, iYear) = RealToStr(yearly_total_cost, 2);
    2054             :         }
    2055           1 :         WriteSubtitle(state, "Operating Cash Flow by Category (With Escalation)");
    2056           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    2057           1 :         if (state.dataSQLiteProcedures->sqlite) {
    2058           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    2059             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Operating Cash Flow by Category (With Escalation)");
    2060             :         }
    2061           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    2062           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    2063             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Operating Cash Flow by Category (With Escalation)");
    2064             :         }
    2065           1 :         columnHead.deallocate();
    2066           1 :         rowHead.deallocate();
    2067           1 :         columnWidth.deallocate();
    2068           1 :         tableBody.deallocate();
    2069             :         //---- DEBUG ONLY - Monthly Cash Flows
    2070           1 :         bool showMonthlyCashFlows = false;
    2071           1 :         if (showMonthlyCashFlows) {
    2072           0 :             rowHead.allocate(elcc->lengthStudyTotalMonths);
    2073           0 :             columnHead.allocate(elcc->numCashFlow);
    2074           0 :             columnWidth.allocate(elcc->numCashFlow);
    2075           0 :             tableBody.allocate(elcc->numCashFlow, elcc->lengthStudyTotalMonths);
    2076           0 :             tableBody = "";
    2077           0 :             columnHead(1) = "mnt";
    2078           0 :             columnHead(2) = "rpr";
    2079           0 :             columnHead(3) = "opr";
    2080           0 :             columnHead(4) = "repl";
    2081           0 :             columnHead(5) = "mOvhl";
    2082           0 :             columnHead(6) = "MOvhl";
    2083           0 :             columnHead(7) = "oOpr";
    2084           0 :             columnHead(8) = "cons";
    2085           0 :             columnHead(9) = "slvg";
    2086           0 :             columnHead(10) = "oCap";
    2087           0 :             columnHead(11) = "H2O";
    2088           0 :             columnHead(12) = "ene";
    2089           0 :             columnHead(13) = "tEne";
    2090           0 :             columnHead(14) = "tOpr";
    2091           0 :             columnHead(15) = "tCap";
    2092           0 :             columnHead(16) = "Totl";
    2093           0 :             for (jObj = CostCategory::Num; jObj < elcc->numCashFlow; ++jObj) {
    2094           0 :                 columnHead(jObj + 1) = elcc->CashFlow[jObj].name;
    2095             :             }
    2096           0 :             for (kMonth = 1; kMonth <= elcc->lengthStudyTotalMonths; ++kMonth) {
    2097           0 :                 rowHead(kMonth) = format("{} {}",
    2098           0 :                                          UtilityRoutines::MonthNamesCC[static_cast<int>(1 + (kMonth + elcc->baseDateMonth - 2) % 12) - 1],
    2099           0 :                                          elcc->baseDateYear + int((kMonth - 1) / 12));
    2100             :             }
    2101           0 :             for (kMonth = 1; kMonth <= elcc->lengthStudyTotalMonths; ++kMonth) {
    2102           0 :                 for (jObj = 0; jObj < elcc->numCashFlow; ++jObj) {
    2103           0 :                     tableBody(jObj + 1, kMonth) = RealToStr(elcc->CashFlow[jObj].mnAmount(kMonth), 2);
    2104             :                 }
    2105             :             }
    2106           0 :             WriteSubtitle(state, "DEBUG ONLY - Monthly Cash Flows");
    2107           0 :             WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    2108           0 :             if (state.dataSQLiteProcedures->sqlite) {
    2109           0 :                 state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    2110             :                     tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "DEBUG ONLY - Monthly Cash Flows");
    2111             :             }
    2112           0 :             if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    2113           0 :                 state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    2114             :                     tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "DEBUG ONLY - Monthly Cash Flows");
    2115             :             }
    2116           0 :             columnHead.deallocate();
    2117           0 :             rowHead.deallocate();
    2118           0 :             columnWidth.deallocate();
    2119           0 :             tableBody.deallocate();
    2120             :         }
    2121             :         //---- Monthly Total Cash Flow
    2122           1 :         rowHead.allocate(elcc->lengthStudyYears);
    2123           1 :         columnHead.allocate(12);
    2124           1 :         columnWidth.allocate(12);
    2125           1 :         columnWidth = 14; // array assignment - same for all columns
    2126           1 :         tableBody.allocate(12, elcc->lengthStudyYears);
    2127           1 :         tableBody = "";
    2128          13 :         for (kMonth = 1; kMonth <= 12; ++kMonth) {
    2129          12 :             columnHead(kMonth) = UtilityRoutines::MonthNamesCC[static_cast<int>(kMonth - 1)];
    2130             :         }
    2131          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    2132          22 :             rowHead(iYear) = fmt::to_string(elcc->baseDateYear + iYear - 1);
    2133             :         }
    2134          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    2135         286 :             for (kMonth = 1; kMonth <= 12; ++kMonth) {
    2136         264 :                 tableBody(kMonth, iYear) = RealToStr(elcc->CashFlow[CostCategory::TotGrand].mnAmount((iYear - 1) * 12 + kMonth), 2);
    2137             :             }
    2138             :         }
    2139           1 :         WriteSubtitle(state, "Monthly Total Cash Flow (Without Escalation)");
    2140           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    2141           1 :         if (state.dataSQLiteProcedures->sqlite) {
    2142           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    2143             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Monthly Total Cash Flow (Without Escalation)");
    2144             :         }
    2145           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    2146           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    2147             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Monthly Total Cash Flow (Without Escalation)");
    2148             :         }
    2149           1 :         columnHead.deallocate();
    2150           1 :         rowHead.deallocate();
    2151           1 :         columnWidth.deallocate();
    2152           1 :         tableBody.deallocate();
    2153             :         //---- Present Value for Recurring, Nonrecurring and Energy Costs
    2154           1 :         numRows = max(1, elcc->numRecurringCosts + elcc->numNonrecurringCost + elcc->numResourcesUsed);
    2155           1 :         rowHead.allocate(numRows + 1);
    2156           1 :         columnHead.allocate(5);
    2157           1 :         columnWidth.allocate(5);
    2158           1 :         columnWidth = 14; // array assignment - same for all columns
    2159           1 :         tableBody.allocate(5, numRows + 1);
    2160           1 :         tableBody = "";
    2161           1 :         columnHead(1) = "Category";
    2162           1 :         columnHead(2) = "Kind";
    2163           1 :         columnHead(3) = "Cost";
    2164           1 :         columnHead(4) = "Present Value";
    2165           1 :         columnHead(5) = "Present Value Factor";
    2166           1 :         totalPV = 0.0;
    2167           1 :         rowHead(numRows + 1) = TotalUC;
    2168           8 :         for (jObj = 0; jObj < (elcc->numRecurringCosts + elcc->numNonrecurringCost + elcc->numResourcesUsed); ++jObj) {
    2169           7 :             offset = CostCategory::Num;
    2170           7 :             rowHead(jObj + 1) = elcc->CashFlow[offset + jObj].name;
    2171           7 :             switch (elcc->CashFlow[offset + jObj].Category) {
    2172           7 :             case CostCategory::Maintenance:
    2173             :             case CostCategory::Repair:
    2174             :             case CostCategory::Operation:
    2175             :             case CostCategory::Replacement:
    2176             :             case CostCategory::MinorOverhaul:
    2177             :             case CostCategory::MajorOverhaul:
    2178             :             case CostCategory::OtherOperational:
    2179             :             case CostCategory::Construction:
    2180             :             case CostCategory::Salvage:
    2181             :             case CostCategory::OtherCapital:
    2182             :             case CostCategory::Water:
    2183             :             case CostCategory::Energy: {
    2184           7 :                 tableBody(1, jObj + 1) = CostCategoryNames[static_cast<int>(elcc->CashFlow[offset + jObj].Category)];
    2185           7 :                 break;
    2186             :             }
    2187           0 :             default:
    2188           0 :                 tableBody(1, jObj + 1) = "-";
    2189           0 :                 break;
    2190             :             }
    2191           7 :             switch (elcc->CashFlow[offset + jObj].SourceKind) {
    2192           6 :             case SourceKindType::Nonrecurring:
    2193             :             case SourceKindType::Recurring: {
    2194           6 :                 tableBody(2, jObj + 1) = SourceKindTypeNames[static_cast<int>(elcc->CashFlow[offset + jObj].SourceKind)];
    2195           6 :                 break;
    2196             :             }
    2197           1 :             case SourceKindType::Resource: {
    2198           1 :                 if (elcc->CashFlow[offset + jObj].Category == CostCategory::Water) {
    2199           0 :                     tableBody(2, jObj + 1) = ResourceCostCategoryNames[static_cast<int>(ResourceCostCategory::Water)];
    2200             :                 } else {
    2201           1 :                     tableBody(2, jObj + 1) = ResourceCostCategoryNames[static_cast<int>(ResourceCostCategory::Energy)];
    2202             :                 }
    2203           1 :                 break;
    2204             :             }
    2205           0 :             default: {
    2206           0 :                 tableBody(2, jObj + 1) = "-";
    2207           0 :                 break;
    2208             :             }
    2209             :             }
    2210           7 :             tableBody(3, jObj + 1) = RealToStr(elcc->CashFlow[offset + jObj].orginalCost, 2);
    2211           7 :             tableBody(4, jObj + 1) = RealToStr(elcc->CashFlow[offset + jObj].presentValue, 2);
    2212           7 :             totalPV += elcc->CashFlow[offset + jObj].presentValue;
    2213           7 :             if (elcc->CashFlow[offset + jObj].orginalCost != 0.0) {
    2214           7 :                 tableBody(5, jObj + 1) = RealToStr(elcc->CashFlow[offset + jObj].presentValue / elcc->CashFlow[offset + jObj].orginalCost, 4);
    2215             :             } else {
    2216           0 :                 tableBody(5, jObj + 1) = "-";
    2217             :             }
    2218             :         }
    2219           1 :         tableBody(4, numRows + 1) = RealToStr(totalPV, 2);
    2220           1 :         WriteSubtitle(state, "Present Value for Recurring, Nonrecurring and Energy Costs (Before Tax)");
    2221           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    2222           1 :         if (state.dataSQLiteProcedures->sqlite) {
    2223           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    2224             :                 tableBody,
    2225             :                 rowHead,
    2226             :                 columnHead,
    2227             :                 "Life-Cycle Cost Report",
    2228             :                 "Entire Facility",
    2229             :                 "Present Value for Recurring, Nonrecurring and Energy Costs (Before Tax)");
    2230             :         }
    2231           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    2232           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    2233             :                 tableBody,
    2234             :                 rowHead,
    2235             :                 columnHead,
    2236             :                 "Life-Cycle Cost Report",
    2237             :                 "Entire Facility",
    2238             :                 "Present Value for Recurring, Nonrecurring and Energy Costs (Before Tax)");
    2239             :         }
    2240           1 :         columnHead.deallocate();
    2241           1 :         rowHead.deallocate();
    2242           1 :         columnWidth.deallocate();
    2243           1 :         tableBody.deallocate();
    2244             :         //---- Present Value by Category
    2245           1 :         rowHead.allocate(16);
    2246           1 :         columnHead.allocate(1);
    2247           1 :         columnWidth.allocate(1);
    2248           1 :         columnWidth = 14; // array assignment - same for all columns
    2249           1 :         tableBody.allocate(1, 16);
    2250           1 :         tableBody = "";
    2251          17 :         for (int CashFlowCostCategory = CostCategory::Maintenance; CashFlowCostCategory <= CostCategory::TotGrand; ++CashFlowCostCategory) {
    2252          16 :             rowHead(CashFlowCostCategory + 1) = CostCategoryNames[CashFlowCostCategory];
    2253             :         }
    2254           1 :         columnHead(1) = "Present Value";
    2255             : 
    2256          17 :         for (int CashFlowCostCategory = CostCategory::Maintenance; CashFlowCostCategory <= CostCategory::TotGrand; ++CashFlowCostCategory) {
    2257          16 :             tableBody(1, CashFlowCostCategory + 1) = RealToStr(elcc->CashFlow[CashFlowCostCategory].presentValue, 2);
    2258             :         }
    2259             : 
    2260           1 :         WriteSubtitle(state, "Present Value by Category");
    2261           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    2262           1 :         if (state.dataSQLiteProcedures->sqlite) {
    2263           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    2264             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Present Value by Category");
    2265             :         }
    2266           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    2267           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    2268             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Present Value by Category");
    2269             :         }
    2270           1 :         columnHead.deallocate();
    2271           1 :         rowHead.deallocate();
    2272           1 :         columnWidth.deallocate();
    2273           1 :         tableBody.deallocate();
    2274             :         //---- Present Value by Year
    2275           1 :         rowHead.allocate(elcc->lengthStudyYears + 1);
    2276           1 :         columnHead.allocate(3);
    2277           1 :         columnWidth.allocate(3);
    2278           1 :         columnWidth = 14; // array assignment - same for all columns
    2279           1 :         tableBody.allocate(3, elcc->lengthStudyYears + 1);
    2280           1 :         tableBody = "";
    2281           1 :         columnHead(1) = "Total Cost (Without Escalation)";
    2282           1 :         columnHead(2) = "Total Cost (With Escalation)";
    2283           1 :         columnHead(3) = "Present Value of Costs";
    2284             : 
    2285           1 :         totalPV = 0.0;
    2286          23 :         for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    2287          22 :             rowHead(iYear) = format("{} {}", UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->baseDateMonth)], elcc->baseDateYear + iYear - 1);
    2288          22 :             tableBody(1, iYear) = RealToStr(elcc->CashFlow[CostCategory::TotGrand].yrAmount(iYear), 2);
    2289             :             // adjust for escalated energy costs
    2290          22 :             Real64 yearly_total_cost = elcc->CashFlow[CostCategory::TotGrand].yrAmount(iYear) + elcc->EscalatedTotEnergy(iYear) -
    2291          22 :                                        elcc->CashFlow[CostCategory::TotEnergy].yrAmount(iYear);
    2292          22 :             tableBody(2, iYear) = RealToStr(yearly_total_cost, 2);
    2293          22 :             tableBody(3, iYear) = RealToStr(elcc->CashFlow[CostCategory::TotGrand].yrPresVal(iYear), 2);
    2294          22 :             totalPV += elcc->CashFlow[CostCategory::TotGrand].yrPresVal(iYear);
    2295             :         }
    2296             : 
    2297           1 :         rowHead(elcc->lengthStudyYears + 1) = TotalUC;
    2298           1 :         tableBody(3, elcc->lengthStudyYears + 1) = RealToStr(totalPV, 2);
    2299             : 
    2300           1 :         WriteSubtitle(state, "Present Value by Year");
    2301           1 :         WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    2302           1 :         if (state.dataSQLiteProcedures->sqlite) {
    2303           0 :             state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    2304             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Present Value by Year");
    2305             :         }
    2306           1 :         if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    2307           0 :             state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    2308             :                 tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "Present Value by Year");
    2309             :         }
    2310           1 :         columnHead.deallocate();
    2311           1 :         rowHead.deallocate();
    2312           1 :         columnWidth.deallocate();
    2313           1 :         tableBody.deallocate();
    2314             :         //---- After Tax Estimate
    2315           1 :         if (elcc->taxRate != 0.0) {
    2316           0 :             rowHead.allocate(elcc->lengthStudyYears + 1);
    2317           0 :             columnHead.allocate(5);
    2318           0 :             columnWidth.allocate(5);
    2319           0 :             columnWidth = 14; // array assignment - same for all columns
    2320           0 :             tableBody.allocate(5, elcc->lengthStudyYears + 1);
    2321           0 :             tableBody = "";
    2322           0 :             columnHead(1) = "Depreciated Capital";
    2323           0 :             columnHead(2) = "Taxable Income";
    2324           0 :             columnHead(3) = "Income Taxes";
    2325           0 :             columnHead(4) = "After Tax Cash Flow";
    2326           0 :             columnHead(5) = "After Tax Present Value";
    2327             : 
    2328           0 :             totalPV = 0.0;
    2329           0 :             for (iYear = 1; iYear <= elcc->lengthStudyYears; ++iYear) {
    2330           0 :                 rowHead(iYear) =
    2331           0 :                     format("{} {}", UtilityRoutines::MonthNamesCC[static_cast<int>(elcc->baseDateMonth)], elcc->baseDateYear + iYear - 1);
    2332           0 :                 tableBody(1, iYear) = RealToStr(elcc->DepreciatedCapital(iYear), 2);
    2333           0 :                 tableBody(2, iYear) = RealToStr(elcc->TaxableIncome(iYear), 2);
    2334           0 :                 tableBody(3, iYear) = RealToStr(elcc->Taxes(iYear), 2);
    2335           0 :                 tableBody(4, iYear) = RealToStr(elcc->AfterTaxCashFlow(iYear), 2);
    2336           0 :                 tableBody(5, iYear) = RealToStr(elcc->AfterTaxPresentValue(iYear), 2);
    2337           0 :                 totalPV += elcc->AfterTaxPresentValue(iYear);
    2338             :             }
    2339             : 
    2340           0 :             rowHead(elcc->lengthStudyYears + 1) = TotalUC;
    2341           0 :             tableBody(5, elcc->lengthStudyYears + 1) = RealToStr(totalPV, 2);
    2342             : 
    2343           0 :             WriteSubtitle(state, "After Tax Estimate");
    2344           0 :             WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
    2345           0 :             if (state.dataSQLiteProcedures->sqlite) {
    2346           0 :                 state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
    2347             :                     tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "After Tax Estimate");
    2348             :             }
    2349           0 :             if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
    2350           0 :                 state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
    2351             :                     tableBody, rowHead, columnHead, "Life-Cycle Cost Report", "Entire Facility", "After Tax Estimate");
    2352             :             }
    2353           0 :             columnHead.deallocate();
    2354           0 :             rowHead.deallocate();
    2355           0 :             columnWidth.deallocate();
    2356           0 :             tableBody.deallocate();
    2357             :         }
    2358             :     }
    2359           1 : }
    2360             : 
    2361        2313 : } // namespace EnergyPlus::EconomicLifeCycleCost

Generated by: LCOV version 1.13