LCOV - code coverage report
Current view: top level - EnergyPlus - MicroturbineElectricGenerator.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 517 986 52.4 %
Date: 2023-01-17 19:17:23 Functions: 11 11 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/Array.functions.hh>
      53             : #include <ObjexxFCL/Fmath.hh>
      54             : 
      55             : // EnergyPlus Headers
      56             : #include <EnergyPlus/BranchNodeConnections.hh>
      57             : #include <EnergyPlus/CurveManager.hh>
      58             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      59             : #include <EnergyPlus/DataEnvironment.hh>
      60             : #include <EnergyPlus/DataHVACGlobals.hh>
      61             : #include <EnergyPlus/DataIPShortCuts.hh>
      62             : #include <EnergyPlus/DataLoopNode.hh>
      63             : #include <EnergyPlus/DataPrecisionGlobals.hh>
      64             : #include <EnergyPlus/FluidProperties.hh>
      65             : #include <EnergyPlus/General.hh>
      66             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      67             : #include <EnergyPlus/MicroturbineElectricGenerator.hh>
      68             : #include <EnergyPlus/NodeInputManager.hh>
      69             : #include <EnergyPlus/OutAirNodeManager.hh>
      70             : #include <EnergyPlus/OutputProcessor.hh>
      71             : #include <EnergyPlus/Plant/DataPlant.hh>
      72             : #include <EnergyPlus/PlantUtilities.hh>
      73             : #include <EnergyPlus/Psychrometrics.hh>
      74             : #include <EnergyPlus/UtilityRoutines.hh>
      75             : 
      76             : namespace EnergyPlus::MicroturbineElectricGenerator {
      77             : 
      78             : // MODULE INFORMATION:
      79             : //       AUTHOR         R. Raustad/D. Shirey
      80             : //       DATE WRITTEN   Mar 2008
      81             : //       MODIFIED       na
      82             : //       RE-ENGINEERED  na
      83             : 
      84             : // PURPOSE OF THIS MODULE:
      85             : //  This module simulates the performance of microturbine electric
      86             : //  generators.
      87             : 
      88             : // METHODOLOGY EMPLOYED:
      89             : //  Once the electric power manager determines that the MT Generator
      90             : //  is available, it calls SimMTGenerator which in turn calls the
      91             : //  appropriate microturbine generator model.
      92             : //  MT Generator models are based on polynomial curve fits of generator
      93             : //  performance data.
      94             : 
      95       52099 : PlantComponent *MTGeneratorSpecs::factory(EnergyPlusData &state, std::string const &objectName)
      96             : {
      97             :     // Process the input data for generator if it hasn't been done already
      98       52099 :     if (state.dataMircoturbElectGen->GetMTInput) {
      99           6 :         GetMTGeneratorInput(state);
     100           6 :         state.dataMircoturbElectGen->GetMTInput = false;
     101             :     }
     102             : 
     103             :     // Now look for this particular gen in the list
     104       52099 :     for (auto &thisMTG : state.dataMircoturbElectGen->MTGenerator) {
     105       52099 :         if (thisMTG.Name == objectName) {
     106       52099 :             return &thisMTG;
     107             :         }
     108             :     }
     109             :     // If we didn't find it, fatal
     110           0 :     ShowFatalError(state,
     111             :                    "LocalMicroTurbineGeneratorFactory: Error getting inputs for microturbine generator named: " + objectName); // LCOV_EXCL_LINE
     112             :     // Shut up the compiler
     113             :     return nullptr; // LCOV_EXCL_LINE
     114             : }
     115             : 
     116           6 : void GetMTGeneratorInput(EnergyPlusData &state)
     117             : {
     118             :     // SUBROUTINE INFORMATION:
     119             :     //       AUTHOR         R. Raustad/D. Shirey
     120             :     //       DATE WRITTEN   Mar 2008
     121             :     //       MODIFIED       na
     122             :     //       RE-ENGINEERED  na
     123             : 
     124             :     // PURPOSE OF THIS SUBROUTINE:
     125             :     //  This routine gets the input information for the Microturbine (MT) Generator model.
     126             : 
     127           6 :     bool ErrorsFound(false);
     128             : 
     129           6 :     state.dataIPShortCut->cCurrentModuleObject = "Generator:MicroTurbine";
     130           6 :     state.dataMircoturbElectGen->NumMTGenerators =
     131           6 :         state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
     132             : 
     133           6 :     if (state.dataMircoturbElectGen->NumMTGenerators <= 0) {
     134           0 :         ShowSevereError(state, "No " + state.dataIPShortCut->cCurrentModuleObject + " equipment specified in input file");
     135           0 :         ErrorsFound = true;
     136             :     }
     137             : 
     138             :     // ALLOCATE ARRAYS
     139           6 :     state.dataMircoturbElectGen->MTGenerator.allocate(state.dataMircoturbElectGen->NumMTGenerators);
     140             : 
     141             :     // LOAD ARRAYS WITH MICROTURBINE GENERATOR DATA
     142          12 :     for (int GeneratorNum = 1; GeneratorNum <= state.dataMircoturbElectGen->NumMTGenerators; ++GeneratorNum) {
     143             :         int NumAlphas;
     144             :         int NumNums;
     145             :         int IOStat;
     146          12 :         Array1D<Real64> NumArray(19);
     147          12 :         Array1D_string AlphArray(20);
     148          36 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     149           6 :                                                                  state.dataIPShortCut->cCurrentModuleObject,
     150             :                                                                  GeneratorNum,
     151             :                                                                  AlphArray,
     152             :                                                                  NumAlphas,
     153             :                                                                  NumArray,
     154             :                                                                  NumNums,
     155             :                                                                  IOStat,
     156           6 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     157           6 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     158           6 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     159           6 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     160           6 :         UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
     161           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name = AlphArray(1);
     162             : 
     163           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecPowerOutput = NumArray(1);
     164           6 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecPowerOutput <= 0.0) {
     165           0 :             ShowSevereError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(1), NumArray(1)));
     166           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     167           0 :             ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(1) + " must be greater than 0.");
     168           0 :             ErrorsFound = true;
     169             :         }
     170             : 
     171           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MinElecPowerOutput = NumArray(2);
     172           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MaxElecPowerOutput = NumArray(3);
     173             : 
     174           6 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MinElecPowerOutput < 0.0) {
     175           0 :             ShowSevereError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(2), NumArray(2)));
     176           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     177           0 :             ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(2) + " must be greater than 0.");
     178           0 :             ErrorsFound = true;
     179             :         }
     180             : 
     181           6 :         if (state.dataIPShortCut->lNumericFieldBlanks(3)) {
     182           0 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MaxElecPowerOutput =
     183           0 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecPowerOutput;
     184             :         } else {
     185           6 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MaxElecPowerOutput <= 0.0) {
     186           0 :                 ShowSevereError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(3), NumArray(3)));
     187           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     188           0 :                 ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(3) + " must be greater than 0.");
     189           0 :                 ErrorsFound = true;
     190             :             }
     191             :         }
     192             : 
     193          12 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MinElecPowerOutput >=
     194           6 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MaxElecPowerOutput) {
     195           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "= " + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name);
     196           0 :             ShowContinueError(state,
     197           0 :                               format("{} [{:.2R}] > {} [{:.2R}]",
     198           0 :                                      state.dataIPShortCut->cNumericFieldNames(2),
     199             :                                      NumArray(2),
     200           0 :                                      state.dataIPShortCut->cNumericFieldNames(3),
     201           0 :                                      NumArray(3)));
     202           0 :             ShowContinueError(state, "Minimum Full Load Electrical Power Output must be less than or equal");
     203           0 :             ShowContinueError(state, "to Maximum Full Load Electrical Power Output.");
     204           0 :             ErrorsFound = true;
     205             :         }
     206             : 
     207          12 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecPowerOutput >
     208          12 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MaxElecPowerOutput ||
     209           6 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecPowerOutput <
     210           6 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MinElecPowerOutput) {
     211           0 :             ShowSevereError(state, state.dataIPShortCut->cCurrentModuleObject + "= " + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name);
     212           0 :             ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(1) + " must be >= " + state.dataIPShortCut->cNumericFieldNames(2));
     213           0 :             ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(1) + " must be <= " + state.dataIPShortCut->cNumericFieldNames(3));
     214           0 :             ShowContinueError(state, format("{} = {:.2R}", state.dataIPShortCut->cNumericFieldNames(1), NumArray(1)));
     215           0 :             ShowContinueError(state, format("{} = {:.2R}", state.dataIPShortCut->cNumericFieldNames(2), NumArray(2)));
     216           0 :             ShowContinueError(state, format("{} = {:.2R}", state.dataIPShortCut->cNumericFieldNames(3), NumArray(3)));
     217           0 :             ErrorsFound = true;
     218             :         }
     219             : 
     220           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecEfficiencyLHV = NumArray(4);
     221             : 
     222           6 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecEfficiencyLHV <= 0.0) {
     223           0 :             ShowSevereError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(4), NumArray(4)));
     224           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     225           0 :             ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(4) + " must be greater than 0.");
     226           0 :             ErrorsFound = true;
     227             :         }
     228             : 
     229           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp = NumArray(5);
     230           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletHumRat = NumArray(6);
     231           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElevation = NumArray(7);
     232             : 
     233           6 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletHumRat <= 0.0) {
     234           0 :             ShowSevereError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(6), NumArray(6)));
     235           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     236           0 :             ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(6) + " must be greater than 0.");
     237           0 :             ErrorsFound = true;
     238             :         } else {
     239             :             // Reference barometric pressure, adjusted for reference elevation (Pa)
     240             :             Real64 RefBaroPressure =
     241           6 :                 101325.0 * std::pow(1.0 - 2.25577e-05 * state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElevation, 5.2559);
     242           6 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletDensity =
     243          18 :                 Psychrometrics::PsyRhoAirFnPbTdbW(state,
     244             :                                                   RefBaroPressure,
     245           6 :                                                   state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp,
     246           6 :                                                   state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletHumRat);
     247             :         }
     248             : 
     249           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ElecPowFTempElevCurveNum =
     250           6 :             Curve::GetCurveIndex(state, AlphArray(2)); // Convert curve name to number
     251           6 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ElecPowFTempElevCurveNum == 0) {
     252           0 :             ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(2) + '=' + AlphArray(2));
     253           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     254           0 :             ErrorsFound = true;
     255             :         } else {
     256             :             // Verify curve object, only legal type is BiQuadratic
     257             : 
     258           6 :             if (!ErrorsFound) {
     259             :                 // Check electrical power output at reference combustion inlet temp and elevation
     260             :                 // Output of Electrical Power Output Modifier Curve (function of temp and elev)
     261          30 :                 Real64 ElectOutFTempElevOutput = Curve::CurveValue(state,
     262           6 :                                                                    state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ElecPowFTempElevCurveNum,
     263           6 :                                                                    state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp,
     264          12 :                                                                    state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElevation);
     265           6 :                 if (std::abs(ElectOutFTempElevOutput - 1.0) > 0.1) {
     266           0 :                     ShowWarningError(state,
     267           0 :                                      state.dataIPShortCut->cCurrentModuleObject + " \"" +
     268           0 :                                          state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     269           0 :                     ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(2) + " = " + AlphArray(2));
     270           0 :                     ShowContinueError(state, "...Curve output at reference conditions should equal 1 (+-10%).");
     271           0 :                     ShowContinueError(state,
     272           0 :                                       format("...Reference combustion air inlet temperature = {:.4T} C",
     273           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp));
     274           0 :                     ShowContinueError(state,
     275           0 :                                       format("...Reference elevation                        = {:.4T} m",
     276           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElevation));
     277           0 :                     ShowContinueError(state, format("...Curve output                               = {:.4T}", ElectOutFTempElevOutput));
     278             :                 }
     279             :             }
     280             :         }
     281             : 
     282           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ElecEffFTempCurveNum =
     283           6 :             Curve::GetCurveIndex(state, AlphArray(3)); // Convert curve name to number
     284           6 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ElecEffFTempCurveNum == 0) {
     285           0 :             ShowSevereError(state,
     286           0 :                             state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     287           0 :             ShowSevereError(state, state.dataIPShortCut->cAlphaFieldNames(3) + " not found = " + AlphArray(3));
     288           0 :             ErrorsFound = true;
     289             :         } else {
     290             :             // Verify curve object, only legal types are Quadratic and Cubic
     291             : 
     292           6 :             if (!ErrorsFound) {
     293             :                 // Check electrical efficiency at reference combustion inlet temp
     294             :                 // Output of Electrical Efficiency Modifier Curve (function of temp)
     295          24 :                 Real64 ElecEfficFTempOutput = Curve::CurveValue(state,
     296           6 :                                                                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ElecEffFTempCurveNum,
     297          12 :                                                                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp);
     298           6 :                 if (std::abs(ElecEfficFTempOutput - 1.0) > 0.1) {
     299           0 :                     ShowWarningError(state,
     300           0 :                                      state.dataIPShortCut->cCurrentModuleObject + " \"" +
     301           0 :                                          state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     302           0 :                     ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(3) + " = " + AlphArray(3));
     303           0 :                     ShowContinueError(state, "... Curve output at reference condition should equal 1 (+-10%).");
     304           0 :                     ShowContinueError(state,
     305           0 :                                       format("... Reference combustion air inlet temperature = {:.4T} C",
     306           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp));
     307           0 :                     ShowContinueError(state, format("... Curve output                               = {:.4T}", ElecEfficFTempOutput));
     308             :                 }
     309             :             }
     310             :         }
     311             : 
     312           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ElecEffFPLRCurveNum =
     313           6 :             Curve::GetCurveIndex(state, AlphArray(4)); // Convert curve name to number
     314           6 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ElecEffFPLRCurveNum == 0) {
     315           0 :             ShowSevereError(state,
     316           0 :                             state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     317           0 :             ShowSevereError(state, state.dataIPShortCut->cAlphaFieldNames(4) + " not found = " + AlphArray(4));
     318           0 :             ErrorsFound = true;
     319             :         } else {
     320             :             // Verify curve object, only legal types are Quadratic and Cubic
     321             : 
     322           6 :             if (!ErrorsFound) {
     323             :                 // Check electrical efficiency at PLR = 1
     324             :                 // Output of Electrical Efficiency Modifier Curve (function of PLR)
     325             :                 Real64 ElecEfficFPLROutput =
     326           6 :                     Curve::CurveValue(state, state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ElecEffFPLRCurveNum, 1.0);
     327           6 :                 if (std::abs(ElecEfficFPLROutput - 1.0) > 0.1) {
     328           0 :                     ShowWarningError(state,
     329           0 :                                      state.dataIPShortCut->cCurrentModuleObject + " \"" +
     330           0 :                                          state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     331           0 :                     ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(4) + " = " + AlphArray(4));
     332           0 :                     ShowContinueError(state, "... Curve output at a part-load ratio of 1 should equal 1 (+-10%).");
     333           0 :                     ShowContinueError(state, format("... Curve output = {:.4T}", ElecEfficFPLROutput));
     334             :                 }
     335             : 
     336           6 :                 Real64 Var1Min(0.0);
     337           6 :                 Real64 Var1Max(0.0);
     338           6 :                 Curve::GetCurveMinMaxValues(state, state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ElecEffFPLRCurveNum, Var1Min, Var1Max);
     339           6 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MinPartLoadRat = Var1Min;
     340           6 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MaxPartLoadRat = Var1Max;
     341             :             }
     342             :         }
     343             : 
     344             :         // Validate fuel type input
     345           6 :         bool FuelTypeError(false);
     346           6 :         UtilityRoutines::ValidateFuelType(state, AlphArray(5), state.dataMircoturbElectGen->MTGenerator(GeneratorNum).FuelType, FuelTypeError);
     347           6 :         if (FuelTypeError) {
     348           0 :             ShowSevereError(state,
     349           0 :                             state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     350           0 :             ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(5) + "  = " + AlphArray(5));
     351           0 :             ErrorsFound = true;
     352           0 :             FuelTypeError = false;
     353             :         }
     354             : 
     355           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).FuelHigherHeatingValue = NumArray(8);
     356           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).FuelLowerHeatingValue = NumArray(9);
     357             : 
     358           6 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).FuelLowerHeatingValue <= 0.0) {
     359           0 :             ShowSevereError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(9), NumArray(9)));
     360           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     361           0 :             ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(9) + " must be greater than 0.");
     362           0 :             ErrorsFound = true;
     363             :         }
     364             : 
     365           6 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).FuelHigherHeatingValue <= 0.0) {
     366           0 :             ShowSevereError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(8), NumArray(8)));
     367           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     368           0 :             ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(8) + " must be greater than 0.");
     369           0 :             ErrorsFound = true;
     370             :         }
     371             : 
     372          12 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).FuelLowerHeatingValue >
     373           6 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).FuelHigherHeatingValue) {
     374           0 :             ShowSevereError(state,
     375           0 :                             state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     376           0 :             ShowContinueError(
     377           0 :                 state, state.dataIPShortCut->cNumericFieldNames(8) + " must be greater than the " + state.dataIPShortCut->cNumericFieldNames(9));
     378           0 :             ShowContinueError(state, format("{}={:.2R}", state.dataIPShortCut->cNumericFieldNames(8), NumArray(8)));
     379           0 :             ShowContinueError(state, format("{}={:.2R}", state.dataIPShortCut->cNumericFieldNames(9), NumArray(9)));
     380           0 :             ErrorsFound = true;
     381             :         }
     382             : 
     383           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).StandbyPower = NumArray(10);
     384           6 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).StandbyPower < 0.0) {
     385           0 :             ShowWarningError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(10), NumArray(10)));
     386           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     387           0 :             ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(10) + " must be greater than 0.");
     388           0 :             ShowContinueError(state, "Resetting to 0 and the simulation continues.");
     389           0 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).StandbyPower = 0.0;
     390             :         }
     391             : 
     392           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).AncillaryPower = NumArray(11);
     393           6 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).AncillaryPower < 0.0) {
     394           0 :             ShowWarningError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(11), NumArray(11)));
     395           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     396           0 :             ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(11) + " must be greater than 0.");
     397           0 :             ShowContinueError(state, "Resetting to 0 and the simulation continues.");
     398           0 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).AncillaryPower = 0.0;
     399             :         }
     400             : 
     401           6 :         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).AncillaryPowerFuelCurveNum =
     402           6 :             Curve::GetCurveIndex(state, AlphArray(6)); // Convert curve name to number
     403             :         //   If blank, then the calc routine assumes modifier curve value = 1 for entire simulation
     404           6 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(6) && state.dataMircoturbElectGen->MTGenerator(GeneratorNum).AncillaryPowerFuelCurveNum == 0) {
     405           0 :             ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(6) + '=' + AlphArray(6));
     406           0 :             ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     407           0 :             ErrorsFound = true;
     408           6 :         } else if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).AncillaryPowerFuelCurveNum > 0) {
     409             :             // Verify curve object, only legal type is Quadratic
     410             : 
     411           0 :             if (!ErrorsFound) {
     412             :                 // Fuel mass flow rate at reference conditions (kg/s)
     413           0 :                 Real64 RefFuelUseMdot = (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecPowerOutput /
     414           0 :                                          state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecEfficiencyLHV) /
     415           0 :                                         (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).FuelLowerHeatingValue * 1000.0);
     416             :                 // Output of Ancillary Power Modifer Curve (function of temps and fuel flow)
     417             :                 Real64 AncillaryPowerOutput =
     418           0 :                     Curve::CurveValue(state, state.dataMircoturbElectGen->MTGenerator(GeneratorNum).AncillaryPowerFuelCurveNum, RefFuelUseMdot);
     419           0 :                 if (std::abs(AncillaryPowerOutput - 1.0) > 0.1) {
     420           0 :                     ShowWarningError(state,
     421           0 :                                      state.dataIPShortCut->cCurrentModuleObject + " \"" +
     422           0 :                                          state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     423           0 :                     ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(6) + " = " + AlphArray(6));
     424           0 :                     ShowContinueError(state, "... Curve output at reference conditions should equal 1 (+-10%).");
     425           0 :                     ShowContinueError(state,
     426           0 :                                       format("... Reference Electrical Power Output           = {:.2T} W",
     427           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecPowerOutput));
     428           0 :                     ShowContinueError(state,
     429           0 :                                       format("... Reference Electrical Efficiency (LHV basis) = {:.4T}",
     430           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecEfficiencyLHV));
     431           0 :                     ShowContinueError(state,
     432           0 :                                       format("... Fuel Lower Heating Value                    = {:.2T} kJ/kg",
     433           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).FuelLowerHeatingValue));
     434           0 :                     ShowContinueError(state, format("... Calculated fuel flow                        = {:.4T} kg/s", RefFuelUseMdot));
     435           0 :                     ShowContinueError(state, format("... Curve output                                = {:.4T}", AncillaryPowerOutput));
     436             :                 }
     437             :             }
     438             :         }
     439             : 
     440           6 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) {
     441           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecInletNodeNum =
     442           6 :                 NodeInputManager::GetOnlySingleNode(state,
     443           2 :                                                     AlphArray(7),
     444             :                                                     ErrorsFound,
     445             :                                                     DataLoopNode::ConnectionObjectType::GeneratorMicroTurbine,
     446           2 :                                                     state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name,
     447             :                                                     DataLoopNode::NodeFluidType::Water,
     448             :                                                     DataLoopNode::ConnectionType::Inlet,
     449             :                                                     NodeInputManager::CompFluidStream::Primary,
     450           2 :                                                     DataLoopNode::ObjectIsNotParent);
     451             :         }
     452             : 
     453           6 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) {
     454           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecOutletNodeNum =
     455           6 :                 NodeInputManager::GetOnlySingleNode(state,
     456           2 :                                                     AlphArray(8),
     457             :                                                     ErrorsFound,
     458             :                                                     DataLoopNode::ConnectionObjectType::GeneratorMicroTurbine,
     459           2 :                                                     state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name,
     460             :                                                     DataLoopNode::NodeFluidType::Water,
     461             :                                                     DataLoopNode::ConnectionType::Outlet,
     462             :                                                     NodeInputManager::CompFluidStream::Primary,
     463           2 :                                                     DataLoopNode::ObjectIsNotParent);
     464             :         }
     465             : 
     466           8 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecInletNodeNum > 0 &&
     467           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecOutletNodeNum > 0) {
     468           6 :             BranchNodeConnections::TestCompSet(state,
     469           2 :                                                state.dataIPShortCut->cCurrentModuleObject,
     470           2 :                                                state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name,
     471           2 :                                                AlphArray(7),
     472           2 :                                                AlphArray(8),
     473             :                                                "Heat Recovery Nodes");
     474             :         }
     475             : 
     476          14 :         if ((state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecOutletNodeNum > 0 &&
     477          12 :              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecInletNodeNum == 0) ||
     478          10 :             (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecOutletNodeNum == 0 &&
     479           4 :              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecInletNodeNum > 0)) {
     480           0 :             ShowSevereError(state,
     481           0 :                             state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     482           0 :             ShowContinueError(state, "... If one Heat Recovery Water Node Name is specified, then both the Inlet and Outlet Heat Recovery");
     483           0 :             ShowContinueError(state, "... Water Node Names must be specified. Only one water node is being specified for this generator.");
     484           0 :             ErrorsFound = true;
     485             :         }
     486             : 
     487             :         //   Heat recovery to water input fields only valid if water nodes are defined
     488           8 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecInletNodeNum != 0 &&
     489           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecOutletNodeNum != 0) {
     490             : 
     491           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecActive = true;
     492             : 
     493           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefThermalEffLHV = NumArray(12);
     494           2 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefThermalEffLHV < 0.0) {
     495           0 :                 ShowWarningError(
     496           0 :                     state, state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     497           0 :                 ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(12) + " must be >= 0.");
     498           0 :                 ShowContinueError(state, "Resetting to 0 and the simulation continues.");
     499           0 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefThermalEffLHV = 0.0;
     500             :             }
     501             : 
     502             :             // Next store thermal power output ranges using nominal thermal to electrical efficiency ratio and electrical power data
     503           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefThermalPowerOutput =
     504           4 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecPowerOutput *
     505           4 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefThermalEffLHV /
     506           2 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecEfficiencyLHV;
     507           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MinThermalPowerOutput =
     508           4 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MinElecPowerOutput *
     509           4 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefThermalEffLHV /
     510           2 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecEfficiencyLHV;
     511           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MaxThermalPowerOutput =
     512           4 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).MaxElecPowerOutput *
     513           4 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefThermalEffLHV /
     514           2 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElecEfficiencyLHV;
     515             : 
     516           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefInletWaterTemp = NumArray(13);
     517             : 
     518           2 :             if (UtilityRoutines::SameString(AlphArray(9), "InternalControl")) {
     519           0 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).InternalFlowControl =
     520             :                     true; //  A9, \field Heat Recovery Water Flow Operating Mode
     521           0 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).PlantFlowControl = false;
     522             :             }
     523           2 :             if ((!(UtilityRoutines::SameString(AlphArray(9), "InternalControl"))) && (!(UtilityRoutines::SameString(AlphArray(9), "PlantControl")))) {
     524           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(9) + '=' + AlphArray(9));
     525           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     526           0 :                 ShowContinueError(state, "Operating Mode must be INTERNAL CONTROL or PLANT CONTROL.");
     527           0 :                 ErrorsFound = true;
     528             :             }
     529             : 
     530           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefHeatRecVolFlowRate = NumArray(14);
     531             : 
     532           2 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefHeatRecVolFlowRate <= 0.0) {
     533           0 :                 ShowSevereError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(14), NumArray(14)));
     534           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     535           0 :                 ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(14) + " must be greater than 0.");
     536           0 :                 ErrorsFound = true;
     537             :             }
     538             : 
     539           2 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).InternalFlowControl) { // Get Heat Recovery Water Flow Rate Modifier Curve
     540             : 
     541           0 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecFlowFTempPowCurveNum = Curve::GetCurveIndex(state, AlphArray(10));
     542           0 :                 if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecFlowFTempPowCurveNum != 0) {
     543             :                     // Verify curve object, only legal type is BiQuadratic
     544             :                 }
     545             : 
     546             :             } // End of IF (MTGenerator(GeneratorNum)%InternalFlowControl) THEN
     547             : 
     548           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ThermEffFTempElevCurveNum =
     549           2 :                 Curve::GetCurveIndex(state, AlphArray(11)); // convert curve name to number
     550           2 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ThermEffFTempElevCurveNum != 0) {
     551             :                 // Verify curve object, only legal types are BiQuadratic and BiCubic
     552             : 
     553           2 :                 if (!ErrorsFound) {
     554             :                     // Output of Thermal Efficiency Modifier Curve (function of temp and elevation)
     555             :                     Real64 ThermalEffTempElevOutput =
     556          10 :                         Curve::CurveValue(state,
     557           2 :                                           state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ThermEffFTempElevCurveNum,
     558           2 :                                           state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp,
     559           4 :                                           state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElevation);
     560             : 
     561           2 :                     if (std::abs(ThermalEffTempElevOutput - 1.0) > 0.1) {
     562           0 :                         ShowWarningError(state,
     563           0 :                                          state.dataIPShortCut->cCurrentModuleObject + " \"" +
     564           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     565           0 :                         ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(11) + " = " + AlphArray(11));
     566           0 :                         ShowContinueError(state, "... Curve output at reference conditions should equal 1 (+-10%).");
     567           0 :                         ShowContinueError(state,
     568           0 :                                           format("... Reference combustion air inlet temperature      = {:.4T} C",
     569           0 :                                                  state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp));
     570           0 :                         ShowContinueError(state,
     571           0 :                                           format("... Reference elevation                             = {:.4T} m",
     572           0 :                                                  state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefElevation));
     573             :                     }
     574             :                 }
     575             :             }
     576             : 
     577           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecRateFPLRCurveNum =
     578           2 :                 Curve::GetCurveIndex(state, AlphArray(12)); // convert curve name to number
     579           2 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecRateFPLRCurveNum != 0) {
     580             :                 // Verify curve object, only legal types are Quadratic or Cubic
     581             : 
     582           2 :                 if (!ErrorsFound) {
     583             :                     // Output of Heat Recovery Rate Modifier Curve (function of PLR)
     584             :                     Real64 HeatRecRateFPLROutput =
     585           2 :                         Curve::CurveValue(state, state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecRateFPLRCurveNum, 1.0);
     586             : 
     587           2 :                     if (std::abs(HeatRecRateFPLROutput - 1.0) > 0.1) {
     588           0 :                         ShowWarningError(state,
     589           0 :                                          state.dataIPShortCut->cCurrentModuleObject + " \"" +
     590           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     591           0 :                         ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(12) + " = " + AlphArray(12));
     592           0 :                         ShowContinueError(state, "... Curve output at a part-load ratio of 1 should equal 1 (+-10%).");
     593           0 :                         ShowContinueError(state, format("... Curve output = {:.4T}", HeatRecRateFPLROutput));
     594             :                     }
     595             :                 }
     596             :             }
     597             : 
     598           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecRateFTempCurveNum =
     599           2 :                 Curve::GetCurveIndex(state, AlphArray(13)); // convert curve name to number
     600           2 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecRateFTempCurveNum != 0) {
     601             :                 // Verify curve object, only legal type is Quadratic
     602             : 
     603           2 :                 if (!ErrorsFound) {
     604             :                     // Output of Heat Recovery Rate Modifier Curve (function of inlet water temp)
     605           8 :                     Real64 HeatRecRateFTempOutput = Curve::CurveValue(state,
     606           2 :                                                                       state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecRateFTempCurveNum,
     607           4 :                                                                       state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefInletWaterTemp);
     608             : 
     609           2 :                     if (std::abs(HeatRecRateFTempOutput - 1.0) > 0.1) {
     610           0 :                         ShowWarningError(state,
     611           0 :                                          state.dataIPShortCut->cCurrentModuleObject + " \"" +
     612           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     613           0 :                         ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(13) + " = " + AlphArray(13));
     614           0 :                         ShowContinueError(state, "... Curve output at reference condition should equal 1 (+-10%).");
     615           0 :                         ShowContinueError(state,
     616           0 :                                           format("... Reference inlet water temperature temperature      = {:.4T} C",
     617           0 :                                                  state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefInletWaterTemp));
     618           0 :                         ShowContinueError(state, format("... Curve output = {:.4T}", HeatRecRateFTempOutput));
     619             :                     }
     620             :                 }
     621             :             }
     622             : 
     623           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecRateFWaterFlowCurveNum = Curve::GetCurveIndex(state, AlphArray(14));
     624           2 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecRateFWaterFlowCurveNum != 0) {
     625             :                 // Verify curve object, only legal type is Quadratic
     626             : 
     627           2 :                 if (!ErrorsFound) {
     628             :                     // Output of Heat Recovery Rate Modifier Curve (function of water flow rate)
     629             :                     Real64 HeatRecRateFFlowOutput =
     630           8 :                         Curve::CurveValue(state,
     631           2 :                                           state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecRateFWaterFlowCurveNum,
     632           4 :                                           state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefHeatRecVolFlowRate);
     633             : 
     634           2 :                     if (std::abs(HeatRecRateFFlowOutput - 1.0) > 0.1) {
     635           0 :                         ShowWarningError(state,
     636           0 :                                          state.dataIPShortCut->cCurrentModuleObject + " \"" +
     637           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     638           0 :                         ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(14) + " = " + AlphArray(14));
     639           0 :                         ShowContinueError(state, "... Curve output at reference condition should equal 1 (+-10%).");
     640           0 :                         ShowContinueError(state,
     641           0 :                                           format("... Reference Heat Recovery Water Flow Rate      = {:.4T} m3/s",
     642           0 :                                                  state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefHeatRecVolFlowRate));
     643           0 :                         ShowContinueError(state, format("... Curve output = {:.4T}", HeatRecRateFFlowOutput));
     644             :                     }
     645             :                 }
     646             :             }
     647             : 
     648           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMinVolFlowRate = NumArray(15);
     649           2 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMinVolFlowRate < 0.0) {
     650           0 :                 ShowWarningError(
     651           0 :                     state, state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     652           0 :                 ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(15) + " must be >= 0.");
     653           0 :                 ShowContinueError(state, "Resetting to 0 and the simulation continues.");
     654           0 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMinVolFlowRate = 0.0;
     655             :             }
     656             : 
     657           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMaxVolFlowRate = NumArray(16);
     658           2 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMaxVolFlowRate < 0.0) {
     659           0 :                 ShowWarningError(
     660           0 :                     state, state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     661           0 :                 ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(16) + " must be >= 0.");
     662           0 :                 ShowContinueError(state, "Resetting to 0 and the simulation continues.");
     663           0 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMaxVolFlowRate = 0.0;
     664             :             }
     665             : 
     666           4 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMaxVolFlowRate <
     667           2 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMinVolFlowRate) {
     668           0 :                 ShowWarningError(
     669           0 :                     state, state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     670           0 :                 ShowContinueError(state,
     671           0 :                                   state.dataIPShortCut->cNumericFieldNames(16) + " must be >= " + state.dataIPShortCut->cNumericFieldNames(15));
     672           0 :                 ShowContinueError(state,
     673           0 :                                   "Resetting " + state.dataIPShortCut->cNumericFieldNames(16) + " = " + state.dataIPShortCut->cNumericFieldNames(15) +
     674             :                                       " and the simulation continues.");
     675           0 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMaxVolFlowRate =
     676           0 :                     state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMinVolFlowRate;
     677             :             }
     678             : 
     679             :             //     Check if reference heat recovery water flow rate is below the minimum flow rate
     680           4 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefHeatRecVolFlowRate <
     681           2 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMinVolFlowRate) {
     682           0 :                 ShowWarningError(
     683           0 :                     state, state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     684           0 :                 ShowContinueError(state,
     685           0 :                                   state.dataIPShortCut->cNumericFieldNames(14) + " must be >= " + state.dataIPShortCut->cNumericFieldNames(15));
     686           0 :                 ShowContinueError(state,
     687           0 :                                   "Resetting " + state.dataIPShortCut->cNumericFieldNames(14) + " = " + state.dataIPShortCut->cNumericFieldNames(15) +
     688             :                                       " and the simulation continues.");
     689           0 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefHeatRecVolFlowRate =
     690           0 :                     state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMinVolFlowRate;
     691             :             }
     692             : 
     693             :             //     Check if reference heat recovery water flow rate is above the maximum flow rate
     694           4 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefHeatRecVolFlowRate >
     695           2 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMaxVolFlowRate) {
     696           0 :                 ShowWarningError(
     697           0 :                     state, state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     698           0 :                 ShowContinueError(state,
     699           0 :                                   state.dataIPShortCut->cNumericFieldNames(14) + " must be <= " + state.dataIPShortCut->cNumericFieldNames(16));
     700           0 :                 ShowContinueError(state,
     701           0 :                                   "Resetting " + state.dataIPShortCut->cNumericFieldNames(14) + " = " + state.dataIPShortCut->cNumericFieldNames(16) +
     702             :                                       " and the simulation continues.");
     703           0 :                 state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefHeatRecVolFlowRate =
     704           0 :                     state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMaxVolFlowRate;
     705             :             }
     706             : 
     707           4 :             PlantUtilities::RegisterPlantCompDesignFlow(state,
     708           2 :                                                         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecInletNodeNum,
     709           2 :                                                         state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMaxVolFlowRate);
     710             : 
     711           2 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).HeatRecMaxWaterTemp = NumArray(17);
     712             : 
     713             :         } // End of 'IF (MTGenerator(GeneratorNum)%HeatRecInletNodeNum .NE. 0 .AND. &
     714             :         //             MTGenerator(GeneratorNum)%HeatRecOutletNodeNum .NE. 0) THEN'
     715             : 
     716           6 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) {
     717           3 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).CombustionAirInletNodeNum =
     718           6 :                 NodeInputManager::GetOnlySingleNode(state,
     719           3 :                                                     AlphArray(15),
     720             :                                                     ErrorsFound,
     721             :                                                     DataLoopNode::ConnectionObjectType::GeneratorMicroTurbine,
     722           3 :                                                     AlphArray(1),
     723             :                                                     DataLoopNode::NodeFluidType::Air,
     724             :                                                     DataLoopNode::ConnectionType::Inlet,
     725             :                                                     NodeInputManager::CompFluidStream::Secondary,
     726           3 :                                                     DataLoopNode::ObjectIsNotParent);
     727             :         }
     728             : 
     729             :         //    Combustion air inlet node must be an outside air node
     730           9 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(15) &&
     731           3 :             !OutAirNodeManager::CheckOutAirNodeNumber(state, state.dataMircoturbElectGen->MTGenerator(GeneratorNum).CombustionAirInletNodeNum)) {
     732           0 :             ShowSevereError(state,
     733           0 :                             state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     734           0 :             ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(15) + " is not a valid Outdoor Air Node = " + AlphArray(15));
     735           0 :             ShowContinueError(state, "it does not appear in an OutdoorAir:NodeList or as an OutdoorAir:Node.");
     736           0 :             ErrorsFound = true;
     737             :         }
     738             : 
     739           6 :         if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) {
     740           3 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).CombustionAirOutletNodeNum =
     741           6 :                 NodeInputManager::GetOnlySingleNode(state,
     742           3 :                                                     AlphArray(16),
     743             :                                                     ErrorsFound,
     744             :                                                     DataLoopNode::ConnectionObjectType::GeneratorMicroTurbine,
     745           3 :                                                     AlphArray(1),
     746             :                                                     DataLoopNode::NodeFluidType::Air,
     747             :                                                     DataLoopNode::ConnectionType::Outlet,
     748             :                                                     NodeInputManager::CompFluidStream::Secondary,
     749           3 :                                                     DataLoopNode::ObjectIsNotParent);
     750             :         }
     751             : 
     752           9 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).CombustionAirOutletNodeNum > 0 &&
     753           3 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).CombustionAirInletNodeNum == 0) {
     754           0 :             ShowSevereError(state,
     755           0 :                             state.dataIPShortCut->cCurrentModuleObject + " \"" + state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     756           0 :             ShowContinueError(state,
     757           0 :                               "A " + state.dataIPShortCut->cAlphaFieldNames(15) + " must be specified when a " +
     758           0 :                                   state.dataIPShortCut->cAlphaFieldNames(16) + " is specified.");
     759           0 :             ErrorsFound = true;
     760             :         }
     761             : 
     762             :         //   Get other exhaust air inputs only if combustion air inlet and outlet nodes are valid
     763           9 :         if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).CombustionAirOutletNodeNum > 0 &&
     764           3 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).CombustionAirInletNodeNum > 0) {
     765             : 
     766           3 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhAirCalcsActive = true;
     767           3 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefExhaustAirMassFlowRate = NumArray(18);
     768           3 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefExhaustAirMassFlowRate <= 0.0 &&
     769           0 :                 !state.dataIPShortCut->lNumericFieldBlanks(18)) {
     770           0 :                 ShowSevereError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(18), NumArray(18)));
     771           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     772           0 :                 ShowContinueError(state, state.dataIPShortCut->cNumericFieldNames(18) + " must be greater than 0.");
     773           0 :                 ErrorsFound = true;
     774             :             }
     775             : 
     776           3 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhFlowFTempCurveNum = Curve::GetCurveIndex(state, AlphArray(17));
     777           3 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhFlowFTempCurveNum != 0) {
     778             :                 // Verify curve object, only legal types are Quadratic and Cubic
     779             : 
     780           3 :                 if (!ErrorsFound) {
     781             :                     // Output of Exhaust Air Flow Modifier Curve (function of inlet air temp)
     782          12 :                     Real64 ExhFlowFTempOutput = Curve::CurveValue(state,
     783           3 :                                                                   state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhFlowFTempCurveNum,
     784           6 :                                                                   state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp);
     785             : 
     786           3 :                     if (std::abs(ExhFlowFTempOutput - 1.0) > 0.1) {
     787           0 :                         ShowWarningError(state,
     788           0 :                                          state.dataIPShortCut->cCurrentModuleObject + " \"" +
     789           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     790           0 :                         ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(17) + " = " + AlphArray(17));
     791           0 :                         ShowContinueError(state, "... Curve output at reference condition should equal 1 (+-10%).");
     792           0 :                         ShowContinueError(state,
     793           0 :                                           format("... Reference combustion air inlet temperature      = {:.4T} C",
     794           0 :                                                  state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp));
     795           0 :                         ShowContinueError(state, format("... Curve output = {:.4T}", ExhFlowFTempOutput));
     796             :                     }
     797             :                 }
     798             :             }
     799             : 
     800           3 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhFlowFPLRCurveNum =
     801           3 :                 Curve::GetCurveIndex(state, AlphArray(18)); // convert curve name to number
     802           3 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhFlowFPLRCurveNum != 0) {
     803             :                 // Verify curve object, legal types are Quadratic or Cubic
     804             : 
     805           3 :                 if (!ErrorsFound) {
     806             :                     // Output of Exhaust Air Flow Modifier Curve (function of PLR)
     807             :                     Real64 ExhFlowFPLROutput =
     808           3 :                         Curve::CurveValue(state, state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhFlowFPLRCurveNum, 1.0);
     809             : 
     810           3 :                     if (std::abs(ExhFlowFPLROutput - 1.0) > 0.1) {
     811           0 :                         ShowWarningError(state,
     812           0 :                                          state.dataIPShortCut->cCurrentModuleObject + " \"" +
     813           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     814           0 :                         ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(18) + " = " + AlphArray(18));
     815           0 :                         ShowContinueError(state, "... Curve output at a part-load ratio of 1 should equal 1 (+-10%).");
     816           0 :                         ShowContinueError(state, format("... Curve output = {:.4T}", ExhFlowFPLROutput));
     817             :                     }
     818             :                 }
     819             :             }
     820             : 
     821           3 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).NomExhAirOutletTemp = NumArray(19);
     822             : 
     823           3 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhAirTempFTempCurveNum = Curve::GetCurveIndex(state, AlphArray(19));
     824           3 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhAirTempFTempCurveNum != 0) {
     825             :                 // Verify curve object, only legal types are Quadratic and Cubic
     826             : 
     827           3 :                 if (!ErrorsFound) {
     828             :                     // Output of Exhaust Air Temperature Modifier Curve (function of inlet air temp)
     829          12 :                     Real64 ExhAirTempFTempOutput = Curve::CurveValue(state,
     830           3 :                                                                      state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhAirTempFTempCurveNum,
     831           6 :                                                                      state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp);
     832             : 
     833           3 :                     if (std::abs(ExhAirTempFTempOutput - 1.0) > 0.1) {
     834           0 :                         ShowWarningError(state,
     835           0 :                                          state.dataIPShortCut->cCurrentModuleObject + " \"" +
     836           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     837           0 :                         ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(19) + " = " + AlphArray(19));
     838           0 :                         ShowContinueError(state, "... Curve output at reference condition should equal 1 (+-10%).");
     839           0 :                         ShowContinueError(state,
     840           0 :                                           format("... Reference combustion air inlet temperature      = {:.4T} C",
     841           0 :                                                  state.dataMircoturbElectGen->MTGenerator(GeneratorNum).RefCombustAirInletTemp));
     842           0 :                         ShowContinueError(state, format("... Curve output = {:.4T}", ExhAirTempFTempOutput));
     843             :                     }
     844             :                 }
     845             :             }
     846             : 
     847           3 :             state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhAirTempFPLRCurveNum =
     848           3 :                 Curve::GetCurveIndex(state, AlphArray(20)); // convert curve name to number
     849           3 :             if (state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhAirTempFPLRCurveNum != 0) {
     850             :                 // Verify curve object, legal types are Quadratic or Cubic
     851             : 
     852           3 :                 if (!ErrorsFound) {
     853             :                     // Output of Exhaust Air Temperature Modifier Curve (function of PLR)
     854             :                     Real64 ExhOutAirTempFPLROutput =
     855           3 :                         Curve::CurveValue(state, state.dataMircoturbElectGen->MTGenerator(GeneratorNum).ExhAirTempFPLRCurveNum, 1.0);
     856             : 
     857           3 :                     if (std::abs(ExhOutAirTempFPLROutput - 1.0) > 0.1) {
     858           0 :                         ShowWarningError(state,
     859           0 :                                          state.dataIPShortCut->cCurrentModuleObject + " \"" +
     860           0 :                                              state.dataMircoturbElectGen->MTGenerator(GeneratorNum).Name + "\"");
     861           0 :                         ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(20) + " = " + AlphArray(20));
     862           0 :                         ShowContinueError(state, "... Curve output at a part-load ratio of 1 should equal 1 (+-10%).");
     863           0 :                         ShowContinueError(state, format("... Curve output = {:.4T}", ExhOutAirTempFPLROutput));
     864             :                     }
     865             :                 }
     866             :             }
     867             : 
     868             :         } // End of '    IF (MTGenerator(GeneratorNum)%CombustionAirOutletNodeNum .GT. 0 .AND. &
     869             :           //                 MTGenerator(GeneratorNum)%CombustionAirInletNodeNum .GT. 0) THEN
     870             :     }
     871             : 
     872           6 :     if (ErrorsFound) {
     873           0 :         ShowFatalError(state, "Errors found in processing input for " + state.dataIPShortCut->cCurrentModuleObject);
     874             :     }
     875           6 : }
     876             : 
     877           6 : void MTGeneratorSpecs::setupOutputVars(EnergyPlusData &state)
     878             : {
     879          12 :     SetupOutputVariable(state,
     880             :                         "Generator Produced AC Electricity Rate",
     881             :                         OutputProcessor::Unit::W,
     882             :                         this->ElecPowerGenerated,
     883             :                         OutputProcessor::SOVTimeStepType::System,
     884             :                         OutputProcessor::SOVStoreType::Average,
     885           6 :                         this->Name);
     886             : 
     887          12 :     SetupOutputVariable(state,
     888             :                         "Generator Produced AC Electricity Energy",
     889             :                         OutputProcessor::Unit::J,
     890             :                         this->EnergyGen,
     891             :                         OutputProcessor::SOVTimeStepType::System,
     892             :                         OutputProcessor::SOVStoreType::Summed,
     893             :                         this->Name,
     894             :                         _,
     895             :                         "ElectricityProduced",
     896             :                         "COGENERATION",
     897             :                         _,
     898           6 :                         "Plant");
     899             : 
     900          12 :     SetupOutputVariable(state,
     901             :                         "Generator LHV Basis Electric Efficiency",
     902             :                         OutputProcessor::Unit::None,
     903             :                         this->ElectricEfficiencyLHV,
     904             :                         OutputProcessor::SOVTimeStepType::System,
     905             :                         OutputProcessor::SOVStoreType::Average,
     906           6 :                         this->Name);
     907             : 
     908             :     //    Fuel specific report variables
     909          18 :     SetupOutputVariable(state,
     910          12 :                         "Generator " + this->FuelType + " HHV Basis Rate",
     911             :                         OutputProcessor::Unit::W,
     912             :                         this->FuelEnergyUseRateHHV,
     913             :                         OutputProcessor::SOVTimeStepType::System,
     914             :                         OutputProcessor::SOVStoreType::Average,
     915             :                         this->Name);
     916             : 
     917          18 :     SetupOutputVariable(state,
     918          12 :                         "Generator " + this->FuelType + " HHV Basis Energy",
     919             :                         OutputProcessor::Unit::J,
     920             :                         this->FuelEnergyHHV,
     921             :                         OutputProcessor::SOVTimeStepType::System,
     922             :                         OutputProcessor::SOVStoreType::Summed,
     923             :                         this->Name,
     924             :                         _,
     925             :                         this->FuelType,
     926             :                         "COGENERATION",
     927             :                         _,
     928             :                         "Plant");
     929             : 
     930          18 :     SetupOutputVariable(state,
     931          12 :                         "Generator " + this->FuelType + " Mass Flow Rate",
     932             :                         OutputProcessor::Unit::kg_s,
     933             :                         this->FuelMdot,
     934             :                         OutputProcessor::SOVTimeStepType::System,
     935             :                         OutputProcessor::SOVStoreType::Average,
     936             :                         this->Name);
     937             : 
     938             :     //    general fuel use report (to match other generators)
     939          12 :     SetupOutputVariable(state,
     940             :                         "Generator Fuel HHV Basis Rate",
     941             :                         OutputProcessor::Unit::W,
     942             :                         this->FuelEnergyUseRateHHV,
     943             :                         OutputProcessor::SOVTimeStepType::System,
     944             :                         OutputProcessor::SOVStoreType::Average,
     945           6 :                         this->Name);
     946             : 
     947          12 :     SetupOutputVariable(state,
     948             :                         "Generator Fuel HHV Basis Energy",
     949             :                         OutputProcessor::Unit::J,
     950             :                         this->FuelEnergyHHV,
     951             :                         OutputProcessor::SOVTimeStepType::System,
     952             :                         OutputProcessor::SOVStoreType::Summed,
     953           6 :                         this->Name);
     954             : 
     955             :     //    Heat recovery (to water) report variables
     956           6 :     if (this->HeatRecActive) {
     957             : 
     958           4 :         SetupOutputVariable(state,
     959             :                             "Generator Produced Thermal Rate",
     960             :                             OutputProcessor::Unit::W,
     961             :                             this->QHeatRecovered,
     962             :                             OutputProcessor::SOVTimeStepType::System,
     963             :                             OutputProcessor::SOVStoreType::Average,
     964           2 :                             this->Name);
     965             : 
     966           4 :         SetupOutputVariable(state,
     967             :                             "Generator Produced Thermal Energy",
     968             :                             OutputProcessor::Unit::J,
     969             :                             this->ExhaustEnergyRec,
     970             :                             OutputProcessor::SOVTimeStepType::System,
     971             :                             OutputProcessor::SOVStoreType::Summed,
     972             :                             this->Name,
     973             :                             _,
     974             :                             "ENERGYTRANSFER",
     975             :                             "HEATRECOVERY",
     976             :                             _,
     977           2 :                             "Plant");
     978             : 
     979           4 :         SetupOutputVariable(state,
     980             :                             "Generator Thermal Efficiency LHV Basis",
     981             :                             OutputProcessor::Unit::None,
     982             :                             this->ThermalEfficiencyLHV,
     983             :                             OutputProcessor::SOVTimeStepType::System,
     984             :                             OutputProcessor::SOVStoreType::Average,
     985           2 :                             this->Name);
     986             : 
     987           4 :         SetupOutputVariable(state,
     988             :                             "Generator Heat Recovery Inlet Temperature",
     989             :                             OutputProcessor::Unit::C,
     990             :                             this->HeatRecInletTemp,
     991             :                             OutputProcessor::SOVTimeStepType::System,
     992             :                             OutputProcessor::SOVStoreType::Average,
     993           2 :                             this->Name);
     994             : 
     995           4 :         SetupOutputVariable(state,
     996             :                             "Generator Heat Recovery Outlet Temperature",
     997             :                             OutputProcessor::Unit::C,
     998             :                             this->HeatRecOutletTemp,
     999             :                             OutputProcessor::SOVTimeStepType::System,
    1000             :                             OutputProcessor::SOVStoreType::Average,
    1001           2 :                             this->Name);
    1002             : 
    1003           4 :         SetupOutputVariable(state,
    1004             :                             "Generator Heat Recovery Water Mass Flow Rate",
    1005             :                             OutputProcessor::Unit::kg_s,
    1006             :                             this->HeatRecMdot,
    1007             :                             OutputProcessor::SOVTimeStepType::System,
    1008             :                             OutputProcessor::SOVStoreType::Average,
    1009           2 :                             this->Name);
    1010             :     }
    1011             : 
    1012           6 :     if (this->StandbyPower > 0.0) { // Report Standby Power if entered by user
    1013          10 :         SetupOutputVariable(state,
    1014             :                             "Generator Standby Electricity Rate",
    1015             :                             OutputProcessor::Unit::W,
    1016             :                             this->StandbyPowerRate,
    1017             :                             OutputProcessor::SOVTimeStepType::System,
    1018             :                             OutputProcessor::SOVStoreType::Average,
    1019           5 :                             this->Name);
    1020             : 
    1021          10 :         SetupOutputVariable(state,
    1022             :                             "Generator Standby Electricity Energy",
    1023             :                             OutputProcessor::Unit::J,
    1024             :                             this->StandbyEnergy,
    1025             :                             OutputProcessor::SOVTimeStepType::System,
    1026             :                             OutputProcessor::SOVStoreType::Summed,
    1027             :                             this->Name,
    1028             :                             _,
    1029             :                             "Electricity",
    1030             :                             "Cogeneration",
    1031             :                             _,
    1032           5 :                             "Plant");
    1033             :     }
    1034             : 
    1035           6 :     if (this->AncillaryPower > 0.0) { // Report Ancillary Power if entered by user
    1036          10 :         SetupOutputVariable(state,
    1037             :                             "Generator Ancillary Electricity Rate",
    1038             :                             OutputProcessor::Unit::W,
    1039             :                             this->AncillaryPowerRate,
    1040             :                             OutputProcessor::SOVTimeStepType::System,
    1041             :                             OutputProcessor::SOVStoreType::Average,
    1042           5 :                             this->Name);
    1043             : 
    1044          10 :         SetupOutputVariable(state,
    1045             :                             "Generator Ancillary Electricity Energy",
    1046             :                             OutputProcessor::Unit::J,
    1047             :                             this->AncillaryEnergy,
    1048             :                             OutputProcessor::SOVTimeStepType::System,
    1049             :                             OutputProcessor::SOVStoreType::Summed,
    1050           5 :                             this->Name);
    1051             :     }
    1052             : 
    1053             :     //   Report combustion air outlet conditions if exhaust air calculations are active
    1054           6 :     if (this->ExhAirCalcsActive) {
    1055           6 :         SetupOutputVariable(state,
    1056             :                             "Generator Exhaust Air Mass Flow Rate",
    1057             :                             OutputProcessor::Unit::kg_s,
    1058             :                             this->ExhaustAirMassFlowRate,
    1059             :                             OutputProcessor::SOVTimeStepType::System,
    1060             :                             OutputProcessor::SOVStoreType::Average,
    1061           3 :                             this->Name);
    1062             : 
    1063           6 :         SetupOutputVariable(state,
    1064             :                             "Generator Exhaust Air Temperature",
    1065             :                             OutputProcessor::Unit::C,
    1066             :                             this->ExhaustAirTemperature,
    1067             :                             OutputProcessor::SOVTimeStepType::System,
    1068             :                             OutputProcessor::SOVStoreType::Average,
    1069           3 :                             this->Name);
    1070             :     }
    1071           6 : }
    1072             : 
    1073       85930 : void MTGeneratorSpecs::simulate([[maybe_unused]] EnergyPlusData &state,
    1074             :                                 [[maybe_unused]] const PlantLocation &calledFromLocation,
    1075             :                                 [[maybe_unused]] bool FirstHVACIteration,
    1076             :                                 [[maybe_unused]] Real64 &CurLoad,
    1077             :                                 [[maybe_unused]] bool RunFlag)
    1078             : {
    1079             :     // empty function to emulate current behavior as of conversion to using the PlantComponent calling structure.
    1080             :     // calls from the plant side... do nothing.
    1081             :     // calls from the ElectricPowerServiceManger call the init, calc, and update worker functions
    1082       85930 : }
    1083             : 
    1084          10 : void MTGeneratorSpecs::getDesignCapacities([[maybe_unused]] EnergyPlusData &state,
    1085             :                                            [[maybe_unused]] const PlantLocation &calledFromLocation,
    1086             :                                            Real64 &MaxLoad,
    1087             :                                            Real64 &MinLoad,
    1088             :                                            Real64 &OptLoad)
    1089             : {
    1090          10 :     MaxLoad = 0.0;
    1091          10 :     MinLoad = 0.0;
    1092          10 :     OptLoad = 0.0;
    1093          10 : }
    1094             : 
    1095       52096 : void MTGeneratorSpecs::InitMTGenerators(EnergyPlusData &state,
    1096             :                                         bool const RunFlag,
    1097             :                                         Real64 const MyLoad, // electrical load in W
    1098             :                                         bool const FirstHVACIteration)
    1099             : {
    1100             : 
    1101             :     // SUBROUTINE INFORMATION:
    1102             :     //       AUTHOR         R. Raustad/D. Shirey
    1103             :     //       DATE WRITTEN   Mar 2008
    1104             :     //       MODIFIED       na
    1105             :     //       RE-ENGINEERED  B. Griffith, Sept 2010, plant upgrades, general fluid props
    1106             : 
    1107             :     // PURPOSE OF THIS SUBROUTINE:
    1108             :     //  This subroutine is for initializations of the CT generators.
    1109             : 
    1110             :     // METHODOLOGY EMPLOYED:
    1111             :     //  Uses the status flags to trigger initializations.
    1112             : 
    1113       52096 :     this->oneTimeInit(state); // end one time inits
    1114             : 
    1115       52096 :     if (!this->HeatRecActive) return;
    1116             : 
    1117             :     // Do the Begin Environment initializations
    1118       19542 :     if (state.dataGlobal->BeginEnvrnFlag && this->MyEnvrnFlag) {
    1119             :         // set the node max and min mass flow rates
    1120          16 :         PlantUtilities::InitComponentNodes(state, 0.0, this->HeatRecMaxMassFlowRate, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
    1121             : 
    1122          16 :         state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp = 20.0; // Set the node temperature, assuming freeze control
    1123          16 :         state.dataLoopNodes->Node(this->HeatRecOutletNodeNum).Temp = 20.0;
    1124             : 
    1125          16 :         this->MyEnvrnFlag = false;
    1126             :     } // end environmental inits
    1127             : 
    1128       19542 :     if (!state.dataGlobal->BeginEnvrnFlag) {
    1129       19262 :         this->MyEnvrnFlag = true;
    1130             :     }
    1131             : 
    1132             :     // set/request flow rates
    1133       19542 :     if (FirstHVACIteration) {
    1134             : 
    1135             :         Real64 DesiredMassFlowRate;
    1136       12594 :         if (!RunFlag) {
    1137       10490 :             DesiredMassFlowRate = 0.0;
    1138             : 
    1139        2104 :         } else if (RunFlag && this->InternalFlowControl) {
    1140             :             // assume dispatch power in MyLoad is what gets produced (future, reset during calc routine and iterate)
    1141           0 :             if (this->HeatRecFlowFTempPowCurveNum != 0) {
    1142           0 :                 DesiredMassFlowRate =
    1143           0 :                     this->DesignHeatRecMassFlowRate *
    1144           0 :                     Curve::CurveValue(state, this->HeatRecFlowFTempPowCurveNum, state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp, MyLoad);
    1145             :             } else {
    1146           0 :                 DesiredMassFlowRate = this->DesignHeatRecMassFlowRate; // Assume modifier = 1 if curve not specified
    1147             :             }
    1148             : 
    1149           0 :             DesiredMassFlowRate = max(DataPrecisionGlobals::constant_zero, DesiredMassFlowRate); // protect from neg. curve result
    1150             : 
    1151        2104 :         } else if (RunFlag && (!this->InternalFlowControl)) {
    1152        2104 :             DesiredMassFlowRate = this->DesignHeatRecMassFlowRate;
    1153             :         }
    1154             : 
    1155       12594 :         PlantUtilities::SetComponentFlowRate(state, DesiredMassFlowRate, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum, this->HRPlantLoc);
    1156             :     } else { // not FirstHVACIteration
    1157        6948 :         if (!RunFlag) {
    1158        5684 :             state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRate =
    1159        5684 :                 min(DataPrecisionGlobals::constant_zero, state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRateMaxAvail);
    1160        5684 :             state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRate =
    1161        5684 :                 max(DataPrecisionGlobals::constant_zero, state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRateMinAvail);
    1162             : 
    1163        1264 :         } else if (RunFlag && this->InternalFlowControl) {
    1164             :             // assume dispatch power in MyLoad is what gets produced (future, reset during calc routine and iterate)
    1165           0 :             if (this->HeatRecFlowFTempPowCurveNum != 0) {
    1166             :                 Real64 DesiredMassFlowRate =
    1167           0 :                     this->DesignHeatRecMassFlowRate *
    1168           0 :                     Curve::CurveValue(state, this->HeatRecFlowFTempPowCurveNum, state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp, MyLoad);
    1169           0 :                 PlantUtilities::SetComponentFlowRate(
    1170             :                     state, DesiredMassFlowRate, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum, this->HRPlantLoc);
    1171             :             } else {
    1172           0 :                 PlantUtilities::SetComponentFlowRate(
    1173             :                     state, this->HeatRecMdot, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum, this->HRPlantLoc);
    1174           0 :             }
    1175        1264 :         } else if (RunFlag && (!this->InternalFlowControl)) {
    1176        1264 :             PlantUtilities::SetComponentFlowRate(state, this->HeatRecMdot, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum, this->HRPlantLoc);
    1177             :         }
    1178             :     }
    1179             : }
    1180             : 
    1181       52096 : void MTGeneratorSpecs::CalcMTGeneratorModel(EnergyPlusData &state,
    1182             :                                             bool const RunFlag,  // TRUE when generator is being asked to operate
    1183             :                                             Real64 const MyLoad) // Generator demand (W)
    1184             : {
    1185             :     // SUBROUTINE INFORMATION:
    1186             :     //       AUTHOR         R. Raustad/D. Shirey
    1187             :     //       DATE WRITTEN   Mar 2008
    1188             :     //       MODIFIED       na
    1189             :     //       RE-ENGINEERED  na
    1190             : 
    1191             :     // PURPOSE OF THIS SUBROUTINE:
    1192             :     //  Simulate a combustion generator.
    1193             : 
    1194             :     // METHODOLOGY EMPLOYED:
    1195             :     //  Curve fits of performance data.
    1196             : 
    1197       52096 :     Real64 constexpr KJtoJ(1000.0);          // Convert kilojoules to joules
    1198       52096 :     int constexpr MaxAncPowerIter(50);       // Maximum number of iteration (subroutine ancillary power iteration loop)
    1199       52096 :     Real64 constexpr AncPowerDiffToler(5.0); // Tolerance for Ancillary Power Difference (W)
    1200       52096 :     Real64 constexpr RelaxFactor(0.7);       // Relaxation factor for iteration loop
    1201             :     static constexpr std::string_view RoutineName("CalcMTGeneratorModel");
    1202             : 
    1203             :     //   Load local variables from data structure (for code readability)
    1204             :     // Min allowed operating fraction at full load
    1205       52096 :     Real64 minPartLoadRat = this->MinPartLoadRat;
    1206             : 
    1207             :     // Max allowed operating fraction at full load
    1208       52096 :     Real64 maxPartLoadRat = this->MaxPartLoadRat;
    1209             : 
    1210             :     // Generator reference capacity (W)
    1211       52096 :     Real64 ReferencePowerOutput = this->RefElecPowerOutput;
    1212             : 
    1213             :     // Reference electrical efficiency
    1214       52096 :     Real64 RefElecEfficiency = this->RefElecEfficiencyLHV;
    1215             : 
    1216             :     //   Initialize variables
    1217       52096 :     this->ElecPowerGenerated = 0.0;
    1218       52096 :     this->HeatRecInletTemp = 0.0;
    1219       52096 :     this->HeatRecOutletTemp = 0.0;
    1220       52096 :     this->HeatRecMdot = 0.0;
    1221       52096 :     this->QHeatRecovered = 0.0;
    1222       52096 :     this->ExhaustEnergyRec = 0.0;
    1223       52096 :     this->FuelEnergyUseRateHHV = 0.0;
    1224       52096 :     this->FuelMdot = 0.0;
    1225       52096 :     this->AncillaryPowerRate = 0.0;
    1226       52096 :     this->StandbyPowerRate = 0.0;
    1227       52096 :     this->FuelEnergyUseRateLHV = 0.0;
    1228       52096 :     this->ExhaustAirMassFlowRate = 0.0;
    1229       52096 :     this->ExhaustAirTemperature = 0.0;
    1230       52096 :     this->ExhaustAirHumRat = 0.0;
    1231             : 
    1232             :     Real64 HeatRecInTemp; // Heat recovery fluid inlet temperature (C)
    1233             :     Real64 heatRecMdot;   // Heat recovery fluid mass flow rate (kg/s)
    1234             :     Real64 HeatRecCp;     // Specific heat of the heat recovery fluid (J/kg-K)
    1235             : 
    1236       52096 :     if (this->HeatRecActive) {
    1237       19542 :         HeatRecInTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
    1238       39084 :         HeatRecCp = FluidProperties::GetSpecificHeatGlycol(state,
    1239       19542 :                                                            state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
    1240             :                                                            HeatRecInTemp,
    1241       19542 :                                                            state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
    1242             :                                                            RoutineName);
    1243       19542 :         heatRecMdot = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).MassFlowRate;
    1244             :     } else {
    1245       32554 :         HeatRecInTemp = 0.0;
    1246       32554 :         HeatRecCp = 0.0;
    1247       32554 :         heatRecMdot = 0.0;
    1248             :     }
    1249             : 
    1250             :     Real64 CombustionAirInletTemp;  // Combustion air inlet temperature (C)
    1251             :     Real64 CombustionAirInletPress; // Barometric pressure of combustion inlet air (Pa)
    1252             :     Real64 CombustionAirInletW;     // Combustion air inlet humidity ratio (kg/kg)
    1253             : 
    1254             :     //   Set combustion inlet air temperature, humidity ratio and pressure local variables
    1255       52096 :     if (this->CombustionAirInletNodeNum == 0) { // no inlet air node specified, so use weather file values
    1256       24592 :         CombustionAirInletTemp = state.dataEnvrn->OutDryBulbTemp;
    1257       24592 :         CombustionAirInletW = state.dataEnvrn->OutHumRat;
    1258       24592 :         CombustionAirInletPress = state.dataEnvrn->OutBaroPress;
    1259             :     } else { // use inlet node information
    1260       27504 :         CombustionAirInletTemp = state.dataLoopNodes->Node(this->CombustionAirInletNodeNum).Temp;
    1261       27504 :         CombustionAirInletW = state.dataLoopNodes->Node(this->CombustionAirInletNodeNum).HumRat;
    1262       27504 :         CombustionAirInletPress = state.dataLoopNodes->Node(this->CombustionAirInletNodeNum).Press;
    1263       27504 :         if (state.dataLoopNodes->Node(this->CombustionAirInletNodeNum).Height > 0.0) {
    1264             :         }
    1265             :         //     Initialize combustion outlet air conditions to inlet air conditions (all node properties)
    1266       27504 :         if (this->ExhAirCalcsActive) {
    1267       27504 :             state.dataLoopNodes->Node(this->CombustionAirOutletNodeNum) = state.dataLoopNodes->Node(this->CombustionAirInletNodeNum);
    1268             :         }
    1269             :     }
    1270             : 
    1271             :     //   If no loop demand or generator OFF, set some variables and then return
    1272             :     //    IF (.NOT. RunFlag .OR. MyLoad .LE. 0.0d0) THEN
    1273       52096 :     if (MyLoad <= 0.0) {
    1274       33484 :         this->HeatRecInletTemp = HeatRecInTemp;
    1275       33484 :         this->HeatRecOutletTemp = HeatRecInTemp;
    1276       33484 :         if (RunFlag) {
    1277           0 :             this->StandbyPowerRate = this->StandbyPower;
    1278             :         }
    1279       33484 :         this->ExhaustAirTemperature = CombustionAirInletTemp;
    1280       33484 :         this->ExhaustAirHumRat = CombustionAirInletW;
    1281       33484 :         return;
    1282             :     }
    1283             : 
    1284             :     //   Calculate power modifier curve value (function of inlet air temperature and elevation)
    1285             :     // Power ratio as a function of inlet air temperature and elevation
    1286       18612 :     Real64 PowerFTempElev = Curve::CurveValue(state, this->ElecPowFTempElevCurveNum, CombustionAirInletTemp, state.dataEnvrn->Elevation);
    1287             : 
    1288             :     //   Warn user if power modifier curve output is less than 0
    1289       18612 :     if (PowerFTempElev < 0.0) {
    1290           0 :         if (this->PowerFTempElevErrorIndex == 0) {
    1291             :             //        MTGenerator(GeneratorNum)%PowerFTempElevErrorCount = MTGenerator(GeneratorNum)%PowerFTempElevErrorCount + 1
    1292           0 :             ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1293           0 :             ShowContinueError(state,
    1294           0 :                               format("... Electrical Power Modifier curve (function of temperature and elevation) output is less than zero ({:.4T}).",
    1295           0 :                                      PowerFTempElev));
    1296           0 :             ShowContinueError(state, format("... Value occurs using a combustion inlet air temperature of {:.2T} C.", CombustionAirInletTemp));
    1297           0 :             ShowContinueError(state, format("... and an elevation of {:.2T} m.", state.dataEnvrn->Elevation));
    1298           0 :             ShowContinueErrorTimeStamp(state, "... Resetting curve output to zero and continuing simulation.");
    1299             :         }
    1300           0 :         ShowRecurringWarningErrorAtEnd(state,
    1301           0 :                                        "GENERATOR:MICROTURBINE \"" + this->Name +
    1302             :                                            "\": Electrical Power Modifier curve is less than zero warning continues...",
    1303             :                                        this->PowerFTempElevErrorIndex,
    1304             :                                        PowerFTempElev,
    1305             :                                        PowerFTempElev);
    1306           0 :         PowerFTempElev = 0.0;
    1307             :     }
    1308             : 
    1309             :     //   Calculate available full-load power output. cannot exceed maximum full-load power output.
    1310             :     // Generator full-load power output at actual inlet conditions and elevation (W)
    1311       18612 :     Real64 FullLoadPowerOutput = min((ReferencePowerOutput * PowerFTempElev), this->MaxElecPowerOutput);
    1312             :     //   Also can't be below the minimum full-load power output.
    1313       18612 :     FullLoadPowerOutput = max(FullLoadPowerOutput, this->MinElecPowerOutput);
    1314             : 
    1315             :     // Ancillary power used by pump (if not specified in manufacturers data)
    1316       18612 :     Real64 ancillaryPowerRate = this->AncillaryPower;
    1317             : 
    1318             :     // Difference between ancillary power rate and ancillary power rate last (last iteration)
    1319       18612 :     Real64 AncillaryPowerRateDiff = AncPowerDiffToler + 1.0; // Initialize to force through DO WHILE Loop at least once
    1320             : 
    1321       18612 :     Real64 PLR(0.0);                    // Generator operating part load ratio
    1322       18612 :     Real64 elecPowerGenerated(0.0);     // Generator electric power output (W)
    1323       18612 :     Real64 FuelUseEnergyRateLHV(0.0);   // Rate of fuel energy required to run microturbine, LHV basis (W)
    1324       18612 :     Real64 fuelHigherHeatingValue(0.0); // Higher heating value (LLV) of fuel kJ/kg)
    1325       18612 :     Real64 fuelLowerHeatingValue(0.0);  // Lower heating value (LLV) of fuel kJ/kg)
    1326       18612 :     Real64 AnciPowerFMdotFuel(0.0);     // Ancillary power as a function of fuel flow curve output
    1327       18612 :     int AncPowerCalcIterIndex = 0;      // Index for subroutine iteration loop if Ancillary Power (function of fuel flow) is used
    1328             : 
    1329       55836 :     while (AncillaryPowerRateDiff > AncPowerDiffToler && AncPowerCalcIterIndex <= MaxAncPowerIter) {
    1330             : 
    1331       18612 :         ++AncPowerCalcIterIndex; // Increment iteration loop counter
    1332             : 
    1333             :         //     Calculate operating power output (gross)
    1334       18612 :         elecPowerGenerated = min(max(0.0, MyLoad + ancillaryPowerRate), FullLoadPowerOutput);
    1335             : 
    1336             :         //     Calculate PLR, but must be between the minPLR and maxPLR
    1337       18612 :         if (FullLoadPowerOutput > 0.0) {
    1338       18612 :             PLR = min(elecPowerGenerated / FullLoadPowerOutput, maxPartLoadRat);
    1339       18612 :             PLR = max(PLR, minPartLoadRat);
    1340             :         } else {
    1341           0 :             PLR = 0.0;
    1342             :         }
    1343             : 
    1344             :         //     Recalculate elecPowerGenerated based on "final" PLR
    1345       18612 :         elecPowerGenerated = FullLoadPowerOutput * PLR;
    1346             : 
    1347             :         //     Calculate electrical efficiency modifier curve output (function of temp)
    1348             :         // Electrical efficiency as a function of temperature curve output
    1349       18612 :         Real64 ElecEfficiencyFTemp = Curve::CurveValue(state, this->ElecEffFTempCurveNum, CombustionAirInletTemp);
    1350             : 
    1351             :         //     Warn user if efficiency modifier curve output is less than 0
    1352       18612 :         if (ElecEfficiencyFTemp < 0.0) {
    1353           0 :             if (this->EffFTempErrorIndex == 0) {
    1354             :                 //          MTGenerator(GeneratorNum)%EffFTempErrorCount = MTGenerator(GeneratorNum)%EffFTempErrorCount + 1
    1355           0 :                 ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1356           0 :                 ShowContinueError(
    1357             :                     state,
    1358           0 :                     format("... Electrical Efficiency Modifier (function of temperature) output is less than zero ({:.4T}).", ElecEfficiencyFTemp));
    1359           0 :                 ShowContinueError(state, format("... Value occurs using a combustion inlet air temperature of {:.2T} C.", CombustionAirInletTemp));
    1360           0 :                 ShowContinueErrorTimeStamp(state, "... Resetting curve output to zero and continuing simulation.");
    1361             :             }
    1362           0 :             ShowRecurringWarningErrorAtEnd(
    1363             :                 state,
    1364           0 :                 "GENERATOR:MICROTURBINE \"" + this->Name +
    1365             :                     "\": Electrical Efficiency Modifier (function of temperature) output is less than zero warning continues...",
    1366             :                 this->EffFTempErrorIndex,
    1367             :                 ElecEfficiencyFTemp,
    1368             :                 ElecEfficiencyFTemp);
    1369           0 :             ElecEfficiencyFTemp = 0.0;
    1370             :         }
    1371             : 
    1372             :         //     Calculate efficiency modifier curve output (function of PLR)
    1373             :         // Electrical efficiency as a function of PLR curve output
    1374       18612 :         Real64 ElecEfficiencyFPLR = Curve::CurveValue(state, this->ElecEffFPLRCurveNum, PLR);
    1375             : 
    1376             :         //     Warn user if efficiency modifier curve output is less than 0
    1377       18612 :         if (ElecEfficiencyFPLR < 0.0) {
    1378           0 :             if (this->EffFPLRErrorIndex == 0) {
    1379           0 :                 ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1380           0 :                 ShowContinueError(state,
    1381           0 :                                   format("... Electrical Efficiency Modifier (function of part-load ratio) output is less than zero ({:.4T}).",
    1382           0 :                                          ElecEfficiencyFPLR));
    1383           0 :                 ShowContinueError(state, format("... Value occurs using a part-load ratio of {:.3T}.", PLR));
    1384           0 :                 ShowContinueErrorTimeStamp(state, "... Resetting curve output to zero and continuing simulation.");
    1385             :             }
    1386           0 :             ShowRecurringWarningErrorAtEnd(
    1387             :                 state,
    1388           0 :                 "GENERATOR:MICROTURBINE \"" + this->Name +
    1389             :                     "\": Electrical Efficiency Modifier (function of part-load ratio) output is less than zero warning continues...",
    1390             :                 this->EffFPLRErrorIndex,
    1391             :                 ElecEfficiencyFPLR,
    1392             :                 ElecEfficiencyFPLR);
    1393           0 :             ElecEfficiencyFPLR = 0.0;
    1394             :         }
    1395             : 
    1396             :         //     Calculate operating electrical efficiency
    1397             :         // Actual operating efficiency
    1398       18612 :         Real64 OperatingElecEfficiency = RefElecEfficiency * ElecEfficiencyFTemp * ElecEfficiencyFPLR;
    1399             : 
    1400             :         //     Calculate fuel use (W = J/s), LHV basis
    1401       18612 :         if (OperatingElecEfficiency > 0.0) {
    1402       18612 :             FuelUseEnergyRateLHV = elecPowerGenerated / OperatingElecEfficiency;
    1403             :         } else {
    1404           0 :             FuelUseEnergyRateLHV = 0.0; // If fuel use rate is zero, then
    1405           0 :             elecPowerGenerated = 0.0;   //  electric power generated must be zero.
    1406             :         }
    1407             : 
    1408             :         //     Set fuel heating values
    1409       18612 :         fuelHigherHeatingValue = this->FuelHigherHeatingValue;
    1410       18612 :         fuelLowerHeatingValue = this->FuelLowerHeatingValue;
    1411             : 
    1412             :         //     Calculate fuel mass flow rate
    1413       18612 :         this->FuelMdot = FuelUseEnergyRateLHV / (fuelLowerHeatingValue * KJtoJ);
    1414             : 
    1415             :         //     Calculate ancillary power requirement
    1416       18612 :         if (this->AncillaryPowerFuelCurveNum > 0) {
    1417           0 :             AnciPowerFMdotFuel = Curve::CurveValue(state, this->AncillaryPowerFuelCurveNum, this->FuelMdot);
    1418             :             //       Warn user if ancillary power modifier curve output is less than 0
    1419           0 :             if (AnciPowerFMdotFuel < 0.0) {
    1420           0 :                 if (this->AnciPowerFMdotFuelErrorIndex == 0) {
    1421           0 :                     ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1422           0 :                     ShowContinueError(
    1423             :                         state,
    1424           0 :                         format("... Ancillary Power Modifier (function of fuel input) output is less than zero ({:.4T}).", AnciPowerFMdotFuel));
    1425           0 :                     ShowContinueError(state, format("... Value occurs using a fuel input mass flow rate of {:.4T} kg/s.", this->FuelMdot));
    1426           0 :                     ShowContinueErrorTimeStamp(state, "... Resetting curve output to zero and continuing simulation.");
    1427             :                 }
    1428           0 :                 ShowRecurringWarningErrorAtEnd(
    1429             :                     state,
    1430           0 :                     "GENERATOR:MICROTURBINE \"" + this->Name +
    1431             :                         "\": Ancillary Power Modifier (function of fuel input) output is less than zero warning continues...",
    1432             :                     this->AnciPowerFMdotFuelErrorIndex,
    1433             :                     AnciPowerFMdotFuel,
    1434             :                     AnciPowerFMdotFuel);
    1435           0 :                 AnciPowerFMdotFuel = 0.0;
    1436             :             }
    1437             :         } else {
    1438       18612 :             AnciPowerFMdotFuel = 1.0;
    1439             :         }
    1440             : 
    1441             :         // Ancillary power used by pump from last iteration (iteration loop within this subroutine)
    1442       18612 :         Real64 AncillaryPowerRateLast = ancillaryPowerRate;
    1443             : 
    1444       18612 :         if (this->AncillaryPowerFuelCurveNum > 0) {
    1445           0 :             ancillaryPowerRate = RelaxFactor * this->AncillaryPower * AnciPowerFMdotFuel - (1.0 - RelaxFactor) * AncillaryPowerRateLast;
    1446             :         }
    1447             : 
    1448       18612 :         AncillaryPowerRateDiff = std::abs(ancillaryPowerRate - AncillaryPowerRateLast);
    1449             :     }
    1450             : 
    1451       18612 :     if (AncPowerCalcIterIndex > MaxAncPowerIter) {
    1452             : 
    1453           0 :         if (this->AnciPowerIterErrorIndex == 0) {
    1454           0 :             ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1455           0 :             ShowContinueError(state, "... Iteration loop for electric power generation is not converging within tolerance.");
    1456           0 :             ShowContinueError(state, "... Check the Ancillary Power Modifier Curve (function of fuel input).");
    1457           0 :             ShowContinueError(state, format("... Ancillary Power = {:.1T} W.", ancillaryPowerRate));
    1458           0 :             ShowContinueError(state, format("... Fuel input rate = {:.4T} kg/s.", AnciPowerFMdotFuel));
    1459           0 :             ShowContinueErrorTimeStamp(state, "... Simulation will continue.");
    1460             :         }
    1461           0 :         ShowRecurringWarningErrorAtEnd(state,
    1462           0 :                                        "GENERATOR:MICROTURBINE \"" + this->Name +
    1463             :                                            "\": Iteration loop for electric power generation is not converging within tolerance continues...",
    1464             :                                        this->AnciPowerIterErrorIndex);
    1465             :     }
    1466             : 
    1467             :     //   Calculate electrical power generated
    1468       18612 :     this->ElecPowerGenerated = elecPowerGenerated - ancillaryPowerRate;
    1469             : 
    1470             :     //   Report fuel energy use rate on HHV basis, which is the unit of measure when the fuel is sold
    1471       18612 :     this->FuelEnergyUseRateHHV = this->FuelMdot * fuelHigherHeatingValue * KJtoJ;
    1472       18612 :     this->AncillaryPowerRate = ancillaryPowerRate;     // Move to data structure for later reporting
    1473       18612 :     this->FuelEnergyUseRateLHV = FuelUseEnergyRateLHV; // Move to data structure for reporting calculations
    1474             : 
    1475             :     //   When generator operates, standby losses are 0
    1476       18612 :     this->StandbyPowerRate = 0.0;
    1477             : 
    1478       18612 :     Real64 QHeatRecToWater = 0.0; // Recovered waste heat to water (W)
    1479             : 
    1480             :     //   Calculate heat recovery if active
    1481       18612 :     if (this->HeatRecActive) {
    1482             : 
    1483             :         // Thermal efficiency as a function of air temperature and elevation
    1484             :         Real64 ThermalEffFTempElev;
    1485        3368 :         if (this->ThermEffFTempElevCurveNum > 0) {
    1486        3368 :             ThermalEffFTempElev = Curve::CurveValue(state, this->ThermEffFTempElevCurveNum, CombustionAirInletTemp, state.dataEnvrn->Elevation);
    1487             :             //       Warn user if power modifier curve output is less than 0
    1488        3368 :             if (ThermalEffFTempElev < 0.0) {
    1489           0 :                 if (this->ThermEffFTempElevErrorIndex == 0) {
    1490           0 :                     ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1491           0 :                     ShowContinueError(
    1492             :                         state,
    1493           0 :                         format("... Electrical Power Modifier curve (function of temperature and elevation) output is less than zero ({:.4T}).",
    1494           0 :                                PowerFTempElev));
    1495           0 :                     ShowContinueError(state,
    1496           0 :                                       format("... Value occurs using a combustion inlet air temperature of {:.2T} C.", CombustionAirInletTemp));
    1497           0 :                     ShowContinueError(state, format("... and an elevation of {:.2T} m.", state.dataEnvrn->Elevation));
    1498           0 :                     ShowContinueErrorTimeStamp(state, "... Resetting curve output to zero and continuing simulation.");
    1499             :                 }
    1500           0 :                 ShowRecurringWarningErrorAtEnd(state,
    1501           0 :                                                "GENERATOR:MICROTURBINE \"" + this->Name +
    1502             :                                                    "\": Electrical Power Modifier curve is less than zero warning continues...",
    1503             :                                                this->ThermEffFTempElevErrorIndex,
    1504             :                                                ThermalEffFTempElev,
    1505             :                                                ThermalEffFTempElev);
    1506           0 :                 ThermalEffFTempElev = 0.0;
    1507             :             }
    1508             :         } else {
    1509           0 :             ThermalEffFTempElev = 1.0; // If no curve provided, assume multiplier factor = 1.0
    1510             :         }
    1511             : 
    1512        3368 :         QHeatRecToWater = FuelUseEnergyRateLHV * this->RefThermalEffLHV * ThermalEffFTempElev;
    1513             :         Real64 HeatRecRateFPLR; // Heat recovery rate as a function of PLR curve output
    1514             : 
    1515             :         //     Calculate heat recovery rate modifier curve output (function of PLR)
    1516        3368 :         if (this->HeatRecRateFPLRCurveNum > 0) {
    1517        3368 :             HeatRecRateFPLR = Curve::CurveValue(state, this->HeatRecRateFPLRCurveNum, PLR);
    1518             :             //       Warn user if heat recovery modifier curve output is less than 0
    1519        3368 :             if (HeatRecRateFPLR < 0.0) {
    1520           0 :                 if (this->HeatRecRateFPLRErrorIndex == 0) {
    1521           0 :                     ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1522           0 :                     ShowContinueError(
    1523             :                         state,
    1524           0 :                         format("... Heat Recovery Rate Modifier (function of part-load ratio) output is less than zero ({:.4T}).", HeatRecRateFPLR));
    1525           0 :                     ShowContinueError(state, format("... Value occurs using a part-load ratio of {:.3T}.", PLR));
    1526           0 :                     ShowContinueErrorTimeStamp(state, "... Resetting curve output to zero and continuing simulation.");
    1527             :                 }
    1528           0 :                 ShowRecurringWarningErrorAtEnd(
    1529             :                     state,
    1530           0 :                     "GENERATOR:MICROTURBINE \"" + this->Name +
    1531             :                         "\": Heat Recovery Rate Modifier (function of part-load ratio) output is less than zero warning continues...",
    1532             :                     this->HeatRecRateFPLRErrorIndex,
    1533             :                     HeatRecRateFPLR,
    1534             :                     HeatRecRateFPLR);
    1535           0 :                 HeatRecRateFPLR = 0.0;
    1536             :             }
    1537             :         } else {
    1538           0 :             HeatRecRateFPLR = 1.0; // If no curve provided, assume multiplier factor = 1.0
    1539             :         }
    1540             : 
    1541             :         Real64 HeatRecRateFTemp; // Heat recovery rate as a function of inlet water temp curve output
    1542             : 
    1543             :         //     Calculate heat recovery rate modifier curve output (function of inlet water temp)
    1544        3368 :         if (this->HeatRecRateFTempCurveNum > 0) {
    1545        3368 :             HeatRecRateFTemp = Curve::CurveValue(state, this->HeatRecRateFTempCurveNum, HeatRecInTemp);
    1546        3368 :             if (HeatRecRateFTemp < 0.0) {
    1547           0 :                 if (this->HeatRecRateFTempErrorIndex == 0) {
    1548           0 :                     ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1549           0 :                     ShowContinueError(state,
    1550           0 :                                       format("... Heat Recovery Rate Modifier (function of inlet water temp) output is less than zero ({:.4T}).",
    1551           0 :                                              HeatRecRateFTemp));
    1552           0 :                     ShowContinueError(state, format("... Value occurs using an inlet water temperature temperature of {:.2T} C.", HeatRecInTemp));
    1553           0 :                     ShowContinueErrorTimeStamp(state, "... Resetting curve output to zero and continuing simulation.");
    1554             :                 }
    1555           0 :                 ShowRecurringWarningErrorAtEnd(
    1556             :                     state,
    1557           0 :                     "GENERATOR:MICROTURBINE \"" + this->Name +
    1558             :                         "\": Heat Recovery Rate Modifier (function of inlet water temp) output is less than zero warning continues...",
    1559             :                     this->HeatRecRateFTempErrorIndex,
    1560             :                     HeatRecRateFTemp,
    1561             :                     HeatRecRateFTemp);
    1562           0 :                 HeatRecRateFTemp = 0.0;
    1563             :             }
    1564             :         } else {
    1565           0 :             HeatRecRateFTemp = 1.0; // If no curve provided, assume multiplier factor = 1.0
    1566             :         }
    1567             : 
    1568             :         Real64 HeatRecRateFFlow; // Heat recovery rate as a function of water flow rate curve output
    1569             : 
    1570             :         //     Calculate heat recovery rate modifier curve output (function of water [volumetric] flow rate)
    1571        3368 :         if (this->HeatRecRateFWaterFlowCurveNum > 0) {
    1572        6736 :             Real64 rho = FluidProperties::GetDensityGlycol(state,
    1573        3368 :                                                            state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
    1574             :                                                            HeatRecInTemp,
    1575        3368 :                                                            state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
    1576        3368 :                                                            RoutineName);
    1577             : 
    1578             :             // Heat recovery fluid flow rate (m3/s)
    1579        3368 :             Real64 HeatRecVolFlowRate = heatRecMdot / rho;
    1580        3368 :             HeatRecRateFFlow = Curve::CurveValue(state, this->HeatRecRateFWaterFlowCurveNum, HeatRecVolFlowRate);
    1581        3368 :             if (HeatRecRateFFlow < 0.0) {
    1582           0 :                 if (this->HeatRecRateFFlowErrorIndex == 0) {
    1583           0 :                     ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1584           0 :                     ShowContinueError(
    1585             :                         state,
    1586           0 :                         format("... Heat Recovery Rate Modifier (function of water flow rate) output is less than zero ({:.4T}).", HeatRecRateFFlow));
    1587           0 :                     ShowContinueError(state, format("... Value occurs using a water flow rate of {:.4T} m3/s.", HeatRecVolFlowRate));
    1588           0 :                     ShowContinueErrorTimeStamp(state, "... Resetting curve output to zero and continuing simulation.");
    1589             :                 }
    1590           0 :                 ShowRecurringWarningErrorAtEnd(
    1591             :                     state,
    1592           0 :                     "GENERATOR:MICROTURBINE \"" + this->Name +
    1593             :                         "\": Heat Recovery Rate Modifier (function of water flow rate) output is less than zero warning continues...",
    1594             :                     this->HeatRecRateFFlowErrorIndex,
    1595             :                     HeatRecRateFFlow,
    1596             :                     HeatRecRateFFlow);
    1597           0 :                 HeatRecRateFFlow = 0.0;
    1598             :             }
    1599             :         } else {
    1600           0 :             HeatRecRateFFlow = 1.0; // If no curve provided, assume multiplier factor = 1.0
    1601             :         }
    1602             : 
    1603        3368 :         QHeatRecToWater *= HeatRecRateFPLR * HeatRecRateFTemp * HeatRecRateFFlow;
    1604             : 
    1605             :         Real64 HeatRecOutTemp; // Heat recovery fluid outlet temperature (C)
    1606             : 
    1607             :         //     Check for divide by zero
    1608        3368 :         if ((heatRecMdot > 0.0) && (HeatRecCp > 0.0)) {
    1609        3368 :             HeatRecOutTemp = HeatRecInTemp + QHeatRecToWater / (heatRecMdot * HeatRecCp);
    1610             :         } else {
    1611           0 :             heatRecMdot = 0.0;
    1612           0 :             HeatRecOutTemp = HeatRecInTemp;
    1613           0 :             QHeatRecToWater = 0.0;
    1614             :         }
    1615             : 
    1616             :         //     Now verify the maximum heat recovery temperature was not exceeded
    1617        3368 :         if (HeatRecOutTemp > this->HeatRecMaxWaterTemp) {
    1618             : 
    1619        1659 :             Real64 MinHeatRecMdot = 0.0; // Heat recovery flow rate if minimal heat recovery is accomplished (kg/s)
    1620             : 
    1621        1659 :             if (this->HeatRecMaxWaterTemp != HeatRecInTemp) {
    1622        1659 :                 MinHeatRecMdot = QHeatRecToWater / (HeatRecCp * (this->HeatRecMaxWaterTemp - HeatRecInTemp));
    1623        1659 :                 if (MinHeatRecMdot < 0.0) MinHeatRecMdot = 0.0;
    1624             :             }
    1625             : 
    1626             :             //       Recalculate outlet water temperature with minimum flow rate (will normally match the max water outlet temp,
    1627             :             //       unless the inlet water temp is greater than the max outlet temp)
    1628             :             Real64 HRecRatio; // When maximum temperature is reached the amount of recovered heat has to be reduced
    1629             : 
    1630        1659 :             if ((MinHeatRecMdot > 0.0) && (HeatRecCp > 0.0)) {
    1631        1651 :                 HeatRecOutTemp = QHeatRecToWater / (MinHeatRecMdot * HeatRecCp) + HeatRecInTemp;
    1632        1651 :                 HRecRatio = heatRecMdot / MinHeatRecMdot;
    1633             :             } else {
    1634           8 :                 HeatRecOutTemp = HeatRecInTemp;
    1635           8 :                 HRecRatio = 0.0;
    1636             :             }
    1637        1659 :             QHeatRecToWater *= HRecRatio; // Scale heat recovery rate using HRecRatio. Don't adjust flow rate.
    1638             :         }
    1639             : 
    1640             :         //     Check water mass flow rate against minimum
    1641        3368 :         if (this->HeatRecMinMassFlowRate > heatRecMdot && heatRecMdot > 0.0) {
    1642           0 :             if (this->HRMinFlowErrorIndex == 0) {
    1643           0 :                 ShowWarningError(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1644           0 :                 ShowContinueError(state,
    1645           0 :                                   format("...Heat reclaim water flow rate is below the generators minimum mass flow rate of ({:.4T}).",
    1646           0 :                                          this->HeatRecMinMassFlowRate));
    1647           0 :                 ShowContinueError(state, format("...Heat reclaim water mass flow rate = {:.4T}.", heatRecMdot));
    1648           0 :                 ShowContinueErrorTimeStamp(state, "...Check inputs for heat recovery water flow rate.");
    1649             :             }
    1650           0 :             ShowRecurringWarningErrorAtEnd(
    1651             :                 state,
    1652           0 :                 "GENERATOR:MICROTURBINE \"" + this->Name +
    1653             :                     "\": Heat recovery water flow rate is below the generators minimum mass flow rate warning continues...",
    1654             :                 this->HRMinFlowErrorIndex,
    1655             :                 heatRecMdot,
    1656             :                 heatRecMdot);
    1657             :         }
    1658             : 
    1659             :         //     Check water mass flow rate against maximum
    1660        3368 :         if (heatRecMdot > this->HeatRecMaxMassFlowRate && heatRecMdot > 0.0) {
    1661           0 :             if (this->HRMaxFlowErrorIndex == 0) {
    1662           0 :                 ShowWarningError(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1663           0 :                 ShowContinueError(state,
    1664           0 :                                   format("...Heat reclaim water flow rate is above the generators maximum mass flow rate of ({:.4T}).",
    1665           0 :                                          this->HeatRecMaxMassFlowRate));
    1666           0 :                 ShowContinueError(state, format("...Heat reclaim water mass flow rate = {:.4T}.", heatRecMdot));
    1667           0 :                 ShowContinueErrorTimeStamp(state, "...Check inputs for heat recovery water flow rate.");
    1668             :             }
    1669           0 :             ShowRecurringWarningErrorAtEnd(
    1670             :                 state,
    1671           0 :                 "GENERATOR:MICROTURBINE \"" + this->Name +
    1672             :                     "\": Heat recovery water flow rate is above the generators maximum mass flow rate warning continues...",
    1673             :                 this->HRMaxFlowErrorIndex,
    1674             :                 heatRecMdot,
    1675             :                 heatRecMdot);
    1676             :         }
    1677             : 
    1678             :         //     Set report variables
    1679        3368 :         this->HeatRecInletTemp = HeatRecInTemp;
    1680        3368 :         this->HeatRecOutletTemp = HeatRecOutTemp;
    1681        3368 :         this->HeatRecMdot = heatRecMdot;
    1682        3368 :         this->QHeatRecovered = QHeatRecToWater;
    1683             : 
    1684             :     } // End of  IF (MTGenerator(GeneratorNum)%HeatRecActive) THEN
    1685             : 
    1686             :     //   Calculate combustion air outlet conditions if exhaust air calculations are active
    1687       18612 :     if (this->ExhAirCalcsActive) {
    1688             : 
    1689             :         Real64 ExhFlowFTemp; // Exhaust air flow rate as a function of temperature curve output
    1690             : 
    1691        8723 :         if (this->ExhFlowFTempCurveNum != 0) { // Exhaust Flow Rate versus Inlet Air Temp
    1692        8723 :             ExhFlowFTemp = Curve::CurveValue(state, this->ExhFlowFTempCurveNum, CombustionAirInletTemp);
    1693             :             //       Warn user if exhaust modifier curve output is less than or equal to 0
    1694        8723 :             if (ExhFlowFTemp <= 0.0) {
    1695           0 :                 if (this->ExhFlowFTempErrorIndex == 0) {
    1696           0 :                     ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1697           0 :                     ShowContinueError(
    1698             :                         state,
    1699           0 :                         format("...Exhaust Air Flow Rate Modifier (function of temperature) output is less than or equal to zero ({:.4T}).",
    1700           0 :                                ExhFlowFTemp));
    1701           0 :                     ShowContinueError(state, format("...Value occurs using a combustion inlet air temperature of {:.2T}.", CombustionAirInletTemp));
    1702           0 :                     ShowContinueErrorTimeStamp(state, "...Resetting curve output to zero and continuing simulation.");
    1703             :                 }
    1704           0 :                 ShowRecurringWarningErrorAtEnd(
    1705             :                     state,
    1706           0 :                     "GENERATOR:MICROTURBINE \"" + this->Name +
    1707             :                         "\": Exhaust Air Flow Rate Modifier (function of temperature) output is less than or equal to zero warning continues...",
    1708             :                     this->ExhFlowFTempErrorIndex,
    1709             :                     ExhFlowFTemp,
    1710             :                     ExhFlowFTemp);
    1711           0 :                 ExhFlowFTemp = 0.0;
    1712             :             }
    1713             :         } else {
    1714           0 :             ExhFlowFTemp = 1.0; // No curve input means modifier = 1.0 always
    1715             :         }
    1716             : 
    1717             :         Real64 ExhFlowFPLR; // Exhaust air flow rate as a function of part-load ratio curve output
    1718             : 
    1719        8723 :         if (this->ExhFlowFPLRCurveNum != 0) { // Exhaust Flow Rate versus Part-Load Ratio
    1720        8723 :             ExhFlowFPLR = Curve::CurveValue(state, this->ExhFlowFPLRCurveNum, PLR);
    1721             :             //       Warn user if exhaust modifier curve output is less than or equal to 0
    1722        8723 :             if (ExhFlowFPLR <= 0.0) {
    1723           0 :                 if (this->ExhFlowFPLRErrorIndex == 0) {
    1724           0 :                     ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1725           0 :                     ShowContinueError(
    1726             :                         state,
    1727           0 :                         format("...Exhaust Air Flow Rate Modifier (function of part-load ratio) output is less than or equal to zero ({:.4T}).",
    1728           0 :                                ExhFlowFPLR));
    1729           0 :                     ShowContinueError(state, format("...Value occurs using a part-load ratio of {:.2T}.", PLR));
    1730           0 :                     ShowContinueErrorTimeStamp(state, "...Resetting curve output to zero and continuing simulation.");
    1731             :                 }
    1732           0 :                 ShowRecurringWarningErrorAtEnd(state,
    1733           0 :                                                "GENERATOR:MICROTURBINE \"" + this->Name +
    1734             :                                                    "\": Exhaust Air Flow Rate Modifier (function of part-load ratio) output is less than or "
    1735             :                                                    "equal to zero warning continues...",
    1736             :                                                this->ExhFlowFPLRErrorIndex,
    1737             :                                                ExhFlowFPLR,
    1738             :                                                ExhFlowFPLR);
    1739           0 :                 ExhFlowFPLR = 0.0;
    1740             :             }
    1741             :         } else {
    1742           0 :             ExhFlowFPLR = 1.0; // No curve input means modifier = 1.0 always
    1743             :         }
    1744             : 
    1745             :         //     Calculate exhaust air mass flow, accounting for temperature and PLR modifier factors
    1746             :         // Actual exhaust air mass flow rate (accounting for temp and PLR modifier curves)
    1747        8723 :         Real64 ExhAirMassFlowRate = this->RefExhaustAirMassFlowRate * ExhFlowFTemp * ExhFlowFPLR;
    1748             :         //     Adjust for difference in air density at reference conditions versus actual inlet air conditions
    1749             : 
    1750             :         // Density of air at actual combustion inlet air conditions (kg/m3)
    1751        8723 :         Real64 AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state, CombustionAirInletPress, CombustionAirInletTemp, CombustionAirInletW);
    1752        8723 :         if (this->RefCombustAirInletDensity >= 0.0) {
    1753        8723 :             ExhAirMassFlowRate = max(0.0, ExhAirMassFlowRate * AirDensity / this->RefCombustAirInletDensity);
    1754             :         } else {
    1755           0 :             ExhAirMassFlowRate = 0.0;
    1756             :         }
    1757        8723 :         this->ExhaustAirMassFlowRate = ExhAirMassFlowRate;
    1758             : 
    1759             :         Real64 ExhAirTempFTemp; // Exhaust air temperature as a function of inlet air temp curve output
    1760             : 
    1761        8723 :         if (this->ExhAirTempFTempCurveNum != 0) { // Exhaust Air Temp versus Inlet Air Temp
    1762        8723 :             ExhAirTempFTemp = Curve::CurveValue(state, this->ExhAirTempFTempCurveNum, CombustionAirInletTemp);
    1763             :             //       Warn user if exhaust modifier curve output is less than or equal to 0
    1764        8723 :             if (ExhAirTempFTemp <= 0.0) {
    1765           0 :                 if (this->ExhTempFTempErrorIndex == 0) {
    1766           0 :                     ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1767           0 :                     ShowContinueError(
    1768             :                         state,
    1769           0 :                         format("...Exhaust Air Temperature Modifier (function of temperature) output is less than or equal to zero ({:.4T}).",
    1770           0 :                                ExhAirTempFTemp));
    1771           0 :                     ShowContinueError(state, format("...Value occurs using a combustion inlet air temperature of {:.2T}.", CombustionAirInletTemp));
    1772           0 :                     ShowContinueErrorTimeStamp(state, "...Resetting curve output to zero and continuing simulation.");
    1773             :                 }
    1774           0 :                 ShowRecurringWarningErrorAtEnd(state,
    1775           0 :                                                "GENERATOR:MICROTURBINE \"" + this->Name +
    1776             :                                                    "\": Exhaust Air Temperature Modifier (function of temperature) output is less than or equal "
    1777             :                                                    "to zero warning continues...",
    1778             :                                                this->ExhTempFTempErrorIndex,
    1779             :                                                ExhAirTempFTemp,
    1780             :                                                ExhAirTempFTemp);
    1781           0 :                 ExhAirTempFTemp = 0.0;
    1782             :             }
    1783             :         } else {
    1784           0 :             ExhAirTempFTemp = 1.0; // No curve input means modifier = 1.0 always
    1785             :         }
    1786             : 
    1787             :         Real64 ExhAirTempFPLR; // Exhaust air temperature as a function of part-load ratio curve output
    1788             : 
    1789        8723 :         if (this->ExhAirTempFPLRCurveNum != 0) { // Exhaust Air Temp versus Part-Load Ratio
    1790        8723 :             ExhAirTempFPLR = Curve::CurveValue(state, this->ExhAirTempFPLRCurveNum, PLR);
    1791             :             //       Warn user if exhaust modifier curve output is less than or equal to 0
    1792        8723 :             if (ExhAirTempFPLR <= 0.0) {
    1793           0 :                 if (this->ExhTempFPLRErrorIndex == 0) {
    1794           0 :                     ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1795           0 :                     ShowContinueError(
    1796             :                         state,
    1797           0 :                         format("...Exhaust Air Temperature Modifier (function of part-load ratio) output is less than or equal to zero ({:.4T}).",
    1798           0 :                                ExhAirTempFPLR));
    1799           0 :                     ShowContinueError(state, format("...Value occurs using a part-load ratio of {:.2T}.", PLR));
    1800           0 :                     ShowContinueErrorTimeStamp(state, "...Resetting curve output to zero and continuing simulation.");
    1801             :                 }
    1802           0 :                 ShowRecurringWarningErrorAtEnd(state,
    1803           0 :                                                "GENERATOR:MICROTURBINE \"" + this->Name +
    1804             :                                                    "\": Exhaust Air Temperature Modifier (function of part-load ratio) output is less than or "
    1805             :                                                    "equal to zero warning continues...",
    1806             :                                                this->ExhTempFPLRErrorIndex,
    1807             :                                                ExhAirTempFPLR,
    1808             :                                                ExhAirTempFPLR);
    1809           0 :                 ExhAirTempFPLR = 0.0;
    1810             :             }
    1811             :         } else {
    1812           0 :             ExhAirTempFPLR = 1.0; // No curve input means modifier = 1.0 always
    1813             :         }
    1814             : 
    1815        8723 :         if (ExhAirMassFlowRate <= 0.0) {
    1816           0 :             this->ExhaustAirTemperature = CombustionAirInletTemp;
    1817           0 :             this->ExhaustAirHumRat = CombustionAirInletW;
    1818             :         } else {
    1819             :             //       Calculate exhaust air temperature, accounting for inlet air temperature and PLR modifier factors
    1820             :             // Actual exhaust air temperature (accounting for temp and PLR modifier curves)
    1821        8723 :             Real64 ExhaustAirTemp = this->NomExhAirOutletTemp * ExhAirTempFTemp * ExhAirTempFPLR;
    1822        8723 :             this->ExhaustAirTemperature = ExhaustAirTemp;
    1823             :             //       Adjust exhaust air temperature if heat recovery to water is being done
    1824        8723 :             if (QHeatRecToWater > 0.0) {
    1825        3360 :                 Real64 CpAir = Psychrometrics::PsyCpAirFnW(CombustionAirInletW);
    1826        3360 :                 if (CpAir > 0.0) {
    1827        3360 :                     this->ExhaustAirTemperature = ExhaustAirTemp - QHeatRecToWater / (CpAir * ExhAirMassFlowRate);
    1828             :                 }
    1829             :             }
    1830             :             //       Calculate exhaust air humidity ratio
    1831             : 
    1832             :             // Heat of vaporization of water (J/kg)
    1833        8723 :             Real64 H2OHtOfVap = Psychrometrics::PsyHfgAirFnWTdb(1.0, 16.0); // W not used, passing 1.0 as dummy.
    1834             :             // Assume fuel is at 16C (ASHRAE HOF)
    1835        8723 :             if (H2OHtOfVap > 0.0) {
    1836       26169 :                 this->ExhaustAirHumRat = CombustionAirInletW + this->FuelMdot *
    1837       17446 :                                                                    ((fuelHigherHeatingValue - fuelLowerHeatingValue) * KJtoJ / H2OHtOfVap) /
    1838             :                                                                    ExhAirMassFlowRate;
    1839             :             } else {
    1840           0 :                 this->ExhaustAirHumRat = CombustionAirInletW;
    1841             :             }
    1842             :         }
    1843             : 
    1844        8723 :         if (this->ExhaustAirTemperature < CombustionAirInletTemp) {
    1845           0 :             if (this->ExhTempLTInletTempIndex == 0) {
    1846           0 :                 ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1847           0 :                 ShowContinueError(state,
    1848             :                                   "...The model has calculated the exhaust air temperature to be less than the combustion air inlet temperature.");
    1849           0 :                 ShowContinueError(state, format("...Value of exhaust air temperature   ={:.4T} C.", this->ExhaustAirTemperature));
    1850           0 :                 ShowContinueError(state, format("...Value of combustion air inlet temp ={:.4T} C.", CombustionAirInletTemp));
    1851           0 :                 ShowContinueErrorTimeStamp(state, "... Simulation will continue.");
    1852             :             }
    1853           0 :             ShowRecurringWarningErrorAtEnd(state,
    1854           0 :                                            "GENERATOR:MICROTURBINE \"" + this->Name +
    1855             :                                                "\": Exhaust air temperature less than combustion air inlet temperature warning continues...",
    1856             :                                            this->ExhTempLTInletTempIndex,
    1857             :                                            this->ExhaustAirTemperature,
    1858             :                                            this->ExhaustAirTemperature);
    1859             :         }
    1860             : 
    1861        8723 :         if (this->ExhaustAirHumRat < CombustionAirInletW) {
    1862           0 :             if (this->ExhHRLTInletHRIndex == 0) {
    1863           0 :                 ShowWarningMessage(state, "GENERATOR:MICROTURBINE \"" + this->Name + "\"");
    1864           0 :                 ShowContinueError(
    1865             :                     state, "...The model has calculated the exhaust air humidity ratio to be less than the combustion air inlet humidity ratio.");
    1866           0 :                 ShowContinueError(state, format("...Value of exhaust air humidity ratio          ={:.6T} kgWater/kgDryAir.", this->ExhaustAirHumRat));
    1867           0 :                 ShowContinueError(state, format("...Value of combustion air inlet humidity ratio ={:.6T} kgWater/kgDryAir.", CombustionAirInletW));
    1868           0 :                 ShowContinueErrorTimeStamp(state, "... Simulation will continue.");
    1869             :             }
    1870           0 :             ShowRecurringWarningErrorAtEnd(state,
    1871           0 :                                            "GENERATOR:MICROTURBINE \"" + this->Name +
    1872             :                                                "\": Exhaust air humidity ratio less than combustion air inlet humidity ratio warning continues...",
    1873             :                                            this->ExhHRLTInletHRIndex,
    1874             :                                            this->ExhaustAirHumRat,
    1875             :                                            this->ExhaustAirHumRat);
    1876             :         }
    1877             :     }
    1878             : }
    1879             : 
    1880       52096 : void MTGeneratorSpecs::UpdateMTGeneratorRecords(EnergyPlusData &state)
    1881             : {
    1882             :     // SUBROUTINE INFORMATION:
    1883             :     //       AUTHOR         R. Raustad/D. Shirey
    1884             :     //       DATE WRITTEN   Mar 2008
    1885             :     //       MODIFIED       na
    1886             :     //       RE-ENGINEERED  na
    1887             : 
    1888             :     // PURPOSE OF THIS SUBROUTINE:
    1889             :     //  Reporting and updating nodes if necessary.
    1890             : 
    1891       52096 :     if (this->HeatRecActive) {
    1892       19542 :         state.dataLoopNodes->Node(this->HeatRecOutletNodeNum).Temp = this->HeatRecOutletTemp;
    1893             :     }
    1894             : 
    1895       52096 :     if (this->ExhAirCalcsActive) {
    1896       27504 :         state.dataLoopNodes->Node(this->CombustionAirOutletNodeNum).MassFlowRate = this->ExhaustAirMassFlowRate;
    1897       27504 :         state.dataLoopNodes->Node(this->CombustionAirInletNodeNum).MassFlowRate = this->ExhaustAirMassFlowRate;
    1898             : 
    1899       27504 :         state.dataLoopNodes->Node(this->CombustionAirOutletNodeNum).Temp = this->ExhaustAirTemperature;
    1900       27504 :         state.dataLoopNodes->Node(this->CombustionAirOutletNodeNum).HumRat = this->ExhaustAirHumRat;
    1901       27504 :         state.dataLoopNodes->Node(this->CombustionAirOutletNodeNum).MassFlowRateMaxAvail =
    1902       27504 :             state.dataLoopNodes->Node(this->CombustionAirInletNodeNum).MassFlowRateMaxAvail;
    1903       27504 :         state.dataLoopNodes->Node(this->CombustionAirOutletNodeNum).MassFlowRateMinAvail =
    1904       27504 :             state.dataLoopNodes->Node(this->CombustionAirInletNodeNum).MassFlowRateMinAvail;
    1905             :     }
    1906             : 
    1907       52096 :     this->EnergyGen = this->ElecPowerGenerated * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    1908       52096 :     this->ExhaustEnergyRec = this->QHeatRecovered * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    1909       52096 :     this->FuelEnergyHHV = this->FuelEnergyUseRateHHV * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    1910       52096 :     if (this->FuelEnergyUseRateLHV > 0.0) {
    1911       18612 :         this->ElectricEfficiencyLHV = this->ElecPowerGenerated / this->FuelEnergyUseRateLHV;
    1912       18612 :         this->ThermalEfficiencyLHV = this->QHeatRecovered / this->FuelEnergyUseRateLHV;
    1913             :     } else {
    1914       33484 :         this->ElectricEfficiencyLHV = 0.0;
    1915       33484 :         this->ThermalEfficiencyLHV = 0.0;
    1916             :     }
    1917       52096 :     this->AncillaryEnergy = this->AncillaryPowerRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    1918       52096 :     this->StandbyEnergy = this->StandbyPowerRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    1919       52096 : }
    1920       52096 : void MTGeneratorSpecs::oneTimeInit(EnergyPlusData &state)
    1921             : {
    1922             : 
    1923      104192 :     std::string const RoutineName("InitMTGenerators");
    1924             :     bool errFlag;
    1925             : 
    1926       52096 :     if (this->myFlag) {
    1927           6 :         this->setupOutputVars(state);
    1928           6 :         this->myFlag = false;
    1929             :     }
    1930             : 
    1931       52096 :     if (this->MyPlantScanFlag && allocated(state.dataPlnt->PlantLoop) && this->HeatRecActive) {
    1932           2 :         errFlag = false;
    1933           2 :         PlantUtilities::ScanPlantLoopsForObject(
    1934             :             state, this->Name, DataPlant::PlantEquipmentType::Generator_MicroTurbine, this->HRPlantLoc, errFlag, _, _, _, _, _);
    1935           2 :         if (errFlag) {
    1936           0 :             ShowFatalError(state, "InitMTGenerators: Program terminated due to previous condition(s).");
    1937             :         }
    1938             : 
    1939           2 :         this->MyPlantScanFlag = false;
    1940             :     }
    1941             : 
    1942       52096 :     if (this->MySizeAndNodeInitFlag && (!this->MyPlantScanFlag) && this->HeatRecActive) {
    1943             : 
    1944             :         // size mass flow rate
    1945           6 :         Real64 rho = FluidProperties::GetDensityGlycol(state,
    1946           2 :                                                        state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
    1947             :                                                        DataGlobalConstants::InitConvTemp,
    1948           2 :                                                        state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
    1949           2 :                                                        RoutineName);
    1950             : 
    1951           2 :         this->DesignHeatRecMassFlowRate = rho * this->RefHeatRecVolFlowRate;
    1952           2 :         this->HeatRecMaxMassFlowRate = rho * this->HeatRecMaxVolFlowRate;
    1953             : 
    1954           2 :         PlantUtilities::InitComponentNodes(state, 0.0, this->HeatRecMaxMassFlowRate, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
    1955             : 
    1956           2 :         this->MySizeAndNodeInitFlag = false;
    1957             :     }
    1958       52096 : }
    1959             : 
    1960        2313 : } // namespace EnergyPlus::MicroturbineElectricGenerator

Generated by: LCOV version 1.13