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