LCOV - code coverage report
Current view: top level - EnergyPlus - ChillerGasAbsorption.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 18.4 % 1005 185
Test Date: 2025-06-02 12:03:30 Functions: 17.6 % 17 3

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cassert>
      50              : #include <cmath>
      51              : 
      52              : // ObjexxFCL Headers
      53              : #include <ObjexxFCL/Array.functions.hh>
      54              : #include <ObjexxFCL/Fmath.hh>
      55              : 
      56              : // EnergyPlus Headers
      57              : #include <EnergyPlus/Autosizing/Base.hh>
      58              : #include <EnergyPlus/BranchNodeConnections.hh>
      59              : #include <EnergyPlus/ChillerGasAbsorption.hh>
      60              : #include <EnergyPlus/CurveManager.hh>
      61              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      62              : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
      63              : #include <EnergyPlus/DataEnvironment.hh>
      64              : #include <EnergyPlus/DataGlobalConstants.hh>
      65              : #include <EnergyPlus/DataHVACGlobals.hh>
      66              : #include <EnergyPlus/DataIPShortCuts.hh>
      67              : #include <EnergyPlus/DataLoopNode.hh>
      68              : #include <EnergyPlus/DataSizing.hh>
      69              : #include <EnergyPlus/EMSManager.hh>
      70              : #include <EnergyPlus/FluidProperties.hh>
      71              : #include <EnergyPlus/GlobalNames.hh>
      72              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      73              : #include <EnergyPlus/NodeInputManager.hh>
      74              : #include <EnergyPlus/OutAirNodeManager.hh>
      75              : #include <EnergyPlus/OutputProcessor.hh>
      76              : #include <EnergyPlus/OutputReportPredefined.hh>
      77              : #include <EnergyPlus/Plant/DataPlant.hh>
      78              : #include <EnergyPlus/PlantUtilities.hh>
      79              : #include <EnergyPlus/Psychrometrics.hh>
      80              : #include <EnergyPlus/UtilityRoutines.hh>
      81              : 
      82              : namespace EnergyPlus::ChillerGasAbsorption {
      83              : 
      84              : // MODULE INFORMATION:
      85              : //    AUTHOR         Jason Glazer of GARD Analytics, Inc.
      86              : //                   for Gas Research Institute
      87              : //    DATE WRITTEN   March 2001
      88              : //    MODIFIED       Brent Griffith, Nov 2010 plant upgrades, generalize fluid properties
      89              : 
      90              : // PURPOSE OF THIS MODULE:
      91              : //    This module simulates the performance of the direct fired
      92              : //    absorption chiller.
      93              : // METHODOLOGY EMPLOYED:
      94              : //    Once the PlantLoopManager determines that the absorber chiller
      95              : //    is available to meet a loop cooling demand, it calls SimGasAbsorption
      96              : //    which in turn calls the appropriate Absorption Chiller model.
      97              : // REFERENCES:
      98              : //    DOE-2.1e Supplement
      99              : //    PG&E CoolTools GasMod
     100              : // OTHER NOTES:
     101              : //    The curves on this model follow the DOE-2 approach of using
     102              : //    electric and heat input ratios.  In addition, the temperature
     103              : //    correction curve has two independent variables for the
     104              : //    chilled water temperature and either the entering or leaving
     105              : //    condenser water temperature.
     106              : //    The code was originally adopted from the ChillerAbsorption
     107              : //    routine but has been extensively modified.
     108              : //    Development of this module was funded by the Gas Research Institute.
     109              : //    (Please see copyright and disclaimer information at end of module)
     110              : 
     111            0 : GasAbsorberSpecs *GasAbsorberSpecs::factory(EnergyPlusData &state, std::string const &objectName)
     112              : {
     113              :     // Process the input data if it hasn't been done already
     114            0 :     if (state.dataChillerGasAbsorption->getGasAbsorberInputs) {
     115            0 :         GetGasAbsorberInput(state);
     116            0 :         state.dataChillerGasAbsorption->getGasAbsorberInputs = false;
     117              :     }
     118              :     // Now look for this particular pipe in the list
     119            0 :     auto thisObj = std::find_if(state.dataChillerGasAbsorption->GasAbsorber.begin(),
     120            0 :                                 state.dataChillerGasAbsorption->GasAbsorber.end(),
     121            0 :                                 [&objectName](const GasAbsorberSpecs &myObj) { return myObj.Name == objectName; });
     122            0 :     if (thisObj != state.dataChillerGasAbsorption->GasAbsorber.end()) {
     123            0 :         return thisObj;
     124              :     }
     125              :     // If we didn't find it, fatal
     126              :     ShowFatalError(state, format("LocalGasAbsorberFactory: Error getting inputs for comp named: {}", objectName)); // LCOV_EXCL_LINE
     127              :     // Shut up the compiler
     128              :     return nullptr; // LCOV_EXCL_LINE
     129              : }
     130              : 
     131            0 : void GasAbsorberSpecs::simulate(
     132              :     EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag)
     133              : {
     134            0 :     DataPlant::BrLoopType brIdentity(DataPlant::BrLoopType::NoMatch);
     135              : 
     136            0 :     int branchTotalComp = calledFromLocation.branch->TotalComponents;
     137              : 
     138            0 :     for (int iComp = 1; iComp <= branchTotalComp; iComp++) {
     139              :         // kind of a hacky way to find the location of this, but it's what plantloopequip was doing
     140            0 :         int compInletNodeNum = calledFromLocation.branch->Comp(iComp).NodeNumIn;
     141              :         // Match inlet node name of calling branch to determine if this call is for heating or cooling
     142            0 :         if (compInletNodeNum == this->ChillReturnNodeNum) { // Operate as chiller
     143            0 :             brIdentity = DataPlant::BrLoopType::Chiller;
     144            0 :             break;
     145            0 :         } else if (compInletNodeNum == this->HeatReturnNodeNum) { // Operate as heater
     146            0 :             brIdentity = DataPlant::BrLoopType::Heater;
     147            0 :             break;
     148            0 :         } else if (compInletNodeNum == this->CondReturnNodeNum) { // called from condenser loop
     149            0 :             brIdentity = DataPlant::BrLoopType::Condenser;
     150            0 :             break;
     151              :         } else {
     152            0 :             brIdentity = DataPlant::BrLoopType::NoMatch;
     153              :         }
     154              :     }
     155              : 
     156            0 :     if (brIdentity == DataPlant::BrLoopType::Chiller) {
     157              :         // Calculate Node Values
     158              :         // Calculate Equipment and Update Variables
     159            0 :         this->InCoolingMode = RunFlag != 0;
     160            0 :         this->initialize(state);
     161            0 :         this->calculateChiller(state, CurLoad);
     162            0 :         this->updateCoolRecords(state, CurLoad, RunFlag);
     163            0 :     } else if (brIdentity == DataPlant::BrLoopType::Heater) {
     164              :         // Calculate Node Values
     165              :         // Calculate Equipment and Update Variables
     166            0 :         this->InHeatingMode = RunFlag != 0;
     167            0 :         this->initialize(state);
     168            0 :         this->calculateHeater(state, CurLoad, RunFlag);
     169            0 :         this->updateHeatRecords(state, CurLoad, RunFlag);
     170            0 :     } else if (brIdentity == DataPlant::BrLoopType::Condenser) {
     171            0 :         if (this->CDplantLoc.loopNum > 0) {
     172            0 :             PlantUtilities::UpdateChillerComponentCondenserSide(state,
     173              :                                                                 this->CDplantLoc.loopNum,
     174              :                                                                 this->CDplantLoc.loopSideNum,
     175              :                                                                 DataPlant::PlantEquipmentType::Chiller_DFAbsorption,
     176              :                                                                 this->CondReturnNodeNum,
     177              :                                                                 this->CondSupplyNodeNum,
     178              :                                                                 this->TowerLoad,
     179              :                                                                 this->CondReturnTemp,
     180              :                                                                 this->CondSupplyTemp,
     181              :                                                                 this->CondWaterFlowRate,
     182              :                                                                 FirstHVACIteration);
     183              :         }
     184              :     } else {
     185              :         // Error, nodes do not match
     186            0 :         ShowSevereError(state, format("Invalid call to Gas Absorber Chiller {}", this->Name));
     187            0 :         ShowContinueError(state, "Node connections in branch are not consistent with object nodes.");
     188            0 :         ShowFatalError(state, "Preceding conditions cause termination.");
     189              :     }
     190            0 : }
     191              : 
     192            3 : void GasAbsorberSpecs::getDesignCapacities(
     193              :     EnergyPlusData &state, const PlantLocation &calledFromLocation, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad)
     194              : {
     195            3 :     bool matchfound = false;
     196              : 
     197            3 :     int branchTotalComp = calledFromLocation.branch->TotalComponents;
     198              : 
     199            6 :     for (int iComp = 1; iComp <= branchTotalComp; iComp++) {
     200              :         // kind of a hacky way to find the location of this, but it's what plantloopequip was doing
     201            6 :         int compInletNodeNum = calledFromLocation.branch->Comp(iComp).NodeNumIn;
     202              : 
     203            6 :         if (compInletNodeNum == this->ChillReturnNodeNum) { // Operate as chiller
     204            1 :             MinLoad = this->NomCoolingCap * this->MinPartLoadRat;
     205            1 :             MaxLoad = this->NomCoolingCap * this->MaxPartLoadRat;
     206            1 :             OptLoad = this->NomCoolingCap * this->OptPartLoadRat;
     207            1 :             matchfound = true;
     208            1 :             break;
     209            5 :         } else if (compInletNodeNum == this->HeatReturnNodeNum) { // Operate as heater
     210            1 :             Real64 Sim_HeatCap = this->NomCoolingCap * this->NomHeatCoolRatio;
     211            1 :             MinLoad = Sim_HeatCap * this->MinPartLoadRat;
     212            1 :             MaxLoad = Sim_HeatCap * this->MaxPartLoadRat;
     213            1 :             OptLoad = Sim_HeatCap * this->OptPartLoadRat;
     214            1 :             matchfound = true;
     215            1 :             break;
     216            4 :         } else if (compInletNodeNum == this->CondReturnNodeNum) { // called from condenser loop
     217            1 :             MinLoad = 0.0;
     218            1 :             MaxLoad = 0.0;
     219            1 :             OptLoad = 0.0;
     220            1 :             matchfound = true;
     221            1 :             break;
     222              :         } else {
     223            3 :             matchfound = false;
     224              :         }
     225              :     }
     226              : 
     227            3 :     if (!matchfound) {
     228              :         // Error, nodes do not match
     229            0 :         ShowSevereError(state, format("SimGasAbsorber: Invalid call to Gas Absorbtion Chiller-Heater {}", this->Name));
     230            0 :         ShowContinueError(state, "Node connections in branch are not consistent with object nodes.");
     231            0 :         ShowFatalError(state, "Preceding conditions cause termination.");
     232              :     } // Operate as Chiller or Heater
     233            3 : }
     234              : 
     235            0 : void GasAbsorberSpecs::getSizingFactor(Real64 &_SizFac)
     236              : {
     237            0 :     _SizFac = this->SizFac;
     238            0 : }
     239              : 
     240            0 : void GasAbsorberSpecs::onInitLoopEquip(EnergyPlusData &state, const PlantLocation &calledFromLocation)
     241              : {
     242            0 :     this->initialize(state);
     243              : 
     244              :     // kind of a hacky way to find the location of this, but it's what plantloopequip was doing
     245            0 :     int BranchInletNodeNum = calledFromLocation.branch->NodeNumIn;
     246              : 
     247            0 :     if (BranchInletNodeNum == this->ChillReturnNodeNum) {       // Operate as chiller
     248            0 :         this->size(state);                                      // only call from chilled water loop
     249            0 :     } else if (BranchInletNodeNum == this->HeatReturnNodeNum) { // Operate as heater
     250              :         // don't do anything here
     251            0 :     } else if (BranchInletNodeNum == this->CondReturnNodeNum) { // called from condenser loop
     252              :                                                                 // don't do anything here
     253              :     } else {                                                    // Error, nodes do not match
     254            0 :         ShowSevereError(state, format("SimGasAbsorber: Invalid call to Gas Absorbtion Chiller-Heater {}", this->Name));
     255            0 :         ShowContinueError(state, "Node connections in branch are not consistent with object nodes.");
     256            0 :         ShowFatalError(state, "Preceding conditions cause termination.");
     257              :     } // Operate as Chiller or Heater
     258            0 : }
     259              : 
     260            0 : void GasAbsorberSpecs::getDesignTemperatures(Real64 &TempCondInDesign, Real64 &TempEvapOutDesign)
     261              : {
     262            0 :     TempEvapOutDesign = this->TempDesCHWSupply;
     263            0 :     TempCondInDesign = this->TempDesCondReturn;
     264            0 : }
     265              : 
     266            2 : void GetGasAbsorberInput(EnergyPlusData &state)
     267              : {
     268              :     //       AUTHOR:          Jason Glazer
     269              :     //       DATE WRITTEN:    March 2001
     270              :     // This routine will get the input
     271              :     // required by the Direct Fired Absorption chiller model in the object ChillerHeater:Absorption:DirectFired
     272              : 
     273              :     static constexpr std::string_view routineName = "GetGasAbsorptionInput";
     274              : 
     275              :     int NumAlphas; // Number of elements in the alpha array
     276              :     int NumNums;   // Number of elements in the numeric array
     277              :     int IOStat;    // IO Status when calling get input subroutine
     278              :     bool Okay;
     279            2 :     bool Get_ErrorsFound(false);
     280            2 :     int NumGasAbsorbers(0); // number of Absorption Chillers specified in input
     281              : 
     282            2 :     auto &s_ipsc = state.dataIPShortCut;
     283              : 
     284            2 :     s_ipsc->cCurrentModuleObject = "ChillerHeater:Absorption:DirectFired";
     285            2 :     NumGasAbsorbers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     286              : 
     287            2 :     if (NumGasAbsorbers <= 0) {
     288            0 :         ShowSevereError(state, format("No {} equipment found in input file", s_ipsc->cCurrentModuleObject));
     289            0 :         Get_ErrorsFound = true;
     290              :     }
     291              : 
     292            2 :     if (allocated(state.dataChillerGasAbsorption->GasAbsorber)) {
     293            0 :         return;
     294              :     }
     295              : 
     296              :     // ALLOCATE ARRAYS
     297            2 :     state.dataChillerGasAbsorption->GasAbsorber.allocate(NumGasAbsorbers);
     298              : 
     299              :     // LOAD ARRAYS
     300              : 
     301            4 :     for (int AbsorberNum = 1; AbsorberNum <= NumGasAbsorbers; ++AbsorberNum) {
     302            6 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     303            2 :                                                                  s_ipsc->cCurrentModuleObject,
     304              :                                                                  AbsorberNum,
     305            2 :                                                                  s_ipsc->cAlphaArgs,
     306              :                                                                  NumAlphas,
     307            2 :                                                                  s_ipsc->rNumericArgs,
     308              :                                                                  NumNums,
     309              :                                                                  IOStat,
     310              :                                                                  _,
     311            2 :                                                                  s_ipsc->lAlphaFieldBlanks,
     312            2 :                                                                  s_ipsc->cAlphaFieldNames,
     313            2 :                                                                  s_ipsc->cNumericFieldNames);
     314              : 
     315            2 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     316              : 
     317              :         // Get_ErrorsFound will be set to True if problem was found, left untouched otherwise
     318            2 :         GlobalNames::VerifyUniqueChillerName(
     319            4 :             state, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1), Get_ErrorsFound, s_ipsc->cCurrentModuleObject + " Name");
     320              : 
     321            2 :         auto &thisChiller = state.dataChillerGasAbsorption->GasAbsorber(AbsorberNum);
     322            2 :         thisChiller.Name = s_ipsc->cAlphaArgs(1);
     323            2 :         std::string ChillerName = s_ipsc->cCurrentModuleObject + " Named " + thisChiller.Name;
     324              : 
     325              :         // Assign capacities
     326            2 :         thisChiller.NomCoolingCap = s_ipsc->rNumericArgs(1);
     327            2 :         if (thisChiller.NomCoolingCap == DataSizing::AutoSize) {
     328            0 :             thisChiller.NomCoolingCapWasAutoSized = true;
     329              :         }
     330            2 :         thisChiller.NomHeatCoolRatio = s_ipsc->rNumericArgs(2);
     331              :         // Assign efficiencies
     332            2 :         thisChiller.FuelCoolRatio = s_ipsc->rNumericArgs(3);
     333            2 :         thisChiller.FuelHeatRatio = s_ipsc->rNumericArgs(4);
     334            2 :         thisChiller.ElecCoolRatio = s_ipsc->rNumericArgs(5);
     335            2 :         thisChiller.ElecHeatRatio = s_ipsc->rNumericArgs(6);
     336              : 
     337              :         // Assign Node Numbers to specified nodes
     338            2 :         thisChiller.ChillReturnNodeNum = NodeInputManager::GetOnlySingleNode(state,
     339            2 :                                                                              s_ipsc->cAlphaArgs(2),
     340              :                                                                              Get_ErrorsFound,
     341              :                                                                              DataLoopNode::ConnectionObjectType::ChillerHeaterAbsorptionDirectFired,
     342            2 :                                                                              s_ipsc->cAlphaArgs(1),
     343              :                                                                              DataLoopNode::NodeFluidType::Water,
     344              :                                                                              DataLoopNode::ConnectionType::Inlet,
     345              :                                                                              NodeInputManager::CompFluidStream::Primary,
     346              :                                                                              DataLoopNode::ObjectIsNotParent);
     347            4 :         thisChiller.ChillSupplyNodeNum = NodeInputManager::GetOnlySingleNode(state,
     348            2 :                                                                              s_ipsc->cAlphaArgs(3),
     349              :                                                                              Get_ErrorsFound,
     350              :                                                                              DataLoopNode::ConnectionObjectType::ChillerHeaterAbsorptionDirectFired,
     351            2 :                                                                              s_ipsc->cAlphaArgs(1),
     352              :                                                                              DataLoopNode::NodeFluidType::Water,
     353              :                                                                              DataLoopNode::ConnectionType::Outlet,
     354              :                                                                              NodeInputManager::CompFluidStream::Primary,
     355              :                                                                              DataLoopNode::ObjectIsNotParent);
     356            4 :         BranchNodeConnections::TestCompSet(
     357            2 :             state, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1), s_ipsc->cAlphaArgs(2), s_ipsc->cAlphaArgs(3), "Chilled Water Nodes");
     358              :         // Condenser node processing depends on condenser type, see below
     359            2 :         thisChiller.HeatReturnNodeNum = NodeInputManager::GetOnlySingleNode(state,
     360            2 :                                                                             s_ipsc->cAlphaArgs(6),
     361              :                                                                             Get_ErrorsFound,
     362              :                                                                             DataLoopNode::ConnectionObjectType::ChillerHeaterAbsorptionDirectFired,
     363            2 :                                                                             s_ipsc->cAlphaArgs(1),
     364              :                                                                             DataLoopNode::NodeFluidType::Water,
     365              :                                                                             DataLoopNode::ConnectionType::Inlet,
     366              :                                                                             NodeInputManager::CompFluidStream::Tertiary,
     367              :                                                                             DataLoopNode::ObjectIsNotParent);
     368            4 :         thisChiller.HeatSupplyNodeNum = NodeInputManager::GetOnlySingleNode(state,
     369            2 :                                                                             s_ipsc->cAlphaArgs(7),
     370              :                                                                             Get_ErrorsFound,
     371              :                                                                             DataLoopNode::ConnectionObjectType::ChillerHeaterAbsorptionDirectFired,
     372            2 :                                                                             s_ipsc->cAlphaArgs(1),
     373              :                                                                             DataLoopNode::NodeFluidType::Water,
     374              :                                                                             DataLoopNode::ConnectionType::Outlet,
     375              :                                                                             NodeInputManager::CompFluidStream::Tertiary,
     376              :                                                                             DataLoopNode::ObjectIsNotParent);
     377            4 :         BranchNodeConnections::TestCompSet(
     378            2 :             state, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1), s_ipsc->cAlphaArgs(6), s_ipsc->cAlphaArgs(7), "Hot Water Nodes");
     379            2 :         if (Get_ErrorsFound) {
     380            0 :             ShowFatalError(state, format("Errors found in processing node input for {}={}", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     381            0 :             Get_ErrorsFound = false;
     382              :         }
     383              : 
     384              :         // Assign Part Load Ratios
     385            2 :         thisChiller.MinPartLoadRat = s_ipsc->rNumericArgs(7);
     386            2 :         thisChiller.MaxPartLoadRat = s_ipsc->rNumericArgs(8);
     387            2 :         thisChiller.OptPartLoadRat = s_ipsc->rNumericArgs(9);
     388              :         // Assign Design Conditions
     389            2 :         thisChiller.TempDesCondReturn = s_ipsc->rNumericArgs(10);
     390            2 :         thisChiller.TempDesCHWSupply = s_ipsc->rNumericArgs(11);
     391            2 :         thisChiller.EvapVolFlowRate = s_ipsc->rNumericArgs(12);
     392            2 :         if (thisChiller.EvapVolFlowRate == DataSizing::AutoSize) {
     393            0 :             thisChiller.EvapVolFlowRateWasAutoSized = true;
     394              :         }
     395            2 :         if (Util::SameString(s_ipsc->cAlphaArgs(16), "AirCooled")) {
     396            2 :             thisChiller.CondVolFlowRate = 0.0011; // Condenser flow rate not used for this cond type
     397              :         } else {
     398            0 :             thisChiller.CondVolFlowRate = s_ipsc->rNumericArgs(13);
     399            0 :             if (thisChiller.CondVolFlowRate == DataSizing::AutoSize) {
     400            0 :                 thisChiller.CondVolFlowRateWasAutoSized = true;
     401              :             }
     402              :         }
     403            2 :         thisChiller.HeatVolFlowRate = s_ipsc->rNumericArgs(14);
     404            2 :         if (thisChiller.HeatVolFlowRate == DataSizing::AutoSize) {
     405            0 :             thisChiller.HeatVolFlowRateWasAutoSized = true;
     406              :         }
     407              :         // Assign Curve Numbers
     408            2 :         if (s_ipsc->lAlphaFieldBlanks(8)) {
     409            0 :             ShowSevereEmptyField(state, eoh, s_ipsc->cAlphaFieldNames(8));
     410            0 :             Get_ErrorsFound = true;
     411            2 :         } else if ((thisChiller.CoolCapFTCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(8))) == nullptr) {
     412            0 :             ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(8), s_ipsc->cAlphaArgs(8));
     413            0 :             Get_ErrorsFound = true;
     414              :         }
     415              : 
     416            2 :         if (s_ipsc->lAlphaFieldBlanks(9)) {
     417            0 :             ShowSevereEmptyField(state, eoh, s_ipsc->cAlphaFieldNames(9));
     418            0 :             Get_ErrorsFound = true;
     419            2 :         } else if ((thisChiller.FuelCoolFTCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(9))) == nullptr) {
     420            0 :             ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(9), s_ipsc->cAlphaArgs(9));
     421            0 :             Get_ErrorsFound = true;
     422              :         }
     423              : 
     424            2 :         if (s_ipsc->lAlphaFieldBlanks(10)) {
     425            0 :             ShowSevereEmptyField(state, eoh, s_ipsc->cAlphaFieldNames(10));
     426            0 :             Get_ErrorsFound = true;
     427            2 :         } else if ((thisChiller.FuelCoolFPLRCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(10))) == nullptr) {
     428            0 :             ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(10), s_ipsc->cAlphaArgs(10));
     429            0 :             Get_ErrorsFound = true;
     430              :         }
     431              : 
     432            2 :         if (s_ipsc->lAlphaFieldBlanks(11)) {
     433            0 :             ShowSevereEmptyField(state, eoh, s_ipsc->cAlphaFieldNames(11));
     434            0 :             Get_ErrorsFound = true;
     435            2 :         } else if ((thisChiller.ElecCoolFTCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(11))) == nullptr) {
     436            0 :             ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(11), s_ipsc->cAlphaArgs(11));
     437            0 :             Get_ErrorsFound = true;
     438              :         }
     439              : 
     440            2 :         if (s_ipsc->lAlphaFieldBlanks(12)) {
     441            0 :             ShowSevereEmptyField(state, eoh, s_ipsc->cAlphaFieldNames(12));
     442            0 :             Get_ErrorsFound = true;
     443            2 :         } else if ((thisChiller.ElecCoolFPLRCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(12))) == nullptr) {
     444            0 :             ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(12), s_ipsc->cAlphaArgs(12));
     445            0 :             Get_ErrorsFound = true;
     446              :         }
     447              : 
     448            2 :         if (s_ipsc->lAlphaFieldBlanks(13)) {
     449            0 :             ShowSevereEmptyField(state, eoh, s_ipsc->cAlphaFieldNames(13));
     450            0 :             Get_ErrorsFound = true;
     451            2 :         } else if ((thisChiller.HeatCapFCoolCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(13))) == nullptr) {
     452            0 :             ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(13), s_ipsc->cAlphaArgs(13));
     453            0 :             Get_ErrorsFound = true;
     454              :         }
     455              : 
     456            2 :         if (s_ipsc->lAlphaFieldBlanks(14)) {
     457            0 :             ShowSevereEmptyField(state, eoh, s_ipsc->cAlphaFieldNames(14));
     458            0 :             Get_ErrorsFound = true;
     459            2 :         } else if ((thisChiller.FuelHeatFHPLRCurve = Curve::GetCurve(state, s_ipsc->cAlphaArgs(14))) == nullptr) {
     460            0 :             ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(14), s_ipsc->cAlphaArgs(14));
     461            0 :             Get_ErrorsFound = true;
     462              :         }
     463              : 
     464            2 :         if (Get_ErrorsFound) {
     465            0 :             ShowFatalError(state, format("Errors found in processing curve input for {}={}", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     466            0 :             Get_ErrorsFound = false;
     467              :         }
     468              : 
     469            2 :         if (Util::SameString(s_ipsc->cAlphaArgs(15), "LeavingCondenser")) {
     470            0 :             thisChiller.isEnterCondensTemp = false;
     471            2 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(15), "EnteringCondenser")) {
     472            2 :             thisChiller.isEnterCondensTemp = true;
     473              :         } else {
     474            0 :             thisChiller.isEnterCondensTemp = true;
     475            0 :             ShowWarningError(state, format("{}=\"{}\", invalid value", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     476            0 :             ShowContinueError(state, format("Invalid {}=\"{}\"", s_ipsc->cAlphaFieldNames(15), s_ipsc->cAlphaArgs(15)));
     477            0 :             ShowContinueError(state, "resetting to EnteringCondenser, simulation continues");
     478              :         }
     479              :         // Assign Other Parameters
     480            2 :         if (Util::SameString(s_ipsc->cAlphaArgs(16), "AirCooled")) {
     481            2 :             thisChiller.isWaterCooled = false;
     482            0 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(16), "WaterCooled")) {
     483            0 :             thisChiller.isWaterCooled = true;
     484              :         } else {
     485            0 :             thisChiller.isWaterCooled = true;
     486            0 :             ShowWarningError(state, format("{}=\"{}\", invalid value", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     487            0 :             ShowContinueError(state, format("Invalid {}={}", s_ipsc->cAlphaFieldNames(16), s_ipsc->cAlphaArgs(16)));
     488            0 :             ShowContinueError(state, "resetting to WaterCooled, simulation continues");
     489              :         }
     490            2 :         if (!thisChiller.isEnterCondensTemp && !thisChiller.isWaterCooled) {
     491            0 :             thisChiller.isEnterCondensTemp = true;
     492            0 :             ShowWarningError(state, format("{}=\"{}\", invalid value", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     493            0 :             ShowContinueError(state, "Invalid to have both LeavingCondenser and AirCooled.");
     494            0 :             ShowContinueError(state, "resetting to EnteringCondenser, simulation continues");
     495              :         }
     496            2 :         if (thisChiller.isWaterCooled) {
     497            0 :             if (s_ipsc->lAlphaFieldBlanks(5)) {
     498            0 :                 ShowSevereError(state, format("{}=\"{}\", invalid value", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     499            0 :                 ShowContinueError(state, "For WaterCooled chiller the condenser outlet node is required.");
     500            0 :                 Get_ErrorsFound = true;
     501              :             }
     502            0 :             thisChiller.CondReturnNodeNum =
     503            0 :                 NodeInputManager::GetOnlySingleNode(state,
     504            0 :                                                     s_ipsc->cAlphaArgs(4),
     505              :                                                     Get_ErrorsFound,
     506              :                                                     DataLoopNode::ConnectionObjectType::ChillerHeaterAbsorptionDirectFired,
     507            0 :                                                     s_ipsc->cAlphaArgs(1),
     508              :                                                     DataLoopNode::NodeFluidType::Water,
     509              :                                                     DataLoopNode::ConnectionType::Inlet,
     510              :                                                     NodeInputManager::CompFluidStream::Secondary,
     511              :                                                     DataLoopNode::ObjectIsNotParent);
     512            0 :             thisChiller.CondSupplyNodeNum =
     513            0 :                 NodeInputManager::GetOnlySingleNode(state,
     514            0 :                                                     s_ipsc->cAlphaArgs(5),
     515              :                                                     Get_ErrorsFound,
     516              :                                                     DataLoopNode::ConnectionObjectType::ChillerHeaterAbsorptionDirectFired,
     517            0 :                                                     s_ipsc->cAlphaArgs(1),
     518              :                                                     DataLoopNode::NodeFluidType::Water,
     519              :                                                     DataLoopNode::ConnectionType::Outlet,
     520              :                                                     NodeInputManager::CompFluidStream::Secondary,
     521              :                                                     DataLoopNode::ObjectIsNotParent);
     522            0 :             BranchNodeConnections::TestCompSet(
     523            0 :                 state, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1), s_ipsc->cAlphaArgs(4), s_ipsc->cAlphaArgs(5), "Condenser Water Nodes");
     524              :         } else {
     525            2 :             thisChiller.CondReturnNodeNum =
     526            2 :                 NodeInputManager::GetOnlySingleNode(state,
     527            2 :                                                     s_ipsc->cAlphaArgs(4),
     528              :                                                     Get_ErrorsFound,
     529              :                                                     DataLoopNode::ConnectionObjectType::ChillerHeaterAbsorptionDirectFired,
     530            2 :                                                     s_ipsc->cAlphaArgs(1),
     531              :                                                     DataLoopNode::NodeFluidType::Air,
     532              :                                                     DataLoopNode::ConnectionType::OutsideAirReference,
     533              :                                                     NodeInputManager::CompFluidStream::Secondary,
     534              :                                                     DataLoopNode::ObjectIsNotParent);
     535              :             // Condenser outlet node not used for air or evap cooled condenser so ignore cAlphaArgs( 5 )
     536              :             // Connection not required for air or evap cooled condenser so no call to TestCompSet here
     537            2 :             OutAirNodeManager::CheckAndAddAirNodeNumber(state, thisChiller.CondReturnNodeNum, Okay);
     538            2 :             if (!Okay) {
     539            2 :                 ShowWarningError(state, format("{}, Adding OutdoorAir:Node={}", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(4)));
     540              :             }
     541              :         }
     542            2 :         thisChiller.CHWLowLimitTemp = s_ipsc->rNumericArgs(15);
     543            2 :         thisChiller.FuelHeatingValue = s_ipsc->rNumericArgs(16);
     544            2 :         thisChiller.SizFac = s_ipsc->rNumericArgs(17);
     545              : 
     546              :         // Validate fuel type input
     547            2 :         thisChiller.FuelType = static_cast<Constant::eFuel>(getEnumValue(Constant::eFuelNamesUC, s_ipsc->cAlphaArgs(17)));
     548            2 :         if (thisChiller.FuelType == Constant::eFuel::Invalid) {
     549            0 :             ShowSevereError(state, format("{}=\"{}\", invalid value", s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)));
     550            0 :             ShowContinueError(state, format("Invalid {}={}", s_ipsc->cAlphaFieldNames(17), s_ipsc->cAlphaArgs(17)));
     551            0 :             ShowContinueError(
     552              :                 state, "Valid choices are Electricity, NaturalGas, Propane, Diesel, Gasoline, FuelOilNo1, FuelOilNo2,OtherFuel1 or OtherFuel2");
     553            0 :             Get_ErrorsFound = true;
     554              :         }
     555            2 :     }
     556              : 
     557            2 :     if (Get_ErrorsFound) {
     558            0 :         ShowFatalError(state, format("Errors found in processing input for {}", s_ipsc->cCurrentModuleObject));
     559              :     }
     560              : }
     561              : 
     562            0 : void GasAbsorberSpecs::setupOutputVariables(EnergyPlusData &state)
     563              : {
     564            0 :     std::string_view const sFuelType = Constant::eFuelNames[static_cast<int>(this->FuelType)];
     565              : 
     566            0 :     SetupOutputVariable(state,
     567              :                         "Chiller Heater Evaporator Cooling Rate",
     568              :                         Constant::Units::W,
     569            0 :                         this->CoolingLoad,
     570              :                         OutputProcessor::TimeStepType::System,
     571              :                         OutputProcessor::StoreType::Average,
     572            0 :                         this->Name);
     573            0 :     SetupOutputVariable(state,
     574              :                         "Chiller Heater Evaporator Cooling Energy",
     575              :                         Constant::Units::J,
     576            0 :                         this->CoolingEnergy,
     577              :                         OutputProcessor::TimeStepType::System,
     578              :                         OutputProcessor::StoreType::Sum,
     579            0 :                         this->Name,
     580              :                         Constant::eResource::EnergyTransfer,
     581              :                         OutputProcessor::Group::Plant,
     582              :                         OutputProcessor::EndUseCat::Chillers);
     583              : 
     584            0 :     SetupOutputVariable(state,
     585              :                         "Chiller Heater Heating Rate",
     586              :                         Constant::Units::W,
     587            0 :                         this->HeatingLoad,
     588              :                         OutputProcessor::TimeStepType::System,
     589              :                         OutputProcessor::StoreType::Average,
     590            0 :                         this->Name);
     591            0 :     SetupOutputVariable(state,
     592              :                         "Chiller Heater Heating Energy",
     593              :                         Constant::Units::J,
     594            0 :                         this->HeatingEnergy,
     595              :                         OutputProcessor::TimeStepType::System,
     596              :                         OutputProcessor::StoreType::Sum,
     597            0 :                         this->Name,
     598              :                         Constant::eResource::EnergyTransfer,
     599              :                         OutputProcessor::Group::Plant,
     600              :                         OutputProcessor::EndUseCat::Boilers);
     601              : 
     602            0 :     SetupOutputVariable(state,
     603              :                         "Chiller Heater Condenser Heat Transfer Rate",
     604              :                         Constant::Units::W,
     605            0 :                         this->TowerLoad,
     606              :                         OutputProcessor::TimeStepType::System,
     607              :                         OutputProcessor::StoreType::Average,
     608            0 :                         this->Name);
     609            0 :     SetupOutputVariable(state,
     610              :                         "Chiller Heater Condenser Heat Transfer Energy",
     611              :                         Constant::Units::J,
     612            0 :                         this->TowerEnergy,
     613              :                         OutputProcessor::TimeStepType::System,
     614              :                         OutputProcessor::StoreType::Sum,
     615            0 :                         this->Name,
     616              :                         Constant::eResource::EnergyTransfer,
     617              :                         OutputProcessor::Group::Plant,
     618              :                         OutputProcessor::EndUseCat::HeatRejection);
     619              : 
     620            0 :     SetupOutputVariable(state,
     621            0 :                         format("Chiller Heater {} Rate", sFuelType),
     622              :                         Constant::Units::W,
     623            0 :                         this->FuelUseRate,
     624              :                         OutputProcessor::TimeStepType::System,
     625              :                         OutputProcessor::StoreType::Average,
     626            0 :                         this->Name);
     627              :     // Do not include this on meters, this would duplicate the cool fuel and heat fuel
     628            0 :     SetupOutputVariable(state,
     629            0 :                         format("Chiller Heater {} Energy", sFuelType),
     630              :                         Constant::Units::J,
     631            0 :                         this->FuelEnergy,
     632              :                         OutputProcessor::TimeStepType::System,
     633              :                         OutputProcessor::StoreType::Sum,
     634            0 :                         this->Name);
     635              : 
     636            0 :     SetupOutputVariable(state,
     637            0 :                         format("Chiller Heater Cooling {} Rate", sFuelType),
     638              :                         Constant::Units::W,
     639            0 :                         this->CoolFuelUseRate,
     640              :                         OutputProcessor::TimeStepType::System,
     641              :                         OutputProcessor::StoreType::Average,
     642            0 :                         this->Name);
     643            0 :     SetupOutputVariable(state,
     644            0 :                         format("Chiller Heater Cooling {} Energy", sFuelType),
     645              :                         Constant::Units::J,
     646            0 :                         this->CoolFuelEnergy,
     647              :                         OutputProcessor::TimeStepType::System,
     648              :                         OutputProcessor::StoreType::Sum,
     649            0 :                         this->Name,
     650            0 :                         Constant::eFuel2eResource[(int)this->FuelType],
     651              :                         OutputProcessor::Group::Plant,
     652              :                         OutputProcessor::EndUseCat::Cooling);
     653              : 
     654            0 :     SetupOutputVariable(state,
     655              :                         "Chiller Heater Cooling COP",
     656              :                         Constant::Units::W_W,
     657            0 :                         this->FuelCOP,
     658              :                         OutputProcessor::TimeStepType::System,
     659              :                         OutputProcessor::StoreType::Average,
     660            0 :                         this->Name);
     661              : 
     662            0 :     SetupOutputVariable(state,
     663            0 :                         format("Chiller Heater Heating {} Rate", sFuelType),
     664              :                         Constant::Units::W,
     665            0 :                         this->HeatFuelUseRate,
     666              :                         OutputProcessor::TimeStepType::System,
     667              :                         OutputProcessor::StoreType::Average,
     668            0 :                         this->Name);
     669            0 :     SetupOutputVariable(state,
     670            0 :                         format("Chiller Heater Heating {} Energy", sFuelType),
     671              :                         Constant::Units::J,
     672            0 :                         this->HeatFuelEnergy,
     673              :                         OutputProcessor::TimeStepType::System,
     674              :                         OutputProcessor::StoreType::Sum,
     675            0 :                         this->Name,
     676            0 :                         Constant::eFuel2eResource[(int)this->FuelType],
     677              :                         OutputProcessor::Group::Plant,
     678              :                         OutputProcessor::EndUseCat::Heating);
     679              : 
     680            0 :     SetupOutputVariable(state,
     681              :                         "Chiller Heater Electricity Rate",
     682              :                         Constant::Units::W,
     683            0 :                         this->ElectricPower,
     684              :                         OutputProcessor::TimeStepType::System,
     685              :                         OutputProcessor::StoreType::Average,
     686            0 :                         this->Name);
     687              :     // Do not include this on meters, this would duplicate the cool electric and heat electric
     688            0 :     SetupOutputVariable(state,
     689              :                         "Chiller Heater Electricity Energy",
     690              :                         Constant::Units::J,
     691            0 :                         this->ElectricEnergy,
     692              :                         OutputProcessor::TimeStepType::System,
     693              :                         OutputProcessor::StoreType::Sum,
     694            0 :                         this->Name);
     695              : 
     696            0 :     SetupOutputVariable(state,
     697              :                         "Chiller Heater Cooling Electricity Rate",
     698              :                         Constant::Units::W,
     699            0 :                         this->CoolElectricPower,
     700              :                         OutputProcessor::TimeStepType::System,
     701              :                         OutputProcessor::StoreType::Average,
     702            0 :                         this->Name);
     703            0 :     SetupOutputVariable(state,
     704              :                         "Chiller Heater Cooling Electricity Energy",
     705              :                         Constant::Units::J,
     706            0 :                         this->CoolElectricEnergy,
     707              :                         OutputProcessor::TimeStepType::System,
     708              :                         OutputProcessor::StoreType::Sum,
     709            0 :                         this->Name,
     710              :                         Constant::eResource::Electricity,
     711              :                         OutputProcessor::Group::Plant,
     712              :                         OutputProcessor::EndUseCat::Cooling);
     713              : 
     714            0 :     SetupOutputVariable(state,
     715              :                         "Chiller Heater Heating Electricity Rate",
     716              :                         Constant::Units::W,
     717            0 :                         this->HeatElectricPower,
     718              :                         OutputProcessor::TimeStepType::System,
     719              :                         OutputProcessor::StoreType::Average,
     720            0 :                         this->Name);
     721            0 :     SetupOutputVariable(state,
     722              :                         "Chiller Heater Heating Electricity Energy",
     723              :                         Constant::Units::J,
     724            0 :                         this->HeatElectricEnergy,
     725              :                         OutputProcessor::TimeStepType::System,
     726              :                         OutputProcessor::StoreType::Sum,
     727            0 :                         this->Name,
     728              :                         Constant::eResource::Electricity,
     729              :                         OutputProcessor::Group::Plant,
     730              :                         OutputProcessor::EndUseCat::Heating);
     731              : 
     732            0 :     SetupOutputVariable(state,
     733              :                         "Chiller Heater Evaporator Inlet Temperature",
     734              :                         Constant::Units::C,
     735            0 :                         this->ChillReturnTemp,
     736              :                         OutputProcessor::TimeStepType::System,
     737              :                         OutputProcessor::StoreType::Average,
     738            0 :                         this->Name);
     739            0 :     SetupOutputVariable(state,
     740              :                         "Chiller Heater Evaporator Outlet Temperature",
     741              :                         Constant::Units::C,
     742            0 :                         this->ChillSupplyTemp,
     743              :                         OutputProcessor::TimeStepType::System,
     744              :                         OutputProcessor::StoreType::Average,
     745            0 :                         this->Name);
     746            0 :     SetupOutputVariable(state,
     747              :                         "Chiller Heater Evaporator Mass Flow Rate",
     748              :                         Constant::Units::kg_s,
     749            0 :                         this->ChillWaterFlowRate,
     750              :                         OutputProcessor::TimeStepType::System,
     751              :                         OutputProcessor::StoreType::Average,
     752            0 :                         this->Name);
     753              : 
     754            0 :     if (this->isWaterCooled) {
     755            0 :         SetupOutputVariable(state,
     756              :                             "Chiller Heater Condenser Inlet Temperature",
     757              :                             Constant::Units::C,
     758            0 :                             this->CondReturnTemp,
     759              :                             OutputProcessor::TimeStepType::System,
     760              :                             OutputProcessor::StoreType::Average,
     761            0 :                             this->Name);
     762            0 :         SetupOutputVariable(state,
     763              :                             "Chiller Heater Condenser Outlet Temperature",
     764              :                             Constant::Units::C,
     765            0 :                             this->CondSupplyTemp,
     766              :                             OutputProcessor::TimeStepType::System,
     767              :                             OutputProcessor::StoreType::Average,
     768            0 :                             this->Name);
     769            0 :         SetupOutputVariable(state,
     770              :                             "Chiller Heater Condenser Mass Flow Rate",
     771              :                             Constant::Units::kg_s,
     772            0 :                             this->CondWaterFlowRate,
     773              :                             OutputProcessor::TimeStepType::System,
     774              :                             OutputProcessor::StoreType::Average,
     775            0 :                             this->Name);
     776              :     } else {
     777            0 :         SetupOutputVariable(state,
     778              :                             "Chiller Heater Condenser Inlet Temperature",
     779              :                             Constant::Units::C,
     780            0 :                             this->CondReturnTemp,
     781              :                             OutputProcessor::TimeStepType::System,
     782              :                             OutputProcessor::StoreType::Average,
     783            0 :                             this->Name);
     784              :     }
     785              : 
     786            0 :     SetupOutputVariable(state,
     787              :                         "Chiller Heater Heating Inlet Temperature",
     788              :                         Constant::Units::C,
     789            0 :                         this->HotWaterReturnTemp,
     790              :                         OutputProcessor::TimeStepType::System,
     791              :                         OutputProcessor::StoreType::Average,
     792            0 :                         this->Name);
     793            0 :     SetupOutputVariable(state,
     794              :                         "Chiller Heater Heating Outlet Temperature",
     795              :                         Constant::Units::C,
     796            0 :                         this->HotWaterSupplyTemp,
     797              :                         OutputProcessor::TimeStepType::System,
     798              :                         OutputProcessor::StoreType::Average,
     799            0 :                         this->Name);
     800            0 :     SetupOutputVariable(state,
     801              :                         "Chiller Heater Heating Mass Flow Rate",
     802              :                         Constant::Units::kg_s,
     803            0 :                         this->HotWaterFlowRate,
     804              :                         OutputProcessor::TimeStepType::System,
     805              :                         OutputProcessor::StoreType::Average,
     806            0 :                         this->Name);
     807              : 
     808            0 :     SetupOutputVariable(state,
     809              :                         "Chiller Heater Cooling Part Load Ratio",
     810              :                         Constant::Units::None,
     811            0 :                         this->CoolPartLoadRatio,
     812              :                         OutputProcessor::TimeStepType::System,
     813              :                         OutputProcessor::StoreType::Average,
     814            0 :                         this->Name);
     815            0 :     SetupOutputVariable(state,
     816              :                         "Chiller Heater Maximum Cooling Rate",
     817              :                         Constant::Units::W,
     818            0 :                         this->CoolingCapacity,
     819              :                         OutputProcessor::TimeStepType::System,
     820              :                         OutputProcessor::StoreType::Average,
     821            0 :                         this->Name);
     822            0 :     SetupOutputVariable(state,
     823              :                         "Chiller Heater Heating Part Load Ratio",
     824              :                         Constant::Units::None,
     825            0 :                         this->HeatPartLoadRatio,
     826              :                         OutputProcessor::TimeStepType::System,
     827              :                         OutputProcessor::StoreType::Average,
     828            0 :                         this->Name);
     829            0 :     SetupOutputVariable(state,
     830              :                         "Chiller Heater Maximum Heating Rate",
     831              :                         Constant::Units::W,
     832            0 :                         this->HeatingCapacity,
     833              :                         OutputProcessor::TimeStepType::System,
     834              :                         OutputProcessor::StoreType::Average,
     835            0 :                         this->Name);
     836              : 
     837            0 :     SetupOutputVariable(state,
     838              :                         "Chiller Heater Runtime Fraction",
     839              :                         Constant::Units::None,
     840            0 :                         this->FractionOfPeriodRunning,
     841              :                         OutputProcessor::TimeStepType::System,
     842              :                         OutputProcessor::StoreType::Average,
     843            0 :                         this->Name);
     844            0 : }
     845              : 
     846            0 : void GasAbsorberSpecs::oneTimeInit_new(EnergyPlusData &state)
     847              : {
     848              : 
     849            0 :     this->setupOutputVariables(state);
     850              : 
     851              :     // Locate the chillers on the plant loops for later usage
     852            0 :     bool errFlag = false;
     853            0 :     PlantUtilities::ScanPlantLoopsForObject(state,
     854              :                                             this->Name,
     855              :                                             DataPlant::PlantEquipmentType::Chiller_DFAbsorption,
     856            0 :                                             this->CWplantLoc,
     857              :                                             errFlag,
     858            0 :                                             this->CHWLowLimitTemp,
     859              :                                             _,
     860              :                                             _,
     861            0 :                                             this->ChillReturnNodeNum,
     862              :                                             _);
     863            0 :     if (errFlag) {
     864            0 :         ShowFatalError(state, "InitGasAbsorber: Program terminated due to previous condition(s).");
     865              :     }
     866              : 
     867            0 :     PlantUtilities::ScanPlantLoopsForObject(
     868            0 :         state, this->Name, DataPlant::PlantEquipmentType::Chiller_DFAbsorption, this->HWplantLoc, errFlag, _, _, _, this->HeatReturnNodeNum, _);
     869            0 :     if (errFlag) {
     870            0 :         ShowFatalError(state, "InitGasAbsorber: Program terminated due to previous condition(s).");
     871              :     }
     872              : 
     873            0 :     if (this->isWaterCooled) {
     874            0 :         PlantUtilities::ScanPlantLoopsForObject(
     875            0 :             state, this->Name, DataPlant::PlantEquipmentType::Chiller_DFAbsorption, this->CDplantLoc, errFlag, _, _, _, this->CondReturnNodeNum, _);
     876            0 :         if (errFlag) {
     877            0 :             ShowFatalError(state, "InitGasAbsorber: Program terminated due to previous condition(s).");
     878              :         }
     879            0 :         PlantUtilities::InterConnectTwoPlantLoopSides(
     880            0 :             state, this->CWplantLoc, this->CDplantLoc, DataPlant::PlantEquipmentType::Chiller_DFAbsorption, true);
     881            0 :         PlantUtilities::InterConnectTwoPlantLoopSides(
     882            0 :             state, this->HWplantLoc, this->CDplantLoc, DataPlant::PlantEquipmentType::Chiller_DFAbsorption, true);
     883              :     }
     884              : 
     885            0 :     PlantUtilities::InterConnectTwoPlantLoopSides(
     886            0 :         state, this->CWplantLoc, this->HWplantLoc, DataPlant::PlantEquipmentType::Chiller_DFAbsorption, true);
     887              : 
     888              :     // check if outlet node of chilled water side has a setpoint.
     889            0 :     if ((state.dataLoopNodes->Node(this->ChillSupplyNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) &&
     890            0 :         (state.dataLoopNodes->Node(this->ChillSupplyNodeNum).TempSetPointHi == DataLoopNode::SensedNodeFlagValue)) {
     891            0 :         if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
     892            0 :             if (!this->ChillSetPointErrDone) {
     893            0 :                 ShowWarningError(state, format("Missing temperature setpoint on cool side for chiller heater named {}", this->Name));
     894            0 :                 ShowContinueError(state, "  A temperature setpoint is needed at the outlet node of this chiller, use a SetpointManager");
     895            0 :                 ShowContinueError(state, "  The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
     896            0 :                 this->ChillSetPointErrDone = true;
     897              :             }
     898              :         } else {
     899              :             // need call to EMS to check node
     900            0 :             errFlag = false; // but not really fatal yet, but should be.
     901            0 :             EMSManager::CheckIfNodeSetPointManagedByEMS(state, this->ChillSupplyNodeNum, HVAC::CtrlVarType::Temp, errFlag);
     902            0 :             state.dataLoopNodes->NodeSetpointCheck(this->ChillSupplyNodeNum).needsSetpointChecking = false;
     903            0 :             if (errFlag) {
     904            0 :                 if (!this->ChillSetPointErrDone) {
     905            0 :                     ShowWarningError(state, format("Missing temperature setpoint on cool side for chiller heater named {}", this->Name));
     906            0 :                     ShowContinueError(state, "  A temperature setpoint is needed at the outlet node of this chiller evaporator ");
     907            0 :                     ShowContinueError(state, "  use a Setpoint Manager to establish a setpoint at the chiller evaporator outlet node ");
     908            0 :                     ShowContinueError(state, "  or use an EMS actuator to establish a setpoint at the outlet node ");
     909            0 :                     ShowContinueError(state, "  The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
     910            0 :                     this->ChillSetPointErrDone = true;
     911              :                 }
     912              :             }
     913              :         }
     914            0 :         this->ChillSetPointSetToLoop = true;
     915            0 :         state.dataLoopNodes->Node(this->ChillSupplyNodeNum).TempSetPoint =
     916            0 :             state.dataLoopNodes->Node(this->CWplantLoc.loop->TempSetPointNodeNum).TempSetPoint;
     917            0 :         state.dataLoopNodes->Node(this->ChillSupplyNodeNum).TempSetPointHi =
     918            0 :             state.dataLoopNodes->Node(this->CWplantLoc.loop->TempSetPointNodeNum).TempSetPointHi;
     919              :     }
     920              :     // check if outlet node of hot water side has a setpoint.
     921            0 :     if ((state.dataLoopNodes->Node(this->HeatSupplyNodeNum).TempSetPoint == DataLoopNode::SensedNodeFlagValue) &&
     922            0 :         (state.dataLoopNodes->Node(this->HeatSupplyNodeNum).TempSetPointLo == DataLoopNode::SensedNodeFlagValue)) {
     923            0 :         if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
     924            0 :             if (!this->HeatSetPointErrDone) {
     925            0 :                 ShowWarningError(state, format("Missing temperature setpoint on heat side for chiller heater named {}", this->Name));
     926            0 :                 ShowContinueError(state, "  A temperature setpoint is needed at the outlet node of this chiller, use a SetpointManager");
     927            0 :                 ShowContinueError(state, "  The overall loop setpoint will be assumed for chiller. The simulation continues ... ");
     928            0 :                 this->HeatSetPointErrDone = true;
     929              :             }
     930              :         } else {
     931              :             // need call to EMS to check node
     932            0 :             errFlag = false; // but not really fatal yet, but should be.
     933            0 :             EMSManager::CheckIfNodeSetPointManagedByEMS(state, this->HeatSupplyNodeNum, HVAC::CtrlVarType::Temp, errFlag);
     934            0 :             state.dataLoopNodes->NodeSetpointCheck(this->HeatSupplyNodeNum).needsSetpointChecking = false;
     935            0 :             if (errFlag) {
     936            0 :                 if (!this->HeatSetPointErrDone) {
     937            0 :                     ShowWarningError(state, format("Missing temperature setpoint on heat side for chiller heater named {}", this->Name));
     938            0 :                     ShowContinueError(state, "  A temperature setpoint is needed at the outlet node of this chiller heater ");
     939            0 :                     ShowContinueError(state, "  use a Setpoint Manager to establish a setpoint at the heater side outlet node ");
     940            0 :                     ShowContinueError(state, "  or use an EMS actuator to establish a setpoint at the outlet node ");
     941            0 :                     ShowContinueError(state, "  The overall loop setpoint will be assumed for heater side. The simulation continues ... ");
     942            0 :                     this->HeatSetPointErrDone = true;
     943              :                 }
     944              :             }
     945              :         }
     946            0 :         this->HeatSetPointSetToLoop = true;
     947            0 :         state.dataLoopNodes->Node(this->HeatSupplyNodeNum).TempSetPoint =
     948            0 :             state.dataLoopNodes->Node(this->HWplantLoc.loop->TempSetPointNodeNum).TempSetPoint;
     949            0 :         state.dataLoopNodes->Node(this->HeatSupplyNodeNum).TempSetPointLo =
     950            0 :             state.dataLoopNodes->Node(this->HWplantLoc.loop->TempSetPointNodeNum).TempSetPointLo;
     951              :     }
     952            0 : }
     953              : 
     954            0 : void GasAbsorberSpecs::initialize(EnergyPlusData &state)
     955              : {
     956              :     //       AUTHOR         Fred Buhl
     957              :     //       DATE WRITTEN   June 2003
     958              : 
     959              :     // This subroutine is for initializations of direct fired absorption chiller
     960              :     // components.
     961              : 
     962              :     // Uses the status flags to trigger initializations.
     963              : 
     964              :     static constexpr std::string_view RoutineName("InitGasAbsorber");
     965              : 
     966            0 :     Real64 rho = 0.0;  // local fluid density
     967            0 :     Real64 mdot = 0.0; // lcoal fluid mass flow rate
     968              : 
     969              :     // Init more variables
     970              : 
     971            0 :     int CondInletNode = this->CondReturnNodeNum;
     972            0 :     int CondOutletNode = this->CondSupplyNodeNum;
     973            0 :     int HeatInletNode = this->HeatReturnNodeNum;
     974            0 :     int HeatOutletNode = this->HeatSupplyNodeNum;
     975              : 
     976            0 :     if (this->envrnFlag && state.dataGlobal->BeginEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
     977              : 
     978            0 :         if (this->isWaterCooled) {
     979              :             // init max available condenser water flow rate
     980            0 :             if (this->CDplantLoc.loopNum > 0) {
     981            0 :                 rho = this->CDplantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
     982              :             } else {
     983            0 :                 rho = Psychrometrics::RhoH2O(Constant::InitConvTemp);
     984              :             }
     985              : 
     986            0 :             this->DesCondMassFlowRate = rho * this->CondVolFlowRate;
     987            0 :             PlantUtilities::InitComponentNodes(state, 0.0, this->DesCondMassFlowRate, CondInletNode, CondOutletNode);
     988              :         }
     989              : 
     990            0 :         if (this->HWplantLoc.loopNum > 0) {
     991            0 :             rho = this->HWplantLoc.loop->glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
     992              :         } else {
     993            0 :             rho = Psychrometrics::RhoH2O(Constant::InitConvTemp);
     994              :         }
     995            0 :         this->DesHeatMassFlowRate = rho * this->HeatVolFlowRate;
     996              :         // init available hot water flow rate
     997            0 :         PlantUtilities::InitComponentNodes(state, 0.0, this->DesHeatMassFlowRate, HeatInletNode, HeatOutletNode);
     998              : 
     999            0 :         if (this->CWplantLoc.loopNum > 0) {
    1000            0 :             rho = this->CWplantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
    1001              :         } else {
    1002            0 :             rho = Psychrometrics::RhoH2O(Constant::InitConvTemp);
    1003              :         }
    1004            0 :         this->DesEvapMassFlowRate = rho * this->EvapVolFlowRate;
    1005              :         // init available hot water flow rate
    1006            0 :         PlantUtilities::InitComponentNodes(state, 0.0, this->DesEvapMassFlowRate, this->ChillReturnNodeNum, this->ChillSupplyNodeNum);
    1007              : 
    1008            0 :         this->envrnFlag = false;
    1009              :     }
    1010              : 
    1011            0 :     if (!state.dataGlobal->BeginEnvrnFlag) {
    1012            0 :         this->envrnFlag = true;
    1013              :     }
    1014              : 
    1015              :     // this component model works off setpoints on the leaving node
    1016              :     // fill from plant if needed
    1017            0 :     if (this->ChillSetPointSetToLoop) {
    1018            0 :         state.dataLoopNodes->Node(this->ChillSupplyNodeNum).TempSetPoint =
    1019            0 :             state.dataLoopNodes->Node(this->CWplantLoc.loop->TempSetPointNodeNum).TempSetPoint;
    1020            0 :         state.dataLoopNodes->Node(this->ChillSupplyNodeNum).TempSetPointHi =
    1021            0 :             state.dataLoopNodes->Node(this->CWplantLoc.loop->TempSetPointNodeNum).TempSetPointHi;
    1022              :     }
    1023              : 
    1024            0 :     if (this->HeatSetPointSetToLoop) {
    1025            0 :         state.dataLoopNodes->Node(this->HeatSupplyNodeNum).TempSetPoint =
    1026            0 :             state.dataLoopNodes->Node(this->HWplantLoc.loop->TempSetPointNodeNum).TempSetPoint;
    1027            0 :         state.dataLoopNodes->Node(this->HeatSupplyNodeNum).TempSetPointLo =
    1028            0 :             state.dataLoopNodes->Node(this->HWplantLoc.loop->TempSetPointNodeNum).TempSetPointLo;
    1029              :     }
    1030              : 
    1031            0 :     if ((this->isWaterCooled) && ((this->InHeatingMode) || (this->InCoolingMode))) {
    1032            0 :         mdot = this->DesCondMassFlowRate;
    1033              : 
    1034            0 :         PlantUtilities::SetComponentFlowRate(state, mdot, this->CondReturnNodeNum, this->CondSupplyNodeNum, this->CDplantLoc);
    1035              : 
    1036              :     } else {
    1037            0 :         mdot = 0.0;
    1038            0 :         if (this->CDplantLoc.loopNum > 0 && this->isWaterCooled) {
    1039            0 :             PlantUtilities::SetComponentFlowRate(state, mdot, this->CondReturnNodeNum, this->CondSupplyNodeNum, this->CDplantLoc);
    1040              :         }
    1041              :     }
    1042            0 : }
    1043              : 
    1044            0 : void GasAbsorberSpecs::size(EnergyPlusData &state)
    1045              : {
    1046              :     //       AUTHOR         Fred Buhl
    1047              :     //       DATE WRITTEN   June 2003
    1048              :     //       MODIFIED       November 2013 Daeho Kang, add component sizing table entries
    1049              : 
    1050              :     // This subroutine is for sizing direct fired gas absorption chiller components for which
    1051              :     // capacities and flow rates have not been specified in the input.
    1052              : 
    1053              :     // METHODOLOGY EMPLOYED:
    1054              :     // Obtains evaporator flow rate from the plant sizing array. Calculates nominal capacity from
    1055              :     // the evaporator flow rate and the chilled water loop design delta T. The condenser flow rate
    1056              :     // is calculated from the nominal capacity, the COP, and the condenser loop design delta T.
    1057              : 
    1058              :     static constexpr std::string_view RoutineName("SizeGasAbsorber");
    1059              : 
    1060              :     Real64 Cp;                     // local fluid specific heat
    1061              :     Real64 rho;                    // local fluid density
    1062              :     Real64 NomCapUser;             // Hardsized nominal capacity for reporting
    1063              :     Real64 EvapVolFlowRateUser;    // Hardsized evaporator volume flow rate for reporting
    1064              :     Real64 CondVolFlowRateUser;    // Hardsized condenser flow rate for reporting
    1065              :     Real64 HeatRecVolFlowRateUser; // Hardsized generator flow rate for reporting
    1066              : 
    1067            0 :     bool ErrorsFound = false;
    1068            0 :     Real64 tmpNomCap = this->NomCoolingCap;
    1069            0 :     Real64 tmpEvapVolFlowRate = this->EvapVolFlowRate;
    1070            0 :     Real64 tmpCondVolFlowRate = this->CondVolFlowRate;
    1071            0 :     Real64 tmpHeatRecVolFlowRate = this->HeatVolFlowRate;
    1072              : 
    1073            0 :     int PltSizCondNum = 0; // Plant Sizing index for condenser loop
    1074            0 :     if (this->isWaterCooled) {
    1075            0 :         PltSizCondNum = this->CDplantLoc.loop->PlantSizNum;
    1076              :     }
    1077            0 :     int PltSizHeatNum = this->HWplantLoc.loop->PlantSizNum;
    1078            0 :     int PltSizCoolNum = this->CWplantLoc.loop->PlantSizNum;
    1079              : 
    1080            0 :     if (PltSizCoolNum > 0) {
    1081            0 :         if (state.dataSize->PlantSizData(PltSizCoolNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
    1082            0 :             Cp = this->CWplantLoc.loop->glycol->getSpecificHeat(state, Constant::CWInitConvTemp, RoutineName);
    1083            0 :             rho = this->CWplantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
    1084            0 :             tmpNomCap = Cp * rho * state.dataSize->PlantSizData(PltSizCoolNum).DeltaT * state.dataSize->PlantSizData(PltSizCoolNum).DesVolFlowRate *
    1085            0 :                         this->SizFac;
    1086            0 :             if (!this->NomCoolingCapWasAutoSized) {
    1087            0 :                 tmpNomCap = this->NomCoolingCap;
    1088              :             }
    1089              :         } else {
    1090            0 :             if (this->NomCoolingCapWasAutoSized) {
    1091            0 :                 tmpNomCap = 0.0;
    1092              :             }
    1093              :         }
    1094            0 :         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    1095            0 :             if (this->NomCoolingCapWasAutoSized) {
    1096            0 :                 this->NomCoolingCap = tmpNomCap;
    1097            0 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1098            0 :                     BaseSizer::reportSizerOutput(
    1099              :                         state, "ChillerHeater:Absorption:DirectFired", this->Name, "Design Size Nominal Cooling Capacity [W]", tmpNomCap);
    1100              :                 }
    1101            0 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    1102            0 :                     BaseSizer::reportSizerOutput(
    1103              :                         state, "ChillerHeater:Absorption:DirectFired", this->Name, "Initial Design Size Nominal Cooling Capacity [W]", tmpNomCap);
    1104              :                 }
    1105              :             } else {
    1106            0 :                 if (this->NomCoolingCap > 0.0 && tmpNomCap > 0.0) {
    1107            0 :                     NomCapUser = this->NomCoolingCap;
    1108            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1109            0 :                         BaseSizer::reportSizerOutput(state,
    1110              :                                                      "ChillerHeater:Absorption:DirectFired",
    1111              :                                                      this->Name,
    1112              :                                                      "Design Size Nominal Cooling Capacity [W]",
    1113              :                                                      tmpNomCap,
    1114              :                                                      "User-Specified Nominal Cooling Capacity [W]",
    1115              :                                                      NomCapUser);
    1116            0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    1117            0 :                             if ((std::abs(tmpNomCap - NomCapUser) / NomCapUser) > state.dataSize->AutoVsHardSizingThreshold) {
    1118            0 :                                 ShowMessage(
    1119              :                                     state,
    1120            0 :                                     format("SizeChillerHeaterAbsorptionDirectFired: Potential issue with equipment sizing for {}", this->Name));
    1121            0 :                                 ShowContinueError(state, format("User-Specified Nominal Capacity of {:.2R} [W]", NomCapUser));
    1122            0 :                                 ShowContinueError(state, format("differs from Design Size Nominal Capacity of {:.2R} [W]", tmpNomCap));
    1123            0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1124            0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1125              :                             }
    1126              :                         }
    1127              :                     }
    1128            0 :                     tmpNomCap = NomCapUser;
    1129              :                 }
    1130              :             }
    1131              :         }
    1132              :     } else {
    1133            0 :         if (this->NomCoolingCapWasAutoSized) {
    1134            0 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    1135            0 :                 ShowSevereError(state, format("SizeGasAbsorber: ChillerHeater:Absorption:DirectFired=\"{}\", autosize error.", this->Name));
    1136            0 :                 ShowContinueError(state, "Autosizing of Direct Fired Absorption Chiller nominal cooling capacity requires");
    1137            0 :                 ShowContinueError(state, "a cooling loop Sizing:Plant object.");
    1138            0 :                 ErrorsFound = true;
    1139              :             }
    1140              :         } else {
    1141            0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1142            0 :                 if (this->NomCoolingCap > 0.0) {
    1143            0 :                     BaseSizer::reportSizerOutput(
    1144              :                         state, "ChillerHeater:Absorption:DirectFired", this->Name, "User-Specified Nominal Capacity [W]", this->NomCoolingCap);
    1145              :                 }
    1146              :             }
    1147              :         }
    1148              :     }
    1149              : 
    1150            0 :     if (PltSizCoolNum > 0) {
    1151            0 :         if (state.dataSize->PlantSizData(PltSizCoolNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
    1152            0 :             tmpEvapVolFlowRate = state.dataSize->PlantSizData(PltSizCoolNum).DesVolFlowRate * this->SizFac;
    1153            0 :             if (!this->EvapVolFlowRateWasAutoSized) {
    1154            0 :                 tmpEvapVolFlowRate = this->EvapVolFlowRate;
    1155              :             }
    1156              :         } else {
    1157            0 :             if (this->EvapVolFlowRateWasAutoSized) {
    1158            0 :                 tmpEvapVolFlowRate = 0.0;
    1159              :             }
    1160              :         }
    1161            0 :         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    1162            0 :             if (this->EvapVolFlowRateWasAutoSized) {
    1163            0 :                 this->EvapVolFlowRate = tmpEvapVolFlowRate;
    1164            0 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1165            0 :                     BaseSizer::reportSizerOutput(state,
    1166              :                                                  "ChillerHeater:Absorption:DirectFired",
    1167              :                                                  this->Name,
    1168              :                                                  "Design Size Design Chilled Water Flow Rate [m3/s]",
    1169              :                                                  tmpEvapVolFlowRate);
    1170              :                 }
    1171            0 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    1172            0 :                     BaseSizer::reportSizerOutput(state,
    1173              :                                                  "ChillerHeater:Absorption:DirectFired",
    1174              :                                                  this->Name,
    1175              :                                                  "Initial Design Size Design Chilled Water Flow Rate [m3/s]",
    1176              :                                                  tmpEvapVolFlowRate);
    1177              :                 }
    1178              :             } else {
    1179            0 :                 if (this->EvapVolFlowRate > 0.0 && tmpEvapVolFlowRate > 0.0) {
    1180            0 :                     EvapVolFlowRateUser = this->EvapVolFlowRate;
    1181            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1182            0 :                         BaseSizer::reportSizerOutput(state,
    1183              :                                                      "ChillerHeater:Absorption:DirectFired",
    1184              :                                                      this->Name,
    1185              :                                                      "Design Size Design Chilled Water Flow Rate [m3/s]",
    1186              :                                                      tmpEvapVolFlowRate,
    1187              :                                                      "User-Specified Design Chilled Water Flow Rate [m3/s]",
    1188              :                                                      EvapVolFlowRateUser);
    1189            0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    1190            0 :                             if ((std::abs(tmpEvapVolFlowRate - EvapVolFlowRateUser) / EvapVolFlowRateUser) >
    1191            0 :                                 state.dataSize->AutoVsHardSizingThreshold) {
    1192            0 :                                 ShowMessage(state,
    1193            0 :                                             format("SizeChillerAbsorptionDirectFired: Potential issue with equipment sizing for {}", this->Name));
    1194            0 :                                 ShowContinueError(state,
    1195            0 :                                                   format("User-Specified Design Chilled Water Flow Rate of {:.5R} [m3/s]", EvapVolFlowRateUser));
    1196            0 :                                 ShowContinueError(
    1197            0 :                                     state, format("differs from Design Size Design Chilled Water Flow Rate of {:.5R} [m3/s]", tmpEvapVolFlowRate));
    1198            0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1199            0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1200              :                             }
    1201              :                         }
    1202              :                     }
    1203            0 :                     tmpEvapVolFlowRate = EvapVolFlowRateUser;
    1204              :                 }
    1205              :             }
    1206              :         }
    1207              :     } else {
    1208            0 :         if (this->EvapVolFlowRateWasAutoSized) {
    1209            0 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    1210            0 :                 ShowSevereError(state, format("SizeGasAbsorber: ChillerHeater:Absorption:DirectFired=\"{}\", autosize error.", this->Name));
    1211            0 :                 ShowContinueError(state, "Autosizing of Direct Fired Absorption Chiller evap flow rate requires");
    1212            0 :                 ShowContinueError(state, "a cooling loop Sizing:Plant object.");
    1213            0 :                 ErrorsFound = true;
    1214              :             }
    1215              :         } else {
    1216            0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1217            0 :                 if (this->EvapVolFlowRate > 0.0) {
    1218            0 :                     BaseSizer::reportSizerOutput(state,
    1219              :                                                  "ChillerHeater:Absorption:DirectFired",
    1220              :                                                  this->Name,
    1221              :                                                  "User-Specified Design Chilled Water Flow Rate [m3/s]",
    1222              :                                                  this->EvapVolFlowRate);
    1223              :                 }
    1224              :             }
    1225              :         }
    1226              :     }
    1227              : 
    1228            0 :     PlantUtilities::RegisterPlantCompDesignFlow(state, this->ChillReturnNodeNum, tmpEvapVolFlowRate);
    1229              : 
    1230            0 :     if (PltSizHeatNum > 0) {
    1231            0 :         if (state.dataSize->PlantSizData(PltSizHeatNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
    1232            0 :             tmpHeatRecVolFlowRate = state.dataSize->PlantSizData(PltSizHeatNum).DesVolFlowRate * this->SizFac;
    1233            0 :             if (!this->HeatVolFlowRateWasAutoSized) {
    1234            0 :                 tmpHeatRecVolFlowRate = this->HeatVolFlowRate;
    1235              :             }
    1236              : 
    1237              :         } else {
    1238            0 :             if (this->HeatVolFlowRateWasAutoSized) {
    1239            0 :                 tmpHeatRecVolFlowRate = 0.0;
    1240              :             }
    1241              :         }
    1242            0 :         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    1243            0 :             if (this->HeatVolFlowRateWasAutoSized) {
    1244            0 :                 this->HeatVolFlowRate = tmpHeatRecVolFlowRate;
    1245            0 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1246            0 :                     BaseSizer::reportSizerOutput(state,
    1247              :                                                  "ChillerHeater:Absorption:DirectFired",
    1248              :                                                  this->Name,
    1249              :                                                  "Design Size Design Hot Water Flow Rate [m3/s]",
    1250              :                                                  tmpHeatRecVolFlowRate);
    1251              :                 }
    1252            0 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    1253            0 :                     BaseSizer::reportSizerOutput(state,
    1254              :                                                  "ChillerHeater:Absorption:DirectFired",
    1255              :                                                  this->Name,
    1256              :                                                  "Initial Design Size Design Hot Water Flow Rate [m3/s]",
    1257              :                                                  tmpHeatRecVolFlowRate);
    1258              :                 }
    1259              :             } else {
    1260            0 :                 if (this->HeatVolFlowRate > 0.0 && tmpHeatRecVolFlowRate > 0.0) {
    1261            0 :                     HeatRecVolFlowRateUser = this->HeatVolFlowRate;
    1262            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1263            0 :                         BaseSizer::reportSizerOutput(state,
    1264              :                                                      "ChillerHeater:Absorption:DirectFired",
    1265              :                                                      this->Name,
    1266              :                                                      "Design Size Design Hot Water Flow Rate [m3/s]",
    1267              :                                                      tmpHeatRecVolFlowRate,
    1268              :                                                      "User-Specified Design Hot Water Flow Rate [m3/s]",
    1269              :                                                      HeatRecVolFlowRateUser);
    1270            0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    1271            0 :                             if ((std::abs(tmpHeatRecVolFlowRate - HeatRecVolFlowRateUser) / HeatRecVolFlowRateUser) >
    1272            0 :                                 state.dataSize->AutoVsHardSizingThreshold) {
    1273            0 :                                 ShowMessage(
    1274              :                                     state,
    1275            0 :                                     format("SizeChillerHeaterAbsorptionDirectFired: Potential issue with equipment sizing for {}", this->Name));
    1276            0 :                                 ShowContinueError(state,
    1277            0 :                                                   format("User-Specified Design Hot Water Flow Rate of {:.5R} [m3/s]", HeatRecVolFlowRateUser));
    1278            0 :                                 ShowContinueError(
    1279            0 :                                     state, format("differs from Design Size Design Hot Water Flow Rate of {:.5R} [m3/s]", tmpHeatRecVolFlowRate));
    1280            0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1281            0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1282              :                             }
    1283              :                         }
    1284              :                     }
    1285            0 :                     tmpHeatRecVolFlowRate = HeatRecVolFlowRateUser;
    1286              :                 }
    1287              :             }
    1288              :         }
    1289              :     } else {
    1290            0 :         if (this->HeatVolFlowRateWasAutoSized) {
    1291            0 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    1292            0 :                 ShowSevereError(state, format("SizeGasAbsorber: ChillerHeater:Absorption:DirectFired=\"{}\", autosize error.", this->Name));
    1293            0 :                 ShowContinueError(state, "Autosizing of Direct Fired Absorption Chiller hot water flow rate requires");
    1294            0 :                 ShowContinueError(state, "a heating loop Sizing:Plant object.");
    1295            0 :                 ErrorsFound = true;
    1296              :             }
    1297              :         } else {
    1298            0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1299            0 :                 if (this->HeatVolFlowRate > 0.0) {
    1300            0 :                     BaseSizer::reportSizerOutput(state,
    1301              :                                                  "ChillerHeater:Absorption:DirectFired",
    1302              :                                                  this->Name,
    1303              :                                                  "User-Specified Design Hot Water Flow Rate [m3/s]",
    1304              :                                                  this->HeatVolFlowRate);
    1305              :                 }
    1306              :             }
    1307              :         }
    1308              :     }
    1309              : 
    1310            0 :     PlantUtilities::RegisterPlantCompDesignFlow(state, this->HeatReturnNodeNum, tmpHeatRecVolFlowRate);
    1311              : 
    1312            0 :     if (PltSizCondNum > 0 && PltSizCoolNum > 0) {
    1313            0 :         if (state.dataSize->PlantSizData(PltSizCoolNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow && tmpNomCap > 0.0) {
    1314              : 
    1315            0 :             Cp = this->CDplantLoc.loop->glycol->getSpecificHeat(state, this->TempDesCondReturn, RoutineName);
    1316            0 :             rho = this->CDplantLoc.loop->glycol->getDensity(state, this->TempDesCondReturn, RoutineName);
    1317            0 :             tmpCondVolFlowRate = tmpNomCap * (1.0 + this->FuelCoolRatio) / (state.dataSize->PlantSizData(PltSizCondNum).DeltaT * Cp * rho);
    1318            0 :             if (!this->CondVolFlowRateWasAutoSized) {
    1319            0 :                 tmpCondVolFlowRate = this->CondVolFlowRate;
    1320              :             }
    1321              :             // IF (PlantFirstSizesOkayToFinalize) GasAbsorber(ChillNum)%CondVolFlowRate = tmpCondVolFlowRate
    1322              :         } else {
    1323            0 :             if (this->CondVolFlowRateWasAutoSized) {
    1324            0 :                 tmpCondVolFlowRate = 0.0;
    1325              :             }
    1326              :             // IF (PlantFirstSizesOkayToFinalize) GasAbsorber(ChillNum)%CondVolFlowRate = tmpCondVolFlowRate
    1327              :         }
    1328            0 :         if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    1329            0 :             if (this->CondVolFlowRateWasAutoSized) {
    1330            0 :                 this->CondVolFlowRate = tmpCondVolFlowRate;
    1331            0 :                 if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1332            0 :                     BaseSizer::reportSizerOutput(state,
    1333              :                                                  "ChillerHeater:Absorption:DirectFired",
    1334              :                                                  this->Name,
    1335              :                                                  "Design Size Design Condenser Water Flow Rate [m3/s]",
    1336              :                                                  tmpCondVolFlowRate);
    1337              :                 }
    1338            0 :                 if (state.dataPlnt->PlantFirstSizesOkayToReport) {
    1339            0 :                     BaseSizer::reportSizerOutput(state,
    1340              :                                                  "ChillerHeater:Absorption:DirectFired",
    1341              :                                                  this->Name,
    1342              :                                                  "Initial Design Size Design Condenser Water Flow Rate [m3/s]",
    1343              :                                                  tmpCondVolFlowRate);
    1344              :                 }
    1345              :             } else {
    1346            0 :                 if (this->CondVolFlowRate > 0.0 && tmpCondVolFlowRate > 0.0) {
    1347            0 :                     CondVolFlowRateUser = this->CondVolFlowRate;
    1348            0 :                     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1349            0 :                         BaseSizer::reportSizerOutput(state,
    1350              :                                                      "ChillerHeater:Absorption:DirectFired",
    1351              :                                                      this->Name,
    1352              :                                                      "Design Size Design Condenser Water Flow Rate [m3/s]",
    1353              :                                                      tmpCondVolFlowRate,
    1354              :                                                      "User-Specified Design Condenser Water Flow Rate [m3/s]",
    1355              :                                                      CondVolFlowRateUser);
    1356            0 :                         if (state.dataGlobal->DisplayExtraWarnings) {
    1357            0 :                             if ((std::abs(tmpCondVolFlowRate - CondVolFlowRateUser) / CondVolFlowRateUser) >
    1358            0 :                                 state.dataSize->AutoVsHardSizingThreshold) {
    1359            0 :                                 ShowMessage(state,
    1360            0 :                                             format("SizeChillerAbsorptionDirectFired: Potential issue with equipment sizing for {}", this->Name));
    1361            0 :                                 ShowContinueError(state,
    1362            0 :                                                   format("User-Specified Design Condenser Water Flow Rate of {:.5R} [m3/s]", CondVolFlowRateUser));
    1363            0 :                                 ShowContinueError(
    1364            0 :                                     state, format("differs from Design Size Design Condenser Water Flow Rate of {:.5R} [m3/s]", tmpCondVolFlowRate));
    1365            0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1366            0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1367              :                             }
    1368              :                         }
    1369              :                     }
    1370            0 :                     tmpCondVolFlowRate = CondVolFlowRateUser;
    1371              :                 }
    1372              :             }
    1373              :         }
    1374              :     } else {
    1375            0 :         if (this->CondVolFlowRateWasAutoSized) {
    1376            0 :             if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
    1377            0 :                 ShowSevereError(state, format("SizeGasAbsorber: ChillerHeater:Absorption:DirectFired=\"{}\", autosize error.", this->Name));
    1378            0 :                 ShowContinueError(state, "Autosizing of Direct Fired Absorption Chiller condenser flow rate requires a condenser");
    1379            0 :                 ShowContinueError(state, "loop Sizing:Plant object.");
    1380            0 :                 ErrorsFound = true;
    1381              :             }
    1382              :         } else {
    1383            0 :             if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1384            0 :                 if (this->CondVolFlowRate > 0.0) {
    1385            0 :                     BaseSizer::reportSizerOutput(state,
    1386              :                                                  "ChillerHeater:Absorption:DirectFired",
    1387              :                                                  this->Name,
    1388              :                                                  "User-Specified Design Condenser Water Flow Rate [m3/s]",
    1389              :                                                  this->CondVolFlowRate);
    1390              :                 }
    1391              :             }
    1392              :         }
    1393              :     }
    1394              : 
    1395              :     // save the design condenser water volumetric flow rate for use by the condenser water loop sizing algorithms
    1396            0 :     if (this->isWaterCooled) {
    1397            0 :         PlantUtilities::RegisterPlantCompDesignFlow(state, this->CondReturnNodeNum, tmpCondVolFlowRate);
    1398              :     }
    1399              : 
    1400            0 :     if (ErrorsFound) {
    1401            0 :         ShowFatalError(state, "Preceding sizing errors cause program termination");
    1402              :     }
    1403              : 
    1404            0 :     if (state.dataPlnt->PlantFinalSizesOkayToReport) {
    1405              :         // create predefined report
    1406            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechType, this->Name, "ChillerHeater:Absorption:DirectFired");
    1407            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomEff, this->Name, this->FuelCoolRatio);
    1408            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechNomCap, this->Name, this->NomCoolingCap);
    1409              : 
    1410              :         // std 229 new Chillers table
    1411            0 :         OutputReportPredefined::PreDefTableEntry(
    1412            0 :             state, state.dataOutRptPredefined->pdchChillerType, this->Name, "ChillerHeater:Absorption:DirectFired");
    1413            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefCap, this->Name, this->NomCoolingCap);
    1414            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefEff, this->Name, this->FuelCoolRatio);
    1415            0 :         OutputReportPredefined::PreDefTableEntry(
    1416            0 :             state, state.dataOutRptPredefined->pdchChillerRatedCap, this->Name, this->FuelCoolRatio); // did not find rated cap
    1417            0 :         OutputReportPredefined::PreDefTableEntry(state,
    1418            0 :                                                  state.dataOutRptPredefined->pdchChillerRatedEff,
    1419              :                                                  this->Name,
    1420              :                                                  this->NomCoolingCap); // did not find rated eff or cop ; also Eff == COP?
    1421            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerIPLVinSI, this->Name, "N/A");
    1422            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerIPLVinIP, this->Name, "N/A");
    1423            0 :         OutputReportPredefined::PreDefTableEntry(state,
    1424            0 :                                                  state.dataOutRptPredefined->pdchChillerPlantloopName,
    1425              :                                                  this->Name,
    1426            0 :                                                  (this->CWplantLoc.loop != nullptr) ? this->CWplantLoc.loop->Name : "N/A");
    1427            0 :         OutputReportPredefined::PreDefTableEntry(state,
    1428            0 :                                                  state.dataOutRptPredefined->pdchChillerPlantloopBranchName,
    1429              :                                                  this->Name,
    1430            0 :                                                  (this->CWplantLoc.loop != nullptr) ? this->CWplantLoc.branch->Name : "N/A");
    1431            0 :         OutputReportPredefined::PreDefTableEntry(state,
    1432            0 :                                                  state.dataOutRptPredefined->pdchChillerCondLoopName,
    1433              :                                                  this->Name,
    1434            0 :                                                  (this->CDplantLoc.loop != nullptr) ? this->CDplantLoc.loop->Name : "N/A");
    1435            0 :         OutputReportPredefined::PreDefTableEntry(state,
    1436            0 :                                                  state.dataOutRptPredefined->pdchChillerCondLoopBranchName,
    1437              :                                                  this->Name,
    1438            0 :                                                  (this->CDplantLoc.branch != nullptr) ? this->CDplantLoc.branch->Name : "N/A");
    1439            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerMinPLR, this->Name, this->MinPartLoadRat);
    1440            0 :         OutputReportPredefined::PreDefTableEntry(
    1441            0 :             state, state.dataOutRptPredefined->pdchChillerFuelType, this->Name, Constant::eResourceNames[static_cast<int>(this->FuelType)]);
    1442            0 :         OutputReportPredefined::PreDefTableEntry(
    1443            0 :             state, state.dataOutRptPredefined->pdchChillerRatedEntCondTemp, this->Name, this->TempDesCondReturn); // Rated==Ref?
    1444            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRatedLevEvapTemp, this->Name, "N/A");
    1445            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefEntCondTemp, this->Name, this->TempDesCondReturn);
    1446            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRefLevEvapTemp, this->Name, "N/A");
    1447              : 
    1448            0 :         OutputReportPredefined::PreDefTableEntry(
    1449            0 :             state, state.dataOutRptPredefined->pdchChillerDesSizeRefCHWFlowRate, this->Name, this->DesEvapMassFlowRate);
    1450            0 :         OutputReportPredefined::PreDefTableEntry(
    1451            0 :             state, state.dataOutRptPredefined->pdchChillerDesSizeRefCondFluidFlowRate, this->Name, this->DesCondMassFlowRate);
    1452            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerHeatRecPlantloopName, this->Name, "N/A");
    1453            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerHeatRecPlantloopBranchName, this->Name, "N/A");
    1454            0 :         OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchChillerRecRelCapFrac, this->Name, "N/A");
    1455              :     }
    1456            0 : }
    1457              : 
    1458            0 : void GasAbsorberSpecs::calculateChiller(EnergyPlusData &state, Real64 &MyLoad)
    1459              : {
    1460              :     //       AUTHOR         Jason Glazer
    1461              :     //       DATE WRITTEN   March 2001
    1462              : 
    1463              :     // Simulate a direct fired (gas consuming) absorption chiller using
    1464              :     // curves and inputs similar to DOE-2.1e
    1465              : 
    1466              :     // METHODOLOGY EMPLOYED:
    1467              :     // Curve fit of performance data
    1468              : 
    1469              :     // REFERENCES:
    1470              :     // 1.  DOE-2.1e Supplement and source code
    1471              :     // 2.  CoolTools GasMod work
    1472              : 
    1473              :     // FlowLock = 0  if mass flow rates may be changed by loop components
    1474              :     // FlowLock = 1  if mass flow rates may not be changed by loop components
    1475              : 
    1476              :     static constexpr std::string_view RoutineName("CalcGasAbsorberChillerModel");
    1477              : 
    1478              :     // Local copies of GasAbsorberSpecs Type
    1479              :     // all variables that are local copies of data structure
    1480              :     // variables are prefaced with an "l" for local.
    1481              :     // Local copies of GasAbsorberReportVars Type
    1482            0 :     Real64 lCoolingLoad(0.0);              // cooling load on the chiller (previously called QEvap)
    1483            0 :     Real64 lTowerLoad(0.0);                // load on the cooling tower/condenser (previously called QCond)
    1484            0 :     Real64 lCoolFuelUseRate(0.0);          // instantaneous use of gas for period for cooling
    1485            0 :     Real64 lCoolElectricPower(0.0);        // parasitic electric power used  for cooling
    1486            0 :     Real64 lChillSupplyTemp(0.0);          // reporting: evaporator outlet temperature (was EvapOutletTemp)
    1487            0 :     Real64 lCondSupplyTemp(0.0);           // reporting: condenser outlet temperature (was CondOutletTemp)
    1488            0 :     Real64 lCondWaterMassFlowRate(0.0);    // reporting: condenser mass flow rate (was Condmdot)
    1489            0 :     Real64 lCoolPartLoadRatio(0.0);        // operating part load ratio (load/capacity for cooling)
    1490            0 :     Real64 lAvailableCoolingCapacity(0.0); // current capacity after temperature adjustment
    1491            0 :     Real64 lFractionOfPeriodRunning(0.0);
    1492            0 :     Real64 PartLoadRat(0.0);           // actual operating part load ratio of unit (ranges from minplr to 1)
    1493              :     Real64 lChillWaterMassflowratemax; // Maximum flow rate through the evaporator
    1494              : 
    1495              :     // other local variables
    1496            0 :     Real64 ChillSupplySetPointTemp(0.0);
    1497              : 
    1498              :     Real64 calcCondTemp; // the condenser temperature used for curve calculation
    1499              :     // either return or supply depending on user input
    1500              :     Real64 revisedEstimateAvailCap; // final estimate of available capacity if using leaving
    1501              :     // condenser water temperature
    1502              :     Real64 errorAvailCap; // error fraction on final estimate of AvailableCoolingCapacity
    1503              :     DataPlant::LoopSideLocation LoopSideNum;
    1504              : 
    1505              :     // set node values to data structure values for nodes
    1506              : 
    1507            0 :     int lChillReturnNodeNum = this->ChillReturnNodeNum; // Node number on the inlet side of the plant
    1508            0 :     int lChillSupplyNodeNum = this->ChillSupplyNodeNum; // Node number on the outlet side of the plant
    1509            0 :     int lCondReturnNodeNum = this->CondReturnNodeNum;   // Node number on the inlet side of the condenser
    1510              : 
    1511              :     // set local copies of data from rest of input structure
    1512              : 
    1513            0 :     Real64 lNomCoolingCap = this->NomCoolingCap;         // W - design nominal capacity of Absorber
    1514            0 :     Real64 lFuelCoolRatio = this->FuelCoolRatio;         // ratio of fuel input to cooling output
    1515            0 :     Real64 lFuelHeatRatio = this->FuelHeatRatio;         // ratio of fuel input to heating output
    1516            0 :     Real64 lElecCoolRatio = this->ElecCoolRatio;         // ratio of electricity input to cooling output
    1517            0 :     Real64 lMinPartLoadRat = this->MinPartLoadRat;       // min allowed operating frac full load
    1518            0 :     Real64 lMaxPartLoadRat = this->MaxPartLoadRat;       // max allowed operating frac full load
    1519            0 :     bool lIsEnterCondensTemp = this->isEnterCondensTemp; // if using entering conderser water temperature is TRUE, exiting is FALSE
    1520            0 :     bool lIsWaterCooled = this->isWaterCooled;           // if water cooled it is TRUE
    1521            0 :     Real64 lCHWLowLimitTemp = this->CHWLowLimitTemp;     // Chilled Water Lower Limit Temperature
    1522              : 
    1523            0 :     Real64 lHeatElectricPower = this->HeatElectricPower; // parasitic electric power used  for heating
    1524            0 :     Real64 lHeatFuelUseRate = this->HeatFuelUseRate;     // instantaneous use of gas for period for heating
    1525            0 :     Real64 lHeatPartLoadRatio = this->HeatPartLoadRatio; // operating part load ratio (load/capacity for heating)
    1526              : 
    1527              :     // initialize entering conditions
    1528            0 :     Real64 lChillReturnTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp;
    1529            0 :     Real64 lChillWaterMassFlowRate = state.dataLoopNodes->Node(lChillReturnNodeNum).MassFlowRate;
    1530            0 :     Real64 lCondReturnTemp = state.dataLoopNodes->Node(lCondReturnNodeNum).Temp;
    1531              :     // Commenting this could be cause of diffs - lCondWaterMassFlowRate = Node(lCondReturnNodeNum).MassFlowRate;
    1532            0 :     switch (this->CWplantLoc.loop->LoopDemandCalcScheme) {
    1533            0 :     case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
    1534            0 :         ChillSupplySetPointTemp = state.dataLoopNodes->Node(lChillSupplyNodeNum).TempSetPoint;
    1535            0 :     } break;
    1536            0 :     case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
    1537            0 :         ChillSupplySetPointTemp = state.dataLoopNodes->Node(lChillSupplyNodeNum).TempSetPointHi;
    1538            0 :     } break;
    1539            0 :     default: {
    1540            0 :         assert(false);
    1541              :     } break;
    1542              :     }
    1543            0 :     Real64 ChillDeltaTemp = std::abs(lChillReturnTemp - ChillSupplySetPointTemp);
    1544              : 
    1545              :     // local fluid specific heat for chilled water
    1546            0 :     Real64 Cp_CW = this->CWplantLoc.loop->glycol->getSpecificHeat(state, lChillReturnTemp, RoutineName);
    1547              :     // local fluid specific heat for condenser water
    1548            0 :     Real64 Cp_CD = 0; // putting this here as a dummy initialization to hush the compiler warning, in real runs this value should never be used
    1549            0 :     if (this->CDplantLoc.loopNum > 0) {
    1550            0 :         Cp_CD = this->CDplantLoc.loop->glycol->getSpecificHeat(state, lChillReturnTemp, RoutineName);
    1551              :     }
    1552              : 
    1553              :     // If no loop demand or Absorber OFF, return
    1554              :     // will need to modify when absorber can act as a boiler
    1555            0 :     if (MyLoad >= 0 || !((this->InHeatingMode) || (this->InCoolingMode))) {
    1556              :         // set node temperatures
    1557            0 :         lChillSupplyTemp = lChillReturnTemp;
    1558            0 :         lCondSupplyTemp = lCondReturnTemp;
    1559            0 :         lCondWaterMassFlowRate = 0.0;
    1560            0 :         if (lIsWaterCooled) {
    1561            0 :             PlantUtilities::SetComponentFlowRate(state, lCondWaterMassFlowRate, this->CondReturnNodeNum, this->CondSupplyNodeNum, this->CDplantLoc);
    1562              :         }
    1563              :         // Commenting this could cause diffs - ChillDeltaTemp = 0.0;
    1564            0 :         lFractionOfPeriodRunning = min(1.0, max(lHeatPartLoadRatio, lCoolPartLoadRatio) / lMinPartLoadRat);
    1565              :     } else {
    1566              : 
    1567              :         // if water cooled use the input node otherwise just use outside air temperature
    1568            0 :         if (lIsWaterCooled) {
    1569              :             // most manufacturers rate have tables of entering condenser water temperature
    1570              :             // but a few use leaving condenser water temperature so we have a flag
    1571              :             // when leaving is used it uses the previous iterations value of the value
    1572            0 :             lCondReturnTemp = state.dataLoopNodes->Node(lCondReturnNodeNum).Temp;
    1573            0 :             if (lIsEnterCondensTemp) {
    1574            0 :                 calcCondTemp = lCondReturnTemp;
    1575              :             } else {
    1576            0 :                 if (this->oldCondSupplyTemp == 0) {
    1577            0 :                     this->oldCondSupplyTemp = lCondReturnTemp + 8.0; // if not previously estimated assume 8C greater than return
    1578              :                 }
    1579            0 :                 calcCondTemp = this->oldCondSupplyTemp;
    1580              :             }
    1581              :             // Set mass flow rates
    1582            0 :             lCondWaterMassFlowRate = this->DesCondMassFlowRate;
    1583            0 :             PlantUtilities::SetComponentFlowRate(state, lCondWaterMassFlowRate, this->CondReturnNodeNum, this->CondSupplyNodeNum, this->CDplantLoc);
    1584              :         } else {
    1585              :             // air cooled
    1586            0 :             state.dataLoopNodes->Node(lCondReturnNodeNum).Temp = state.dataLoopNodes->Node(lCondReturnNodeNum).OutAirDryBulb;
    1587            0 :             calcCondTemp = state.dataLoopNodes->Node(lCondReturnNodeNum).OutAirDryBulb;
    1588            0 :             lCondReturnTemp = state.dataLoopNodes->Node(lCondReturnNodeNum).Temp;
    1589            0 :             lCondWaterMassFlowRate = 0.0;
    1590            0 :             if (this->CDplantLoc.loopNum > 0) {
    1591            0 :                 PlantUtilities::SetComponentFlowRate(
    1592            0 :                     state, lCondWaterMassFlowRate, this->CondReturnNodeNum, this->CondSupplyNodeNum, this->CDplantLoc);
    1593              :             }
    1594              :         }
    1595              : 
    1596              :         // Determine available cooling capacity using the setpoint temperature
    1597            0 :         lAvailableCoolingCapacity = lNomCoolingCap * this->CoolCapFTCurve->value(state, ChillSupplySetPointTemp, calcCondTemp);
    1598              : 
    1599              :         // Calculate current load for cooling
    1600            0 :         MyLoad = sign(max(std::abs(MyLoad), lAvailableCoolingCapacity * lMinPartLoadRat), MyLoad);
    1601            0 :         MyLoad = sign(min(std::abs(MyLoad), lAvailableCoolingCapacity * lMaxPartLoadRat), MyLoad);
    1602              : 
    1603              :         // Determine the following variables depending on if the flow has been set in
    1604              :         // the nodes (flowlock=1 to 2) or if the amount of load is still be determined (flowlock=0)
    1605              :         //    chilled water flow,
    1606              :         //    cooling load taken by the chiller, and
    1607              :         //    supply temperature
    1608            0 :         lChillWaterMassflowratemax = this->DesEvapMassFlowRate;
    1609              : 
    1610            0 :         switch (this->CWplantLoc.side->FlowLock) {
    1611            0 :         case DataPlant::FlowLock::Unlocked: { // mass flow rates may be changed by loop components
    1612            0 :             this->PossibleSubcooling = false;
    1613            0 :             lCoolingLoad = std::abs(MyLoad);
    1614            0 :             if (ChillDeltaTemp != 0.0) {
    1615            0 :                 lChillWaterMassFlowRate = std::abs(lCoolingLoad / (Cp_CW * ChillDeltaTemp));
    1616            0 :                 if (lChillWaterMassFlowRate - lChillWaterMassflowratemax > DataBranchAirLoopPlant::MassFlowTolerance) {
    1617            0 :                     this->PossibleSubcooling = true;
    1618              :                 }
    1619              : 
    1620            0 :                 PlantUtilities::SetComponentFlowRate(
    1621            0 :                     state, lChillWaterMassFlowRate, this->ChillReturnNodeNum, this->ChillSupplyNodeNum, this->CWplantLoc);
    1622              :                 // Commenting this could cause diffs - lChillSupplyTemp = ChillSupplySetPointTemp;
    1623              :             } else {
    1624            0 :                 lChillWaterMassFlowRate = 0.0;
    1625            0 :                 ShowRecurringWarningErrorAtEnd(state,
    1626            0 :                                                "GasAbsorberChillerModel:Cooling\"" + this->Name + "\", DeltaTemp = 0 in mass flow calculation",
    1627            0 :                                                this->DeltaTempCoolErrCount);
    1628              :             }
    1629            0 :             lChillSupplyTemp = ChillSupplySetPointTemp;
    1630            0 :         } break;
    1631            0 :         case DataPlant::FlowLock::Locked: { // mass flow rates may not be changed by loop components
    1632            0 :             lChillWaterMassFlowRate = state.dataLoopNodes->Node(lChillReturnNodeNum).MassFlowRate;
    1633            0 :             if (this->PossibleSubcooling) {
    1634            0 :                 lCoolingLoad = std::abs(MyLoad);
    1635              : 
    1636            0 :                 ChillDeltaTemp = lCoolingLoad / lChillWaterMassFlowRate / Cp_CW;
    1637            0 :                 lChillSupplyTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp - ChillDeltaTemp;
    1638              :             } else {
    1639            0 :                 ChillDeltaTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp - ChillSupplySetPointTemp;
    1640            0 :                 lCoolingLoad = std::abs(lChillWaterMassFlowRate * Cp_CW * ChillDeltaTemp);
    1641            0 :                 lChillSupplyTemp = ChillSupplySetPointTemp;
    1642              :             }
    1643              :             // Check that the Chiller Supply outlet temp honors both plant loop temp low limit and also the chiller low limit
    1644            0 :             if (lChillSupplyTemp < lCHWLowLimitTemp) {
    1645            0 :                 if ((state.dataLoopNodes->Node(lChillReturnNodeNum).Temp - lCHWLowLimitTemp) > DataPlant::DeltaTempTol) {
    1646            0 :                     lChillSupplyTemp = lCHWLowLimitTemp;
    1647            0 :                     ChillDeltaTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp - lChillSupplyTemp;
    1648            0 :                     lCoolingLoad = lChillWaterMassFlowRate * Cp_CW * ChillDeltaTemp;
    1649              :                 } else {
    1650            0 :                     lChillSupplyTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp;
    1651            0 :                     ChillDeltaTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp - lChillSupplyTemp;
    1652            0 :                     lCoolingLoad = lChillWaterMassFlowRate * Cp_CW * ChillDeltaTemp;
    1653              :                 }
    1654              :             }
    1655            0 :             if (lChillSupplyTemp < state.dataLoopNodes->Node(lChillSupplyNodeNum).TempMin) {
    1656            0 :                 if ((state.dataLoopNodes->Node(lChillReturnNodeNum).Temp - state.dataLoopNodes->Node(lChillSupplyNodeNum).TempMin) >
    1657              :                     DataPlant::DeltaTempTol) {
    1658            0 :                     lChillSupplyTemp = state.dataLoopNodes->Node(lChillSupplyNodeNum).TempMin;
    1659            0 :                     ChillDeltaTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp - lChillSupplyTemp;
    1660            0 :                     lCoolingLoad = lChillWaterMassFlowRate * Cp_CW * ChillDeltaTemp;
    1661              :                 } else {
    1662            0 :                     lChillSupplyTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp;
    1663            0 :                     ChillDeltaTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp - lChillSupplyTemp;
    1664            0 :                     lCoolingLoad = lChillWaterMassFlowRate * Cp_CW * ChillDeltaTemp;
    1665              :                 }
    1666              :             }
    1667              : 
    1668              :             // Checks Coolingload on the basis of the machine limits.
    1669            0 :             if (lCoolingLoad > std::abs(MyLoad)) {
    1670            0 :                 if (lChillWaterMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
    1671            0 :                     lCoolingLoad = std::abs(MyLoad);
    1672            0 :                     ChillDeltaTemp = lCoolingLoad / lChillWaterMassFlowRate / Cp_CW;
    1673            0 :                     lChillSupplyTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp - ChillDeltaTemp;
    1674              :                 } else {
    1675            0 :                     lChillSupplyTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp;
    1676            0 :                     ChillDeltaTemp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp - lChillSupplyTemp;
    1677            0 :                     lCoolingLoad = lChillWaterMassFlowRate * Cp_CW * ChillDeltaTemp;
    1678              :                 }
    1679              :             }
    1680            0 :         } break;
    1681            0 :         default:
    1682            0 :             break;
    1683              :         }
    1684              : 
    1685              :         // Calculate operating part load ratio for cooling
    1686            0 :         PartLoadRat = min(std::abs(MyLoad) / lAvailableCoolingCapacity, lMaxPartLoadRat);
    1687            0 :         PartLoadRat = max(lMinPartLoadRat, PartLoadRat);
    1688              : 
    1689            0 :         if (lAvailableCoolingCapacity > 0.0) {
    1690            0 :             if (std::abs(MyLoad) / lAvailableCoolingCapacity < lMinPartLoadRat) {
    1691            0 :                 lCoolPartLoadRatio = MyLoad / lAvailableCoolingCapacity;
    1692              :             } else {
    1693            0 :                 lCoolPartLoadRatio = PartLoadRat;
    1694              :             }
    1695              :         } else { // Else if AvailableCoolingCapacity < 0.0
    1696            0 :             lCoolPartLoadRatio = 0.0;
    1697              :         }
    1698              : 
    1699              :         // calculate the fraction of the time period that the chiller would be running
    1700              :         // use maximum from heating and cooling sides
    1701            0 :         if (lCoolPartLoadRatio < lMinPartLoadRat || lHeatPartLoadRatio < lMinPartLoadRat) {
    1702            0 :             lFractionOfPeriodRunning = min(1.0, max(lHeatPartLoadRatio, lCoolPartLoadRatio) / lMinPartLoadRat);
    1703              :         } else {
    1704            0 :             lFractionOfPeriodRunning = 1.0;
    1705              :         }
    1706              : 
    1707              :         // Calculate fuel consumption for cooling
    1708              :         // fuel used for cooling availCap * HIR * HIR-FT * HIR-FPLR
    1709            0 :         lCoolFuelUseRate = lAvailableCoolingCapacity * lFuelCoolRatio * this->FuelCoolFTCurve->value(state, lChillSupplyTemp, calcCondTemp) *
    1710            0 :                            this->FuelCoolFPLRCurve->value(state, lCoolPartLoadRatio) * lFractionOfPeriodRunning;
    1711              : 
    1712              :         // Calculate electric parasitics used
    1713              :         // based on nominal capacity, not available capacity,
    1714              :         // electric used for cooling nomCap * %OP * EIR * EIR-FT * EIR-FPLR
    1715            0 :         lCoolElectricPower = lNomCoolingCap * lElecCoolRatio * lFractionOfPeriodRunning *
    1716            0 :                              this->ElecCoolFTCurve->value(state, lChillSupplyTemp, calcCondTemp) *
    1717            0 :                              this->ElecCoolFPLRCurve->value(state, lCoolPartLoadRatio);
    1718              : 
    1719              :         // determine conderser load which is cooling load plus the
    1720              :         // fuel used for cooling times the burner efficiency plus
    1721              :         // the electricity used
    1722            0 :         lTowerLoad = lCoolingLoad + lCoolFuelUseRate / lFuelHeatRatio + lCoolElectricPower;
    1723              : 
    1724              :         // for water cooled condenser make sure enough flow rate
    1725              :         // for air cooled condenser just set supply to return temperature
    1726            0 :         if (lIsWaterCooled) {
    1727            0 :             if (lCondWaterMassFlowRate > DataBranchAirLoopPlant::MassFlowTolerance) {
    1728            0 :                 lCondSupplyTemp = lCondReturnTemp + lTowerLoad / (lCondWaterMassFlowRate * Cp_CD);
    1729              :             } else {
    1730            0 :                 if (this->lCondWaterMassFlowRate_Index == 0) {
    1731            0 :                     ShowSevereError(state, format("CalcGasAbsorberChillerModel: Condenser flow = 0, for Gas Absorber Chiller={}", this->Name));
    1732            0 :                     ShowContinueErrorTimeStamp(state, "");
    1733              :                     // ShowFatalError(state, "Program Terminates due to previous error condition.");
    1734              :                 }
    1735            0 :                 ShowRecurringSevereErrorAtEnd(state,
    1736            0 :                                               format("CalcGasAbsorberChillerModel: Condenser flow = 0, for Gas Absorber Chiller={}: Condenser flow "
    1737              :                                                      "rate = 0 severe error warning continues...",
    1738            0 :                                                      this->Name),                // Message automatically written to "error file" at end of simulation
    1739            0 :                                               this->lCondWaterMassFlowRate_Index // Recurring message index, if zero, next available index is assigned
    1740              :                 );
    1741              :             }
    1742              :         } else {
    1743            0 :             lCondSupplyTemp = lCondReturnTemp; // if air cooled condenser just set supply and return to same temperature
    1744              :         }
    1745              : 
    1746              :         // save the condenser water supply temperature for next iteration if that is used in lookup
    1747              :         // and if capacity is large enough error than report problem
    1748            0 :         this->oldCondSupplyTemp = lCondSupplyTemp;
    1749            0 :         if (!lIsEnterCondensTemp) {
    1750              :             // calculate the fraction of the estimated error between the capacity based on the previous
    1751              :             // iteration's value of condenser supply temperature and the actual calculated condenser supply
    1752              :             // temperature.  If this becomes too common then may need to iterate a solution instead of
    1753              :             // relying on previous iteration method.
    1754            0 :             revisedEstimateAvailCap = lNomCoolingCap * this->CoolCapFTCurve->value(state, ChillSupplySetPointTemp, lCondSupplyTemp);
    1755            0 :             if (revisedEstimateAvailCap > 0.0) {
    1756            0 :                 errorAvailCap = std::abs((revisedEstimateAvailCap - lAvailableCoolingCapacity) / revisedEstimateAvailCap);
    1757            0 :                 if (errorAvailCap > 0.05) { // if more than 5% error in estimate
    1758            0 :                     ShowRecurringWarningErrorAtEnd(state,
    1759            0 :                                                    "GasAbsorberChillerModel:\"" + this->Name + "\", poor Condenser Supply Estimate",
    1760            0 :                                                    this->CondErrCount,
    1761              :                                                    errorAvailCap,
    1762              :                                                    errorAvailCap);
    1763              :                 }
    1764              :             }
    1765              :         }
    1766              :     } // IF(MyLoad>=0 .OR. .NOT. RunFlag)
    1767              :     // Write into the Report Variables except for nodes
    1768            0 :     this->CoolingLoad = lCoolingLoad;
    1769            0 :     this->TowerLoad = lTowerLoad;
    1770            0 :     this->CoolFuelUseRate = lCoolFuelUseRate;
    1771            0 :     this->CoolElectricPower = lCoolElectricPower;
    1772            0 :     this->CondReturnTemp = lCondReturnTemp;
    1773            0 :     this->ChillReturnTemp = lChillReturnTemp;
    1774            0 :     this->CondSupplyTemp = lCondSupplyTemp;
    1775            0 :     this->ChillSupplyTemp = lChillSupplyTemp;
    1776            0 :     this->ChillWaterFlowRate = lChillWaterMassFlowRate;
    1777            0 :     this->CondWaterFlowRate = lCondWaterMassFlowRate;
    1778            0 :     this->CoolPartLoadRatio = lCoolPartLoadRatio;
    1779            0 :     this->CoolingCapacity = lAvailableCoolingCapacity;
    1780            0 :     this->FractionOfPeriodRunning = lFractionOfPeriodRunning;
    1781              : 
    1782              :     // write the combined heating and cooling fuel used and electric used
    1783            0 :     this->FuelUseRate = lCoolFuelUseRate + lHeatFuelUseRate;
    1784            0 :     this->ElectricPower = lCoolElectricPower + lHeatElectricPower;
    1785            0 : }
    1786              : 
    1787            1 : void GasAbsorberSpecs::calculateHeater(EnergyPlusData &state, Real64 &MyLoad, bool const RunFlag)
    1788              : {
    1789              :     //       AUTHOR         Jason Glazer and Michael J. Witte
    1790              :     //       DATE WRITTEN   March 2001
    1791              :     // Simulate a direct fired (gas consuming) absorption chiller using
    1792              :     // curves and inputs similar to DOE-2.1e
    1793              : 
    1794              :     // METHODOLOGY EMPLOYED:
    1795              :     // Curve fit of performance data
    1796              : 
    1797              :     // REFERENCES:
    1798              :     // 1.  DOE-2.1e Supplement and source code
    1799              :     // 2.  CoolTools GasMod work
    1800              : 
    1801              :     // FlowLock = 0  if mass flow rates may be changed by loop components
    1802              :     // FlowLock = 1  if mass flow rates may not be changed by loop components
    1803              :     // FlowLock = 2  if overloaded and mass flow rates has changed to a small amount and Tout drops
    1804              :     //                 below Setpoint
    1805              : 
    1806              :     // SUBROUTINE PARAMETER DEFINITIONS:
    1807              :     static constexpr std::string_view RoutineName("CalcGasAbsorberHeaterModel");
    1808              : 
    1809              :     // Local copies of GasAbsorberSpecs Type
    1810              :     // all variables that are local copies of data structure
    1811              :     // variables are prefaced with an "l" for local.
    1812              :     Real64 lNomCoolingCap;    // W - design nominal capacity of Absorber
    1813              :     Real64 lNomHeatCoolRatio; // ratio of heating to cooling capacity
    1814              :     Real64 lFuelHeatRatio;    // ratio of fuel input to heating output
    1815              :     Real64 lElecHeatRatio;    // ratio of electricity input to heating output
    1816              :     int lHeatReturnNodeNum;   // absorber steam inlet node number, water side
    1817              :     int lHeatSupplyNodeNum;   // absorber steam outlet node number, water side
    1818              :     Real64 lMinPartLoadRat;   // min allowed operating frac full load
    1819              :     Real64 lMaxPartLoadRat;   // max allowed operating frac full load
    1820              :     // Local copies of GasAbsorberReportVars Type
    1821            1 :     Real64 lHeatingLoad(0.0);              // heating load on the chiller
    1822            1 :     Real64 lCoolFuelUseRate(0.0);          // instantaneous use of gas for period for cooling
    1823            1 :     Real64 lHeatFuelUseRate(0.0);          // instantaneous use of gas for period for heating
    1824            1 :     Real64 lCoolElectricPower(0.0);        // parasitic electric power used  for cooling
    1825            1 :     Real64 lHeatElectricPower(0.0);        // parasitic electric power used  for heating
    1826            1 :     Real64 lHotWaterReturnTemp(0.0);       // reporting: hot water return (inlet) temperature
    1827            1 :     Real64 lHotWaterSupplyTemp(0.0);       // reporting: hot water supply (outlet) temperature
    1828            1 :     Real64 lHotWaterMassFlowRate(0.0);     // reporting: hot water mass flow rate
    1829            1 :     Real64 lCoolPartLoadRatio(0.0);        // operating part load ratio (load/capacity for cooling)
    1830            1 :     Real64 lHeatPartLoadRatio(0.0);        // operating part load ratio (load/capacity for heating)
    1831            1 :     Real64 lAvailableHeatingCapacity(0.0); // current heating capacity
    1832            1 :     Real64 lFractionOfPeriodRunning(0.0);
    1833              :     // other local variables
    1834            1 :     Real64 HeatDeltaTemp(0.0); // hot water temperature difference
    1835            1 :     Real64 HeatSupplySetPointTemp(0.0);
    1836              :     Real64 Cp_HW; // local fluid specific heat for hot water
    1837              : 
    1838              :     // set node values to data structure values for nodes
    1839              : 
    1840            1 :     lHeatReturnNodeNum = this->HeatReturnNodeNum;
    1841            1 :     lHeatSupplyNodeNum = this->HeatSupplyNodeNum;
    1842              : 
    1843              :     // set local copies of data from rest of input structure
    1844              : 
    1845            1 :     lNomCoolingCap = this->NomCoolingCap;
    1846            1 :     lNomHeatCoolRatio = this->NomHeatCoolRatio;
    1847            1 :     lFuelHeatRatio = this->FuelHeatRatio;
    1848            1 :     lElecHeatRatio = this->ElecHeatRatio;
    1849            1 :     lMinPartLoadRat = this->MinPartLoadRat;
    1850            1 :     lMaxPartLoadRat = this->MaxPartLoadRat;
    1851              : 
    1852            1 :     Cp_HW = this->HWplantLoc.loop->glycol->getSpecificHeat(state, lHotWaterReturnTemp, RoutineName);
    1853              : 
    1854            1 :     lCoolElectricPower = this->CoolElectricPower;
    1855            1 :     lCoolFuelUseRate = this->CoolFuelUseRate;
    1856            1 :     lCoolPartLoadRatio = this->CoolPartLoadRatio;
    1857              : 
    1858              :     // initialize entering conditions
    1859            1 :     lHotWaterReturnTemp = state.dataLoopNodes->Node(lHeatReturnNodeNum).Temp;
    1860            1 :     lHotWaterMassFlowRate = state.dataLoopNodes->Node(lHeatReturnNodeNum).MassFlowRate;
    1861            1 :     switch (this->HWplantLoc.loop->LoopDemandCalcScheme) {
    1862            1 :     case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
    1863            1 :         HeatSupplySetPointTemp = state.dataLoopNodes->Node(lHeatSupplyNodeNum).TempSetPoint;
    1864            1 :     } break;
    1865            0 :     case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
    1866            0 :         HeatSupplySetPointTemp = state.dataLoopNodes->Node(lHeatSupplyNodeNum).TempSetPointLo;
    1867            0 :     } break;
    1868            0 :     default: {
    1869            0 :         assert(false);
    1870              :     } break;
    1871              :     }
    1872            1 :     HeatDeltaTemp = std::abs(lHotWaterReturnTemp - HeatSupplySetPointTemp);
    1873              : 
    1874              :     // If no loop demand or Absorber OFF, return
    1875              :     // will need to modify when absorber can act as a boiler
    1876            1 :     if (MyLoad <= 0 || !RunFlag) {
    1877              :         // set node temperatures
    1878            0 :         lHotWaterSupplyTemp = lHotWaterReturnTemp;
    1879              :         // Commenting this could cause diffs - HeatDeltaTemp = 0.0;
    1880            0 :         lFractionOfPeriodRunning = min(1.0, max(lHeatPartLoadRatio, lCoolPartLoadRatio) / lMinPartLoadRat);
    1881              :     } else {
    1882              : 
    1883              :         // Determine available heating capacity using the current cooling load
    1884            1 :         lAvailableHeatingCapacity =
    1885            1 :             this->NomHeatCoolRatio * this->NomCoolingCap * this->HeatCapFCoolCurve->value(state, (this->CoolingLoad / this->NomCoolingCap));
    1886              : 
    1887              :         // Calculate current load for heating
    1888            1 :         MyLoad = sign(max(std::abs(MyLoad), this->HeatingCapacity * lMinPartLoadRat), MyLoad);
    1889            1 :         MyLoad = sign(min(std::abs(MyLoad), this->HeatingCapacity * lMaxPartLoadRat), MyLoad);
    1890              : 
    1891              :         // Determine the following variables depending on if the flow has been set in
    1892              :         // the nodes (flowlock=1 to 2) or if the amount of load is still be determined (flowlock=0)
    1893              :         //    chilled water flow,
    1894              :         //    cooling load taken by the chiller, and
    1895              :         //    supply temperature
    1896            1 :         switch (this->HWplantLoc.side->FlowLock) {
    1897            0 :         case DataPlant::FlowLock::Unlocked: { // mass flow rates may be changed by loop components
    1898            0 :             lHeatingLoad = std::abs(MyLoad);
    1899            0 :             if (HeatDeltaTemp != 0) {
    1900            0 :                 lHotWaterMassFlowRate = std::abs(lHeatingLoad / (Cp_HW * HeatDeltaTemp));
    1901              : 
    1902            0 :                 PlantUtilities::SetComponentFlowRate(
    1903            0 :                     state, lHotWaterMassFlowRate, this->HeatReturnNodeNum, this->HeatSupplyNodeNum, this->HWplantLoc);
    1904              : 
    1905              :             } else {
    1906            0 :                 lHotWaterMassFlowRate = 0.0;
    1907            0 :                 ShowRecurringWarningErrorAtEnd(state,
    1908            0 :                                                "GasAbsorberChillerModel:Heating\"" + this->Name + "\", DeltaTemp = 0 in mass flow calculation",
    1909            0 :                                                this->DeltaTempHeatErrCount);
    1910              :             }
    1911            0 :             lHotWaterSupplyTemp = HeatSupplySetPointTemp;
    1912            0 :         } break;
    1913            1 :         case DataPlant::FlowLock::Locked: { // mass flow rates may not be changed by loop components
    1914            1 :             lHotWaterSupplyTemp = HeatSupplySetPointTemp;
    1915            1 :             lHeatingLoad = std::abs(lHotWaterMassFlowRate * Cp_HW * HeatDeltaTemp);
    1916            1 :         } break;
    1917            0 :         default:
    1918            0 :             break;
    1919              :         }
    1920              : 
    1921              :         // Calculate operating part load ratio for cooling
    1922            1 :         if (lAvailableHeatingCapacity <= 0.0) {
    1923            1 :             lAvailableHeatingCapacity = 0.0;
    1924            1 :             lHeatPartLoadRatio = 0.0;
    1925              :         } else {
    1926            0 :             lHeatPartLoadRatio = lHeatingLoad / lAvailableHeatingCapacity;
    1927              :         }
    1928              : 
    1929              :         // Calculate fuel consumption for cooling
    1930              :         // fuel used for cooling availCap * HIR * HIR-FT * HIR-FPLR
    1931              : 
    1932            1 :         lHeatFuelUseRate = lAvailableHeatingCapacity * lFuelHeatRatio * this->FuelHeatFHPLRCurve->value(state, lHeatPartLoadRatio);
    1933              : 
    1934              :         // calculate the fraction of the time period that the chiller would be running
    1935              :         // use maximum from heating and cooling sides
    1936            1 :         lFractionOfPeriodRunning = min(1.0, max(lHeatPartLoadRatio, lCoolPartLoadRatio) / lMinPartLoadRat);
    1937              : 
    1938              :         // Calculate electric parasitics used
    1939              :         // for heating based on nominal capacity not available capacity
    1940            1 :         lHeatElectricPower = lNomCoolingCap * lNomHeatCoolRatio * lElecHeatRatio * lFractionOfPeriodRunning;
    1941              :         // Coodinate electric parasitics for heating and cooling to avoid double counting
    1942              :         // Total electric is the max of heating electric or cooling electric
    1943              :         // If heating electric is greater, leave cooling electric and subtract if off of heating elec
    1944              :         // If cooling electric is greater, set heating electric to zero
    1945            1 :         if (lHeatElectricPower <= lCoolElectricPower) {
    1946            0 :             lHeatElectricPower = 0.0;
    1947              :         } else {
    1948            1 :             lHeatElectricPower -= lCoolElectricPower;
    1949              :         }
    1950              : 
    1951              :     } // IF(MyLoad==0 .OR. .NOT. RunFlag)
    1952              :     // Write into the Report Variables except for nodes
    1953            1 :     this->HeatingLoad = lHeatingLoad;
    1954            1 :     this->HeatFuelUseRate = lHeatFuelUseRate;
    1955            1 :     this->HeatElectricPower = lHeatElectricPower;
    1956            1 :     this->HotWaterReturnTemp = lHotWaterReturnTemp;
    1957            1 :     this->HotWaterSupplyTemp = lHotWaterSupplyTemp;
    1958            1 :     this->HotWaterFlowRate = lHotWaterMassFlowRate;
    1959            1 :     this->HeatPartLoadRatio = lHeatPartLoadRatio;
    1960            1 :     this->HeatingCapacity = lAvailableHeatingCapacity;
    1961            1 :     this->FractionOfPeriodRunning = lFractionOfPeriodRunning;
    1962              : 
    1963              :     // write the combined heating and cooling fuel used and electric used
    1964            1 :     this->FuelUseRate = lCoolFuelUseRate + lHeatFuelUseRate;
    1965            1 :     this->ElectricPower = lCoolElectricPower + lHeatElectricPower;
    1966            1 : }
    1967              : 
    1968            0 : void GasAbsorberSpecs::updateCoolRecords(EnergyPlusData &state,
    1969              :                                          Real64 const MyLoad, // current load
    1970              :                                          bool const RunFlag   // TRUE if Absorber operating
    1971              : )
    1972              : {
    1973              :     //       AUTHOR         Jason Glazer
    1974              :     //       DATE WRITTEN   March 2001
    1975              : 
    1976            0 :     int lChillReturnNodeNum = this->ChillReturnNodeNum;
    1977            0 :     int lChillSupplyNodeNum = this->ChillSupplyNodeNum;
    1978            0 :     int lCondReturnNodeNum = this->CondReturnNodeNum;
    1979            0 :     int lCondSupplyNodeNum = this->CondSupplyNodeNum;
    1980              : 
    1981            0 :     if (MyLoad == 0 || !RunFlag) {
    1982            0 :         state.dataLoopNodes->Node(lChillSupplyNodeNum).Temp = state.dataLoopNodes->Node(lChillReturnNodeNum).Temp;
    1983            0 :         if (this->isWaterCooled) {
    1984            0 :             state.dataLoopNodes->Node(lCondSupplyNodeNum).Temp = state.dataLoopNodes->Node(lCondReturnNodeNum).Temp;
    1985              :         }
    1986              :     } else {
    1987            0 :         state.dataLoopNodes->Node(lChillSupplyNodeNum).Temp = this->ChillSupplyTemp;
    1988            0 :         if (this->isWaterCooled) {
    1989            0 :             state.dataLoopNodes->Node(lCondSupplyNodeNum).Temp = this->CondSupplyTemp;
    1990              :         }
    1991              :     }
    1992              : 
    1993              :     // convert power to energy and instantaneous use to use over the time step
    1994            0 :     this->CoolingEnergy = this->CoolingLoad * state.dataHVACGlobal->TimeStepSysSec;
    1995            0 :     this->TowerEnergy = this->TowerLoad * state.dataHVACGlobal->TimeStepSysSec;
    1996            0 :     this->FuelEnergy = this->FuelUseRate * state.dataHVACGlobal->TimeStepSysSec;
    1997            0 :     this->CoolFuelEnergy = this->CoolFuelUseRate * state.dataHVACGlobal->TimeStepSysSec;
    1998            0 :     this->ElectricEnergy = this->ElectricPower * state.dataHVACGlobal->TimeStepSysSec;
    1999            0 :     this->CoolElectricEnergy = this->CoolElectricPower * state.dataHVACGlobal->TimeStepSysSec;
    2000            0 :     if (this->CoolFuelUseRate != 0.0) {
    2001            0 :         this->FuelCOP = this->CoolingLoad / this->CoolFuelUseRate;
    2002              :     } else {
    2003            0 :         this->FuelCOP = 0.0;
    2004              :     }
    2005            0 : }
    2006              : 
    2007            0 : void GasAbsorberSpecs::updateHeatRecords(EnergyPlusData &state,
    2008              :                                          Real64 const MyLoad, // current load
    2009              :                                          bool const RunFlag   // TRUE if Absorber operating
    2010              : )
    2011              : {
    2012              :     //       AUTHOR         Jason Glazer
    2013              :     //       DATE WRITTEN   March 2001
    2014              : 
    2015            0 :     int lHeatReturnNodeNum = this->HeatReturnNodeNum;
    2016            0 :     int lHeatSupplyNodeNum = this->HeatSupplyNodeNum;
    2017              : 
    2018            0 :     if (MyLoad == 0 || !RunFlag) {
    2019            0 :         state.dataLoopNodes->Node(lHeatSupplyNodeNum).Temp = state.dataLoopNodes->Node(lHeatReturnNodeNum).Temp;
    2020              :     } else {
    2021            0 :         state.dataLoopNodes->Node(lHeatSupplyNodeNum).Temp = this->HotWaterSupplyTemp;
    2022              :     }
    2023              : 
    2024              :     // convert power to energy and instantaneous use to use over the time step
    2025            0 :     this->HeatingEnergy = this->HeatingLoad * state.dataHVACGlobal->TimeStepSysSec;
    2026            0 :     this->FuelEnergy = this->FuelUseRate * state.dataHVACGlobal->TimeStepSysSec;
    2027            0 :     this->HeatFuelEnergy = this->HeatFuelUseRate * state.dataHVACGlobal->TimeStepSysSec;
    2028            0 :     this->ElectricEnergy = this->ElectricPower * state.dataHVACGlobal->TimeStepSysSec;
    2029            0 :     this->HeatElectricEnergy = this->HeatElectricPower * state.dataHVACGlobal->TimeStepSysSec;
    2030            0 : }
    2031              : 
    2032            0 : void GasAbsorberSpecs::oneTimeInit([[maybe_unused]] EnergyPlusData &state)
    2033              : {
    2034            0 : }
    2035              : 
    2036              : } // namespace EnergyPlus::ChillerGasAbsorption
        

Generated by: LCOV version 2.0-1