LCOV - code coverage report
Current view: top level - EnergyPlus - ICEngineElectricGenerator.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 304 362 84.0 %
Date: 2024-08-24 18:31:18 Functions: 10 10 100.0 %

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

Generated by: LCOV version 1.14