LCOV - code coverage report
Current view: top level - EnergyPlus - ICEngineElectricGenerator.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 284 341 83.3 %
Date: 2023-01-17 19:17:23 Functions: 12 12 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/DataHVACGlobals.hh>
      60             : #include <EnergyPlus/DataIPShortCuts.hh>
      61             : #include <EnergyPlus/DataLoopNode.hh>
      62             : #include <EnergyPlus/FluidProperties.hh>
      63             : #include <EnergyPlus/General.hh>
      64             : #include <EnergyPlus/ICEngineElectricGenerator.hh>
      65             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      66             : #include <EnergyPlus/NodeInputManager.hh>
      67             : #include <EnergyPlus/OutputProcessor.hh>
      68             : #include <EnergyPlus/Plant/DataPlant.hh>
      69             : #include <EnergyPlus/PlantUtilities.hh>
      70             : #include <EnergyPlus/UtilityRoutines.hh>
      71             : 
      72             : namespace EnergyPlus {
      73             : 
      74             : namespace ICEngineElectricGenerator {
      75             : 
      76             :     // MODULE INFORMATION:
      77             :     //       AUTHOR         Dan Fisher
      78             :     //       DATE WRITTEN   Sept. 2000
      79             :     //       MODIFIED       na
      80             :     //       RE-ENGINEERED  na
      81             : 
      82             :     // PURPOSE OF THIS MODULE:
      83             :     // This module simulates the operation of IC ENGINE Generators.
      84             : 
      85             :     // METHODOLOGY EMPLOYED:
      86             :     // Once the ElectricPowerManager determines that the IC ENGINE Generator
      87             :     // is available to meet an electric load demand, it calls SimICEngineGenerator
      88             :     // which in turn calls the ICEngine Generator model.
      89             : 
      90       45006 :     PlantComponent *ICEngineGeneratorSpecs::factory(EnergyPlusData &state, std::string const &objectName)
      91             :     {
      92             :         // Process the input data for ICEGen if it hasn't been done already
      93       45006 :         if (state.dataICEngElectGen->getICEInput) {
      94           5 :             GetICEngineGeneratorInput(state);
      95           5 :             state.dataICEngElectGen->getICEInput = false;
      96             :         }
      97             : 
      98             :         // Now look for this particular generator in the list
      99       45006 :         for (auto &thisICE : state.dataICEngElectGen->ICEngineGenerator) {
     100       45006 :             if (thisICE.Name == objectName) {
     101       45006 :                 return &thisICE;
     102             :             }
     103             :         }
     104             :         // If we didn't find it, fatal
     105           0 :         ShowFatalError(state,
     106           0 :                        "LocalICEngineGeneratorFactory: Error getting inputs for internal combustion engine generator named: " +
     107             :                            objectName); // LCOV_EXCL_LINE
     108             :         // Shut up the compiler
     109             :         return nullptr; // LCOV_EXCL_LINE
     110             :     }
     111             : 
     112           5 :     void GetICEngineGeneratorInput(EnergyPlusData &state)
     113             :     {
     114             :         // SUBROUTINE INFORMATION:
     115             :         //       AUTHOR:          Dan Fisher
     116             :         //       DATE WRITTEN:    Sept. 2000
     117             : 
     118             :         // PURPOSE OF THIS SUBROUTINE:
     119             :         // This routine will get the input
     120             :         // required by the IC ENGINE Generator models.
     121             : 
     122             :         int genNum;                   // Generator counter
     123             :         int NumAlphas;                // Number of elements in the alpha array
     124             :         int NumNums;                  // Number of elements in the numeric array
     125             :         int IOStat;                   // IO Status when calling get input subroutine
     126          10 :         Array1D_string AlphArray(10); // character string data
     127          10 :         Array1D<Real64> NumArray(11); // numeric data
     128           5 :         bool ErrorsFound(false);      // error flag
     129             : 
     130           5 :         auto &ICEngineGenerator(state.dataICEngElectGen->ICEngineGenerator);
     131             : 
     132           5 :         state.dataIPShortCut->cCurrentModuleObject = "Generator:InternalCombustionEngine";
     133           5 :         state.dataICEngElectGen->NumICEngineGenerators =
     134           5 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
     135             : 
     136           5 :         if (state.dataICEngElectGen->NumICEngineGenerators <= 0) {
     137           0 :             ShowSevereError(state, "No " + state.dataIPShortCut->cCurrentModuleObject + " equipment specified in input file");
     138           0 :             ErrorsFound = true;
     139             :         }
     140             : 
     141             :         // ALLOCATE ARRAYS
     142           5 :         ICEngineGenerator.allocate(state.dataICEngElectGen->NumICEngineGenerators);
     143             : 
     144             :         // LOAD ARRAYS WITH IC ENGINE Generator CURVE FIT  DATA
     145          10 :         for (genNum = 1; genNum <= state.dataICEngElectGen->NumICEngineGenerators; ++genNum) {
     146          25 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     147           5 :                                                                      state.dataIPShortCut->cCurrentModuleObject,
     148             :                                                                      genNum,
     149             :                                                                      AlphArray,
     150             :                                                                      NumAlphas,
     151             :                                                                      NumArray,
     152             :                                                                      NumNums,
     153             :                                                                      IOStat,
     154             :                                                                      _,
     155           5 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     156           5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     157           5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     158           5 :             UtilityRoutines::IsNameEmpty(state, AlphArray(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
     159             : 
     160           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).Name = AlphArray(1);
     161             : 
     162           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).RatedPowerOutput = NumArray(1);
     163           5 :             if (NumArray(1) == 0.0) {
     164           0 :                 ShowSevereError(state, format("Invalid {}={:.2R}", state.dataIPShortCut->cNumericFieldNames(1), NumArray(1)));
     165           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     166           0 :                 ErrorsFound = true;
     167             :             }
     168             : 
     169             :             // Not sure what to do with electric nodes, so do not use optional arguments
     170           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).ElectricCircuitNode =
     171          10 :                 NodeInputManager::GetOnlySingleNode(state,
     172           5 :                                                     AlphArray(2),
     173             :                                                     ErrorsFound,
     174             :                                                     DataLoopNode::ConnectionObjectType::GeneratorInternalCombustionEngine,
     175           5 :                                                     AlphArray(1),
     176             :                                                     DataLoopNode::NodeFluidType::Electric,
     177             :                                                     DataLoopNode::ConnectionType::Electric,
     178             :                                                     NodeInputManager::CompFluidStream::Primary,
     179           5 :                                                     DataLoopNode::ObjectIsNotParent);
     180             : 
     181           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).MinPartLoadRat = NumArray(2);
     182           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).MaxPartLoadRat = NumArray(3);
     183           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).OptPartLoadRat = NumArray(4);
     184             : 
     185             :             // Load Special IC ENGINE Generator Curve Fit Inputs
     186           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).ElecOutputFuelCurve =
     187           5 :                 Curve::GetCurveIndex(state, AlphArray(3)); // convert curve name to number
     188           5 :             if (state.dataICEngElectGen->ICEngineGenerator(genNum).ElecOutputFuelCurve == 0) {
     189           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + '=' + AlphArray(3));
     190           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     191           0 :                 ErrorsFound = true;
     192             :             }
     193             : 
     194           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).RecJacHeattoFuelCurve =
     195           5 :                 Curve::GetCurveIndex(state, AlphArray(4)); // convert curve name to number
     196           5 :             if (state.dataICEngElectGen->ICEngineGenerator(genNum).RecJacHeattoFuelCurve == 0) {
     197           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(4) + '=' + AlphArray(4));
     198           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     199           0 :                 ErrorsFound = true;
     200             :             }
     201             : 
     202           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).RecLubeHeattoFuelCurve =
     203           5 :                 Curve::GetCurveIndex(state, AlphArray(5)); // convert curve name to number
     204           5 :             if (state.dataICEngElectGen->ICEngineGenerator(genNum).RecLubeHeattoFuelCurve == 0) {
     205           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(5) + '=' + AlphArray(5));
     206           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     207           0 :                 ErrorsFound = true;
     208             :             }
     209             : 
     210           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).TotExhausttoFuelCurve =
     211           5 :                 Curve::GetCurveIndex(state, AlphArray(6)); // convert curve name to number
     212           5 :             if (state.dataICEngElectGen->ICEngineGenerator(genNum).TotExhausttoFuelCurve == 0) {
     213           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(6) + '=' + AlphArray(6));
     214           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     215           0 :                 ErrorsFound = true;
     216             :             }
     217             : 
     218           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).ExhaustTempCurve =
     219           5 :                 Curve::GetCurveIndex(state, AlphArray(7)); // convert curve name to number
     220           5 :             if (state.dataICEngElectGen->ICEngineGenerator(genNum).ExhaustTempCurve == 0) {
     221           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(7) + '=' + AlphArray(7));
     222           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     223           0 :                 ErrorsFound = true;
     224             :             } else {
     225           5 :                 Real64 xValue = Curve::CurveValue(state, state.dataICEngElectGen->ICEngineGenerator(genNum).ExhaustTempCurve, 1.0);
     226           5 :                 if (xValue < ReferenceTemp) {
     227           0 :                     ShowSevereError(state, "GetICEngineGeneratorInput: " + state.dataIPShortCut->cAlphaFieldNames(7) + " output has very low value.");
     228           0 :                     ShowContinueError(state, format("...curve generates [{:.3R} C] at PLR=1.0", xValue));
     229           0 :                     ShowContinueError(state,
     230           0 :                                       format("...this is less than the Reference Temperature [{:.2R} C] and may cause errors.", ReferenceTemp));
     231             :                 }
     232             :             }
     233             : 
     234           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).UACoef(1) = NumArray(5);
     235           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).UACoef(2) = NumArray(6);
     236             : 
     237           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).MaxExhaustperPowerOutput = NumArray(7);
     238           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).DesignMinExitGasTemp = NumArray(8);
     239           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).FuelHeatingValue = NumArray(9);
     240           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).DesignHeatRecVolFlowRate = NumArray(10);
     241           5 :             if (state.dataICEngElectGen->ICEngineGenerator(genNum).DesignHeatRecVolFlowRate > 0.0) {
     242           3 :                 state.dataICEngElectGen->ICEngineGenerator(genNum).HeatRecActive = true;
     243           3 :                 state.dataICEngElectGen->ICEngineGenerator(genNum).HeatRecInletNodeNum =
     244           6 :                     NodeInputManager::GetOnlySingleNode(state,
     245           3 :                                                         AlphArray(8),
     246             :                                                         ErrorsFound,
     247             :                                                         DataLoopNode::ConnectionObjectType::GeneratorInternalCombustionEngine,
     248           3 :                                                         AlphArray(1),
     249             :                                                         DataLoopNode::NodeFluidType::Water,
     250             :                                                         DataLoopNode::ConnectionType::Inlet,
     251             :                                                         NodeInputManager::CompFluidStream::Primary,
     252           3 :                                                         DataLoopNode::ObjectIsNotParent);
     253           3 :                 if (state.dataICEngElectGen->ICEngineGenerator(genNum).HeatRecInletNodeNum == 0) {
     254           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(8) + '=' + AlphArray(8));
     255           0 :                     ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     256           0 :                     ErrorsFound = true;
     257             :                 }
     258           3 :                 state.dataICEngElectGen->ICEngineGenerator(genNum).HeatRecOutletNodeNum =
     259           6 :                     NodeInputManager::GetOnlySingleNode(state,
     260           3 :                                                         AlphArray(9),
     261             :                                                         ErrorsFound,
     262             :                                                         DataLoopNode::ConnectionObjectType::GeneratorInternalCombustionEngine,
     263           3 :                                                         AlphArray(1),
     264             :                                                         DataLoopNode::NodeFluidType::Water,
     265             :                                                         DataLoopNode::ConnectionType::Outlet,
     266             :                                                         NodeInputManager::CompFluidStream::Primary,
     267           3 :                                                         DataLoopNode::ObjectIsNotParent);
     268           3 :                 if (state.dataICEngElectGen->ICEngineGenerator(genNum).HeatRecOutletNodeNum == 0) {
     269           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(9) + '=' + AlphArray(9));
     270           0 :                     ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     271           0 :                     ErrorsFound = true;
     272             :                 }
     273           9 :                 BranchNodeConnections::TestCompSet(
     274           6 :                     state, state.dataIPShortCut->cCurrentModuleObject, AlphArray(1), AlphArray(8), AlphArray(9), "Heat Recovery Nodes");
     275           6 :                 PlantUtilities::RegisterPlantCompDesignFlow(state,
     276           3 :                                                             state.dataICEngElectGen->ICEngineGenerator(genNum).HeatRecInletNodeNum,
     277           3 :                                                             state.dataICEngElectGen->ICEngineGenerator(genNum).DesignHeatRecVolFlowRate);
     278             :             } else {
     279           2 :                 state.dataICEngElectGen->ICEngineGenerator(genNum).HeatRecActive = false;
     280           2 :                 state.dataICEngElectGen->ICEngineGenerator(genNum).HeatRecInletNodeNum = 0;
     281           2 :                 state.dataICEngElectGen->ICEngineGenerator(genNum).HeatRecOutletNodeNum = 0;
     282           2 :                 if (!state.dataIPShortCut->lAlphaFieldBlanks(8) || !state.dataIPShortCut->lAlphaFieldBlanks(9)) {
     283           0 :                     ShowWarningError(state,
     284           0 :                                      "Since Design Heat Flow Rate = 0.0, Heat Recovery inactive for " + state.dataIPShortCut->cCurrentModuleObject +
     285           0 :                                          '=' + AlphArray(1));
     286           0 :                     ShowContinueError(state, "However, Node names were specified for Heat Recovery inlet or outlet nodes");
     287             :                 }
     288             :             }
     289             : 
     290             :             // Validate fuel type input
     291           5 :             bool FuelTypeError(false);
     292           5 :             UtilityRoutines::ValidateFuelType(state, AlphArray(10), state.dataICEngElectGen->ICEngineGenerator(genNum).FuelType, FuelTypeError);
     293           5 :             if (FuelTypeError) {
     294           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(10) + '=' + AlphArray(10));
     295           0 :                 ShowContinueError(state, "Entered in " + state.dataIPShortCut->cCurrentModuleObject + '=' + AlphArray(1));
     296           0 :                 ErrorsFound = true;
     297           0 :                 FuelTypeError = false;
     298             :             }
     299             : 
     300           5 :             state.dataICEngElectGen->ICEngineGenerator(genNum).HeatRecMaxTemp = NumArray(11);
     301             :         }
     302             : 
     303           5 :         if (ErrorsFound) {
     304           0 :             ShowFatalError(state, "Errors found in processing input for " + state.dataIPShortCut->cCurrentModuleObject);
     305             :         }
     306           5 :     }
     307             : 
     308           5 :     void ICEngineGeneratorSpecs::setupOutputVars(EnergyPlusData &state)
     309             :     {
     310          10 :         SetupOutputVariable(state,
     311             :                             "Generator Produced AC Electricity Rate",
     312             :                             OutputProcessor::Unit::W,
     313             :                             this->ElecPowerGenerated,
     314             :                             OutputProcessor::SOVTimeStepType::System,
     315             :                             OutputProcessor::SOVStoreType::Average,
     316           5 :                             this->Name);
     317             : 
     318          10 :         SetupOutputVariable(state,
     319             :                             "Generator Produced AC Electricity Energy",
     320             :                             OutputProcessor::Unit::J,
     321             :                             this->ElecEnergyGenerated,
     322             :                             OutputProcessor::SOVTimeStepType::System,
     323             :                             OutputProcessor::SOVStoreType::Summed,
     324             :                             this->Name,
     325             :                             _,
     326             :                             "ElectricityProduced",
     327             :                             "COGENERATION",
     328             :                             _,
     329           5 :                             "Plant");
     330             : 
     331          15 :         SetupOutputVariable(state,
     332          10 :                             "Generator " + this->FuelType + " Rate",
     333             :                             OutputProcessor::Unit::W,
     334             :                             this->FuelEnergyUseRate,
     335             :                             OutputProcessor::SOVTimeStepType::System,
     336             :                             OutputProcessor::SOVStoreType::Average,
     337             :                             this->Name);
     338             : 
     339          15 :         SetupOutputVariable(state,
     340          10 :                             "Generator " + this->FuelType + " Energy",
     341             :                             OutputProcessor::Unit::J,
     342             :                             this->FuelEnergy,
     343             :                             OutputProcessor::SOVTimeStepType::System,
     344             :                             OutputProcessor::SOVStoreType::Summed,
     345             :                             this->Name,
     346             :                             _,
     347             :                             this->FuelType,
     348             :                             "COGENERATION",
     349             :                             _,
     350             :                             "Plant");
     351             : 
     352             :         //    general fuel use report to match other generators.
     353          10 :         SetupOutputVariable(state,
     354             :                             "Generator Fuel HHV Basis Rate",
     355             :                             OutputProcessor::Unit::W,
     356             :                             this->FuelEnergyUseRate,
     357             :                             OutputProcessor::SOVTimeStepType::System,
     358             :                             OutputProcessor::SOVStoreType::Average,
     359           5 :                             this->Name);
     360             : 
     361          10 :         SetupOutputVariable(state,
     362             :                             "Generator Fuel HHV Basis Energy",
     363             :                             OutputProcessor::Unit::J,
     364             :                             this->FuelEnergy,
     365             :                             OutputProcessor::SOVTimeStepType::System,
     366             :                             OutputProcessor::SOVStoreType::Summed,
     367           5 :                             this->Name);
     368             : 
     369          15 :         SetupOutputVariable(state,
     370          10 :                             "Generator " + this->FuelType + " Mass Flow Rate",
     371             :                             OutputProcessor::Unit::kg_s,
     372             :                             this->FuelMdot,
     373             :                             OutputProcessor::SOVTimeStepType::System,
     374             :                             OutputProcessor::SOVStoreType::Average,
     375             :                             this->Name);
     376             : 
     377          10 :         SetupOutputVariable(state,
     378             :                             "Generator Exhaust Air Temperature",
     379             :                             OutputProcessor::Unit::C,
     380             :                             this->ExhaustStackTemp,
     381             :                             OutputProcessor::SOVTimeStepType::System,
     382             :                             OutputProcessor::SOVStoreType::Average,
     383           5 :                             this->Name);
     384             : 
     385           5 :         if (this->HeatRecActive) {
     386           6 :             SetupOutputVariable(state,
     387             :                                 "Generator Heat Recovery Mass Flow Rate",
     388             :                                 OutputProcessor::Unit::kg_s,
     389             :                                 this->HeatRecMdotActual,
     390             :                                 OutputProcessor::SOVTimeStepType::System,
     391             :                                 OutputProcessor::SOVStoreType::Average,
     392           3 :                                 this->Name);
     393             : 
     394           6 :             SetupOutputVariable(state,
     395             :                                 "Generator Jacket Heat Recovery Rate",
     396             :                                 OutputProcessor::Unit::W,
     397             :                                 this->QJacketRecovered,
     398             :                                 OutputProcessor::SOVTimeStepType::System,
     399             :                                 OutputProcessor::SOVStoreType::Average,
     400           3 :                                 this->Name);
     401             : 
     402           6 :             SetupOutputVariable(state,
     403             :                                 "Generator Jacket Heat Recovery Energy",
     404             :                                 OutputProcessor::Unit::J,
     405             :                                 this->JacketEnergyRec,
     406             :                                 OutputProcessor::SOVTimeStepType::System,
     407             :                                 OutputProcessor::SOVStoreType::Summed,
     408             :                                 this->Name,
     409             :                                 _,
     410             :                                 "ENERGYTRANSFER",
     411             :                                 "HEATRECOVERY",
     412             :                                 _,
     413           3 :                                 "Plant");
     414             : 
     415           6 :             SetupOutputVariable(state,
     416             :                                 "Generator Lube Heat Recovery Rate",
     417             :                                 OutputProcessor::Unit::W,
     418             :                                 this->QLubeOilRecovered,
     419             :                                 OutputProcessor::SOVTimeStepType::System,
     420             :                                 OutputProcessor::SOVStoreType::Average,
     421           3 :                                 this->Name);
     422             : 
     423           6 :             SetupOutputVariable(state,
     424             :                                 "Generator Lube Heat Recovery Energy",
     425             :                                 OutputProcessor::Unit::J,
     426             :                                 this->LubeOilEnergyRec,
     427             :                                 OutputProcessor::SOVTimeStepType::System,
     428             :                                 OutputProcessor::SOVStoreType::Summed,
     429             :                                 this->Name,
     430             :                                 _,
     431             :                                 "ENERGYTRANSFER",
     432             :                                 "HEATRECOVERY",
     433             :                                 _,
     434           3 :                                 "Plant");
     435             : 
     436           6 :             SetupOutputVariable(state,
     437             :                                 "Generator Exhaust Heat Recovery Rate",
     438             :                                 OutputProcessor::Unit::W,
     439             :                                 this->QExhaustRecovered,
     440             :                                 OutputProcessor::SOVTimeStepType::System,
     441             :                                 OutputProcessor::SOVStoreType::Average,
     442           3 :                                 this->Name);
     443             : 
     444           6 :             SetupOutputVariable(state,
     445             :                                 "Generator Exhaust Heat Recovery Energy",
     446             :                                 OutputProcessor::Unit::J,
     447             :                                 this->ExhaustEnergyRec,
     448             :                                 OutputProcessor::SOVTimeStepType::System,
     449             :                                 OutputProcessor::SOVStoreType::Summed,
     450             :                                 this->Name,
     451             :                                 _,
     452             :                                 "ENERGYTRANSFER",
     453             :                                 "HEATRECOVERY",
     454             :                                 _,
     455           3 :                                 "Plant");
     456             : 
     457           6 :             SetupOutputVariable(state,
     458             :                                 "Generator Produced Thermal Rate",
     459             :                                 OutputProcessor::Unit::W,
     460             :                                 this->QTotalHeatRecovered,
     461             :                                 OutputProcessor::SOVTimeStepType::System,
     462             :                                 OutputProcessor::SOVStoreType::Average,
     463           3 :                                 this->Name);
     464             : 
     465           6 :             SetupOutputVariable(state,
     466             :                                 "Generator Produced Thermal Energy",
     467             :                                 OutputProcessor::Unit::J,
     468             :                                 this->TotalHeatEnergyRec,
     469             :                                 OutputProcessor::SOVTimeStepType::System,
     470             :                                 OutputProcessor::SOVStoreType::Summed,
     471           3 :                                 this->Name);
     472             : 
     473           6 :             SetupOutputVariable(state,
     474             :                                 "Generator Heat Recovery Inlet Temperature",
     475             :                                 OutputProcessor::Unit::C,
     476             :                                 this->HeatRecInletTemp,
     477             :                                 OutputProcessor::SOVTimeStepType::System,
     478             :                                 OutputProcessor::SOVStoreType::Average,
     479           3 :                                 this->Name);
     480             : 
     481           6 :             SetupOutputVariable(state,
     482             :                                 "Generator Heat Recovery Outlet Temperature",
     483             :                                 OutputProcessor::Unit::C,
     484             :                                 this->HeatRecOutletTemp,
     485             :                                 OutputProcessor::SOVTimeStepType::System,
     486             :                                 OutputProcessor::SOVStoreType::Average,
     487           3 :                                 this->Name);
     488             :         }
     489           5 :     }
     490             : 
     491          15 :     void ICEngineGeneratorSpecs::getDesignCapacities(
     492             :         [[maybe_unused]] EnergyPlusData &state, const EnergyPlus::PlantLocation &, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad)
     493             :     {
     494          15 :         MaxLoad = 0.0;
     495          15 :         MinLoad = 0.0;
     496          15 :         OptLoad = 0.0;
     497          15 :     }
     498             : 
     499      107671 :     void ICEngineGeneratorSpecs::simulate(EnergyPlusData &state,
     500             :                                           [[maybe_unused]] const EnergyPlus::PlantLocation &calledFromLocation,
     501             :                                           bool FirstHVACIteration,
     502             :                                           [[maybe_unused]] Real64 &CurLoad,
     503             :                                           [[maybe_unused]] bool RunFlag)
     504             :     {
     505             :         // empty function to emulate current behavior as of conversion to using the PlantComponent calling structure.
     506             :         // calls from the plant side only update the plant nodes.
     507             :         // calls from the ElectricPowerServiceManger call the init, calc, and update worker functions directly.
     508             : 
     509      107671 :         PlantUtilities::UpdateComponentHeatRecoverySide(state,
     510             :                                                         this->HRPlantLoc.loopNum,
     511             :                                                         this->HRPlantLoc.loopSideNum,
     512             :                                                         DataPlant::PlantEquipmentType::Generator_ICEngine,
     513             :                                                         this->HeatRecInletNodeNum,
     514             :                                                         this->HeatRecOutletNodeNum,
     515             :                                                         this->QTotalHeatRecovered,
     516             :                                                         this->HeatRecInletTemp,
     517             :                                                         this->HeatRecOutletTemp,
     518             :                                                         this->HeatRecMdotActual,
     519             :                                                         FirstHVACIteration);
     520      107671 :     }
     521             : 
     522       45003 :     void ICEngineGeneratorSpecs::CalcICEngineGeneratorModel(EnergyPlusData &state, bool const RunFlag, Real64 const MyLoad)
     523             :     {
     524             :         // SUBROUTINE INFORMATION:
     525             :         //       AUTHOR         Dan Fisher
     526             :         //       DATE WRITTEN   Sept. 2000
     527             :         //       MODIFIED     na
     528             :         //       RE-ENGINEERED
     529             : 
     530             :         // PURPOSE OF THIS SUBROUTINE:
     531             :         // simulate a IC ENGINE generator using the BLAST model
     532             : 
     533             :         // METHODOLOGY EMPLOYED:
     534             :         // curve fit of performance data:
     535             : 
     536       45003 :         constexpr Real64 ExhaustCP(1.047); // Exhaust Gas Specific Heat (J/kg-K)
     537       45003 :         constexpr Real64 KJtoJ(1000.0);    // convert Kjoules to joules
     538             : 
     539             :         // Heat Recovery Fluid Mass FlowRate (kg/s)
     540             :         Real64 HeatRecMdot;
     541             : 
     542             :         // Heat Recovery Fluid Inlet Temperature (C)
     543             :         Real64 HeatRecInTemp;
     544             : 
     545       45003 :         if (this->HeatRecActive) {
     546       27609 :             int HeatRecInNode = this->HeatRecInletNodeNum;
     547       27609 :             HeatRecInTemp = state.dataLoopNodes->Node(HeatRecInNode).Temp;
     548       27609 :             HeatRecMdot = state.dataLoopNodes->Node(HeatRecInNode).MassFlowRate;
     549             : 
     550             :         } else {
     551       17394 :             HeatRecInTemp = 0.0;
     552       17394 :             HeatRecMdot = 0.0;
     553             :         }
     554             : 
     555             :         // If no loop demand or Generator OFF, return
     556       45003 :         if (!RunFlag) {
     557       35242 :             this->ElecPowerGenerated = 0.0;
     558       35242 :             this->ElecEnergyGenerated = 0.0;
     559       35242 :             this->HeatRecInletTemp = HeatRecInTemp;
     560       35242 :             this->HeatRecOutletTemp = HeatRecInTemp;
     561       35242 :             this->HeatRecMdotActual = 0.0;
     562       35242 :             this->QJacketRecovered = 0.0;
     563       35242 :             this->QExhaustRecovered = 0.0;
     564       35242 :             this->QLubeOilRecovered = 0.0;
     565       35242 :             this->QTotalHeatRecovered = 0.0;
     566       35242 :             this->JacketEnergyRec = 0.0;
     567       35242 :             this->ExhaustEnergyRec = 0.0;
     568       35242 :             this->LubeOilEnergyRec = 0.0;
     569       35242 :             this->TotalHeatEnergyRec = 0.0;
     570       35242 :             this->FuelEnergyUseRate = 0.0;
     571       35242 :             this->FuelEnergy = 0.0;
     572       35242 :             this->FuelMdot = 0.0;
     573       35242 :             this->ExhaustStackTemp = 0.0;
     574             : 
     575       35242 :             return;
     576             :         }
     577             : 
     578             :         // Generator output (W)
     579        9761 :         Real64 elecPowerGenerated = min(MyLoad, this->RatedPowerOutput);
     580        9761 :         elecPowerGenerated = max(elecPowerGenerated, 0.0);
     581             : 
     582             :         // Generator operating part load ratio
     583        9761 :         Real64 PLR = min(elecPowerGenerated / this->RatedPowerOutput, this->MaxPartLoadRat);
     584        9761 :         PLR = max(PLR, this->MinPartLoadRat);
     585        9761 :         elecPowerGenerated = PLR * this->RatedPowerOutput;
     586             : 
     587             :         // DETERMINE FUEL CONSUMED AND AVAILABLE WASTE HEAT
     588             : 
     589             :         // Use Curve fit to determine Fuel Energy Input.  For electric power generated in Watts, the fuel
     590             :         // energy input is calculated in J/s.  The PLBasedFuelInputCurve selects ratio of fuel flow (J/s)/power generated (J/s).
     591             :         Real64 fuelEnergyUseRate; // IC ENGINE fuel use rate (W)
     592        9761 :         if (PLR > 0.0) {
     593             :             // (RELDC) Ratio of generator output to Fuel Energy Input
     594        9761 :             Real64 elecOutputFuelRat = Curve::CurveValue(state, this->ElecOutputFuelCurve, PLR);
     595        9761 :             fuelEnergyUseRate = elecPowerGenerated / elecOutputFuelRat;
     596             :         } else {
     597           0 :             fuelEnergyUseRate = 0.0;
     598             :         }
     599             : 
     600             :         // Use Curve fit to determine heat recovered in the water jacket.  This curve calculates the water jacket heat recovered (J/s) by
     601             :         // multiplying the total fuel input (J/s) by the fraction of that power that could be recovered in the water jacket at that
     602             :         // particular part load.
     603             : 
     604             :         // (RJACDC) Ratio of Recoverable Jacket Heat to Fuel Energy Input
     605        9761 :         Real64 recJacHeattoFuelRat = Curve::CurveValue(state, this->RecJacHeattoFuelCurve, PLR);
     606             : 
     607             :         // water jacket heat recovered (W)
     608        9761 :         Real64 QJacketRec = fuelEnergyUseRate * recJacHeattoFuelRat;
     609             : 
     610             :         // Use Curve fit to determine Heat Recovered Lubricant heat.  This curve calculates the lube heat recovered (J/s) by
     611             :         // multiplying the total fuel input (J/s) by the fraction of that power that could be recovered in the lube oil at that
     612             :         // particular part load.
     613             :         // (RLUBDC) Ratio of Recoverable Lube Oil Heat to Fuel Energy Input
     614        9761 :         Real64 recLubeHeattoFuelRat = Curve::CurveValue(state, this->RecLubeHeattoFuelCurve, PLR);
     615             : 
     616             :         // lube oil cooler heat recovered (W)
     617        9761 :         Real64 QLubeOilRec = fuelEnergyUseRate * recLubeHeattoFuelRat;
     618             : 
     619             :         // Use Curve fit to determine Heat Recovered from the exhaust.  This curve calculates the  heat recovered (J/s) by
     620             :         // multiplying the total fuel input (J/s) by the fraction of that power that could be recovered in the exhaust at that
     621             :         // particular part load.
     622             : 
     623             :         // (REXDC) Total Exhaust Energy Input to Fuel Energy Input
     624        9761 :         Real64 totExhausttoFuelRat = Curve::CurveValue(state, this->TotExhausttoFuelCurve, PLR);
     625             : 
     626             :         // total engine exhaust heat (W)
     627        9761 :         Real64 QExhaustTotal = fuelEnergyUseRate * totExhausttoFuelRat;
     628             : 
     629             :         // exhaust gas heat recovered (W)
     630             :         Real64 QExhaustRec;
     631             : 
     632             :         // engine stack temp. (C)
     633        9761 :         Real64 exhaustStackTemp = 0.0;
     634             : 
     635             :         // Use Curve fit to determine Exhaust Temperature in C.  The temperature is simply a curve fit
     636             :         // of the exhaust temperature in C to the part load ratio.
     637        9761 :         if (PLR > 0.0) {
     638             :             // (TEX) Exhaust Gas Temp
     639        9761 :             Real64 exhaustTemp = Curve::CurveValue(state, this->ExhaustTempCurve, PLR);
     640             : 
     641        9761 :             if (exhaustTemp > ReferenceTemp) {
     642             : 
     643             :                 // exhaust gas mass flow rate (kg/s)
     644        9761 :                 Real64 ExhaustGasFlow = QExhaustTotal / (ExhaustCP * (exhaustTemp - ReferenceTemp));
     645             : 
     646             :                 // Use Curve fit to determine stack exhaustTemp after heat recovery
     647             :                 // (UACDC) exhaust gas Heat Exchanger UA
     648        9761 :                 Real64 UA_loc = this->UACoef(1) * std::pow(this->RatedPowerOutput, this->UACoef(2));
     649             : 
     650             :                 // design engine stact saturated steam exhaustTemp. (C)
     651        9761 :                 Real64 designMinExitGasTemp = this->DesignMinExitGasTemp;
     652             : 
     653        9761 :                 exhaustStackTemp = designMinExitGasTemp +
     654       19522 :                                    (exhaustTemp - designMinExitGasTemp) /
     655        9761 :                                        std::exp(UA_loc / (max(ExhaustGasFlow, this->MaxExhaustperPowerOutput * this->RatedPowerOutput) * ExhaustCP));
     656             : 
     657        9761 :                 QExhaustRec = max(ExhaustGasFlow * ExhaustCP * (exhaustTemp - exhaustStackTemp), 0.0);
     658             :             } else {
     659           0 :                 if (this->ErrExhaustTempIndex == 0) {
     660           0 :                     ShowWarningMessage(
     661           0 :                         state, "CalcICEngineGeneratorModel: " + this->TypeOf + "=\"" + this->Name + "\" low Exhaust Temperature from Curve Value");
     662           0 :                     ShowContinueError(state, format("...curve generated temperature=[{:.3R} C], PLR=[{:.3R}].", exhaustTemp, PLR));
     663           0 :                     ShowContinueError(state, "...simulation will continue with exhaust heat reclaim set to 0.");
     664             :                 }
     665           0 :                 ShowRecurringWarningErrorAtEnd(state,
     666           0 :                                                "CalcICEngineGeneratorModel: " + this->TypeOf + "=\"" + this->Name +
     667             :                                                    "\" low Exhaust Temperature continues...",
     668             :                                                this->ErrExhaustTempIndex,
     669             :                                                exhaustTemp,
     670             :                                                exhaustTemp,
     671             :                                                _,
     672             :                                                "[C]",
     673             :                                                "[C]");
     674           0 :                 QExhaustRec = 0.0;
     675           0 :                 exhaustStackTemp = this->DesignMinExitGasTemp;
     676             :             }
     677             :         } else {
     678           0 :             QExhaustRec = 0.0;
     679             :             // Bug exhaustStackTemp not set but used below
     680             :         }
     681             : 
     682        9761 :         Real64 qTotalHeatRecovered = QExhaustRec + QLubeOilRec + QJacketRec;
     683             : 
     684             :         // When Max Temp is reached the amount of recovered heat has to be reduced.
     685             :         Real64 HRecRatio;
     686             : 
     687        9761 :         if (this->HeatRecActive) {
     688        7315 :             this->CalcICEngineGenHeatRecovery(state, qTotalHeatRecovered, HeatRecMdot, HRecRatio);
     689        7315 :             QExhaustRec *= HRecRatio;
     690        7315 :             QLubeOilRec *= HRecRatio;
     691        7315 :             QJacketRec *= HRecRatio;
     692        7315 :             qTotalHeatRecovered *= HRecRatio;
     693             :         } else {
     694        2446 :             this->HeatRecInletTemp = HeatRecInTemp;
     695        2446 :             this->HeatRecOutletTemp = HeatRecInTemp;
     696        2446 :             this->HeatRecMdotActual = HeatRecMdot;
     697             :         }
     698             : 
     699             :         // Calculate Energy
     700             :         // Generator output (J)
     701        9761 :         Real64 ElectricEnergyGen = elecPowerGenerated * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
     702             : 
     703             :         // IC ENGINE fuel use (J)
     704        9761 :         Real64 FuelEnergyUsed = fuelEnergyUseRate * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
     705             : 
     706             :         // water jacket heat recovered (J)
     707        9761 :         Real64 jacketEnergyRec = QJacketRec * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
     708             : 
     709             :         // lube oil cooler heat recovered (J)
     710        9761 :         Real64 lubeOilEnergyRec = QLubeOilRec * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
     711             : 
     712             :         // exhaust gas heat recovered (J)
     713        9761 :         Real64 exhaustEnergyRec = QExhaustRec * state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
     714        9761 :         this->ElecPowerGenerated = elecPowerGenerated;
     715        9761 :         this->ElecEnergyGenerated = ElectricEnergyGen;
     716        9761 :         this->QJacketRecovered = QJacketRec;
     717        9761 :         this->QLubeOilRecovered = QLubeOilRec;
     718        9761 :         this->QExhaustRecovered = QExhaustRec;
     719        9761 :         this->QTotalHeatRecovered = qTotalHeatRecovered;
     720        9761 :         this->JacketEnergyRec = jacketEnergyRec;
     721        9761 :         this->LubeOilEnergyRec = lubeOilEnergyRec;
     722        9761 :         this->ExhaustEnergyRec = exhaustEnergyRec;
     723        9761 :         this->QTotalHeatRecovered = (QExhaustRec + QLubeOilRec + QJacketRec);
     724        9761 :         this->TotalHeatEnergyRec = (exhaustEnergyRec + lubeOilEnergyRec + jacketEnergyRec);
     725        9761 :         this->FuelEnergyUseRate = std::abs(fuelEnergyUseRate);
     726        9761 :         this->FuelEnergy = std::abs(FuelEnergyUsed);
     727             : 
     728             :         // Heating Value of Fuel in kJ/kg
     729        9761 :         Real64 fuelHeatingValue = this->FuelHeatingValue;
     730             : 
     731        9761 :         this->FuelMdot = std::abs(fuelEnergyUseRate) / (fuelHeatingValue * KJtoJ);
     732        9761 :         this->ExhaustStackTemp = exhaustStackTemp;
     733             :     }
     734             : 
     735        7315 :     void ICEngineGeneratorSpecs::CalcICEngineGenHeatRecovery(EnergyPlusData &state,
     736             :                                                              Real64 const EnergyRecovered,
     737             :                                                              Real64 const HeatRecMdot,
     738             :                                                              Real64 &HRecRatio)
     739             :     {
     740             :         // SUBROUTINE INFORMATION:
     741             :         //       AUTHOR:          Brandon Anderson
     742             :         //       DATE WRITTEN:    November 2000
     743             : 
     744             :         // PURPOSE OF THIS SUBROUTINE:
     745             :         // To perform heat recovery calculations and node updates
     746             : 
     747             :         // METHODOLOGY EMPLOYED: This routine is required for the heat recovery loop.
     748             :         // It works in conjunction with the Heat Recovery Manager, and the PlantWaterHeater.
     749             :         // The chiller sets the flow on the loop first by the input design flow rate and then
     750             :         // performs a check to verify that
     751             : 
     752             :         static constexpr std::string_view RoutineName("CalcICEngineGeneratorModel");
     753             : 
     754             :         // Need to set the HeatRecRatio to 1.0 if it is not modified
     755        7315 :         HRecRatio = 1.0;
     756             : 
     757        7315 :         Real64 HeatRecInTemp = state.dataLoopNodes->Node(this->HeatRecInletNodeNum).Temp;
     758       14630 :         Real64 HeatRecCp = FluidProperties::GetSpecificHeatGlycol(state,
     759        7315 :                                                                   state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
     760             :                                                                   HeatRecInTemp,
     761        7315 :                                                                   state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
     762        7315 :                                                                   RoutineName);
     763             : 
     764             :         // Don't divide by zero - Note This also results in no heat recovery when
     765             :         //  design Mdot for Heat Recovery - Specified on Chiller Input - is zero
     766             :         //  In order to see what minimum heat recovery flow rate is for the design temperature
     767             :         //  The design heat recovery flow rate can be set very small, but greater than zero.
     768             : 
     769             :         Real64 HeatRecOutTemp;
     770             : 
     771        7315 :         if ((HeatRecMdot > 0) && (HeatRecCp > 0)) {
     772        7315 :             HeatRecOutTemp = (EnergyRecovered) / (HeatRecMdot * HeatRecCp) + HeatRecInTemp;
     773             :         } else {
     774           0 :             HeatRecOutTemp = HeatRecInTemp;
     775             :         }
     776             : 
     777             :         // Note: check to make sure the Max Temperature was not exceeded
     778        7315 :         if (HeatRecOutTemp > this->HeatRecMaxTemp) {
     779             :             Real64 MinHeatRecMdot;
     780        2314 :             if (this->HeatRecMaxTemp != HeatRecInTemp) {
     781        2314 :                 MinHeatRecMdot = (EnergyRecovered) / (HeatRecCp * (this->HeatRecMaxTemp - HeatRecInTemp));
     782        2314 :                 if (MinHeatRecMdot < 0.0) MinHeatRecMdot = 0.0;
     783             :             } else {
     784           0 :                 MinHeatRecMdot = 0.0;
     785             :             }
     786             : 
     787             :             // Recalculate Outlet Temperature, with adjusted flowrate
     788        2314 :             if ((MinHeatRecMdot > 0.0) && (HeatRecCp > 0.0)) {
     789        2314 :                 HeatRecOutTemp = (EnergyRecovered) / (MinHeatRecMdot * HeatRecCp) + HeatRecInTemp;
     790        2314 :                 HRecRatio = HeatRecMdot / MinHeatRecMdot;
     791             :             } else {
     792           0 :                 HeatRecOutTemp = HeatRecInTemp;
     793           0 :                 HRecRatio = 0.0;
     794             :             }
     795             :         }
     796             : 
     797             :         // Update global variables for reporting later
     798        7315 :         this->HeatRecInletTemp = HeatRecInTemp;
     799        7315 :         this->HeatRecOutletTemp = HeatRecOutTemp;
     800        7315 :         this->HeatRecMdotActual = HeatRecMdot;
     801        7315 :     }
     802             : 
     803       45003 :     void ICEngineGeneratorSpecs::InitICEngineGenerators(EnergyPlusData &state, bool const RunFlag, bool const FirstHVACIteration)
     804             :     {
     805             : 
     806             :         // SUBROUTINE INFORMATION:
     807             :         //       AUTHOR         Dan Fisher
     808             :         //       DATE WRITTEN   Oct 2000
     809             :         //       MODIFIED       na
     810             :         //       RE-ENGINEERED  Brent Griffith, Sept 2010, plant upgrades, generalize fluid props
     811             : 
     812             :         // PURPOSE OF THIS SUBROUTINE:
     813             :         // This subroutine is for initializations of the IC ENGINE generators.
     814             : 
     815             :         // METHODOLOGY EMPLOYED:
     816             :         // Uses the status flags to trigger initializations.
     817             : 
     818       45003 :         this->oneTimeInit(state); // end one time inits
     819             : 
     820             :         // Do the Begin Environment initializations
     821       45003 :         if (state.dataGlobal->BeginEnvrnFlag && this->MyEnvrnFlag && this->HeatRecActive) {
     822          22 :             int HeatRecInletNode = this->HeatRecInletNodeNum;
     823          22 :             int HeatRecOutletNode = this->HeatRecOutletNodeNum;
     824             :             // set the node Temperature, assuming freeze control
     825          22 :             state.dataLoopNodes->Node(HeatRecInletNode).Temp = 20.0;
     826          22 :             state.dataLoopNodes->Node(HeatRecOutletNode).Temp = 20.0;
     827             :             // set the node max and min mass flow rates
     828          22 :             PlantUtilities::InitComponentNodes(state, 0.0, this->DesignHeatRecMassFlowRate, HeatRecInletNode, HeatRecOutletNode);
     829             : 
     830          22 :             this->MyEnvrnFlag = false;
     831             :         } // end environmental inits
     832             : 
     833       45003 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     834       44582 :             this->MyEnvrnFlag = true;
     835             :         }
     836             : 
     837       45003 :         if (this->HeatRecActive) {
     838       27609 :             if (FirstHVACIteration) {
     839             :                 Real64 mdot;
     840       17956 :                 if (RunFlag) {
     841        4766 :                     mdot = this->DesignHeatRecMassFlowRate;
     842             :                 } else {
     843       13190 :                     mdot = 0.0;
     844             :                 }
     845       17956 :                 PlantUtilities::SetComponentFlowRate(state, mdot, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum, this->HRPlantLoc);
     846             : 
     847             :             } else {
     848        9653 :                 PlantUtilities::SetComponentFlowRate(
     849             :                     state, this->HeatRecMdotActual, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum, this->HRPlantLoc);
     850             :             }
     851             :         }
     852       45003 :     }
     853             : 
     854       45003 :     void ICEngineGeneratorSpecs::update(EnergyPlusData &state)
     855             :     {
     856       45003 :         if (this->HeatRecActive) {
     857       27609 :             int HeatRecOutletNode = this->HeatRecOutletNodeNum;
     858       27609 :             state.dataLoopNodes->Node(HeatRecOutletNode).Temp = this->HeatRecOutletTemp;
     859             :         }
     860       45003 :     }
     861       45003 :     void ICEngineGeneratorSpecs::oneTimeInit(EnergyPlusData &state)
     862             :     {
     863             :         static constexpr std::string_view RoutineName("InitICEngineGenerators");
     864             : 
     865             :         bool errFlag;
     866             : 
     867       45003 :         if (this->myFlag) {
     868           5 :             this->setupOutputVars(state);
     869           5 :             this->myFlag = false;
     870             :         }
     871             : 
     872       45003 :         if (this->MyPlantScanFlag && allocated(state.dataPlnt->PlantLoop) && this->HeatRecActive) {
     873           3 :             errFlag = false;
     874           3 :             PlantUtilities::ScanPlantLoopsForObject(
     875             :                 state, this->Name, DataPlant::PlantEquipmentType::Generator_ICEngine, this->HRPlantLoc, errFlag, _, _, _, _, _);
     876           3 :             if (errFlag) {
     877           0 :                 ShowFatalError(state, "InitICEngineGenerators: Program terminated due to previous condition(s).");
     878             :             }
     879             : 
     880           3 :             this->MyPlantScanFlag = false;
     881             :         }
     882             : 
     883       45003 :         if (this->MySizeAndNodeInitFlag && (!this->MyPlantScanFlag) && this->HeatRecActive) {
     884             : 
     885             :             // size mass flow rate
     886           6 :             Real64 rho = FluidProperties::GetDensityGlycol(state,
     887           3 :                                                            state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidName,
     888             :                                                            DataGlobalConstants::InitConvTemp,
     889           3 :                                                            state.dataPlnt->PlantLoop(this->HRPlantLoc.loopNum).FluidIndex,
     890           3 :                                                            RoutineName);
     891             : 
     892           3 :             this->DesignHeatRecMassFlowRate = rho * this->DesignHeatRecVolFlowRate;
     893           3 :             this->HeatRecMdotDesign = this->DesignHeatRecMassFlowRate;
     894             : 
     895           3 :             PlantUtilities::InitComponentNodes(state, 0.0, this->DesignHeatRecMassFlowRate, this->HeatRecInletNodeNum, this->HeatRecOutletNodeNum);
     896             : 
     897           3 :             this->MySizeAndNodeInitFlag = false;
     898             :         }
     899       45003 :     }
     900             : 
     901             : } // namespace ICEngineElectricGenerator
     902             : 
     903        2313 : } // namespace EnergyPlus

Generated by: LCOV version 1.13