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