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