Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Autosizing/Base.hh>
57 : #include <EnergyPlus/BranchNodeConnections.hh>
58 : #include <EnergyPlus/Data/EnergyPlusData.hh>
59 : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
60 : #include <EnergyPlus/DataEnvironment.hh>
61 : #include <EnergyPlus/DataHVACGlobals.hh>
62 : #include <EnergyPlus/DataIPShortCuts.hh>
63 : #include <EnergyPlus/DataLoopNode.hh>
64 : #include <EnergyPlus/DataSizing.hh>
65 : #include <EnergyPlus/DataWater.hh>
66 : #include <EnergyPlus/EvaporativeFluidCoolers.hh>
67 : #include <EnergyPlus/FluidProperties.hh>
68 : #include <EnergyPlus/General.hh>
69 : #include <EnergyPlus/GlobalNames.hh>
70 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
71 : #include <EnergyPlus/NodeInputManager.hh>
72 : #include <EnergyPlus/OutAirNodeManager.hh>
73 : #include <EnergyPlus/OutputProcessor.hh>
74 : #include <EnergyPlus/OutputReportPredefined.hh>
75 : #include <EnergyPlus/Plant/DataPlant.hh>
76 : #include <EnergyPlus/PlantUtilities.hh>
77 : #include <EnergyPlus/Psychrometrics.hh>
78 : #include <EnergyPlus/ScheduleManager.hh>
79 : #include <EnergyPlus/UtilityRoutines.hh>
80 : #include <EnergyPlus/WaterManager.hh>
81 :
82 : namespace EnergyPlus {
83 :
84 : namespace EvaporativeFluidCoolers {
85 :
86 : // MODULE INFORMATION:
87 : // AUTHOR Chandan Sharma
88 : // DATE WRITTEN May 2009
89 : // MODIFIED na
90 : // RE-ENGINEERED na
91 :
92 : // PURPOSE OF THIS MODULE:
93 : // Model the performance of evaporative fluid coolers
94 :
95 : // METHODOLOGY EMPLOYED:
96 : // Based on cooling tower by Shirey, Raustad: Dec 2000; Shirey, Sept 2002
97 :
98 : constexpr std::string_view cEvapFluidCooler_SingleSpeed("EvaporativeFluidCooler:SingleSpeed");
99 : constexpr std::string_view cEvapFluidCooler_TwoSpeed("EvaporativeFluidCooler:TwoSpeed");
100 : constexpr std::array<std::string_view, static_cast<int>(CapacityControl::Num)> controlNamesUC = {"FANCYCLING", "FLUIDBYPASS"};
101 : constexpr std::array<std::string_view, static_cast<int>(EvapLoss::Num)> evapLossNamesUC = {"LOSSFACTOR", "SATURATEDEXIT"};
102 : constexpr std::array<std::string_view, static_cast<int>(Blowdown::Num)> blowDownNamesUC = {"CONCENTRATIONRATIO", "SCHEDULEDRATE"};
103 :
104 : EvapFluidCoolerSpecs *
105 3 : EvapFluidCoolerSpecs::factory(EnergyPlusData &state, DataPlant::PlantEquipmentType objectType, std::string const &objectName)
106 : {
107 : // Process the input data if it hasn't been done already
108 3 : if (state.dataEvapFluidCoolers->GetEvapFluidCoolerInputFlag) {
109 3 : GetEvapFluidCoolerInput(state);
110 3 : state.dataEvapFluidCoolers->GetEvapFluidCoolerInputFlag = false;
111 : }
112 :
113 : // Now look for this particular object
114 6 : auto thisObj = std::find_if(
115 3 : state.dataEvapFluidCoolers->SimpleEvapFluidCooler.begin(),
116 3 : state.dataEvapFluidCoolers->SimpleEvapFluidCooler.end(),
117 3 : [&objectType, &objectName](const EvapFluidCoolerSpecs &myObj) { return myObj.Type == objectType && myObj.Name == objectName; });
118 3 : if (thisObj != state.dataEvapFluidCoolers->SimpleEvapFluidCooler.end()) {
119 3 : return thisObj;
120 : }
121 : // If we didn't find it, fatal
122 : ShowFatalError(state, format("LocalEvapFluidCoolerFactory: Error getting inputs for object named: {}", objectName)); // LCOV_EXCL_LINE
123 : // Shut up the compiler
124 : return nullptr; // LCOV_EXCL_LINE
125 : }
126 :
127 3 : void GetEvapFluidCoolerInput(EnergyPlusData &state)
128 : {
129 :
130 : // SUBROUTINE INFORMATION:
131 : // AUTHOR: Chandan Sharma
132 : // DATE WRITTEN: May 2009
133 : // MODIFIED Chandan Sharma, April 2010
134 : // RE-ENGINEERED na
135 :
136 : // PURPOSE OF THIS SUBROUTINE:
137 : // Obtains input data for evaporative fluid coolers and stores it in SimpleEvapFluidCooler data structure.
138 :
139 : // METHODOLOGY EMPLOYED:
140 : // Uses "Get" routines to read in the data.
141 :
142 : // REFERENCES:
143 : // Based on GetTowerInput subroutine from Don Shirey, Jan 2001 and Sept/Oct 2002
144 : // B.A. Qureshi and S.M. Zubair , Prediction of evaporation losses in evaporative fluid coolers
145 : // Applied thermal engineering 27 (2007) 520-527
146 :
147 : static constexpr std::string_view routineName = "GetEvapFluidCoolerInput";
148 :
149 : int NumAlphas; // Number of elements in the alpha array
150 : int NumNums; // Number of elements in the numeric array
151 : int IOStat; // IO Status when calling get input subroutine
152 3 : bool ErrorsFound(false); // Logical flag set .TRUE. if errors found while getting input data
153 3 : Array1D<Real64> NumArray(25); // Numeric input data array
154 3 : Array1D_string AlphArray(13); // Character string input data array
155 :
156 : // Get number of all evaporative fluid coolers specified in the input data file (idf)
157 3 : int NumSingleSpeedEvapFluidCoolers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cEvapFluidCooler_SingleSpeed);
158 3 : int NumTwoSpeedEvapFluidCoolers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cEvapFluidCooler_TwoSpeed);
159 3 : int NumSimpleEvapFluidCoolers = NumSingleSpeedEvapFluidCoolers + NumTwoSpeedEvapFluidCoolers;
160 :
161 3 : if (NumSimpleEvapFluidCoolers <= 0) {
162 0 : ShowFatalError(state,
163 : "No evaporative fluid cooler objects found in input, however, a branch object has specified an evaporative fluid cooler. "
164 : "Search the input for evaporative fluid cooler to determine the cause for this error.");
165 : }
166 :
167 : // Allocate data structures to hold evaporative fluid cooler input data,
168 : // report data and evaporative fluid cooler inlet conditions
169 3 : state.dataEvapFluidCoolers->SimpleEvapFluidCooler.allocate(NumSimpleEvapFluidCoolers);
170 3 : state.dataEvapFluidCoolers->UniqueSimpleEvapFluidCoolerNames.reserve(NumSimpleEvapFluidCoolers);
171 :
172 : // Load data structures with evaporative fluid cooler input data
173 3 : state.dataIPShortCut->cCurrentModuleObject = cEvapFluidCooler_SingleSpeed;
174 5 : for (int SingleSpeedEvapFluidCoolerNumber = 1; SingleSpeedEvapFluidCoolerNumber <= NumSingleSpeedEvapFluidCoolers;
175 : ++SingleSpeedEvapFluidCoolerNumber) {
176 2 : int EvapFluidCoolerNum = SingleSpeedEvapFluidCoolerNumber;
177 6 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
178 2 : state.dataIPShortCut->cCurrentModuleObject,
179 : SingleSpeedEvapFluidCoolerNumber,
180 : AlphArray,
181 : NumAlphas,
182 : NumArray,
183 : NumNums,
184 : IOStat,
185 : _,
186 2 : state.dataIPShortCut->lAlphaFieldBlanks,
187 2 : state.dataIPShortCut->cAlphaFieldNames,
188 2 : state.dataIPShortCut->cNumericFieldNames);
189 :
190 2 : ErrorObjectHeader eoh{routineName, state.dataIPShortCut->cCurrentModuleObject, AlphArray(1)};
191 :
192 2 : GlobalNames::VerifyUniqueInterObjectName(state,
193 2 : state.dataEvapFluidCoolers->UniqueSimpleEvapFluidCoolerNames,
194 2 : AlphArray(1),
195 2 : state.dataIPShortCut->cCurrentModuleObject,
196 2 : state.dataIPShortCut->cAlphaFieldNames(1),
197 : ErrorsFound);
198 :
199 2 : auto &thisEFC = state.dataEvapFluidCoolers->SimpleEvapFluidCooler(EvapFluidCoolerNum);
200 :
201 2 : thisEFC.Name = AlphArray(1);
202 2 : thisEFC.EvapFluidCoolerType = state.dataIPShortCut->cCurrentModuleObject;
203 2 : thisEFC.Type = DataPlant::PlantEquipmentType::EvapFluidCooler_SingleSpd;
204 2 : thisEFC.EvapFluidCoolerMassFlowRateMultiplier = 2.5;
205 2 : thisEFC.WaterInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
206 2 : AlphArray(2),
207 : ErrorsFound,
208 : DataLoopNode::ConnectionObjectType::EvaporativeFluidCoolerSingleSpeed,
209 2 : AlphArray(1),
210 : DataLoopNode::NodeFluidType::Water,
211 : DataLoopNode::ConnectionType::Inlet,
212 : NodeInputManager::CompFluidStream::Primary,
213 : DataLoopNode::ObjectIsNotParent);
214 4 : thisEFC.WaterOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
215 2 : AlphArray(3),
216 : ErrorsFound,
217 : DataLoopNode::ConnectionObjectType::EvaporativeFluidCoolerSingleSpeed,
218 2 : AlphArray(1),
219 : DataLoopNode::NodeFluidType::Water,
220 : DataLoopNode::ConnectionType::Outlet,
221 : NodeInputManager::CompFluidStream::Primary,
222 : DataLoopNode::ObjectIsNotParent);
223 4 : BranchNodeConnections::TestCompSet(
224 2 : state, state.dataIPShortCut->cCurrentModuleObject, AlphArray(1), AlphArray(2), AlphArray(3), "Chilled Water Nodes");
225 2 : thisEFC.HighSpeedAirFlowRate = NumArray(1);
226 2 : if (thisEFC.HighSpeedAirFlowRate == DataSizing::AutoSize) {
227 1 : thisEFC.HighSpeedAirFlowRateWasAutoSized = true;
228 : }
229 2 : thisEFC.HighSpeedFanPower = NumArray(2);
230 2 : if (thisEFC.HighSpeedFanPower == DataSizing::AutoSize) {
231 1 : thisEFC.HighSpeedFanPowerWasAutoSized = true;
232 : }
233 2 : thisEFC.DesignSprayWaterFlowRate = NumArray(3);
234 2 : thisEFC.HeatRejectCapNomCapSizingRatio = NumArray(4);
235 2 : thisEFC.HighSpeedStandardDesignCapacity = NumArray(5);
236 2 : thisEFC.HighSpeedEvapFluidCoolerUA = NumArray(6);
237 2 : if (thisEFC.HighSpeedEvapFluidCoolerUA == DataSizing::AutoSize) {
238 1 : thisEFC.HighSpeedEvapFluidCoolerUAWasAutoSized = true;
239 : }
240 2 : thisEFC.DesignWaterFlowRate = NumArray(7);
241 2 : if (thisEFC.DesignWaterFlowRate == DataSizing::AutoSize) {
242 1 : thisEFC.DesignWaterFlowRateWasAutoSized = true;
243 : }
244 2 : thisEFC.HighSpeedUserSpecifiedDesignCapacity = NumArray(8);
245 2 : thisEFC.DesignEnteringWaterTemp = NumArray(9);
246 2 : thisEFC.DesignEnteringAirTemp = NumArray(10);
247 2 : thisEFC.DesignEnteringAirWetBulbTemp = NumArray(11);
248 :
249 2 : if (state.dataIPShortCut->lAlphaFieldBlanks(4) || AlphArray(4).empty()) {
250 0 : ShowSevereError(
251 : state,
252 0 : format("{}, \"{}\" Performance input method is not specified. ", state.dataIPShortCut->cCurrentModuleObject, thisEFC.Name));
253 0 : ErrorsFound = true;
254 : } else {
255 2 : thisEFC.PerformanceInputMethod = AlphArray(4);
256 : }
257 :
258 : // outdoor air inlet node
259 2 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
260 2 : thisEFC.OutdoorAirInletNodeNum = 0;
261 : } else {
262 0 : thisEFC.OutdoorAirInletNodeNum =
263 0 : NodeInputManager::GetOnlySingleNode(state,
264 0 : AlphArray(5),
265 : ErrorsFound,
266 : DataLoopNode::ConnectionObjectType::EvaporativeFluidCoolerSingleSpeed,
267 0 : thisEFC.Name,
268 : DataLoopNode::NodeFluidType::Air,
269 : DataLoopNode::ConnectionType::OutsideAirReference,
270 : NodeInputManager::CompFluidStream::Primary,
271 : DataLoopNode::ObjectIsNotParent);
272 0 : if (!OutAirNodeManager::CheckOutAirNodeNumber(state, thisEFC.OutdoorAirInletNodeNum)) {
273 0 : ShowSevereError(state,
274 0 : format("{}, \"{}\" Outdoor Air Inlet DataLoopNode::Node Name not valid Outdoor Air DataLoopNode::Node= {}",
275 0 : state.dataIPShortCut->cCurrentModuleObject,
276 0 : thisEFC.Name,
277 : AlphArray(5)));
278 0 : ShowContinueError(state, "...does not appear in an OutdoorAir:NodeList or as an OutdoorAir:DataLoopNode::Node.");
279 0 : ErrorsFound = true;
280 : }
281 : }
282 :
283 : // fluid bypass for single speed evaporative fluid cooler
284 2 : if (state.dataIPShortCut->lAlphaFieldBlanks(6) || AlphArray(6).empty()) {
285 2 : thisEFC.capacityControl = CapacityControl::FanCycling; // FanCycling
286 : } else {
287 0 : thisEFC.capacityControl = static_cast<CapacityControl>(getEnumValue(controlNamesUC, Util::makeUPPER(AlphArray(6))));
288 0 : if (thisEFC.capacityControl == CapacityControl::Invalid) {
289 0 : thisEFC.capacityControl = CapacityControl::FanCycling;
290 0 : ShowWarningError(state,
291 0 : format("{}, \"{}\" The Capacity Control is not specified correctly. The default Fan Cycling is used.",
292 0 : state.dataIPShortCut->cCurrentModuleObject,
293 0 : thisEFC.Name));
294 : }
295 : }
296 :
297 2 : thisEFC.SizFac = NumArray(12); // N11 \field Sizing Factor
298 2 : if (thisEFC.SizFac <= 0.0) {
299 0 : thisEFC.SizFac = 1.0;
300 : }
301 :
302 2 : if (AlphArray(7).empty()) {
303 0 : thisEFC.EvapLossMode = EvapLoss::ByMoistTheory;
304 : } else {
305 2 : thisEFC.EvapLossMode = static_cast<EvapLoss>(getEnumValue(evapLossNamesUC, Util::makeUPPER(AlphArray(7))));
306 2 : if (thisEFC.EvapLossMode == EvapLoss::Invalid) {
307 0 : ShowSevereError(state, format("Invalid, {} = {}", state.dataIPShortCut->cAlphaFieldNames(7), AlphArray(7)));
308 0 : ShowContinueError(state, format("Entered in {} = {}", state.dataIPShortCut->cCurrentModuleObject, AlphArray(1)));
309 0 : ErrorsFound = true;
310 : }
311 : }
312 :
313 2 : thisEFC.UserEvapLossFactor = NumArray(13); // N13 , \field Evaporation Loss Factor
314 2 : if ((NumNums < 13) && (thisEFC.UserEvapLossFactor == 0.0)) {
315 : // assume Evaporation loss factor not entered and should be calculated
316 2 : if ((state.dataEnvrn->OutRelHumValue >= 0.1) && (state.dataEnvrn->OutRelHumValue <= 0.7)) {
317 : // Use correlation by B.A. Qureshi and S.M. Zubair if within these limits
318 0 : thisEFC.UserEvapLossFactor =
319 0 : (113.0 - 8.417 * state.dataEnvrn->OutRelHumValue + 1.6147 * state.dataEnvrn->OutDryBulbTemp) * 1.0e-5;
320 : } else { // Inlet conditions are out of the limit of correlation; An approximate default value of loss factor is used
321 2 : thisEFC.UserEvapLossFactor = 0.2;
322 : }
323 : }
324 :
325 2 : thisEFC.DriftLossFraction = NumArray(14) / 100.0; // N14, \field Drift Loss Percent
326 :
327 2 : if ((NumNums < 13) && (thisEFC.DriftLossFraction == 0.0)) {
328 : // assume Drift loss not entered and should be defaulted
329 0 : thisEFC.DriftLossFraction = 0.008 / 100.0;
330 : }
331 2 : thisEFC.ConcentrationRatio = NumArray(15); // N15, \field Blowdown Concentration Ratio
332 :
333 2 : if (AlphArray(8).empty()) {
334 0 : thisEFC.BlowdownMode = Blowdown::ByConcentration;
335 0 : if ((NumNums < 15) && (thisEFC.ConcentrationRatio == 0.0)) {
336 : // assume Concentration ratio was omitted and should be defaulted
337 0 : thisEFC.ConcentrationRatio = 3.0;
338 : }
339 : } else {
340 2 : thisEFC.BlowdownMode = static_cast<Blowdown>(getEnumValue(blowDownNamesUC, Util::makeUPPER(AlphArray(8))));
341 2 : if (thisEFC.BlowdownMode == Blowdown::Invalid) {
342 0 : ShowSevereError(state, format("Invalid, {} = {}", state.dataIPShortCut->cAlphaFieldNames(8), AlphArray(8)));
343 0 : ShowContinueError(state, format("Entered in {} ={}", state.dataIPShortCut->cCurrentModuleObject, AlphArray(1)));
344 0 : ErrorsFound = true;
345 : }
346 : }
347 :
348 2 : if (thisEFC.BlowdownMode == Blowdown::BySchedule) {
349 0 : if ((thisEFC.blowdownSched = Sched::GetSchedule(state, AlphArray(9))) == nullptr) {
350 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(9), AlphArray(9));
351 0 : ErrorsFound = true;
352 : }
353 : }
354 :
355 2 : if (AlphArray(10).empty()) {
356 2 : thisEFC.SuppliedByWaterSystem = false;
357 : } else { // water from storage tank
358 0 : WaterManager::SetupTankDemandComponent(state,
359 0 : AlphArray(1),
360 0 : state.dataIPShortCut->cCurrentModuleObject,
361 0 : AlphArray(10),
362 : ErrorsFound,
363 0 : thisEFC.WaterTankID,
364 0 : thisEFC.WaterTankDemandARRID);
365 0 : thisEFC.SuppliedByWaterSystem = true;
366 : }
367 :
368 : // Check various inputs to ensure that all the required variables are specified.
369 :
370 2 : if (thisEFC.DesignSprayWaterFlowRate <= 0.0) {
371 0 : ShowSevereError(state,
372 0 : format("{} \"{}\". Evaporative fluid cooler input requires a design spray water flow rate greater than zero for all "
373 : "performance input methods.",
374 0 : state.dataIPShortCut->cCurrentModuleObject,
375 0 : thisEFC.Name));
376 0 : ErrorsFound = true;
377 : }
378 2 : if (thisEFC.HighSpeedAirFlowRate <= 0.0 && thisEFC.HighSpeedAirFlowRate != DataSizing::AutoSize) {
379 0 : ShowSevereError(state,
380 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
381 0 : state.dataIPShortCut->cCurrentModuleObject,
382 : AlphArray(1),
383 0 : state.dataIPShortCut->cNumericFieldNames(1),
384 0 : state.dataIPShortCut->cAlphaFieldNames(4),
385 : AlphArray(4)));
386 0 : ErrorsFound = true;
387 : }
388 2 : if (thisEFC.HighSpeedFanPower <= 0.0 && thisEFC.HighSpeedFanPower != DataSizing::AutoSize) {
389 0 : ShowSevereError(state,
390 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
391 0 : state.dataIPShortCut->cCurrentModuleObject,
392 : AlphArray(1),
393 0 : state.dataIPShortCut->cNumericFieldNames(2),
394 0 : state.dataIPShortCut->cAlphaFieldNames(4),
395 : AlphArray(4)));
396 0 : ErrorsFound = true;
397 : }
398 :
399 2 : if (Util::SameString(AlphArray(4), "UFACTORTIMESAREAANDDESIGNWATERFLOWRATE")) {
400 1 : thisEFC.PerformanceInputMethod_Num = PIM::UFactor;
401 1 : if (thisEFC.HighSpeedEvapFluidCoolerUA <= 0.0 && thisEFC.HighSpeedEvapFluidCoolerUA != DataSizing::AutoSize) {
402 0 : ShowSevereError(state,
403 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
404 0 : state.dataIPShortCut->cCurrentModuleObject,
405 : AlphArray(1),
406 0 : state.dataIPShortCut->cNumericFieldNames(6),
407 0 : state.dataIPShortCut->cAlphaFieldNames(4),
408 : AlphArray(4)));
409 0 : ErrorsFound = true;
410 : }
411 1 : if (thisEFC.DesignWaterFlowRate <= 0.0 && thisEFC.DesignWaterFlowRate != DataSizing::AutoSize) {
412 0 : ShowSevereError(state,
413 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
414 0 : state.dataIPShortCut->cCurrentModuleObject,
415 : AlphArray(1),
416 0 : state.dataIPShortCut->cNumericFieldNames(7),
417 0 : state.dataIPShortCut->cAlphaFieldNames(4),
418 : AlphArray(4)));
419 0 : ErrorsFound = true;
420 : }
421 1 : } else if (Util::SameString(AlphArray(4), "STANDARDDESIGNCAPACITY")) {
422 0 : thisEFC.PerformanceInputMethod_Num = PIM::StandardDesignCapacity;
423 0 : if (thisEFC.HighSpeedStandardDesignCapacity <= 0.0) {
424 0 : ShowSevereError(state,
425 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
426 0 : state.dataIPShortCut->cCurrentModuleObject,
427 : AlphArray(1),
428 0 : state.dataIPShortCut->cNumericFieldNames(5),
429 0 : state.dataIPShortCut->cAlphaFieldNames(4),
430 : AlphArray(4)));
431 0 : ErrorsFound = true;
432 : }
433 1 : } else if (Util::SameString(AlphArray(4), "USERSPECIFIEDDESIGNCAPACITY")) {
434 1 : thisEFC.PerformanceInputMethod_Num = PIM::UserSpecifiedDesignCapacity;
435 1 : if (thisEFC.DesignWaterFlowRate <= 0.0 && thisEFC.DesignWaterFlowRate != DataSizing::AutoSize) {
436 0 : ShowSevereError(state,
437 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
438 0 : state.dataIPShortCut->cCurrentModuleObject,
439 : AlphArray(1),
440 0 : state.dataIPShortCut->cNumericFieldNames(7),
441 0 : state.dataIPShortCut->cAlphaFieldNames(4),
442 : AlphArray(4)));
443 0 : ErrorsFound = true;
444 : }
445 1 : if (thisEFC.HighSpeedUserSpecifiedDesignCapacity <= 0.0) {
446 0 : ShowSevereError(state,
447 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
448 0 : state.dataIPShortCut->cCurrentModuleObject,
449 : AlphArray(1),
450 0 : state.dataIPShortCut->cNumericFieldNames(8),
451 0 : state.dataIPShortCut->cAlphaFieldNames(4),
452 : AlphArray(4)));
453 0 : ErrorsFound = true;
454 : }
455 1 : if (thisEFC.DesignEnteringWaterTemp <= 0.0) {
456 0 : ShowSevereError(state,
457 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be >0 for {} = \"{}\".",
458 0 : state.dataIPShortCut->cCurrentModuleObject,
459 : AlphArray(1),
460 0 : state.dataIPShortCut->cNumericFieldNames(9),
461 0 : state.dataIPShortCut->cAlphaFieldNames(4),
462 : AlphArray(4)));
463 0 : ErrorsFound = true;
464 : }
465 1 : if (thisEFC.DesignEnteringAirTemp <= 0.0) {
466 0 : ShowSevereError(state,
467 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be >0 for {} = \"{}\".",
468 0 : state.dataIPShortCut->cCurrentModuleObject,
469 : AlphArray(1),
470 0 : state.dataIPShortCut->cNumericFieldNames(10),
471 0 : state.dataIPShortCut->cAlphaFieldNames(4),
472 : AlphArray(4)));
473 0 : ErrorsFound = true;
474 : }
475 1 : if (thisEFC.DesignEnteringAirWetBulbTemp <= 0.0) {
476 0 : ShowSevereError(state,
477 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be >0 for {} = \"{}\".",
478 0 : state.dataIPShortCut->cCurrentModuleObject,
479 : AlphArray(1),
480 0 : state.dataIPShortCut->cNumericFieldNames(11),
481 0 : state.dataIPShortCut->cAlphaFieldNames(4),
482 : AlphArray(4)));
483 0 : ErrorsFound = true;
484 : }
485 1 : if (thisEFC.DesignEnteringWaterTemp <= thisEFC.DesignEnteringAirWetBulbTemp) {
486 0 : ShowSevereError(state,
487 0 : format("{} = \"{}\", {} must be greater than {}.",
488 0 : state.dataIPShortCut->cCurrentModuleObject,
489 : AlphArray(1),
490 0 : state.dataIPShortCut->cNumericFieldNames(9),
491 0 : state.dataIPShortCut->cNumericFieldNames(11)));
492 0 : ErrorsFound = true;
493 : }
494 1 : if (thisEFC.DesignEnteringAirTemp <= thisEFC.DesignEnteringAirWetBulbTemp) {
495 0 : ShowSevereError(state,
496 0 : format("{} = \"{}\", {} must be greater than {}.",
497 0 : state.dataIPShortCut->cCurrentModuleObject,
498 : AlphArray(1),
499 0 : state.dataIPShortCut->cNumericFieldNames(10),
500 0 : state.dataIPShortCut->cNumericFieldNames(11)));
501 0 : ErrorsFound = true;
502 : }
503 : } else { // Evaporative fluid cooler performance input method is not specified as a valid "choice"
504 0 : ShowSevereError(state,
505 0 : format("{} = \"{}\". Evaporative fluid cooler Performance Input Method must be "
506 : "\"UFactorTimesAreaAndDesignWaterFlowRate\" or \"StandardDesignCapacity\" or \"UserSpecifiedDesignCapacity\".",
507 0 : state.dataIPShortCut->cCurrentModuleObject,
508 0 : thisEFC.Name));
509 0 : ShowContinueError(state, format("Evaporative fluid cooler Performance Input Method currently specified as: {}", AlphArray(4)));
510 0 : ErrorsFound = true;
511 : }
512 :
513 : } // End Single-Speed Evaporative Fluid Cooler Loop
514 :
515 3 : state.dataIPShortCut->cCurrentModuleObject = cEvapFluidCooler_TwoSpeed;
516 4 : for (int TwoSpeedEvapFluidCoolerNumber = 1; TwoSpeedEvapFluidCoolerNumber <= NumTwoSpeedEvapFluidCoolers; ++TwoSpeedEvapFluidCoolerNumber) {
517 1 : int EvapFluidCoolerNum = NumSingleSpeedEvapFluidCoolers + TwoSpeedEvapFluidCoolerNumber;
518 3 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
519 1 : state.dataIPShortCut->cCurrentModuleObject,
520 : TwoSpeedEvapFluidCoolerNumber,
521 : AlphArray,
522 : NumAlphas,
523 : NumArray,
524 : NumNums,
525 : IOStat,
526 : _,
527 1 : state.dataIPShortCut->lAlphaFieldBlanks,
528 1 : state.dataIPShortCut->cAlphaFieldNames,
529 1 : state.dataIPShortCut->cNumericFieldNames);
530 :
531 1 : ErrorObjectHeader eoh{routineName, state.dataIPShortCut->cCurrentModuleObject, AlphArray(1)};
532 :
533 1 : GlobalNames::VerifyUniqueInterObjectName(state,
534 1 : state.dataEvapFluidCoolers->UniqueSimpleEvapFluidCoolerNames,
535 1 : AlphArray(1),
536 1 : state.dataIPShortCut->cCurrentModuleObject,
537 1 : state.dataIPShortCut->cAlphaFieldNames(1),
538 : ErrorsFound);
539 :
540 1 : auto &thisEFC = state.dataEvapFluidCoolers->SimpleEvapFluidCooler(EvapFluidCoolerNum);
541 :
542 1 : thisEFC.Name = AlphArray(1);
543 1 : thisEFC.EvapFluidCoolerType = state.dataIPShortCut->cCurrentModuleObject;
544 1 : thisEFC.Type = DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd;
545 1 : thisEFC.EvapFluidCoolerMassFlowRateMultiplier = 2.5;
546 1 : thisEFC.WaterInletNodeNum = NodeInputManager::GetOnlySingleNode(state,
547 1 : AlphArray(2),
548 : ErrorsFound,
549 : DataLoopNode::ConnectionObjectType::EvaporativeFluidCoolerTwoSpeed,
550 1 : AlphArray(1),
551 : DataLoopNode::NodeFluidType::Water,
552 : DataLoopNode::ConnectionType::Inlet,
553 : NodeInputManager::CompFluidStream::Primary,
554 : DataLoopNode::ObjectIsNotParent);
555 2 : thisEFC.WaterOutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
556 1 : AlphArray(3),
557 : ErrorsFound,
558 : DataLoopNode::ConnectionObjectType::EvaporativeFluidCoolerTwoSpeed,
559 1 : AlphArray(1),
560 : DataLoopNode::NodeFluidType::Water,
561 : DataLoopNode::ConnectionType::Outlet,
562 : NodeInputManager::CompFluidStream::Primary,
563 : DataLoopNode::ObjectIsNotParent);
564 2 : BranchNodeConnections::TestCompSet(
565 1 : state, state.dataIPShortCut->cCurrentModuleObject, AlphArray(1), AlphArray(2), AlphArray(3), "Chilled Water Nodes");
566 :
567 1 : thisEFC.HighSpeedAirFlowRate = NumArray(1);
568 1 : if (thisEFC.HighSpeedAirFlowRate == DataSizing::AutoSize) {
569 1 : thisEFC.HighSpeedAirFlowRateWasAutoSized = true;
570 : }
571 1 : thisEFC.HighSpeedFanPower = NumArray(2);
572 1 : if (thisEFC.HighSpeedFanPower == DataSizing::AutoSize) {
573 1 : thisEFC.HighSpeedFanPowerWasAutoSized = true;
574 : }
575 1 : thisEFC.LowSpeedAirFlowRate = NumArray(3);
576 1 : if (thisEFC.LowSpeedAirFlowRate == DataSizing::AutoSize) {
577 1 : thisEFC.LowSpeedAirFlowRateWasAutoSized = true;
578 : }
579 1 : thisEFC.LowSpeedAirFlowRateSizingFactor = NumArray(4);
580 1 : thisEFC.LowSpeedFanPower = NumArray(5);
581 1 : if (thisEFC.LowSpeedFanPower == DataSizing::AutoSize) {
582 1 : thisEFC.LowSpeedFanPowerWasAutoSized = true;
583 : }
584 1 : thisEFC.LowSpeedFanPowerSizingFactor = NumArray(6);
585 1 : thisEFC.DesignSprayWaterFlowRate = NumArray(7);
586 1 : thisEFC.HeatRejectCapNomCapSizingRatio = NumArray(8);
587 1 : thisEFC.HighSpeedStandardDesignCapacity = NumArray(9);
588 1 : thisEFC.LowSpeedStandardDesignCapacity = NumArray(10);
589 1 : thisEFC.HighSpeedEvapFluidCoolerUA = NumArray(12);
590 1 : if (thisEFC.HighSpeedEvapFluidCoolerUA == DataSizing::AutoSize) {
591 1 : thisEFC.HighSpeedEvapFluidCoolerUAWasAutoSized = true;
592 : }
593 1 : thisEFC.LowSpeedEvapFluidCoolerUA = NumArray(13);
594 1 : if (thisEFC.LowSpeedEvapFluidCoolerUA == DataSizing::AutoSize) {
595 1 : thisEFC.LowSpeedEvapFluidCoolerUAWasAutoSized = true;
596 : }
597 1 : thisEFC.LowSpeedEvapFluidCoolerUASizingFactor = NumArray(14);
598 1 : thisEFC.DesignWaterFlowRate = NumArray(15);
599 1 : if (thisEFC.DesignWaterFlowRate == DataSizing::AutoSize) {
600 1 : thisEFC.DesignWaterFlowRateWasAutoSized = true;
601 : }
602 1 : thisEFC.HighSpeedUserSpecifiedDesignCapacity = NumArray(16);
603 1 : thisEFC.LowSpeedUserSpecifiedDesignCapacity = NumArray(17);
604 1 : thisEFC.DesignEnteringWaterTemp = NumArray(19);
605 1 : thisEFC.DesignEnteringAirTemp = NumArray(20);
606 1 : thisEFC.DesignEnteringAirWetBulbTemp = NumArray(21);
607 :
608 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
609 0 : ShowSevereError(
610 : state,
611 0 : format("{}, \"{}\" Performance input method is not specified. ", state.dataIPShortCut->cCurrentModuleObject, thisEFC.Name));
612 0 : ErrorsFound = true;
613 : } else {
614 1 : thisEFC.PerformanceInputMethod = AlphArray(4);
615 : }
616 :
617 : // outdoor air inlet node
618 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(5)) {
619 1 : thisEFC.OutdoorAirInletNodeNum = 0;
620 : } else {
621 0 : thisEFC.OutdoorAirInletNodeNum =
622 0 : NodeInputManager::GetOnlySingleNode(state,
623 0 : AlphArray(5),
624 : ErrorsFound,
625 : DataLoopNode::ConnectionObjectType::EvaporativeFluidCoolerTwoSpeed,
626 0 : thisEFC.Name,
627 : DataLoopNode::NodeFluidType::Air,
628 : DataLoopNode::ConnectionType::OutsideAirReference,
629 : NodeInputManager::CompFluidStream::Primary,
630 : DataLoopNode::ObjectIsNotParent);
631 0 : if (!OutAirNodeManager::CheckOutAirNodeNumber(state, thisEFC.OutdoorAirInletNodeNum)) {
632 0 : ShowSevereError(state,
633 0 : format("{}, \"{}\" Outdoor Air Inlet DataLoopNode::Node Name not valid Outdoor Air DataLoopNode::Node= {}",
634 0 : state.dataIPShortCut->cCurrentModuleObject,
635 0 : thisEFC.Name,
636 : AlphArray(5)));
637 0 : ShowContinueError(state, "...does not appear in an OutdoorAir:NodeList or as an OutdoorAir:DataLoopNode::Node.");
638 0 : ErrorsFound = true;
639 : }
640 : }
641 :
642 1 : thisEFC.SizFac = NumArray(22); // N16 \field Sizing Factor
643 1 : if (thisEFC.SizFac <= 0.0) {
644 0 : thisEFC.SizFac = 1.0;
645 : }
646 :
647 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
648 0 : thisEFC.EvapLossMode = EvapLoss::ByMoistTheory;
649 : } else {
650 1 : thisEFC.EvapLossMode = static_cast<EvapLoss>(getEnumValue(evapLossNamesUC, Util::makeUPPER(AlphArray(6))));
651 1 : if (thisEFC.EvapLossMode == EvapLoss::Invalid) {
652 0 : ShowSevereError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(6), AlphArray(6)));
653 0 : ShowContinueError(state, format("Entered in {} = {}", state.dataIPShortCut->cCurrentModuleObject, AlphArray(1)));
654 0 : ErrorsFound = true;
655 : }
656 : }
657 :
658 1 : thisEFC.UserEvapLossFactor = NumArray(23); // N23 , \field Evaporation Loss Factor
659 1 : if ((NumNums < 23) && (thisEFC.UserEvapLossFactor == 0.0)) {
660 : // assume Evaporation loss factor not entered and should be calculated
661 0 : if ((state.dataEnvrn->OutRelHumValue >= 0.1) && (state.dataEnvrn->OutRelHumValue <= 0.7)) {
662 : // Use correlation by B.A. Qureshi and S.M. Zubair if within these limits
663 0 : thisEFC.UserEvapLossFactor =
664 0 : (113.0 - 8.417 * state.dataEnvrn->OutRelHumValue + 1.6147 * state.dataEnvrn->OutDryBulbTemp) * 1.0e-5;
665 : } else { // Inlet conditions are out of the limit of correlation; An approximate default value of loss factor is used
666 0 : thisEFC.UserEvapLossFactor = 0.2;
667 : }
668 : }
669 1 : thisEFC.DriftLossFraction = NumArray(24) / 100.0; // N24, \field Drift Loss Percent
670 1 : if ((NumNums < 24) && (thisEFC.DriftLossFraction == 0.0)) {
671 : // assume Drift loss not entered and should be defaulted
672 0 : thisEFC.DriftLossFraction = 0.008 / 100.0;
673 : }
674 :
675 1 : thisEFC.ConcentrationRatio = NumArray(25); // N25, \field Blowdown Concentration Ratio
676 :
677 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(7)) {
678 0 : thisEFC.BlowdownMode = Blowdown::ByConcentration;
679 0 : if ((NumNums < 25) && (thisEFC.ConcentrationRatio == 0.0)) {
680 : // assume Concentration ratio was omitted and should be defaulted
681 0 : thisEFC.ConcentrationRatio = 3.0;
682 : }
683 : } else {
684 1 : thisEFC.BlowdownMode = static_cast<Blowdown>(getEnumValue(blowDownNamesUC, Util::makeUPPER(AlphArray(7))));
685 1 : if (thisEFC.BlowdownMode == Blowdown::Invalid) {
686 0 : ShowSevereError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(7), AlphArray(7)));
687 0 : ShowContinueError(state, format("Entered in {} = {}", state.dataIPShortCut->cCurrentModuleObject, AlphArray(1)));
688 0 : ErrorsFound = true;
689 : }
690 : }
691 :
692 1 : if (thisEFC.BlowdownMode == Blowdown::BySchedule) {
693 0 : if ((thisEFC.blowdownSched = Sched::GetSchedule(state, AlphArray(8))) == nullptr) {
694 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(8), AlphArray(8));
695 0 : ErrorsFound = true;
696 : }
697 : }
698 :
699 1 : if (state.dataIPShortCut->lAlphaFieldBlanks(9)) {
700 1 : thisEFC.SuppliedByWaterSystem = false;
701 : } else { // water from storage tank
702 0 : WaterManager::SetupTankDemandComponent(state,
703 0 : AlphArray(1),
704 0 : state.dataIPShortCut->cCurrentModuleObject,
705 0 : AlphArray(9),
706 : ErrorsFound,
707 0 : thisEFC.WaterTankID,
708 0 : thisEFC.WaterTankDemandARRID);
709 0 : thisEFC.SuppliedByWaterSystem = true;
710 : }
711 :
712 : // Check various inputs to ensure that all the required variables are specified.
713 :
714 1 : if (thisEFC.DesignSprayWaterFlowRate <= 0.0) {
715 0 : ShowSevereError(state,
716 0 : format("{} \"{}\". Evaporative fluid cooler input requires a design spray water flow rate greater than zero for all "
717 : "performance input methods.",
718 0 : state.dataIPShortCut->cCurrentModuleObject,
719 0 : thisEFC.Name));
720 0 : ErrorsFound = true;
721 : }
722 1 : if (thisEFC.HighSpeedAirFlowRate <= 0.0 && thisEFC.HighSpeedAirFlowRate != DataSizing::AutoSize) {
723 0 : ShowSevereError(state,
724 0 : format("{}= \"{}\". Evaporative fluid cooler input requires design air flow rate at high fan speed to be greater "
725 : "than zero for all performance input methods.",
726 0 : state.dataIPShortCut->cCurrentModuleObject,
727 0 : thisEFC.Name));
728 0 : ErrorsFound = true;
729 : }
730 1 : if (thisEFC.LowSpeedAirFlowRate <= 0.0 && thisEFC.LowSpeedAirFlowRate != DataSizing::AutoSize) {
731 0 : ShowSevereError(state,
732 0 : format("{}= \"{}\". Evaporative fluid cooler input requires design air flow rate at low fan speed to be greater than "
733 : "zero for all performance input methods.",
734 0 : state.dataIPShortCut->cCurrentModuleObject,
735 0 : thisEFC.Name));
736 0 : ErrorsFound = true;
737 : }
738 : // High speed air flow rate must be greater than low speed air flow rate.
739 : // Can't tell yet if autosized, check later in InitEvapFluidCooler.
740 1 : if (thisEFC.HighSpeedAirFlowRate <= thisEFC.LowSpeedAirFlowRate && thisEFC.HighSpeedAirFlowRate != DataSizing::AutoSize) {
741 0 : ShowSevereError(
742 : state,
743 0 : format(
744 : "{} = \"{}\". Evaporative fluid cooler air flow rate at low fan speed must be less than the air flow rate at high fan speed.",
745 0 : state.dataIPShortCut->cCurrentModuleObject,
746 0 : thisEFC.Name));
747 0 : ErrorsFound = true;
748 : }
749 1 : if (thisEFC.HighSpeedFanPower <= 0.0 && thisEFC.HighSpeedFanPower != DataSizing::AutoSize) {
750 0 : ShowSevereError(state,
751 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
752 0 : state.dataIPShortCut->cCurrentModuleObject,
753 : AlphArray(1),
754 0 : state.dataIPShortCut->cNumericFieldNames(2),
755 0 : state.dataIPShortCut->cAlphaFieldNames(4),
756 : AlphArray(4)));
757 0 : ErrorsFound = true;
758 : }
759 1 : if (thisEFC.LowSpeedFanPower <= 0.0 && thisEFC.LowSpeedFanPower != DataSizing::AutoSize) {
760 0 : ShowSevereError(state,
761 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
762 0 : state.dataIPShortCut->cCurrentModuleObject,
763 : AlphArray(1),
764 0 : state.dataIPShortCut->cNumericFieldNames(5),
765 0 : state.dataIPShortCut->cAlphaFieldNames(4),
766 : AlphArray(4)));
767 0 : ErrorsFound = true;
768 : }
769 1 : if (thisEFC.HighSpeedFanPower <= thisEFC.LowSpeedFanPower && thisEFC.HighSpeedFanPower != DataSizing::AutoSize) {
770 0 : ShowSevereError(state,
771 0 : format("{} = \"{}\". Evaporative fluid cooler low speed fan power must be less than the high speed fan power .",
772 0 : state.dataIPShortCut->cCurrentModuleObject,
773 0 : thisEFC.Name));
774 0 : ErrorsFound = true;
775 : }
776 :
777 1 : if (Util::SameString(AlphArray(4), "UFACTORTIMESAREAANDDESIGNWATERFLOWRATE")) {
778 1 : thisEFC.PerformanceInputMethod_Num = PIM::UFactor;
779 1 : if (thisEFC.HighSpeedEvapFluidCoolerUA <= 0.0 && thisEFC.HighSpeedEvapFluidCoolerUA != DataSizing::AutoSize) {
780 0 : ShowSevereError(state,
781 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
782 0 : state.dataIPShortCut->cCurrentModuleObject,
783 : AlphArray(1),
784 0 : state.dataIPShortCut->cNumericFieldNames(12),
785 0 : state.dataIPShortCut->cAlphaFieldNames(4),
786 : AlphArray(4)));
787 0 : ErrorsFound = true;
788 : }
789 1 : if (thisEFC.LowSpeedEvapFluidCoolerUA <= 0.0 && thisEFC.LowSpeedEvapFluidCoolerUA != DataSizing::AutoSize) {
790 0 : ShowSevereError(state,
791 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
792 0 : state.dataIPShortCut->cCurrentModuleObject,
793 : AlphArray(1),
794 0 : state.dataIPShortCut->cNumericFieldNames(13),
795 0 : state.dataIPShortCut->cAlphaFieldNames(4),
796 : AlphArray(4)));
797 0 : ErrorsFound = true;
798 : }
799 1 : if (thisEFC.HighSpeedEvapFluidCoolerUA <= thisEFC.LowSpeedEvapFluidCoolerUA &&
800 1 : thisEFC.HighSpeedEvapFluidCoolerUA != DataSizing::AutoSize) {
801 0 : ShowSevereError(state,
802 0 : format("{} = \"{}\". Evaporative fluid cooler U-factor Times Area Value at Low Fan Speed must be less than the "
803 : "U-factor Times Area Value at High Fan Speed.",
804 0 : state.dataIPShortCut->cCurrentModuleObject,
805 0 : thisEFC.Name));
806 0 : ErrorsFound = true;
807 : }
808 1 : if (thisEFC.DesignWaterFlowRate <= 0.0 && thisEFC.DesignWaterFlowRate != DataSizing::AutoSize) {
809 0 : ShowSevereError(state,
810 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
811 0 : state.dataIPShortCut->cCurrentModuleObject,
812 : AlphArray(1),
813 0 : state.dataIPShortCut->cNumericFieldNames(15),
814 0 : state.dataIPShortCut->cAlphaFieldNames(4),
815 : AlphArray(4)));
816 0 : ErrorsFound = true;
817 : }
818 0 : } else if (Util::SameString(AlphArray(4), "STANDARDDESIGNCAPACITY")) {
819 0 : thisEFC.PerformanceInputMethod_Num = PIM::StandardDesignCapacity;
820 0 : if (thisEFC.HighSpeedStandardDesignCapacity <= 0.0) {
821 0 : ShowSevereError(state,
822 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
823 0 : state.dataIPShortCut->cCurrentModuleObject,
824 : AlphArray(1),
825 0 : state.dataIPShortCut->cNumericFieldNames(9),
826 0 : state.dataIPShortCut->cAlphaFieldNames(4),
827 : AlphArray(4)));
828 0 : ErrorsFound = true;
829 : }
830 0 : if (thisEFC.LowSpeedStandardDesignCapacity <= 0.0) {
831 0 : ShowSevereError(state,
832 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
833 0 : state.dataIPShortCut->cCurrentModuleObject,
834 : AlphArray(1),
835 0 : state.dataIPShortCut->cNumericFieldNames(10),
836 0 : state.dataIPShortCut->cAlphaFieldNames(4),
837 : AlphArray(4)));
838 0 : ErrorsFound = true;
839 : }
840 0 : if (thisEFC.LowSpeedStandardDesignCapacity >= thisEFC.HighSpeedStandardDesignCapacity) {
841 0 : ShowSevereError(
842 : state,
843 0 : format("{} = \"{}\". Low-Speed Standard Design Capacity must be less than the High-Speed Standard Design Capacity.",
844 0 : state.dataIPShortCut->cCurrentModuleObject,
845 0 : thisEFC.Name));
846 0 : ErrorsFound = true;
847 : }
848 0 : } else if (Util::SameString(AlphArray(4), "USERSPECIFIEDDESIGNCAPACITY")) {
849 0 : thisEFC.PerformanceInputMethod_Num = PIM::UserSpecifiedDesignCapacity;
850 0 : if (thisEFC.DesignWaterFlowRate <= 0.0 && thisEFC.DesignWaterFlowRate != DataSizing::AutoSize) {
851 0 : ShowSevereError(state,
852 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
853 0 : state.dataIPShortCut->cCurrentModuleObject,
854 : AlphArray(1),
855 0 : state.dataIPShortCut->cNumericFieldNames(15),
856 0 : state.dataIPShortCut->cAlphaFieldNames(4),
857 : AlphArray(4)));
858 0 : ErrorsFound = true;
859 : }
860 0 : if (thisEFC.HighSpeedUserSpecifiedDesignCapacity <= 0.0) {
861 0 : ShowSevereError(state,
862 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
863 0 : state.dataIPShortCut->cCurrentModuleObject,
864 : AlphArray(1),
865 0 : state.dataIPShortCut->cNumericFieldNames(16),
866 0 : state.dataIPShortCut->cAlphaFieldNames(4),
867 : AlphArray(4)));
868 0 : ErrorsFound = true;
869 : }
870 0 : if (thisEFC.LowSpeedUserSpecifiedDesignCapacity <= 0.0) {
871 0 : ShowSevereError(state,
872 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be > 0 for {} = \"{}\".",
873 0 : state.dataIPShortCut->cCurrentModuleObject,
874 : AlphArray(1),
875 0 : state.dataIPShortCut->cNumericFieldNames(17),
876 0 : state.dataIPShortCut->cAlphaFieldNames(4),
877 : AlphArray(4)));
878 0 : ErrorsFound = true;
879 : }
880 0 : if (thisEFC.HighSpeedEvapFluidCoolerUA != 0.0) {
881 0 : if (thisEFC.HighSpeedEvapFluidCoolerUA > 0.0) {
882 0 : ShowSevereError(state,
883 0 : format("{} = \"{}\". UserSpecifiedDesignCapacity performance input method and evaporative fluid cooler UA at "
884 : "high fan speed have been specified.",
885 0 : state.dataIPShortCut->cCurrentModuleObject,
886 0 : thisEFC.Name));
887 : } else {
888 0 : ShowSevereError(state,
889 0 : format("{} = \"{}\". UserSpecifiedDesignCapacity performance input method has been specified and evaporative "
890 : "fluid cooler UA at high fan speed is being autosized.",
891 0 : state.dataIPShortCut->cCurrentModuleObject,
892 0 : thisEFC.Name));
893 : }
894 0 : ShowContinueError(state,
895 : "Evaporative fluid cooler UA at high fan speed must be left blank when UserSpecifiedDesignCapacity performance "
896 : "input method is used.");
897 0 : ErrorsFound = true;
898 : }
899 0 : if (thisEFC.LowSpeedEvapFluidCoolerUA != 0.0) {
900 0 : if (thisEFC.LowSpeedEvapFluidCoolerUA > 0.0) {
901 0 : ShowSevereError(state,
902 0 : format("{} = \"{}\". UserSpecifiedDesignCapacity performance input method and evaporative fluid cooler UA at "
903 : "low fan speed have been specified.",
904 0 : state.dataIPShortCut->cCurrentModuleObject,
905 0 : thisEFC.Name));
906 : } else {
907 0 : ShowSevereError(state,
908 0 : format("{} = \"{}\". UserSpecifiedDesignCapacity performance input method has been specified and evaporative "
909 : "fluid cooler UA at low fan speed is being autosized.",
910 0 : state.dataIPShortCut->cCurrentModuleObject,
911 0 : thisEFC.Name));
912 : }
913 0 : ShowContinueError(state,
914 : "Evaporative fluid cooler UA at low fan speed must be left blank when UserSpecifiedDesignCapacity performance "
915 : "input method is used.");
916 0 : ErrorsFound = true;
917 : }
918 0 : if (thisEFC.LowSpeedUserSpecifiedDesignCapacity >= thisEFC.HighSpeedUserSpecifiedDesignCapacity) {
919 0 : ShowSevereError(
920 : state,
921 0 : format(
922 : "{} = \"{}\". Low-Speed User Specified Design Capacity must be less than the High-Speed User Specified Design Capacity.",
923 0 : state.dataIPShortCut->cCurrentModuleObject,
924 0 : thisEFC.Name));
925 0 : ErrorsFound = true;
926 : }
927 0 : if (thisEFC.DesignEnteringWaterTemp <= 0.0) {
928 0 : ShowSevereError(state,
929 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be >0 for {} = \"{}\".",
930 0 : state.dataIPShortCut->cCurrentModuleObject,
931 : AlphArray(1),
932 0 : state.dataIPShortCut->cNumericFieldNames(19),
933 0 : state.dataIPShortCut->cAlphaFieldNames(4),
934 : AlphArray(4)));
935 0 : ErrorsFound = true;
936 : }
937 0 : if (thisEFC.DesignEnteringAirTemp <= 0.0) {
938 0 : ShowSevereError(state,
939 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, buy must be >0 for {} = \"{}\".",
940 0 : state.dataIPShortCut->cCurrentModuleObject,
941 : AlphArray(1),
942 0 : state.dataIPShortCut->cNumericFieldNames(20),
943 0 : state.dataIPShortCut->cAlphaFieldNames(4),
944 : AlphArray(4)));
945 0 : ErrorsFound = true;
946 : }
947 0 : if (thisEFC.DesignEnteringAirWetBulbTemp <= 0.0) {
948 0 : ShowSevereError(state,
949 0 : format("{} = \"{}\", invalid data for \"{}\", entered value <= 0.0, but must be >0 for {} = \"{}\".",
950 0 : state.dataIPShortCut->cCurrentModuleObject,
951 : AlphArray(1),
952 0 : state.dataIPShortCut->cNumericFieldNames(21),
953 0 : state.dataIPShortCut->cAlphaFieldNames(4),
954 : AlphArray(4)));
955 0 : ErrorsFound = true;
956 : }
957 0 : if (thisEFC.DesignEnteringWaterTemp <= thisEFC.DesignEnteringAirWetBulbTemp) {
958 0 : ShowSevereError(state,
959 0 : format("{} = \"{}\", {} must be greater than {}.",
960 0 : state.dataIPShortCut->cCurrentModuleObject,
961 : AlphArray(1),
962 0 : state.dataIPShortCut->cNumericFieldNames(19),
963 0 : state.dataIPShortCut->cNumericFieldNames(15)));
964 0 : ErrorsFound = true;
965 : }
966 0 : if (thisEFC.DesignEnteringAirTemp <= thisEFC.DesignEnteringAirWetBulbTemp) {
967 0 : ShowSevereError(state,
968 0 : format("{} = \"{}\", {} must be greater than {}.",
969 0 : state.dataIPShortCut->cCurrentModuleObject,
970 : AlphArray(1),
971 0 : state.dataIPShortCut->cNumericFieldNames(20),
972 0 : state.dataIPShortCut->cNumericFieldNames(15)));
973 0 : ErrorsFound = true;
974 : }
975 : } else { // Evaporative fluid cooler performance input method is not specified as a valid "choice"
976 0 : ShowSevereError(state,
977 0 : format("{} = \"{}\". Evaporative fluid cooler Performance Input Method must be "
978 : "\"UFactorTimesAreaAndDesignWaterFlowRate\" or \"StandardDesignCapacity\" or \"UserSpecifiedDesignCapacity\".",
979 0 : state.dataIPShortCut->cCurrentModuleObject,
980 0 : thisEFC.Name));
981 0 : ShowContinueError(state, format("Evaporative fluid cooler Performance Input Method currently specified as: {}", AlphArray(4)));
982 0 : ErrorsFound = true;
983 : }
984 :
985 : } // End Two-Speed Evaporative Fluid Cooler Loop
986 :
987 3 : if (ErrorsFound) {
988 0 : ShowFatalError(state, "Errors found in getting evaporative fluid cooler input.");
989 : }
990 3 : }
991 :
992 2 : void EvapFluidCoolerSpecs::setupOutputVars(EnergyPlusData &state)
993 : {
994 : // Set up output variables
995 : // CurrentModuleObject='EvaporativeFluidCooler:SingleSpeed'
996 2 : if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_SingleSpd) {
997 :
998 : // Added for fluid bypass
999 2 : SetupOutputVariable(state,
1000 : "Cooling Tower Bypass Fraction",
1001 : Constant::Units::None,
1002 1 : this->BypassFraction,
1003 : OutputProcessor::TimeStepType::System,
1004 : OutputProcessor::StoreType::Average,
1005 1 : this->Name);
1006 : }
1007 :
1008 : // setup common water reporting for all types of evaporative fluid coolers.
1009 : // CurrentModuleObject='EvaporativeFluidCooler:*'
1010 2 : if (this->SuppliedByWaterSystem) {
1011 0 : SetupOutputVariable(state,
1012 : "Cooling Tower Make Up Water Volume Flow Rate",
1013 : Constant::Units::m3_s,
1014 0 : this->MakeUpVdot,
1015 : OutputProcessor::TimeStepType::System,
1016 : OutputProcessor::StoreType::Average,
1017 0 : this->Name);
1018 :
1019 0 : SetupOutputVariable(state,
1020 : "Cooling Tower Make Up Water Volume",
1021 : Constant::Units::m3,
1022 0 : this->MakeUpVol,
1023 : OutputProcessor::TimeStepType::System,
1024 : OutputProcessor::StoreType::Sum,
1025 0 : this->Name);
1026 :
1027 0 : SetupOutputVariable(state,
1028 : "Cooling Tower Storage Tank Water Volume Flow Rate",
1029 : Constant::Units::m3_s,
1030 0 : this->TankSupplyVdot,
1031 : OutputProcessor::TimeStepType::System,
1032 : OutputProcessor::StoreType::Average,
1033 0 : this->Name);
1034 :
1035 0 : SetupOutputVariable(state,
1036 : "Cooling Tower Storage Tank Water Volume",
1037 : Constant::Units::m3,
1038 0 : this->TankSupplyVol,
1039 : OutputProcessor::TimeStepType::System,
1040 : OutputProcessor::StoreType::Sum,
1041 0 : this->Name,
1042 : Constant::eResource::Water,
1043 : OutputProcessor::Group::Plant,
1044 : OutputProcessor::EndUseCat::HeatRejection);
1045 :
1046 0 : SetupOutputVariable(state,
1047 : "Cooling Tower Starved Storage Tank Water Volume Flow Rate",
1048 : Constant::Units::m3_s,
1049 0 : this->StarvedMakeUpVdot,
1050 : OutputProcessor::TimeStepType::System,
1051 : OutputProcessor::StoreType::Average,
1052 0 : this->Name);
1053 :
1054 0 : SetupOutputVariable(state,
1055 : "Cooling Tower Starved Storage Tank Water Volume",
1056 : Constant::Units::m3,
1057 0 : this->StarvedMakeUpVol,
1058 : OutputProcessor::TimeStepType::System,
1059 : OutputProcessor::StoreType::Sum,
1060 0 : this->Name,
1061 : Constant::eResource::Water,
1062 : OutputProcessor::Group::Plant,
1063 : OutputProcessor::EndUseCat::HeatRejection);
1064 :
1065 0 : SetupOutputVariable(state,
1066 : "Cooling Tower Make Up Mains Water Volume",
1067 : Constant::Units::m3,
1068 0 : this->StarvedMakeUpVol,
1069 : OutputProcessor::TimeStepType::System,
1070 : OutputProcessor::StoreType::Sum,
1071 0 : this->Name,
1072 : Constant::eResource::MainsWater,
1073 : OutputProcessor::Group::Plant,
1074 : OutputProcessor::EndUseCat::HeatRejection);
1075 :
1076 : } else { // Evaporative fluid cooler water from mains and gets metered
1077 4 : SetupOutputVariable(state,
1078 : "Cooling Tower Make Up Water Volume Flow Rate",
1079 : Constant::Units::m3_s,
1080 2 : this->MakeUpVdot,
1081 : OutputProcessor::TimeStepType::System,
1082 : OutputProcessor::StoreType::Average,
1083 2 : this->Name);
1084 :
1085 4 : SetupOutputVariable(state,
1086 : "Cooling Tower Make Up Water Volume",
1087 : Constant::Units::m3,
1088 2 : this->MakeUpVol,
1089 : OutputProcessor::TimeStepType::System,
1090 : OutputProcessor::StoreType::Sum,
1091 2 : this->Name,
1092 : Constant::eResource::Water,
1093 : OutputProcessor::Group::Plant,
1094 : OutputProcessor::EndUseCat::HeatRejection);
1095 :
1096 4 : SetupOutputVariable(state,
1097 : "Cooling Tower Make Up Mains Water Volume",
1098 : Constant::Units::m3,
1099 2 : this->MakeUpVol,
1100 : OutputProcessor::TimeStepType::System,
1101 : OutputProcessor::StoreType::Sum,
1102 2 : this->Name,
1103 : Constant::eResource::MainsWater,
1104 : OutputProcessor::Group::Plant,
1105 : OutputProcessor::EndUseCat::HeatRejection);
1106 : }
1107 :
1108 4 : SetupOutputVariable(state,
1109 : "Cooling Tower Inlet Temperature",
1110 : Constant::Units::C,
1111 2 : this->fluidCoolerInletWaterTemp,
1112 : OutputProcessor::TimeStepType::System,
1113 : OutputProcessor::StoreType::Average,
1114 2 : this->Name);
1115 :
1116 4 : SetupOutputVariable(state,
1117 : "Cooling Tower Outlet Temperature",
1118 : Constant::Units::C,
1119 2 : this->fluidCoolerOutletWaterTemp,
1120 : OutputProcessor::TimeStepType::System,
1121 : OutputProcessor::StoreType::Average,
1122 2 : this->Name);
1123 :
1124 4 : SetupOutputVariable(state,
1125 : "Cooling Tower Mass Flow Rate",
1126 : Constant::Units::kg_s,
1127 2 : this->WaterMassFlowRate,
1128 : OutputProcessor::TimeStepType::System,
1129 : OutputProcessor::StoreType::Average,
1130 2 : this->Name);
1131 :
1132 4 : SetupOutputVariable(state,
1133 : "Cooling Tower Heat Transfer Rate",
1134 : Constant::Units::W,
1135 2 : this->Qactual,
1136 : OutputProcessor::TimeStepType::System,
1137 : OutputProcessor::StoreType::Average,
1138 2 : this->Name);
1139 :
1140 4 : SetupOutputVariable(state,
1141 : "Cooling Tower Fan Electricity Rate",
1142 : Constant::Units::W,
1143 2 : this->FanPower,
1144 : OutputProcessor::TimeStepType::System,
1145 : OutputProcessor::StoreType::Average,
1146 2 : this->Name);
1147 :
1148 4 : SetupOutputVariable(state,
1149 : "Cooling Tower Fan Electricity Energy",
1150 : Constant::Units::J,
1151 2 : this->FanEnergy,
1152 : OutputProcessor::TimeStepType::System,
1153 : OutputProcessor::StoreType::Sum,
1154 2 : this->Name,
1155 : Constant::eResource::Electricity,
1156 : OutputProcessor::Group::Plant,
1157 : OutputProcessor::EndUseCat::HeatRejection);
1158 :
1159 4 : SetupOutputVariable(state,
1160 : "Cooling Tower Water Evaporation Volume Flow Rate",
1161 : Constant::Units::m3_s,
1162 2 : this->EvaporationVdot,
1163 : OutputProcessor::TimeStepType::System,
1164 : OutputProcessor::StoreType::Average,
1165 2 : this->Name);
1166 :
1167 4 : SetupOutputVariable(state,
1168 : "Cooling Tower Water Evaporation Volume",
1169 : Constant::Units::m3,
1170 2 : this->EvaporationVol,
1171 : OutputProcessor::TimeStepType::System,
1172 : OutputProcessor::StoreType::Sum,
1173 2 : this->Name);
1174 :
1175 4 : SetupOutputVariable(state,
1176 : "Cooling Tower Water Drift Volume Flow Rate",
1177 : Constant::Units::m3_s,
1178 2 : this->DriftVdot,
1179 : OutputProcessor::TimeStepType::System,
1180 : OutputProcessor::StoreType::Average,
1181 2 : this->Name);
1182 :
1183 4 : SetupOutputVariable(state,
1184 : "Cooling Tower Water Drift Volume",
1185 : Constant::Units::m3,
1186 2 : this->DriftVol,
1187 : OutputProcessor::TimeStepType::System,
1188 : OutputProcessor::StoreType::Sum,
1189 2 : this->Name);
1190 :
1191 4 : SetupOutputVariable(state,
1192 : "Cooling Tower Water Blowdown Volume Flow Rate",
1193 : Constant::Units::m3_s,
1194 2 : this->BlowdownVdot,
1195 : OutputProcessor::TimeStepType::System,
1196 : OutputProcessor::StoreType::Average,
1197 2 : this->Name);
1198 :
1199 4 : SetupOutputVariable(state,
1200 : "Cooling Tower Water Blowdown Volume",
1201 : Constant::Units::m3,
1202 2 : this->BlowdownVol,
1203 : OutputProcessor::TimeStepType::System,
1204 : OutputProcessor::StoreType::Sum,
1205 2 : this->Name);
1206 2 : }
1207 :
1208 0 : void EvapFluidCoolerSpecs::getSizingFactor(Real64 &_sizFac)
1209 : {
1210 0 : _sizFac = this->SizFac;
1211 0 : }
1212 :
1213 3 : void EvapFluidCoolerSpecs::onInitLoopEquip(EnergyPlusData &state, [[maybe_unused]] const PlantLocation &calledFromLocation)
1214 : {
1215 3 : this->InitEvapFluidCooler(state);
1216 3 : this->SizeEvapFluidCooler(state);
1217 3 : }
1218 :
1219 3 : void EvapFluidCoolerSpecs::getDesignCapacities(EnergyPlusData &state, const PlantLocation &, Real64 &MaxLoad, Real64 &MinLoad, Real64 &OptLoad)
1220 : {
1221 3 : if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_SingleSpd ||
1222 2 : this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd) {
1223 3 : MinLoad = 0.0; // signifies non-load based model (i.e. forward heat exchanger model)
1224 3 : MaxLoad = this->HighSpeedStandardDesignCapacity * this->HeatRejectCapNomCapSizingRatio;
1225 3 : OptLoad = this->HighSpeedStandardDesignCapacity;
1226 : } else {
1227 0 : ShowFatalError(state, format("SimEvapFluidCoolers: Invalid evaporative fluid cooler Type Requested = {}", EvapFluidCoolerType));
1228 : }
1229 3 : }
1230 :
1231 2 : void EvapFluidCoolerSpecs::simulate(EnergyPlusData &state,
1232 : [[maybe_unused]] const PlantLocation &calledFromLocation,
1233 : [[maybe_unused]] bool FirstHVACIteration,
1234 : [[maybe_unused]] Real64 &CurLoad,
1235 : bool RunFlag)
1236 : {
1237 :
1238 : // SUBROUTINE INFORMATION:
1239 : // AUTHOR Chandan Sharma
1240 : // DATE WRITTEN May 2009
1241 : // MODIFIED na
1242 : // RE-ENGINEERED na
1243 :
1244 : // PURPOSE OF THIS SUBROUTINE:
1245 : // Main evaporative fluid cooler driver subroutine. Gets called from
1246 : // PlantCondLoopSupplySideManager.
1247 :
1248 : // REFERENCES:
1249 : // Based on SimTowers subroutine by Fred Buhl, May 2002
1250 :
1251 2 : this->AirFlowRateRatio = 0.0; // Ratio of air flow rate through VS Evaporative fluid cooler to design air flow rate
1252 :
1253 2 : this->InitEvapFluidCooler(state);
1254 :
1255 2 : if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_SingleSpd) {
1256 1 : this->CalcSingleSpeedEvapFluidCooler(state);
1257 1 : } else if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd) {
1258 1 : this->CalcTwoSpeedEvapFluidCooler(state);
1259 : } else {
1260 0 : ShowFatalError(state, format("SimEvapFluidCoolers: Invalid evaporative fluid cooler Type Requested = {}", EvapFluidCoolerType));
1261 : }
1262 :
1263 2 : this->CalculateWaterUsage(state);
1264 2 : this->UpdateEvapFluidCooler(state);
1265 2 : this->ReportEvapFluidCooler(state, RunFlag);
1266 2 : }
1267 :
1268 5 : void EvapFluidCoolerSpecs::InitEvapFluidCooler(EnergyPlusData &state)
1269 : {
1270 :
1271 : // SUBROUTINE INFORMATION:
1272 : // AUTHOR Chandan Sharma
1273 : // DATE WRITTEN May 2009
1274 : // MODIFIED na
1275 : // RE-ENGINEERED na
1276 :
1277 : // PURPOSE OF THIS SUBROUTINE:
1278 : // This subroutine is for initializations of the evaporative fluid cooler components and for
1279 : // final checking of evaporative fluid cooler inputs (post autosizing)
1280 :
1281 : // METHODOLOGY EMPLOYED:
1282 : // Uses the status flags to trigger initializations.
1283 :
1284 : // REFERENCES:
1285 : // Based on InitTower subroutine by Don Shirey Sept/Oct 2002, F Buhl Oct 2002
1286 :
1287 : static constexpr std::string_view RoutineName("InitEvapFluidCooler");
1288 :
1289 5 : this->oneTimeInit(state);
1290 :
1291 : // Begin environment initializations
1292 5 : if (this->MyEnvrnFlag && state.dataGlobal->BeginEnvrnFlag && (state.dataPlnt->PlantFirstSizesOkayToFinalize)) {
1293 :
1294 0 : Real64 rho = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
1295 0 : this->DesWaterMassFlowRate = this->DesignWaterFlowRate * rho;
1296 0 : PlantUtilities::InitComponentNodes(state, 0.0, this->DesWaterMassFlowRate, this->WaterInletNodeNum, this->WaterOutletNodeNum);
1297 0 : this->MyEnvrnFlag = false;
1298 : }
1299 :
1300 5 : if (!state.dataGlobal->BeginEnvrnFlag) {
1301 4 : this->MyEnvrnFlag = true;
1302 : }
1303 :
1304 : // Each time initializations
1305 5 : this->WaterInletNode = this->WaterInletNodeNum;
1306 5 : this->inletConds.WaterTemp = state.dataLoopNodes->Node(this->WaterInletNode).Temp;
1307 :
1308 5 : if (this->OutdoorAirInletNodeNum != 0) {
1309 0 : this->inletConds.AirTemp = state.dataLoopNodes->Node(this->OutdoorAirInletNodeNum).Temp;
1310 0 : this->inletConds.AirHumRat = state.dataLoopNodes->Node(this->OutdoorAirInletNodeNum).HumRat;
1311 0 : this->inletConds.AirPress = state.dataLoopNodes->Node(this->OutdoorAirInletNodeNum).Press;
1312 0 : this->inletConds.AirWetBulb = state.dataLoopNodes->Node(this->OutdoorAirInletNodeNum).OutAirWetBulb;
1313 : } else {
1314 5 : this->inletConds.AirTemp = state.dataEnvrn->OutDryBulbTemp;
1315 5 : this->inletConds.AirHumRat = state.dataEnvrn->OutHumRat;
1316 5 : this->inletConds.AirPress = state.dataEnvrn->OutBaroPress;
1317 5 : this->inletConds.AirWetBulb = state.dataEnvrn->OutWetBulbTemp;
1318 : }
1319 :
1320 10 : this->WaterMassFlowRate = PlantUtilities::RegulateCondenserCompFlowReqOp(
1321 5 : state, this->plantLoc, this->DesWaterMassFlowRate * this->EvapFluidCoolerMassFlowRateMultiplier);
1322 :
1323 5 : PlantUtilities::SetComponentFlowRate(state, this->WaterMassFlowRate, this->WaterInletNodeNum, this->WaterOutletNodeNum, this->plantLoc);
1324 5 : }
1325 :
1326 4 : void EvapFluidCoolerSpecs::SizeEvapFluidCooler(EnergyPlusData &state)
1327 : {
1328 :
1329 : // SUBROUTINE INFORMATION:
1330 : // AUTHOR Chandan Sharma
1331 : // DATE WRITTEN May 2009
1332 : // MODIFIED Chandan Sharma, April 2010
1333 : // RE-ENGINEERED na
1334 :
1335 : // PURPOSE OF THIS SUBROUTINE:
1336 : // This subroutine is for sizing evaporative fluid cooler Components for which capacities and flow rates
1337 : // have not been specified in the input. This subroutine also calculates evaporative fluid cooler UA if the user
1338 : // has specified evaporative fluid cooler performance via the "Standard Design Capacity" method.
1339 :
1340 : // METHODOLOGY EMPLOYED:
1341 : // Obtains condenser flow rate from the plant sizing array. If evaporative fluid cooler performance is specified
1342 : // via the "Standard Design Capacity" method, the water flow rate is directly proportional to capacity.
1343 :
1344 : // REFERENCES:
1345 : // Based on SizeTower by Don Shirey, Sept/Oct 2002; Richard Raustad, Feb 2005
1346 :
1347 4 : int constexpr MaxIte(500); // Maximum number of iterations
1348 4 : Real64 constexpr Acc(0.0001); // Accuracy of result
1349 4 : std::string const CalledFrom("SizeEvapFluidCooler");
1350 :
1351 : int SolFla; // Flag of solver
1352 : Real64 UA; // Calculated UA value [W/C]
1353 : Real64 OutWaterTempAtUA0; // Water outlet temperature at UA0
1354 : Real64 OutWaterTempAtUA1; // Water outlet temperature at UA1
1355 :
1356 4 : Real64 DesEvapFluidCoolerLoad = 0.0; // Design evaporative fluid cooler load [W]
1357 4 : Real64 tmpDesignWaterFlowRate = this->DesignWaterFlowRate;
1358 4 : Real64 tmpHighSpeedFanPower = this->HighSpeedFanPower;
1359 4 : Real64 tmpHighSpeedAirFlowRate = this->HighSpeedAirFlowRate;
1360 :
1361 4 : int PltSizCondNum = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).PlantSizNum;
1362 :
1363 4 : if (this->DesignWaterFlowRateWasAutoSized && this->PerformanceInputMethod_Num != PIM::StandardDesignCapacity) {
1364 2 : if (PltSizCondNum > 0) {
1365 :
1366 : // Check when the user specified Condenser/Evaporative Fluid Cooler water design setpoint
1367 : // temperature is less than design inlet air wet bulb temperature
1368 1 : Real64 DesignEnteringAirWetBulb = 0;
1369 1 : if (this->PerformanceInputMethod_Num == PIM::UFactor) {
1370 1 : DesignEnteringAirWetBulb = 25.6;
1371 : } else {
1372 0 : DesignEnteringAirWetBulb = this->DesignEnteringAirWetBulbTemp;
1373 : }
1374 1 : if (state.dataSize->PlantSizData(PltSizCondNum).ExitTemp <= DesignEnteringAirWetBulb) {
1375 0 : ShowSevereError(state, format("Error when autosizing the UA value for Evaporative Fluid Cooler = {}.", this->Name));
1376 0 : ShowContinueError(state,
1377 0 : format("Design Loop Exit Temperature ({:.2R} C) must be greater than design entering air wet-bulb temperature "
1378 : "({:.2R} C) when autosizing the Evaporative Fluid Cooler UA.",
1379 0 : state.dataSize->PlantSizData(PltSizCondNum).ExitTemp,
1380 : DesignEnteringAirWetBulb));
1381 0 : ShowContinueError(
1382 : state,
1383 : "It is recommended that the Design Loop Exit Temperature = Design Entering Air Wet-bulb Temp plus the Evaporative "
1384 : "Fluid Cooler design approach temperature (e.g., 4 C).");
1385 0 : ShowContinueError(
1386 : state,
1387 : "If using HVACTemplate:Plant:ChilledWaterLoop, then check that input field Condenser Water Design Setpoint must be "
1388 : "> Design Entering Air Wet-bulb Temp if autosizing the Evaporative Fluid Cooler.");
1389 0 : ShowFatalError(state, "Review and revise design input values as appropriate.");
1390 : }
1391 :
1392 1 : if (state.dataSize->PlantSizData(PltSizCondNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
1393 0 : tmpDesignWaterFlowRate = state.dataSize->PlantSizData(PltSizCondNum).DesVolFlowRate * this->SizFac;
1394 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1395 0 : this->DesignWaterFlowRate = tmpDesignWaterFlowRate;
1396 : }
1397 :
1398 : } else {
1399 1 : tmpDesignWaterFlowRate = 0.0;
1400 1 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1401 0 : this->DesignWaterFlowRate = tmpDesignWaterFlowRate;
1402 : }
1403 : }
1404 1 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1405 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1406 0 : BaseSizer::reportSizerOutput(
1407 : state, this->EvapFluidCoolerType, this->Name, "Design Water Flow Rate [m3/s]", this->DesignWaterFlowRate);
1408 : }
1409 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1410 0 : BaseSizer::reportSizerOutput(
1411 : state, this->EvapFluidCoolerType, this->Name, "Initial Design Water Flow Rate [m3/s]", this->DesignWaterFlowRate);
1412 : }
1413 : }
1414 : } else {
1415 1 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1416 0 : ShowSevereError(state, format("Autosizing error for evaporative fluid cooler object = {}", this->Name));
1417 0 : ShowFatalError(state, "Autosizing of evaporative fluid cooler condenser flow rate requires a loop Sizing:Plant object.");
1418 : }
1419 : }
1420 : }
1421 :
1422 4 : if (this->PerformanceInputMethod_Num == PIM::UFactor && !this->HighSpeedEvapFluidCoolerUAWasAutoSized) {
1423 1 : if (PltSizCondNum > 0) {
1424 1 : Real64 rho = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getDensity(state, Constant::InitConvTemp, CalledFrom);
1425 1 : Real64 Cp = state.dataPlnt->PlantLoop(this->plantLoc.loopNum)
1426 1 : .glycol->getSpecificHeat(state, state.dataSize->PlantSizData(PltSizCondNum).ExitTemp, CalledFrom);
1427 1 : DesEvapFluidCoolerLoad = rho * Cp * tmpDesignWaterFlowRate * state.dataSize->PlantSizData(PltSizCondNum).DeltaT;
1428 1 : this->HighSpeedStandardDesignCapacity = DesEvapFluidCoolerLoad / this->HeatRejectCapNomCapSizingRatio;
1429 : } else {
1430 0 : this->HighSpeedStandardDesignCapacity = 0.0;
1431 : }
1432 : }
1433 :
1434 4 : if (this->PerformanceInputMethod_Num == PIM::StandardDesignCapacity) {
1435 : // Design water flow rate is assumed to be 3 gpm per ton (SI equivalent 5.382E-8 m3/s per watt)
1436 0 : tmpDesignWaterFlowRate = 5.382e-8 * this->HighSpeedStandardDesignCapacity;
1437 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1438 0 : this->DesignWaterFlowRate = tmpDesignWaterFlowRate;
1439 0 : if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_SingleSpd) {
1440 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1441 0 : BaseSizer::reportSizerOutput(state,
1442 : cEvapFluidCooler_SingleSpeed,
1443 : this->Name,
1444 : "Design Water Flow Rate based on evaporative fluid cooler Standard Design Capacity [m3/s]",
1445 : this->DesignWaterFlowRate);
1446 : }
1447 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1448 0 : BaseSizer::reportSizerOutput(
1449 : state,
1450 : cEvapFluidCooler_SingleSpeed,
1451 : this->Name,
1452 : "Initial Design Water Flow Rate based on evaporative fluid cooler Standard Design Capacity [m3/s]",
1453 : this->DesignWaterFlowRate);
1454 : }
1455 0 : } else if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd) {
1456 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1457 0 : BaseSizer::reportSizerOutput(
1458 : state,
1459 : cEvapFluidCooler_TwoSpeed,
1460 : this->Name,
1461 : "Design Water Flow Rate based on evaporative fluid cooler high-speed Standard Design Capacity [m3/s]",
1462 : this->DesignWaterFlowRate);
1463 : }
1464 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1465 0 : BaseSizer::reportSizerOutput(
1466 : state,
1467 : cEvapFluidCooler_TwoSpeed,
1468 : this->Name,
1469 : "Initial Design Water Flow Rate based on evaporative fluid cooler high-speed Standard Design Capacity [m3/s]",
1470 : this->DesignWaterFlowRate);
1471 : }
1472 : }
1473 : }
1474 : }
1475 :
1476 4 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->WaterInletNodeNum, tmpDesignWaterFlowRate);
1477 :
1478 4 : if (this->HighSpeedFanPowerWasAutoSized) {
1479 : // We assume the nominal fan power is 0.0105 times the design load
1480 2 : if (this->PerformanceInputMethod_Num == PIM::StandardDesignCapacity) {
1481 0 : tmpHighSpeedFanPower = 0.0105 * this->HighSpeedStandardDesignCapacity;
1482 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1483 0 : this->HighSpeedFanPower = tmpHighSpeedFanPower;
1484 : }
1485 2 : } else if (this->PerformanceInputMethod_Num == PIM::UserSpecifiedDesignCapacity) {
1486 0 : tmpHighSpeedFanPower = 0.0105 * this->HighSpeedUserSpecifiedDesignCapacity;
1487 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1488 0 : this->HighSpeedFanPower = tmpHighSpeedFanPower;
1489 : }
1490 : } else {
1491 2 : if (DesEvapFluidCoolerLoad > 0) {
1492 0 : tmpHighSpeedFanPower = 0.0105 * DesEvapFluidCoolerLoad;
1493 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1494 0 : this->HighSpeedFanPower = tmpHighSpeedFanPower;
1495 : }
1496 2 : } else if (PltSizCondNum > 0) {
1497 1 : if (state.dataSize->PlantSizData(PltSizCondNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
1498 0 : Real64 rho = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getDensity(state, Constant::InitConvTemp, CalledFrom);
1499 0 : Real64 Cp = state.dataPlnt->PlantLoop(this->plantLoc.loopNum)
1500 0 : .glycol->getSpecificHeat(state, state.dataSize->PlantSizData(PltSizCondNum).ExitTemp, CalledFrom);
1501 0 : DesEvapFluidCoolerLoad = rho * Cp * tmpDesignWaterFlowRate * state.dataSize->PlantSizData(PltSizCondNum).DeltaT;
1502 0 : tmpHighSpeedFanPower = 0.0105 * DesEvapFluidCoolerLoad;
1503 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1504 0 : this->HighSpeedFanPower = tmpHighSpeedFanPower;
1505 : }
1506 : } else {
1507 1 : tmpHighSpeedFanPower = 0.0;
1508 1 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1509 0 : this->HighSpeedFanPower = tmpHighSpeedFanPower;
1510 : }
1511 : }
1512 : } else {
1513 1 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1514 0 : ShowSevereError(state, "Autosizing of evaporative fluid cooler fan power requires a loop Sizing:Plant object.");
1515 0 : ShowFatalError(state, format(" Occurs in evaporative fluid cooler object= {}", this->Name));
1516 : }
1517 : }
1518 : }
1519 2 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1520 0 : if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_SingleSpd) {
1521 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1522 0 : BaseSizer::reportSizerOutput(
1523 : state, cEvapFluidCooler_SingleSpeed, this->Name, "Fan Power at Design Air Flow Rate [W]", this->HighSpeedFanPower);
1524 : }
1525 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1526 0 : BaseSizer::reportSizerOutput(state,
1527 : cEvapFluidCooler_SingleSpeed,
1528 : this->Name,
1529 : "Initial Fan Power at Design Air Flow Rate [W]",
1530 : this->HighSpeedFanPower);
1531 : }
1532 0 : } else if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd) {
1533 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1534 0 : BaseSizer::reportSizerOutput(
1535 : state, cEvapFluidCooler_TwoSpeed, this->Name, "Fan Power at High Fan Speed [W]", this->HighSpeedFanPower);
1536 : }
1537 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1538 0 : BaseSizer::reportSizerOutput(
1539 : state, cEvapFluidCooler_TwoSpeed, this->Name, "Initial Fan Power at High Fan Speed [W]", this->HighSpeedFanPower);
1540 : }
1541 : }
1542 : }
1543 : }
1544 :
1545 4 : if (this->HighSpeedAirFlowRateWasAutoSized) {
1546 : // Plant Sizing Object is not required to AUTOSIZE this field since its simply a multiple of another field.
1547 :
1548 2 : tmpHighSpeedAirFlowRate = tmpHighSpeedFanPower * 0.5 * (101325.0 / state.dataEnvrn->StdBaroPress) / 190.0;
1549 2 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1550 0 : this->HighSpeedAirFlowRate = tmpHighSpeedAirFlowRate;
1551 :
1552 0 : if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_SingleSpd) {
1553 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1554 0 : BaseSizer::reportSizerOutput(
1555 : state, cEvapFluidCooler_SingleSpeed, this->Name, "Design Air Flow Rate [m3/s]", this->HighSpeedAirFlowRate);
1556 : }
1557 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1558 0 : BaseSizer::reportSizerOutput(
1559 : state, cEvapFluidCooler_SingleSpeed, this->Name, "Initial Design Air Flow Rate [m3/s]", this->HighSpeedAirFlowRate);
1560 : }
1561 0 : } else if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd) {
1562 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1563 0 : BaseSizer::reportSizerOutput(
1564 : state, cEvapFluidCooler_TwoSpeed, this->Name, "Air Flow Rate at High Fan Speed [m3/s]", this->HighSpeedAirFlowRate);
1565 : }
1566 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1567 0 : BaseSizer::reportSizerOutput(state,
1568 : cEvapFluidCooler_TwoSpeed,
1569 : this->Name,
1570 : "Initial Air Flow Rate at High Fan Speed [m3/s]",
1571 : this->HighSpeedAirFlowRate);
1572 : }
1573 : }
1574 : }
1575 : }
1576 :
1577 4 : if (this->HighSpeedEvapFluidCoolerUAWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize &&
1578 0 : this->PerformanceInputMethod_Num == PIM::UFactor) {
1579 0 : if (PltSizCondNum > 0) {
1580 0 : if (state.dataSize->PlantSizData(PltSizCondNum).DesVolFlowRate >= HVAC::SmallWaterVolFlow) {
1581 : // This conditional statement is to trap when the user specified Condenser/Evaporative Fluid Cooler water design setpoint
1582 : // temperature is less than design inlet air wet bulb temperature of 25.6 C
1583 0 : if (state.dataSize->PlantSizData(PltSizCondNum).ExitTemp <= 25.6) {
1584 0 : ShowSevereError(state, format("Error when autosizing the UA value for Evaporative Fluid Cooler = {}.", this->Name));
1585 0 : ShowContinueError(state,
1586 0 : format("Design Loop Exit Temperature ({:.2R} C) must be greater than 25.6 C when autosizing the "
1587 : "Evaporative Fluid Cooler UA.",
1588 0 : state.dataSize->PlantSizData(PltSizCondNum).ExitTemp));
1589 0 : ShowContinueError(state,
1590 0 : format("The Design Loop Exit Temperature specified in Sizing:Plant object = {}",
1591 0 : state.dataSize->PlantSizData(PltSizCondNum).PlantLoopName));
1592 0 : ShowContinueError(state,
1593 : "It is recommended that the Design Loop Exit Temperature = 25.6 C plus the Evaporative Fluid Cooler design "
1594 : "approach temperature (e.g., 4 C).");
1595 0 : ShowContinueError(state,
1596 : "If using HVACTemplate:Plant:ChilledWaterLoop, then check that input field Condenser Water Design Setpoint "
1597 : "must be > 25.6 C if autosizing the Evaporative Fluid Cooler.");
1598 0 : ShowFatalError(state, "Review and revise design input values as appropriate.");
1599 : }
1600 0 : Real64 rho = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getDensity(state, Constant::InitConvTemp, CalledFrom);
1601 0 : Real64 Cp = state.dataPlnt->PlantLoop(this->plantLoc.loopNum)
1602 0 : .glycol->getSpecificHeat(state, state.dataSize->PlantSizData(PltSizCondNum).ExitTemp, CalledFrom);
1603 0 : DesEvapFluidCoolerLoad = rho * Cp * tmpDesignWaterFlowRate * state.dataSize->PlantSizData(PltSizCondNum).DeltaT;
1604 0 : Real64 const par1 = rho * tmpDesignWaterFlowRate; // Design water mass flow rate
1605 0 : Real64 const par2 = tmpHighSpeedAirFlowRate; // Design air volume flow rate
1606 : // Lower bound for UA [W/C]
1607 0 : Real64 UA0 = 0.0001 * DesEvapFluidCoolerLoad; // Assume deltaT = 10000K (limit)
1608 0 : Real64 UA1 = DesEvapFluidCoolerLoad; // Assume deltaT = 1K
1609 0 : this->inletConds.WaterTemp =
1610 0 : state.dataSize->PlantSizData(PltSizCondNum).ExitTemp + state.dataSize->PlantSizData(PltSizCondNum).DeltaT;
1611 0 : this->inletConds.AirTemp = 35.0;
1612 0 : this->inletConds.AirWetBulb = 25.6;
1613 0 : this->inletConds.AirPress = state.dataEnvrn->StdBaroPress;
1614 0 : this->inletConds.AirHumRat =
1615 0 : Psychrometrics::PsyWFnTdbTwbPb(state, this->inletConds.AirTemp, this->inletConds.AirWetBulb, this->inletConds.AirPress);
1616 0 : auto f = [&state, this, DesEvapFluidCoolerLoad, par1, par2, Cp](Real64 UA) {
1617 : Real64 OutWaterTemp; // outlet water temperature [C]
1618 0 : this->SimSimpleEvapFluidCooler(state, par1, par2, UA, OutWaterTemp);
1619 0 : Real64 const CoolingOutput = Cp * par1 * (this->inletConds.WaterTemp - OutWaterTemp);
1620 0 : return (DesEvapFluidCoolerLoad - CoolingOutput) / DesEvapFluidCoolerLoad;
1621 0 : };
1622 0 : General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
1623 0 : if (SolFla == -1) {
1624 0 : ShowWarningError(state, "Iteration limit exceeded in calculating evaporative fluid cooler UA.");
1625 0 : ShowContinueError(state, format("Autosizing of fluid cooler UA failed for evaporative fluid cooler = {}", this->Name));
1626 0 : ShowContinueError(state, format("The final UA value = {:.2R}W/C, and the simulation continues...", UA));
1627 0 : } else if (SolFla == -2) {
1628 0 : this->SimSimpleEvapFluidCooler(state, par1, par2, UA0, OutWaterTempAtUA0);
1629 0 : this->SimSimpleEvapFluidCooler(state, par1, par2, UA1, OutWaterTempAtUA1);
1630 0 : ShowSevereError(state, format("{}: The combination of design input values did not allow the calculation of a ", CalledFrom));
1631 0 : ShowContinueError(state, "reasonable UA value. Review and revise design input values as appropriate. Specifying hard");
1632 0 : ShowContinueError(state,
1633 : "sizes for some \"autosizable\" fields while autosizing other \"autosizable\" fields may be contributing "
1634 : "to this problem.");
1635 0 : ShowContinueError(state, "This model iterates on UA to find the heat transfer required to provide the design outlet ");
1636 0 : ShowContinueError(state, "water temperature. Initially, the outlet water temperatures at high and low UA values are ");
1637 0 : ShowContinueError(state, "calculated. The Design Exit Water Temperature should be between the outlet water ");
1638 0 : ShowContinueError(state, "temperatures calculated at high and low UA values. If the Design Exit Water Temperature is ");
1639 0 : ShowContinueError(state, "out of this range, the solution will not converge and UA will not be calculated. ");
1640 0 : ShowContinueError(state, "The possible solutions could be to manually input adjusted water and/or air flow rates ");
1641 0 : ShowContinueError(
1642 : state,
1643 : "based on the autosized values shown below or to adjust design evaporative fluid cooler air inlet wet-bulb temperature.");
1644 0 : ShowContinueError(state, "Plant:Sizing object inputs also influence these results (e.g. DeltaT and ExitTemp).");
1645 0 : ShowContinueError(state, "Inputs to the evaporative fluid cooler object:");
1646 0 : ShowContinueError(state,
1647 0 : format("Design Evaporative Fluid Cooler Load [W] = {:.2R}", DesEvapFluidCoolerLoad));
1648 0 : ShowContinueError(
1649 0 : state, format("Design Evaporative Fluid Cooler Water Volume Flow Rate [m3/s] = {:.6R}", this->DesignWaterFlowRate));
1650 0 : ShowContinueError(state, format("Design Evaporative Fluid Cooler Air Volume Flow Rate [m3/s] = {:.2R}", par2));
1651 0 : ShowContinueError(
1652 0 : state, format("Design Evaporative Fluid Cooler Air Inlet Wet-bulb Temp [C] = {:.2R}", this->inletConds.AirWetBulb));
1653 0 : ShowContinueError(
1654 0 : state, format("Design Evaporative Fluid Cooler Water Inlet Temp [C] = {:.2R}", this->inletConds.WaterTemp));
1655 0 : ShowContinueError(state, "Inputs to the plant sizing object:");
1656 0 : ShowContinueError(state,
1657 0 : format("Design Exit Water Temp [C] = {:.2R}",
1658 0 : state.dataSize->PlantSizData(PltSizCondNum).ExitTemp));
1659 0 : ShowContinueError(state,
1660 0 : format("Loop Design Temperature Difference [C] = {:.2R}",
1661 0 : state.dataSize->PlantSizData(PltSizCondNum).DeltaT));
1662 0 : ShowContinueError(
1663 0 : state, format("Design Evaporative Fluid Cooler Water Inlet Temp [C] = {:.2R}", this->inletConds.WaterTemp));
1664 0 : ShowContinueError(
1665 0 : state, format("Calculated water outlet temperature at low UA [C](UA = {:.2R} W/C) = {:.2R}", UA0, OutWaterTempAtUA0));
1666 0 : ShowContinueError(
1667 0 : state, format("Calculated water outlet temperature at high UA [C](UA = {:.2R} W/C) = {:.2R}", UA1, OutWaterTempAtUA1));
1668 0 : ShowFatalError(state,
1669 0 : format("Autosizing of Evaporative Fluid Cooler UA failed for Evaporative Fluid Cooler = {}", this->Name));
1670 : }
1671 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1672 0 : this->HighSpeedEvapFluidCoolerUA = UA;
1673 : }
1674 0 : this->HighSpeedStandardDesignCapacity = DesEvapFluidCoolerLoad / this->HeatRejectCapNomCapSizingRatio;
1675 : } else {
1676 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1677 0 : this->HighSpeedEvapFluidCoolerUA = 0.0;
1678 : }
1679 : }
1680 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1681 0 : if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_SingleSpd) {
1682 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1683 0 : BaseSizer::reportSizerOutput(state,
1684 : cEvapFluidCooler_SingleSpeed,
1685 : this->Name,
1686 : "U-Factor Times Area Value at Design Air Flow Rate [W/C]",
1687 : this->HighSpeedEvapFluidCoolerUA);
1688 : }
1689 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1690 0 : BaseSizer::reportSizerOutput(state,
1691 : cEvapFluidCooler_SingleSpeed,
1692 : this->Name,
1693 : "Initial U-Factor Times Area Value at Design Air Flow Rate [W/C]",
1694 : this->HighSpeedEvapFluidCoolerUA);
1695 : }
1696 0 : } else if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd) {
1697 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1698 0 : BaseSizer::reportSizerOutput(state,
1699 : cEvapFluidCooler_TwoSpeed,
1700 : this->Name,
1701 : "U-Factor Times Area Value at High Fan Speed [W/C]",
1702 : this->HighSpeedEvapFluidCoolerUA);
1703 : }
1704 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1705 0 : BaseSizer::reportSizerOutput(state,
1706 : cEvapFluidCooler_TwoSpeed,
1707 : this->Name,
1708 : "Initial U-Factor Times Area Value at High Fan Speed [W/C]",
1709 : this->HighSpeedEvapFluidCoolerUA);
1710 : }
1711 : }
1712 : }
1713 : } else {
1714 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1715 0 : ShowSevereError(state, format("Autosizing error for evaporative fluid cooler object = {}", this->Name));
1716 0 : ShowFatalError(state, "Autosizing of evaporative fluid cooler UA requires a loop Sizing:Plant object.");
1717 : }
1718 : }
1719 : }
1720 :
1721 4 : if (this->PerformanceInputMethod_Num == PIM::StandardDesignCapacity) {
1722 0 : if (this->DesignWaterFlowRate >= HVAC::SmallWaterVolFlow) {
1723 : // Standard Design Capacity doesn't include compressor heat;
1724 : // predefined factor was 1.25 W heat rejection per W of delivered cooling, now a user input with 1.25 default
1725 0 : Real64 rho = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getDensity(state, Constant::InitConvTemp, CalledFrom);
1726 0 : Real64 Cp = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getSpecificHeat(state, 35.0, CalledFrom);
1727 0 : DesEvapFluidCoolerLoad = this->HighSpeedStandardDesignCapacity * this->HeatRejectCapNomCapSizingRatio;
1728 0 : Real64 const par1 = rho * this->DesignWaterFlowRate; // Design water mass flow rate
1729 0 : Real64 const par2 = this->HighSpeedAirFlowRate; // Design air volume flow rate
1730 0 : Real64 UA0 = 0.0001 * DesEvapFluidCoolerLoad; // Assume deltaT = 10000K (limit)
1731 0 : Real64 UA1 = DesEvapFluidCoolerLoad; // Assume deltaT = 1K
1732 0 : this->inletConds.WaterTemp = 35.0; // 95F design inlet water temperature
1733 0 : this->inletConds.AirTemp = 35.0; // 95F design inlet air dry-bulb temp
1734 0 : this->inletConds.AirWetBulb = 25.6; // 78F design inlet air wet-bulb temp
1735 0 : this->inletConds.AirPress = state.dataEnvrn->StdBaroPress;
1736 0 : this->inletConds.AirHumRat =
1737 0 : Psychrometrics::PsyWFnTdbTwbPb(state, this->inletConds.AirTemp, this->inletConds.AirWetBulb, this->inletConds.AirPress);
1738 0 : auto f = [&state, this, DesEvapFluidCoolerLoad, par1, par2, Cp](Real64 UA) {
1739 : Real64 OutWaterTemp; // outlet water temperature [C]
1740 0 : this->SimSimpleEvapFluidCooler(state, par1, par2, UA, OutWaterTemp);
1741 0 : Real64 const CoolingOutput = Cp * par1 * (this->inletConds.WaterTemp - OutWaterTemp);
1742 0 : return (DesEvapFluidCoolerLoad - CoolingOutput) / DesEvapFluidCoolerLoad;
1743 0 : };
1744 0 : General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
1745 0 : if (SolFla == -1) {
1746 0 : ShowWarningError(state, "Iteration limit exceeded in calculating evaporative fluid cooler UA.");
1747 0 : ShowContinueError(state, format("Autosizing of fluid cooler UA failed for evaporative fluid cooler = {}", this->Name));
1748 0 : ShowContinueError(state, format("The final UA value = {:.2R}W/C, and the simulation continues...", UA));
1749 0 : } else if (SolFla == -2) {
1750 0 : ShowSevereError(state, format("{}: The combination of design input values did not allow the calculation of a ", CalledFrom));
1751 0 : ShowContinueError(state, "reasonable UA value. Review and revise design input values as appropriate. ");
1752 0 : ShowFatalError(state, format("Autosizing of Evaporative Fluid Cooler UA failed for Evaporative Fluid Cooler = {}", this->Name));
1753 : }
1754 0 : this->HighSpeedEvapFluidCoolerUA = UA;
1755 : } else {
1756 0 : this->HighSpeedEvapFluidCoolerUA = 0.0;
1757 : }
1758 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1759 0 : if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_SingleSpd) {
1760 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1761 0 : BaseSizer::reportSizerOutput(state,
1762 : cEvapFluidCooler_SingleSpeed,
1763 : this->Name,
1764 : "U-Factor Times Area Value at Design Air Flow Rate [W/C]",
1765 : this->HighSpeedEvapFluidCoolerUA);
1766 : }
1767 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1768 0 : BaseSizer::reportSizerOutput(state,
1769 : cEvapFluidCooler_SingleSpeed,
1770 : this->Name,
1771 : "Initial U-Factor Times Area Value at Design Air Flow Rate [W/C]",
1772 : this->HighSpeedEvapFluidCoolerUA);
1773 : }
1774 0 : } else if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd) {
1775 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1776 0 : BaseSizer::reportSizerOutput(state,
1777 : cEvapFluidCooler_TwoSpeed,
1778 : this->Name,
1779 : "U-Factor Times Area Value at High Fan Speed [W/C]",
1780 : this->HighSpeedEvapFluidCoolerUA);
1781 : }
1782 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1783 0 : BaseSizer::reportSizerOutput(state,
1784 : cEvapFluidCooler_TwoSpeed,
1785 : this->Name,
1786 : "Initial U-Factor Times Area Value at High Fan Speed [W/C]",
1787 : this->HighSpeedEvapFluidCoolerUA);
1788 : }
1789 : }
1790 : }
1791 : }
1792 :
1793 4 : if (this->PerformanceInputMethod_Num == PIM::UserSpecifiedDesignCapacity) {
1794 1 : if (this->DesignWaterFlowRate >= HVAC::SmallWaterVolFlow) {
1795 1 : Real64 rho = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getDensity(state, Constant::InitConvTemp, CalledFrom);
1796 : Real64 Cp =
1797 1 : state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getSpecificHeat(state, this->DesignEnteringWaterTemp, CalledFrom);
1798 1 : DesEvapFluidCoolerLoad = this->HighSpeedUserSpecifiedDesignCapacity;
1799 1 : Real64 const par1 = rho * tmpDesignWaterFlowRate; // Design water mass flow rate
1800 1 : Real64 const par2 = tmpHighSpeedAirFlowRate; // Design air volume flow rate
1801 1 : Real64 UA0 = 0.0001 * DesEvapFluidCoolerLoad; // Assume deltaT = 10000K (limit)
1802 1 : Real64 UA1 = DesEvapFluidCoolerLoad; // Assume deltaT = 1K
1803 :
1804 1 : this->inletConds.WaterTemp = this->DesignEnteringWaterTemp;
1805 1 : this->inletConds.AirTemp = this->DesignEnteringAirTemp;
1806 1 : this->inletConds.AirWetBulb = this->DesignEnteringAirWetBulbTemp;
1807 1 : this->inletConds.AirPress = state.dataEnvrn->StdBaroPress;
1808 1 : this->inletConds.AirHumRat =
1809 1 : Psychrometrics::PsyWFnTdbTwbPb(state, this->inletConds.AirTemp, this->inletConds.AirWetBulb, this->inletConds.AirPress);
1810 19 : auto f = [&state, this, DesEvapFluidCoolerLoad, par1, par2, Cp](Real64 UA) {
1811 : Real64 OutWaterTemp; // outlet water temperature [C]
1812 19 : this->SimSimpleEvapFluidCooler(state, par1, par2, UA, OutWaterTemp);
1813 19 : Real64 const CoolingOutput = Cp * par1 * (this->inletConds.WaterTemp - OutWaterTemp);
1814 19 : return (DesEvapFluidCoolerLoad - CoolingOutput) / DesEvapFluidCoolerLoad;
1815 1 : };
1816 1 : General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
1817 1 : if (SolFla == -1) {
1818 0 : ShowWarningError(state, "Iteration limit exceeded in calculating evaporative fluid cooler UA.");
1819 0 : ShowContinueError(state, format("Autosizing of fluid cooler UA failed for evaporative fluid cooler = {}", this->Name));
1820 0 : ShowContinueError(state, format("The final UA value = {:.2R}W/C, and the simulation continues...", UA));
1821 1 : } else if (SolFla == -2) {
1822 0 : this->SimSimpleEvapFluidCooler(state, par1, par2, UA0, OutWaterTempAtUA0);
1823 0 : this->SimSimpleEvapFluidCooler(state, par1, par2, UA1, OutWaterTempAtUA1);
1824 0 : ShowSevereError(state, format("{}: The combination of design input values did not allow the calculation of a ", CalledFrom));
1825 0 : ShowContinueError(state, "reasonable UA value. Review and revise design input values as appropriate. Specifying hard");
1826 0 : ShowContinueError(
1827 : state,
1828 : R"(sizes for some "autosizable" fields while autosizing other "autosizable" fields may be contributing to this problem.)");
1829 0 : ShowContinueError(state, "This model iterates on UA to find the heat transfer required to provide the design outlet ");
1830 0 : ShowContinueError(state, "water temperature. Initially, the outlet water temperatures at high and low UA values are ");
1831 0 : ShowContinueError(state, "calculated. The Design Exit Water Temperature should be between the outlet water ");
1832 0 : ShowContinueError(state, "temperatures calculated at high and low UA values. If the Design Exit Water Temperature is ");
1833 0 : ShowContinueError(state, "out of this range, the solution will not converge and UA will not be calculated. ");
1834 0 : ShowContinueError(state, "The possible solutions could be to manually input adjusted water and/or air flow rates ");
1835 0 : ShowContinueError(
1836 : state,
1837 : "based on the autosized values shown below or to adjust design evaporative fluid cooler air inlet wet-bulb temperature.");
1838 0 : ShowContinueError(state, "Plant:Sizing object inputs also influence these results (e.g. DeltaT and ExitTemp).");
1839 0 : ShowContinueError(state, "Inputs to the evaporative fluid cooler object:");
1840 0 : ShowContinueError(state,
1841 0 : format("Design Evaporative Fluid Cooler Load [W] = {:.2R}", DesEvapFluidCoolerLoad));
1842 0 : ShowContinueError(state,
1843 0 : format("Design Evaporative Fluid Cooler Water Volume Flow Rate [m3/s] = {:.6R}", this->DesignWaterFlowRate));
1844 0 : ShowContinueError(state, format("Design Evaporative Fluid Cooler Air Volume Flow Rate [m3/s] = {:.2R}", par2));
1845 0 : ShowContinueError(state,
1846 0 : format("Design Evaporative Fluid Cooler Air Inlet Wet-bulb Temp [C] = {:.2R}", this->inletConds.AirWetBulb));
1847 0 : ShowContinueError(state,
1848 0 : format("Design Evaporative Fluid Cooler Water Inlet Temp [C] = {:.2R}", this->inletConds.WaterTemp));
1849 0 : ShowContinueError(state, "Inputs to the plant sizing object:");
1850 0 : ShowContinueError(state,
1851 0 : format("Design Exit Water Temp [C] = {:.2R}",
1852 0 : state.dataSize->PlantSizData(PltSizCondNum).ExitTemp));
1853 0 : ShowContinueError(state,
1854 0 : format("Loop Design Temperature Difference [C] = {:.2R}",
1855 0 : state.dataSize->PlantSizData(PltSizCondNum).DeltaT));
1856 0 : ShowContinueError(state,
1857 0 : format("Design Evaporative Fluid Cooler Water Inlet Temp [C] = {:.2R}", this->inletConds.WaterTemp));
1858 0 : ShowContinueError(state,
1859 0 : format("Calculated water outlet temperature at low UA [C](UA = {:.2R} W/C) = {:.2R}", UA0, OutWaterTempAtUA0));
1860 0 : ShowContinueError(
1861 0 : state, format("Calculated water outlet temperature at high UA [C](UA = {:.2R} W/C) = {:.2R}", UA1, OutWaterTempAtUA1));
1862 0 : ShowFatalError(state, format("Autosizing of Evaporative Fluid Cooler UA failed for Evaporative Fluid Cooler = {}", this->Name));
1863 : }
1864 1 : this->HighSpeedEvapFluidCoolerUA = UA;
1865 : } else {
1866 0 : this->HighSpeedEvapFluidCoolerUA = 0.0;
1867 : }
1868 1 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1869 0 : if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_SingleSpd) {
1870 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1871 0 : BaseSizer::reportSizerOutput(state,
1872 : cEvapFluidCooler_SingleSpeed,
1873 : this->Name,
1874 : "U-Factor Times Area Value at Design Air Flow Rate [W/C]",
1875 : this->HighSpeedEvapFluidCoolerUA);
1876 : }
1877 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1878 0 : BaseSizer::reportSizerOutput(state,
1879 : cEvapFluidCooler_SingleSpeed,
1880 : this->Name,
1881 : "Initial U-Factor Times Area Value at Design Air Flow Rate [W/C]",
1882 : this->HighSpeedEvapFluidCoolerUA);
1883 : }
1884 0 : } else if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd) {
1885 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1886 0 : BaseSizer::reportSizerOutput(state,
1887 : cEvapFluidCooler_TwoSpeed,
1888 : this->Name,
1889 : "U-Factor Times Area Value at High Fan Speed [W/C]",
1890 : this->HighSpeedEvapFluidCoolerUA);
1891 : }
1892 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1893 0 : BaseSizer::reportSizerOutput(state,
1894 : cEvapFluidCooler_TwoSpeed,
1895 : this->Name,
1896 : "Initial U-Factor Times Area Value at High Fan Speed [W/C]",
1897 : this->HighSpeedEvapFluidCoolerUA);
1898 : }
1899 : }
1900 : }
1901 : }
1902 :
1903 4 : if (this->LowSpeedAirFlowRateWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1904 0 : this->LowSpeedAirFlowRate = this->LowSpeedAirFlowRateSizingFactor * this->HighSpeedAirFlowRate;
1905 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1906 0 : BaseSizer::reportSizerOutput(
1907 : state, this->EvapFluidCoolerType, this->Name, "Air Flow Rate at Low Fan Speed [m3/s]", this->LowSpeedAirFlowRate);
1908 : }
1909 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1910 0 : BaseSizer::reportSizerOutput(
1911 : state, this->EvapFluidCoolerType, this->Name, "Initial Air Flow Rate at Low Fan Speed [m3/s]", this->LowSpeedAirFlowRate);
1912 : }
1913 : }
1914 :
1915 4 : if (this->LowSpeedFanPowerWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1916 0 : this->LowSpeedFanPower = this->LowSpeedFanPowerSizingFactor * this->HighSpeedFanPower;
1917 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1918 0 : BaseSizer::reportSizerOutput(state, this->EvapFluidCoolerType, this->Name, "Fan Power at Low Fan Speed [W]", this->LowSpeedFanPower);
1919 : }
1920 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1921 0 : BaseSizer::reportSizerOutput(
1922 : state, this->EvapFluidCoolerType, this->Name, "Initial Fan Power at Low Fan Speed [W]", this->LowSpeedFanPower);
1923 : }
1924 : }
1925 :
1926 4 : if (this->LowSpeedEvapFluidCoolerUAWasAutoSized && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1927 0 : this->LowSpeedEvapFluidCoolerUA = this->LowSpeedEvapFluidCoolerUASizingFactor * this->HighSpeedEvapFluidCoolerUA;
1928 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1929 0 : BaseSizer::reportSizerOutput(state,
1930 : this->EvapFluidCoolerType,
1931 : this->Name,
1932 : "U-Factor Times Area Value at Low Fan Speed [W/C]",
1933 : this->LowSpeedEvapFluidCoolerUA);
1934 : }
1935 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1936 0 : BaseSizer::reportSizerOutput(state,
1937 : this->EvapFluidCoolerType,
1938 : this->Name,
1939 : "Initial U-Factor Times Area Value at Low Fan Speed [W/C]",
1940 : this->LowSpeedEvapFluidCoolerUA);
1941 : }
1942 : }
1943 :
1944 4 : if (this->PerformanceInputMethod_Num == PIM::StandardDesignCapacity && this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd) {
1945 0 : if (this->DesignWaterFlowRate >= HVAC::SmallWaterVolFlow && this->LowSpeedStandardDesignCapacity > 0.0) {
1946 : // Standard design capacity doesn't include compressor heat;
1947 : // predefined factor was 1.25 W heat rejection per W of delivered cooling, now user input with default 1.25
1948 0 : Real64 rho = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getDensity(state, Constant::InitConvTemp, CalledFrom);
1949 : Real64 Cp =
1950 0 : state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getSpecificHeat(state, this->DesignEnteringWaterTemp, CalledFrom);
1951 0 : DesEvapFluidCoolerLoad = this->LowSpeedStandardDesignCapacity * this->HeatRejectCapNomCapSizingRatio;
1952 0 : Real64 const par1 = rho * tmpDesignWaterFlowRate; // Design water mass flow rate
1953 0 : Real64 const par2 = this->LowSpeedAirFlowRate; // Air volume flow rate at low fan speed
1954 0 : Real64 UA0 = 0.0001 * DesEvapFluidCoolerLoad; // Assume deltaT = 10000K (limit)
1955 0 : Real64 UA1 = DesEvapFluidCoolerLoad; // Assume deltaT = 1K
1956 0 : this->inletConds.WaterTemp = 35.0; // 95F design inlet water temperature
1957 0 : this->inletConds.AirTemp = 35.0; // 95F design inlet air dry-bulb temp
1958 0 : this->inletConds.AirWetBulb = 25.6; // 78F design inlet air wet-bulb temp
1959 0 : this->inletConds.AirPress = state.dataEnvrn->StdBaroPress;
1960 0 : this->inletConds.AirHumRat =
1961 0 : Psychrometrics::PsyWFnTdbTwbPb(state, this->inletConds.AirTemp, this->inletConds.AirWetBulb, this->inletConds.AirPress);
1962 0 : auto f = [&state, this, DesEvapFluidCoolerLoad, par1, par2, Cp](Real64 UA) {
1963 : Real64 OutWaterTemp; // outlet water temperature [C]
1964 0 : this->SimSimpleEvapFluidCooler(state, par1, par2, UA, OutWaterTemp);
1965 0 : Real64 const CoolingOutput = Cp * par1 * (this->inletConds.WaterTemp - OutWaterTemp);
1966 0 : return (DesEvapFluidCoolerLoad - CoolingOutput) / DesEvapFluidCoolerLoad;
1967 0 : };
1968 0 : General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
1969 0 : if (SolFla == -1) {
1970 0 : ShowWarningError(state, "Iteration limit exceeded in calculating evaporative fluid cooler UA.");
1971 0 : ShowContinueError(state, format("Autosizing of fluid cooler UA failed for evaporative fluid cooler = {}", this->Name));
1972 0 : ShowContinueError(state, format("The final UA value = {:.2R}W/C, and the simulation continues...", UA));
1973 0 : } else if (SolFla == -2) {
1974 0 : ShowSevereError(state, format("{}: The combination of design input values did not allow the calculation of a ", CalledFrom));
1975 0 : ShowContinueError(state, "reasonable low-speed UA value. Review and revise design input values as appropriate. ");
1976 0 : ShowFatalError(state, format("Autosizing of Evaporative Fluid Cooler UA failed for Evaporative Fluid Cooler = {}", this->Name));
1977 : }
1978 0 : this->LowSpeedEvapFluidCoolerUA = UA;
1979 0 : } else {
1980 0 : this->LowSpeedEvapFluidCoolerUA = 0.0;
1981 : }
1982 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
1983 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
1984 0 : BaseSizer::reportSizerOutput(state,
1985 : this->EvapFluidCoolerType,
1986 : this->Name,
1987 : "U-Factor Times Area Value at Low Fan Speed [W/C]",
1988 : this->LowSpeedEvapFluidCoolerUA);
1989 : }
1990 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
1991 0 : BaseSizer::reportSizerOutput(state,
1992 : this->EvapFluidCoolerType,
1993 : this->Name,
1994 : "Initial U-Factor Times Area Value at Low Fan Speed [W/C]",
1995 : this->LowSpeedEvapFluidCoolerUA);
1996 : }
1997 : }
1998 : }
1999 :
2000 4 : if (this->PerformanceInputMethod_Num == PIM::UserSpecifiedDesignCapacity &&
2001 1 : this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd) {
2002 0 : if (this->DesignWaterFlowRate >= HVAC::SmallWaterVolFlow && this->LowSpeedUserSpecifiedDesignCapacity > 0.0) {
2003 0 : Real64 rho = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getDensity(state, Constant::InitConvTemp, CalledFrom);
2004 : Real64 Cp =
2005 0 : state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getSpecificHeat(state, this->DesignEnteringWaterTemp, CalledFrom);
2006 0 : DesEvapFluidCoolerLoad = this->LowSpeedUserSpecifiedDesignCapacity;
2007 0 : Real64 const par1 = rho * tmpDesignWaterFlowRate; // Design water mass flow rate
2008 0 : Real64 const par2 = this->LowSpeedAirFlowRate; // Air volume flow rate at low fan speed
2009 0 : Real64 UA0 = 0.0001 * DesEvapFluidCoolerLoad; // Assume deltaT = 10000K (limit)
2010 0 : Real64 UA1 = DesEvapFluidCoolerLoad; // Assume deltaT = 1K
2011 0 : this->inletConds.WaterTemp = this->DesignEnteringWaterTemp;
2012 0 : this->inletConds.AirTemp = this->DesignEnteringAirTemp;
2013 0 : this->inletConds.AirWetBulb = this->DesignEnteringAirWetBulbTemp;
2014 0 : this->inletConds.AirPress = state.dataEnvrn->StdBaroPress;
2015 0 : this->inletConds.AirHumRat =
2016 0 : Psychrometrics::PsyWFnTdbTwbPb(state, this->inletConds.AirTemp, this->inletConds.AirWetBulb, this->inletConds.AirPress);
2017 0 : auto f = [&state, this, DesEvapFluidCoolerLoad, par1, par2, Cp](Real64 UA) {
2018 : Real64 OutWaterTemp; // outlet water temperature [C]
2019 0 : this->SimSimpleEvapFluidCooler(state, par1, par2, UA, OutWaterTemp);
2020 0 : Real64 const CoolingOutput = Cp * par1 * (this->inletConds.WaterTemp - OutWaterTemp);
2021 0 : return (DesEvapFluidCoolerLoad - CoolingOutput) / DesEvapFluidCoolerLoad;
2022 0 : };
2023 0 : General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
2024 0 : if (SolFla == -1) {
2025 0 : ShowSevereError(state, "Iteration limit exceeded in calculating EvaporativeFluidCooler UA");
2026 0 : ShowFatalError(state, format("Autosizing of EvaporativeFluidCooler UA failed for EvaporativeFluidCooler {}", this->Name));
2027 0 : } else if (SolFla == -2) {
2028 0 : this->SimSimpleEvapFluidCooler(state, par1, par2, UA0, OutWaterTempAtUA0);
2029 0 : this->SimSimpleEvapFluidCooler(state, par1, par2, UA1, OutWaterTempAtUA1);
2030 0 : ShowSevereError(state, format("{}: The combination of design input values did not allow the calculation of a ", CalledFrom));
2031 0 : ShowContinueError(state, "reasonable UA value. Review and revise design input values as appropriate. Specifying hard");
2032 0 : ShowContinueError(
2033 : state,
2034 : R"(sizes for some "autosizable" fields while autosizing other "autosizable" fields may be contributing to this problem.)");
2035 0 : ShowContinueError(state, "This model iterates on UA to find the heat transfer required to provide the design outlet ");
2036 0 : ShowContinueError(state, "water temperature. Initially, the outlet water temperatures at high and low UA values are ");
2037 0 : ShowContinueError(state, "calculated. The Design Exit Water Temperature should be between the outlet water ");
2038 0 : ShowContinueError(state, "temperatures calculated at high and low UA values. If the Design Exit Water Temperature is ");
2039 0 : ShowContinueError(state, "out of this range, the solution will not converge and UA will not be calculated. ");
2040 0 : ShowContinueError(state, "Inputs to the Evaporative Fluid Cooler model are:");
2041 0 : ShowContinueError(state, format("Design Evaporative Fluid Cooler Load = {:.2R}", DesEvapFluidCoolerLoad));
2042 0 : ShowContinueError(state, format("Design Evaporative Fluid Cooler Water Volume Flow Rate = {:.2R}", par1));
2043 0 : ShowContinueError(state, format("Design Evaporative Fluid Cooler Air Volume Flow Rate = {:.2R}", par2));
2044 0 : ShowContinueError(state, format("Design Evaporative Fluid Cooler Air Inlet Wet-bulb Temp = {:.2R}", this->inletConds.AirWetBulb));
2045 0 : ShowContinueError(state, format("Design Evaporative Fluid Cooler Water Inlet Temp = {:.2R}", this->inletConds.WaterTemp));
2046 0 : ShowContinueError(state,
2047 0 : format("Design Exit Water Temp = {:.2R}",
2048 0 : state.dataSize->PlantSizData(PltSizCondNum).ExitTemp));
2049 0 : ShowContinueError(state, format("Design Evaporative Fluid Cooler Water Inlet Temp [C] = {:.2R}", this->inletConds.WaterTemp));
2050 0 : ShowContinueError(state, format("Calculated water outlet temperature at low UA({:.2R}) = {:.2R}", UA0, OutWaterTempAtUA0));
2051 0 : ShowContinueError(state, format("Calculated water outlet temperature at high UA({:.2R}) = {:.2R}", UA1, OutWaterTempAtUA1));
2052 0 : ShowFatalError(state, format("Autosizing of Evaporative Fluid Cooler UA failed for Evaporative Fluid Cooler = {}", this->Name));
2053 : }
2054 0 : this->LowSpeedEvapFluidCoolerUA = UA;
2055 0 : } else {
2056 0 : this->LowSpeedEvapFluidCoolerUA = 0.0;
2057 : }
2058 0 : if (state.dataPlnt->PlantFirstSizesOkayToFinalize) {
2059 0 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
2060 0 : BaseSizer::reportSizerOutput(state,
2061 : this->EvapFluidCoolerType,
2062 : this->Name,
2063 : "U-Factor Times Area Value at Low Fan Speed [W/C]",
2064 : this->LowSpeedEvapFluidCoolerUA);
2065 : }
2066 0 : if (state.dataPlnt->PlantFirstSizesOkayToReport) {
2067 0 : BaseSizer::reportSizerOutput(state,
2068 : this->EvapFluidCoolerType,
2069 : this->Name,
2070 : "Initial U-Factor Times Area Value at Low Fan Speed [W/C]",
2071 : this->LowSpeedEvapFluidCoolerUA);
2072 : }
2073 : }
2074 : }
2075 :
2076 4 : if (state.dataPlnt->PlantFinalSizesOkayToReport) {
2077 : // create predefined report
2078 0 : std::string equipName = this->Name;
2079 0 : OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchMechType, equipName, this->EvapFluidCoolerType);
2080 0 : OutputReportPredefined::PreDefTableEntry(
2081 0 : state, state.dataOutRptPredefined->pdchMechNomCap, equipName, this->HighSpeedStandardDesignCapacity);
2082 0 : }
2083 4 : }
2084 :
2085 1 : void EvapFluidCoolerSpecs::CalcSingleSpeedEvapFluidCooler(EnergyPlusData &state)
2086 : {
2087 :
2088 : // SUBROUTINE INFORMATION:
2089 : // AUTHOR Chandan Sharma
2090 : // DATE WRITTEN May 2009
2091 : // MODIFIED na
2092 : // RE-ENGINEERED na
2093 :
2094 : // PURPOSE OF THIS SUBROUTINE:
2095 : // To simulate the operation of a single-speed fan evaporative fluid cooler.
2096 :
2097 : // METHODOLOGY EMPLOYED:
2098 : // The evaporative fluid cooler is modeled using effectiveness-NTU relationships for
2099 : // counterflow heat exchangers based on Merkel's theory.
2100 : // The subroutine calculates the period of time required to meet a
2101 : // leaving water temperature setpoint. It assumes that part-load
2102 : // operation represents a linear interpolation of two steady-state regimes.
2103 : // Cyclic losses are neglected. The period of time required to meet the
2104 : // leaving water temperature setpoint is used to determine the required
2105 : // fan power and energy.
2106 : // A RunFlag is passed by the upper level manager to indicate the ON/OFF status,
2107 : // or schedule, of the evaporative fluid cooler. If the evaporative fluid cooler is OFF, outlet water
2108 : // temperature and flow rate are passed through the model from inlet node to
2109 : // outlet node without intervention. Reports are also updated with fan power and energy being zero.
2110 : // When the RunFlag indicates an ON condition for the evaporative fluid cooler, the
2111 : // mass flow rate and water temperature are read from the inlet node of the
2112 : // evaporative fluid cooler (water-side). The outdoor air wet-bulb temperature is used
2113 : // as the entering condition to the evaporative fluid cooler (air-side).
2114 : // The evaporative fluid cooler fan is turned on and design parameters are used
2115 : // to calculate the leaving water temperature.
2116 : // If the calculated leaving water temperature is below the setpoint, a fan
2117 : // run-time fraction is calculated and used to determine fan power. The leaving
2118 : // water temperature setpoint is placed on the outlet node. If the calculated
2119 : // leaving water temperature is at or above the setpoint, the calculated
2120 : // leaving water temperature is placed on the outlet node and the fan runs at
2121 : // full power. Water mass flow rate is passed from inlet node to outlet node
2122 : // with no intervention.
2123 : // REFERENCES:
2124 : // ASHRAE HVAC1KIT: A Toolkit for Primary HVAC System Energy Calculation. 1999.
2125 :
2126 : // Based on SingleSpeedTower subroutine by Dan Fisher ,Sept 1998
2127 : // Dec. 2008. BG. added RunFlag logic per original methodology
2128 :
2129 : static constexpr std::string_view RoutineName("CalcSingleSpeedEvapFluidCooler");
2130 1 : int constexpr MaxIteration(100); // Maximum fluid bypass iteration calculations
2131 1 : std::string const MaxItChar("100");
2132 1 : Real64 constexpr BypassFractionThreshold(0.01); // Threshold to stop bypass iteration
2133 1 : Real64 constexpr OWTLowerLimit(0.0); // The limit of evaporative fluid cooler exit fluid temperature used
2134 : // in the fluid bypass calculation to avoid fluid freezing. For water,
2135 : // it is 0 degreeC and for glycols, it can be much lower. The fluid type
2136 : // is stored at the loop. Current choices are Water and Steam,
2137 : // needs to expand for glycols
2138 :
2139 : Real64 AirFlowRate;
2140 1 : Real64 UAdesign = 0.0; // UA value at design conditions (entered by user or calculated)
2141 : Real64 CpWater;
2142 1 : Real64 TempSetPoint = 0.0;
2143 :
2144 : // set inlet and outlet nodes
2145 1 : this->WaterInletNode = this->WaterInletNodeNum;
2146 1 : this->WaterOutletNode = this->WaterOutletNodeNum;
2147 1 : this->Qactual = 0.0;
2148 1 : this->FanPower = 0.0;
2149 1 : Real64 inletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNode).Temp;
2150 1 : this->OutletWaterTemp = inletWaterTemp;
2151 1 : AirFlowRate = 0.0;
2152 :
2153 1 : auto const &loopSide = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopSide(this->plantLoc.loopSideNum);
2154 1 : DataPlant::LoopDemandCalcScheme calcScheme = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopDemandCalcScheme;
2155 1 : if (calcScheme == DataPlant::LoopDemandCalcScheme::SingleSetPoint) {
2156 1 : TempSetPoint = loopSide.TempSetPoint;
2157 0 : } else if (calcScheme == DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand) {
2158 0 : TempSetPoint = loopSide.TempSetPointHi;
2159 : }
2160 :
2161 : // Added for fluid bypass. First assume no fluid bypass
2162 1 : int BypassFlag = 0;
2163 1 : this->BypassFraction = 0.0;
2164 :
2165 : // MassFlowTol is a parameter to indicate a no flow condition
2166 2 : if (this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance ||
2167 1 : state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopSide(this->plantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Unlocked) {
2168 1 : return;
2169 : }
2170 :
2171 0 : if (inletWaterTemp > TempSetPoint) {
2172 : // Turn on evaporative fluid cooler fan
2173 0 : UAdesign = this->HighSpeedEvapFluidCoolerUA;
2174 0 : AirFlowRate = this->HighSpeedAirFlowRate;
2175 0 : Real64 FanPowerOn = this->HighSpeedFanPower;
2176 :
2177 0 : this->SimSimpleEvapFluidCooler(state, this->WaterMassFlowRate, AirFlowRate, UAdesign, this->OutletWaterTemp);
2178 :
2179 0 : if (this->OutletWaterTemp <= TempSetPoint) {
2180 0 : if (this->capacityControl == CapacityControl::FanCycling || this->OutletWaterTemp <= OWTLowerLimit) {
2181 : // Setpoint was met with pump ON and fan ON, calculate run-time fraction
2182 0 : Real64 FanModeFrac = (TempSetPoint - inletWaterTemp) / (this->OutletWaterTemp - inletWaterTemp);
2183 0 : this->FanPower = FanModeFrac * FanPowerOn;
2184 0 : this->OutletWaterTemp = TempSetPoint;
2185 0 : } else {
2186 : // FluidBypass, fan runs at full speed for the entire time step
2187 : // FanModeFrac = 1.0;
2188 0 : this->FanPower = FanPowerOn;
2189 0 : BypassFlag = 1;
2190 : }
2191 : } else {
2192 : // Setpoint was not met, evaporative fluid cooler ran at full capacity
2193 : // FanModeFrac = 1.0;
2194 0 : this->FanPower = FanPowerOn;
2195 : }
2196 : } else {
2197 : // Inlet water temperature lower than setpoint, assume 100% bypass, evaporative fluid cooler fan off
2198 0 : if (this->capacityControl == CapacityControl::FluidBypass) {
2199 0 : if (inletWaterTemp > OWTLowerLimit) {
2200 0 : this->FanPower = 0.0;
2201 0 : this->BypassFraction = 1.0;
2202 0 : this->OutletWaterTemp = inletWaterTemp;
2203 : }
2204 : }
2205 : }
2206 :
2207 : // Calculate bypass fraction since OWTLowerLimit < OutletWaterTemp < TempSetPoint.
2208 : // The iteration ends when the number of iteration exceeds the limit or the difference
2209 : // between the new and old bypass fractions is less than the threshold.
2210 0 : if (BypassFlag == 1) {
2211 0 : Real64 bypassFraction = (TempSetPoint - this->OutletWaterTemp) / (inletWaterTemp - this->OutletWaterTemp);
2212 0 : if (bypassFraction > 1.0 || bypassFraction < 0.0) {
2213 : // Bypass cannot meet setpoint, assume no bypass
2214 0 : this->BypassFraction = 0.0;
2215 0 : AirFlowRate = 0.0;
2216 : } else {
2217 0 : int NumIteration = 0;
2218 0 : Real64 BypassFraction2 = 0.0; // Fluid bypass fraction
2219 0 : Real64 BypassFractionPrev = bypassFraction;
2220 0 : Real64 OutletWaterTempPrev = this->OutletWaterTemp;
2221 0 : while (NumIteration < MaxIteration) {
2222 0 : ++NumIteration;
2223 : // need to iterate for the new OutletWaterTemp while bypassing evaporative fluid cooler water
2224 0 : this->SimSimpleEvapFluidCooler(
2225 0 : state, this->WaterMassFlowRate * (1.0 - bypassFraction), AirFlowRate, UAdesign, this->OutletWaterTemp);
2226 : // Calc new bypassFraction based on the new OutletWaterTemp
2227 0 : if (std::abs(this->OutletWaterTemp - OWTLowerLimit) <= 0.01) {
2228 0 : BypassFraction2 = bypassFraction;
2229 0 : break;
2230 0 : } else if (this->OutletWaterTemp < OWTLowerLimit) {
2231 : // Set OutletWaterTemp = OWTLowerLimit, and use linear interpolation to calculate the bypassFraction
2232 0 : BypassFraction2 = BypassFractionPrev - (BypassFractionPrev - bypassFraction) * (OutletWaterTempPrev - OWTLowerLimit) /
2233 0 : (OutletWaterTempPrev - this->OutletWaterTemp);
2234 0 : this->SimSimpleEvapFluidCooler(
2235 0 : state, this->WaterMassFlowRate * (1.0 - BypassFraction2), AirFlowRate, UAdesign, this->OutletWaterTemp);
2236 0 : if (this->OutletWaterTemp < OWTLowerLimit) {
2237 : // Use previous iteration values
2238 0 : BypassFraction2 = BypassFractionPrev;
2239 0 : this->OutletWaterTemp = OutletWaterTempPrev;
2240 : }
2241 0 : break;
2242 : } else {
2243 0 : BypassFraction2 = (TempSetPoint - this->OutletWaterTemp) / (inletWaterTemp - this->OutletWaterTemp);
2244 : }
2245 : // Compare two bypassFraction to determine when to stop
2246 0 : if (std::abs(BypassFraction2 - bypassFraction) <= BypassFractionThreshold) {
2247 0 : break;
2248 : }
2249 0 : BypassFractionPrev = bypassFraction;
2250 0 : OutletWaterTempPrev = this->OutletWaterTemp;
2251 0 : bypassFraction = BypassFraction2;
2252 : }
2253 0 : if (NumIteration > MaxIteration) {
2254 0 : ShowWarningError(
2255 0 : state, format("Evaporative fluid cooler fluid bypass iteration exceeds maximum limit of {} for {}", MaxItChar, this->Name));
2256 : }
2257 0 : this->BypassFraction = BypassFraction2;
2258 : // may not meet TempSetPoint due to limit of evaporative fluid cooler outlet temp to OWTLowerLimit
2259 0 : this->OutletWaterTemp = (1.0 - BypassFraction2) * this->OutletWaterTemp + BypassFraction2 * inletWaterTemp;
2260 : }
2261 : }
2262 :
2263 : // Should this be water inlet node num?????
2264 0 : CpWater = state.dataPlnt->PlantLoop(this->plantLoc.loopNum)
2265 0 : .glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->WaterInletNode).Temp, RoutineName);
2266 0 : this->Qactual = this->WaterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNode).Temp - this->OutletWaterTemp);
2267 0 : this->AirFlowRateRatio = AirFlowRate / this->HighSpeedAirFlowRate;
2268 1 : }
2269 :
2270 1 : void EvapFluidCoolerSpecs::CalcTwoSpeedEvapFluidCooler(EnergyPlusData &state)
2271 : {
2272 :
2273 : // SUBROUTINE INFORMATION:
2274 : // AUTHOR Chandan Sharma
2275 : // DATE WRITTEN May 2009
2276 : // MODIFIED na
2277 : // RE-ENGINEERED na
2278 :
2279 : // PURPOSE OF THIS SUBROUTINE:
2280 : // To simulate the operation of a evaporative fluid cooler with a two-speed fan.
2281 :
2282 : // METHODOLOGY EMPLOYED:
2283 : // The evaporative fluid cooler is modeled using effectiveness-NTU relationships for
2284 : // counterflow heat exchangers based on Merkel's theory.
2285 : // The subroutine calculates the period of time required to meet a
2286 : // leaving water temperature setpoint. It assumes that part-load
2287 : // operation represents a linear interpolation of three steady-state regimes
2288 : // (high-speed fan operation and low-speed fan operation ).
2289 : // Cyclic losses are neglected. The period of time required to meet the
2290 : // leaving water temperature setpoint is used to determine the required
2291 : // fan power and energy. When the leaving water temperature is at or above the setpoint
2292 : // the evaporative fluid cooler fan is turned on,
2293 : // .
2294 : // A RunFlag is passed by the upper level manager to indicate the ON/OFF status,
2295 : // or schedule, of the evaporative fluid cooler. If the evaporative fluid cooler is OFF, outlet water
2296 : // temperature and flow rate are passed through the model from inlet node to
2297 : // outlet node without intervention. Reports are also updated with fan power and fan energy being zero.
2298 : // When the RunFlag indicates an ON condition for the evaporative fluid cooler, the
2299 : // mass flow rate and water temperature are read from the inlet node of the
2300 : // evaporative fluid cooler (water-side). The outdoor air wet-bulb temperature is used
2301 : // as the entering condition to the evaporative fluid cooler (air-side). If the incoming
2302 : // water temperature is above the setpoint, the evaporative fluid cooler fan is turned on
2303 : // and parameters for low fan speed are used to again calculate the leaving
2304 : // water temperature. If the calculated leaving water temperature is
2305 : // below the setpoint, a fan run-time fraction (FanModeFrac) is calculated and
2306 : // used to determine fan power. The leaving water temperature setpoint is placed
2307 : // on the outlet node. If the calculated leaving water temperature is at or above
2308 : // the setpoint, the evaporative fluid cooler fan is turned on 'high speed' and the routine is
2309 : // repeated. If the calculated leaving water temperature is below the setpoint,
2310 : // a fan run-time fraction is calculated for the second stage fan and fan power
2311 : // is calculated as FanModeFrac*HighSpeedFanPower+(1-FanModeFrac)*LowSpeedFanPower.
2312 : // If the calculated leaving water temperature is above the leaving water temp.
2313 : // setpoint, the calculated leaving water temperature is placed on the outlet
2314 : // node and the fan runs at full power (High Speed Fan Power). Water mass flow
2315 : // rate is passed from inlet node to outlet node with no intervention.
2316 : // REFERENCES:
2317 : // ASHRAE HVAC1KIT: A Toolkit for Primary HVAC System Energy Calculation. 1999.
2318 : // Based on TwoSpeedTower by Dan Fisher ,Sept. 1998
2319 : // Dec. 2008. BG. added RunFlag logic per original methodology
2320 :
2321 : static constexpr std::string_view RoutineName("CalcTwoSpeedEvapFluidCooler");
2322 :
2323 1 : this->WaterInletNode = this->WaterInletNodeNum;
2324 1 : this->WaterOutletNode = this->WaterOutletNodeNum;
2325 1 : this->Qactual = 0.0;
2326 1 : this->FanPower = 0.0;
2327 1 : this->InletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNode).Temp;
2328 1 : this->OutletWaterTemp = this->InletWaterTemp;
2329 :
2330 1 : Real64 OutletWaterTemp1stStage = this->OutletWaterTemp;
2331 1 : Real64 OutletWaterTemp2ndStage = this->OutletWaterTemp;
2332 1 : Real64 AirFlowRate = 0.0;
2333 1 : Real64 TempSetPoint = 0.0;
2334 1 : switch (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopDemandCalcScheme) {
2335 1 : case DataPlant::LoopDemandCalcScheme::SingleSetPoint: {
2336 1 : TempSetPoint = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopSide(this->plantLoc.loopSideNum).TempSetPoint;
2337 1 : } break;
2338 0 : case DataPlant::LoopDemandCalcScheme::DualSetPointDeadBand: {
2339 0 : TempSetPoint = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopSide(this->plantLoc.loopSideNum).TempSetPointHi;
2340 0 : } break;
2341 0 : default:
2342 0 : break;
2343 : }
2344 :
2345 : // MassFlowTol is a parameter to indicate a no flow condition
2346 2 : if (this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance ||
2347 1 : state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopSide(this->plantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Unlocked) {
2348 1 : return;
2349 : }
2350 :
2351 0 : if (this->InletWaterTemp > TempSetPoint) {
2352 : // Setpoint was not met ,turn on evaporative fluid cooler 1st stage fan
2353 0 : Real64 UAdesign = this->LowSpeedEvapFluidCoolerUA;
2354 0 : AirFlowRate = this->LowSpeedAirFlowRate;
2355 0 : Real64 FanPowerLow = this->LowSpeedFanPower;
2356 : Real64 FanPowerHigh;
2357 0 : this->SimSimpleEvapFluidCooler(state, this->WaterMassFlowRate, AirFlowRate, UAdesign, OutletWaterTemp1stStage);
2358 :
2359 0 : if (OutletWaterTemp1stStage <= TempSetPoint) {
2360 : // Setpoint was met with pump ON and fan ON 1st stage, calculate fan mode fraction
2361 0 : Real64 FanModeFrac = (TempSetPoint - this->InletWaterTemp) / (OutletWaterTemp1stStage - this->InletWaterTemp);
2362 0 : this->FanPower = FanModeFrac * FanPowerLow;
2363 0 : this->OutletWaterTemp = TempSetPoint;
2364 0 : this->Qactual *= FanModeFrac;
2365 : } else {
2366 : // Setpoint was not met, turn on evaporative fluid cooler 2nd stage fan
2367 0 : UAdesign = this->HighSpeedEvapFluidCoolerUA;
2368 0 : AirFlowRate = this->HighSpeedAirFlowRate;
2369 0 : FanPowerHigh = this->HighSpeedFanPower;
2370 :
2371 0 : this->SimSimpleEvapFluidCooler(state, this->WaterMassFlowRate, AirFlowRate, UAdesign, OutletWaterTemp2ndStage);
2372 :
2373 0 : if ((OutletWaterTemp2ndStage <= TempSetPoint) && UAdesign > 0.0) {
2374 : // Setpoint was met with pump ON and fan ON 2nd stage, calculate fan mode fraction
2375 0 : Real64 FanModeFrac = (TempSetPoint - OutletWaterTemp1stStage) / (OutletWaterTemp2ndStage - OutletWaterTemp1stStage);
2376 0 : this->FanPower = (FanModeFrac * FanPowerHigh) + (1.0 - FanModeFrac) * FanPowerLow;
2377 0 : this->OutletWaterTemp = TempSetPoint;
2378 0 : } else {
2379 : // Setpoint was not met, evaporative fluid cooler ran at full capacity
2380 0 : this->OutletWaterTemp = OutletWaterTemp2ndStage;
2381 0 : this->FanPower = FanPowerHigh;
2382 : }
2383 : }
2384 : }
2385 :
2386 : // Should this be water inlet node num??
2387 0 : Real64 CpWater = state.dataPlnt->PlantLoop(this->plantLoc.loopNum)
2388 0 : .glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->WaterInletNode).Temp, RoutineName);
2389 0 : this->Qactual = this->WaterMassFlowRate * CpWater * (state.dataLoopNodes->Node(this->WaterInletNode).Temp - this->OutletWaterTemp);
2390 0 : this->AirFlowRateRatio = AirFlowRate / this->HighSpeedAirFlowRate;
2391 : }
2392 :
2393 19 : void EvapFluidCoolerSpecs::SimSimpleEvapFluidCooler(
2394 : EnergyPlusData &state, Real64 const waterMassFlowRate, Real64 const AirFlowRate, Real64 const UAdesign, Real64 &outletWaterTemp)
2395 : {
2396 :
2397 : // SUBROUTINE INFORMATION:
2398 : // AUTHOR Chandan Sharma
2399 : // DATE WRITTEN May 2009
2400 : // MODIFIED na
2401 : // RE-ENGINEERED na
2402 :
2403 : // PURPOSE OF THIS SUBROUTINE:
2404 : // See purpose for single speed or Two speed evaporative fluid cooler model
2405 :
2406 : // METHODOLOGY EMPLOYED:
2407 : // See methodology for single speed or two speed evaporative fluid cooler model
2408 :
2409 : // REFERENCES:
2410 : // Based on SimTower subroutine by Dan Fisher Sept. 1998
2411 : // Merkel, F. 1925. Verduftungskuhlung. VDI Forschungsarbeiten, Nr 275, Berlin.
2412 : // ASHRAE 1999. HVAC1KIT: A Toolkit for Primary HVAC System Energy Calculations.
2413 :
2414 19 : int constexpr IterMax(50); // Maximum number of iterations allowed
2415 19 : Real64 constexpr WetBulbTolerance(0.00001); // Maximum error for exiting wet-bulb temperature between iterations
2416 19 : Real64 constexpr DeltaTwbTolerance(0.001); // Maximum error (tolerance) in DeltaTwb for iteration convergence [C]
2417 : static constexpr std::string_view RoutineName("SimSimpleEvapFluidCooler");
2418 :
2419 19 : this->WaterInletNode = this->WaterInletNodeNum;
2420 19 : this->WaterOutletNode = this->WaterOutletNodeNum;
2421 19 : Real64 qActual = 0.0;
2422 19 : Real64 WetBulbError = 1.0;
2423 19 : Real64 DeltaTwb = 1.0;
2424 :
2425 : // set local evaporative fluid cooler inlet and outlet temperature variables
2426 19 : this->InletWaterTemp = this->inletConds.WaterTemp;
2427 19 : outletWaterTemp = this->InletWaterTemp;
2428 19 : Real64 InletAirTemp = this->inletConds.AirTemp;
2429 19 : Real64 InletAirWetBulb = this->inletConds.AirWetBulb;
2430 :
2431 19 : if (UAdesign == 0.0) {
2432 0 : return;
2433 : }
2434 :
2435 : // set water and air properties
2436 19 : Real64 AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state, this->inletConds.AirPress, InletAirTemp, this->inletConds.AirHumRat);
2437 19 : Real64 AirMassFlowRate = AirFlowRate * AirDensity;
2438 19 : Real64 CpAir = Psychrometrics::PsyCpAirFnW(this->inletConds.AirHumRat);
2439 19 : Real64 CpWater = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getSpecificHeat(state, this->InletWaterTemp, RoutineName);
2440 19 : Real64 InletAirEnthalpy = Psychrometrics::PsyHFnTdbRhPb(state, InletAirWetBulb, 1.0, this->inletConds.AirPress);
2441 :
2442 : // initialize exiting wet bulb temperature before iterating on final solution
2443 19 : Real64 OutletAirWetBulb = InletAirWetBulb + 6.0;
2444 :
2445 : // Calculate mass flow rates
2446 19 : Real64 MdotCpWater = waterMassFlowRate * CpWater;
2447 19 : int Iter = 0;
2448 95 : while ((WetBulbError > WetBulbTolerance) && (Iter <= IterMax) && (DeltaTwb > DeltaTwbTolerance)) {
2449 76 : ++Iter;
2450 76 : Real64 OutletAirEnthalpy = Psychrometrics::PsyHFnTdbRhPb(state, OutletAirWetBulb, 1.0, this->inletConds.AirPress);
2451 : // calculate the airside specific heat and capacity
2452 76 : Real64 CpAirside = (OutletAirEnthalpy - InletAirEnthalpy) / (OutletAirWetBulb - InletAirWetBulb);
2453 76 : Real64 AirCapacity = AirMassFlowRate * CpAirside;
2454 : // calculate the minimum to maximum capacity ratios of airside and waterside
2455 76 : Real64 CapacityRatioMin = min(AirCapacity, MdotCpWater);
2456 76 : Real64 CapacityRatioMax = max(AirCapacity, MdotCpWater);
2457 76 : Real64 CapacityRatio = CapacityRatioMin / CapacityRatioMax;
2458 : // Calculate heat transfer coefficient and number of transfer units (NTU)
2459 76 : Real64 UAactual = UAdesign * CpAirside / CpAir;
2460 76 : Real64 NumTransferUnits = UAactual / CapacityRatioMin;
2461 : // calculate heat exchanger effectiveness
2462 : Real64 effectiveness;
2463 76 : if (CapacityRatio <= 0.995) {
2464 76 : effectiveness = (1.0 - std::exp(-1.0 * NumTransferUnits * (1.0 - CapacityRatio))) /
2465 76 : (1.0 - CapacityRatio * std::exp(-1.0 * NumTransferUnits * (1.0 - CapacityRatio)));
2466 : } else {
2467 0 : effectiveness = NumTransferUnits / (1.0 + NumTransferUnits);
2468 : }
2469 : // calculate water to air heat transfer and store last exiting WB temp of air
2470 76 : qActual = effectiveness * CapacityRatioMin * (this->InletWaterTemp - InletAirWetBulb);
2471 76 : Real64 OutletAirWetBulbLast = OutletAirWetBulb;
2472 : // calculate new exiting wet bulb temperature of airstream
2473 76 : OutletAirWetBulb = InletAirWetBulb + qActual / AirCapacity;
2474 : // Check error tolerance and exit if satisfied
2475 76 : DeltaTwb = std::abs(OutletAirWetBulb - InletAirWetBulb);
2476 : // Add Constant::Kelvin() to denominator below convert OutletAirWetBulbLast to Kelvin to avoid divide by zero.
2477 : // Wet bulb error units are delta K/K
2478 76 : WetBulbError = std::abs((OutletAirWetBulb - OutletAirWetBulbLast) / (OutletAirWetBulbLast + Constant::Kelvin));
2479 : }
2480 :
2481 19 : if (qActual >= 0.0) {
2482 19 : outletWaterTemp = this->InletWaterTemp - qActual / MdotCpWater;
2483 : } else {
2484 0 : outletWaterTemp = this->InletWaterTemp;
2485 : }
2486 : }
2487 :
2488 2 : void EvapFluidCoolerSpecs::CalculateWaterUsage(EnergyPlusData &state)
2489 : {
2490 :
2491 : // SUBROUTINE INFORMATION:
2492 : // AUTHOR Chandan Sharma
2493 : // DATE WRITTEN May 2009
2494 : // MODIFIED na
2495 : // RE-ENGINEERED na
2496 :
2497 : // PURPOSE OF THIS SUBROUTINE:
2498 : // Collect evaporative fluid cooler water usage calculations for
2499 : // reuse by all the evaporative fluid cooler models.
2500 :
2501 : // REFERENCES:
2502 : // Based on CalculateWaterUsage subroutine for cooling tower by B. Griffith, August 2006
2503 :
2504 : static constexpr std::string_view RoutineName("CalculateWaterUsage");
2505 :
2506 2 : this->BlowdownVdot = 0.0;
2507 2 : this->EvaporationVdot = 0.0;
2508 :
2509 2 : Real64 AverageWaterTemp = (this->InletWaterTemp + this->OutletWaterTemp) / 2.0;
2510 :
2511 : // Set water and air properties
2512 2 : if (this->EvapLossMode == EvapLoss::ByMoistTheory) {
2513 :
2514 : Real64 AirDensity =
2515 2 : Psychrometrics::PsyRhoAirFnPbTdbW(state, this->inletConds.AirPress, this->inletConds.AirTemp, this->inletConds.AirHumRat);
2516 2 : Real64 AirMassFlowRate = this->AirFlowRateRatio * this->HighSpeedAirFlowRate * AirDensity;
2517 2 : Real64 InletAirEnthalpy = Psychrometrics::PsyHFnTdbRhPb(state, this->inletConds.AirWetBulb, 1.0, this->inletConds.AirPress);
2518 :
2519 2 : if (AirMassFlowRate > 0.0) {
2520 : // Calculate outlet air conditions for determining water usage
2521 :
2522 0 : Real64 OutletAirEnthalpy = InletAirEnthalpy + this->Qactual / AirMassFlowRate;
2523 0 : Real64 OutletAirTSat = Psychrometrics::PsyTsatFnHPb(state, OutletAirEnthalpy, this->inletConds.AirPress);
2524 0 : Real64 OutletAirHumRatSat = Psychrometrics::PsyWFnTdbH(state, OutletAirTSat, OutletAirEnthalpy);
2525 :
2526 : // calculate specific humidity ratios (HUMRAT to mass of moist air not dry air)
2527 0 : Real64 InSpecificHumRat = this->inletConds.AirHumRat / (1 + this->inletConds.AirHumRat);
2528 0 : Real64 OutSpecificHumRat = OutletAirHumRatSat / (1 + OutletAirHumRatSat);
2529 :
2530 : // calculate average air temp for density call
2531 0 : Real64 TairAvg = (this->inletConds.AirTemp + OutletAirTSat) / 2.0;
2532 :
2533 : // Amount of water evaporated
2534 0 : Real64 rho = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getDensity(state, TairAvg, RoutineName);
2535 0 : this->EvaporationVdot = (AirMassFlowRate * (OutSpecificHumRat - InSpecificHumRat)) / rho; // [m3/s]
2536 0 : if (this->EvaporationVdot < 0.0) {
2537 0 : this->EvaporationVdot = 0.0;
2538 : }
2539 : } else {
2540 2 : this->EvaporationVdot = 0.0;
2541 : }
2542 :
2543 0 : } else if (this->EvapLossMode == EvapLoss::ByUserFactor) {
2544 0 : Real64 rho = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).glycol->getDensity(state, AverageWaterTemp, RoutineName);
2545 0 : this->EvaporationVdot = this->UserEvapLossFactor * (this->InletWaterTemp - this->OutletWaterTemp) * (this->WaterMassFlowRate / rho);
2546 0 : if (this->EvaporationVdot < 0.0) {
2547 0 : this->EvaporationVdot = 0.0;
2548 : }
2549 : } else {
2550 : // should never come here
2551 : }
2552 :
2553 : // amount of water lost due to drift
2554 2 : this->DriftVdot = this->DesignSprayWaterFlowRate * this->DriftLossFraction * this->AirFlowRateRatio;
2555 :
2556 2 : if (this->BlowdownMode == Blowdown::BySchedule) {
2557 : // Amount of water lost due to blow down (purging contaminants from evaporative fluid cooler basin)
2558 0 : this->BlowdownVdot = (this->blowdownSched != nullptr) ? this->blowdownSched->getCurrentVal() : 0.0;
2559 2 : } else if (this->BlowdownMode == Blowdown::ByConcentration) {
2560 2 : if (this->ConcentrationRatio > 2.0) { // protect divide by zero
2561 2 : this->BlowdownVdot = this->EvaporationVdot / (this->ConcentrationRatio - 1) - this->DriftVdot;
2562 : } else {
2563 0 : this->BlowdownVdot = this->EvaporationVdot - this->DriftVdot;
2564 : }
2565 2 : if (this->BlowdownVdot < 0.0) {
2566 0 : this->BlowdownVdot = 0.0;
2567 : }
2568 : } else {
2569 : // should never come here
2570 : }
2571 :
2572 : // Added for fluid bypass
2573 2 : if (this->capacityControl == CapacityControl::FluidBypass) {
2574 0 : if (this->EvapLossMode == EvapLoss::ByUserFactor) {
2575 0 : this->EvaporationVdot *= (1 - this->BypassFraction);
2576 : }
2577 0 : this->DriftVdot *= (1 - this->BypassFraction);
2578 0 : this->BlowdownVdot *= (1 - this->BypassFraction);
2579 : }
2580 :
2581 2 : this->MakeUpVdot = this->EvaporationVdot + this->DriftVdot + this->BlowdownVdot;
2582 :
2583 : // set demand request in Water Storage if needed
2584 2 : this->StarvedMakeUpVdot = 0.0;
2585 2 : this->TankSupplyVdot = 0.0;
2586 2 : if (this->SuppliedByWaterSystem) {
2587 :
2588 : // set demand request
2589 0 : state.dataWaterData->WaterStorage(this->WaterTankID).VdotRequestDemand(this->WaterTankDemandARRID) = this->MakeUpVdot;
2590 :
2591 0 : Real64 AvailTankVdot = state.dataWaterData->WaterStorage(this->WaterTankID)
2592 0 : .VdotAvailDemand(this->WaterTankDemandARRID); // check what tank can currently provide
2593 :
2594 0 : this->TankSupplyVdot = this->MakeUpVdot; // init
2595 0 : if (AvailTankVdot < this->MakeUpVdot) { // calculate starved flow
2596 0 : this->StarvedMakeUpVdot = this->MakeUpVdot - AvailTankVdot;
2597 0 : this->TankSupplyVdot = AvailTankVdot;
2598 : }
2599 : } else { // supplied by mains
2600 : }
2601 :
2602 : // total water usage
2603 : // update report variables
2604 2 : this->EvaporationVol = this->EvaporationVdot * (state.dataHVACGlobal->TimeStepSysSec);
2605 2 : this->DriftVol = this->DriftVdot * (state.dataHVACGlobal->TimeStepSysSec);
2606 2 : this->BlowdownVol = this->BlowdownVdot * (state.dataHVACGlobal->TimeStepSysSec);
2607 2 : this->MakeUpVol = this->MakeUpVdot * (state.dataHVACGlobal->TimeStepSysSec);
2608 2 : this->TankSupplyVol = this->TankSupplyVdot * (state.dataHVACGlobal->TimeStepSysSec);
2609 2 : this->StarvedMakeUpVol = this->StarvedMakeUpVdot * (state.dataHVACGlobal->TimeStepSysSec);
2610 2 : }
2611 :
2612 2 : void EvapFluidCoolerSpecs::UpdateEvapFluidCooler(EnergyPlusData &state)
2613 : {
2614 :
2615 : // SUBROUTINE INFORMATION:
2616 : // AUTHOR: Chandan Sharma
2617 : // DATE WRITTEN: May 2009
2618 :
2619 : // PURPOSE OF THIS SUBROUTINE:
2620 : // This subroutine is for passing results to the outlet water node.
2621 :
2622 2 : Real64 constexpr TempAllowance(0.02); // Minimum difference b/w fluid cooler water outlet temp and
2623 :
2624 2 : state.dataLoopNodes->Node(this->WaterOutletNode).Temp = this->OutletWaterTemp;
2625 :
2626 2 : if (state.dataPlnt->PlantLoop(this->plantLoc.loopNum).LoopSide(this->plantLoc.loopSideNum).FlowLock == DataPlant::FlowLock::Unlocked ||
2627 0 : state.dataGlobal->WarmupFlag) {
2628 2 : return;
2629 : }
2630 :
2631 : // Check flow rate through evaporative fluid cooler and compare to design flow rate,
2632 : // show warning if greater than Design * Multiplier
2633 0 : if (state.dataLoopNodes->Node(this->WaterOutletNode).MassFlowRate >
2634 0 : this->DesWaterMassFlowRate * this->EvapFluidCoolerMassFlowRateMultiplier) {
2635 0 : ++this->HighMassFlowErrorCount;
2636 0 : if (this->HighMassFlowErrorCount < 2) {
2637 0 : ShowWarningError(state, format("{} \"{}\"", this->EvapFluidCoolerType, this->Name));
2638 0 : ShowContinueError(state, " Condenser Loop Mass Flow Rate is much greater than the evaporative fluid coolers design mass flow rate.");
2639 0 : ShowContinueError(state,
2640 0 : format(" Condenser Loop Mass Flow Rate = {:.6T}", state.dataLoopNodes->Node(this->WaterOutletNode).MassFlowRate));
2641 0 : ShowContinueError(state, format(" Evaporative Fluid Cooler Design Mass Flow Rate = {:.6T}", this->DesWaterMassFlowRate));
2642 0 : ShowContinueErrorTimeStamp(state, "");
2643 : } else {
2644 0 : ShowRecurringWarningErrorAtEnd(
2645 : state,
2646 0 : this->EvapFluidCoolerType + " \"" + this->Name +
2647 : "\" Condenser Loop Mass Flow Rate is much greater than the evaporative fluid coolers design mass flow rate error",
2648 0 : this->HighMassFlowErrorIndex,
2649 0 : state.dataLoopNodes->Node(this->WaterOutletNode).MassFlowRate,
2650 0 : state.dataLoopNodes->Node(this->WaterOutletNode).MassFlowRate);
2651 : }
2652 : }
2653 :
2654 : // Check if OutletWaterTemp is below the minimum condenser loop temp and warn user
2655 0 : Real64 LoopMinTemp = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).MinTemp;
2656 0 : Real64 TempDifference = state.dataPlnt->PlantLoop(this->plantLoc.loopNum).MinTemp - this->OutletWaterTemp;
2657 0 : if (TempDifference > TempAllowance && this->WaterMassFlowRate > 0.0) {
2658 0 : ++this->OutletWaterTempErrorCount;
2659 0 : if (this->OutletWaterTempErrorCount < 2) {
2660 0 : ShowWarningError(state, format("{} \"{}\"", this->EvapFluidCoolerType, this->Name));
2661 0 : ShowContinueError(state,
2662 0 : format("Evaporative fluid cooler water outlet temperature ({:6.2F} C) is below the specified minimum condenser "
2663 : "loop temp of {:6.2F} C",
2664 0 : this->OutletWaterTemp,
2665 : LoopMinTemp));
2666 0 : ShowContinueErrorTimeStamp(state, "");
2667 : } else {
2668 0 : ShowRecurringWarningErrorAtEnd(
2669 : state,
2670 0 : this->EvapFluidCoolerType + " \"" + this->Name +
2671 : "\" Evaporative fluid cooler water outlet temperature is below the specified minimum condenser loop temp error",
2672 0 : this->OutletWaterTempErrorIndex,
2673 0 : this->OutletWaterTemp,
2674 0 : this->OutletWaterTemp);
2675 : }
2676 : }
2677 :
2678 : // Check if water mass flow rate is small (e.g. no flow) and warn user
2679 0 : if (this->WaterMassFlowRate > 0.0 && this->WaterMassFlowRate <= DataBranchAirLoopPlant::MassFlowTolerance) {
2680 0 : ++this->SmallWaterMassFlowErrorCount;
2681 0 : if (this->SmallWaterMassFlowErrorCount < 2) {
2682 0 : ShowWarningError(state, format("{} \"{}\"", this->EvapFluidCoolerType, this->Name));
2683 0 : ShowContinueError(state, "Evaporative fluid cooler water mass flow rate near zero.");
2684 0 : ShowContinueErrorTimeStamp(state, "");
2685 0 : ShowContinueError(state, format("Actual Mass flow = {:.2T}", this->WaterMassFlowRate));
2686 : } else {
2687 0 : ShowRecurringWarningErrorAtEnd(state,
2688 0 : this->EvapFluidCoolerType + " \"" + this->Name +
2689 : "\" Evaporative fluid cooler water mass flow rate near zero error continues...",
2690 0 : this->SmallWaterMassFlowErrorIndex,
2691 0 : this->WaterMassFlowRate,
2692 0 : this->WaterMassFlowRate);
2693 : }
2694 : }
2695 : }
2696 :
2697 2 : void EvapFluidCoolerSpecs::ReportEvapFluidCooler(EnergyPlusData &state, bool const RunFlag)
2698 : {
2699 :
2700 : // SUBROUTINE INFORMATION:
2701 : // AUTHOR: Chandan Sharma
2702 : // DATE WRITTEN: May 2009
2703 : // MODIFIED na
2704 : // RE-ENGINEERED na
2705 :
2706 : // PURPOSE OF THIS SUBROUTINE:
2707 : // This subroutine updates the report variables for the evaporative fluid cooler.
2708 :
2709 2 : Real64 const ReportingConstant = state.dataHVACGlobal->TimeStepSysSec;
2710 :
2711 2 : if (!RunFlag) {
2712 0 : this->fluidCoolerInletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNode).Temp;
2713 0 : this->fluidCoolerOutletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNode).Temp;
2714 0 : this->Qactual = 0.0;
2715 0 : this->FanPower = 0.0;
2716 0 : this->FanEnergy = 0.0;
2717 0 : this->AirFlowRateRatio = 0.0;
2718 0 : this->WaterAmountUsed = 0.0;
2719 0 : this->BypassFraction = 0.0;
2720 : } else {
2721 2 : this->fluidCoolerInletWaterTemp = state.dataLoopNodes->Node(this->WaterInletNode).Temp;
2722 2 : this->fluidCoolerOutletWaterTemp = this->OutletWaterTemp;
2723 2 : this->FanEnergy = this->FanPower * ReportingConstant;
2724 2 : this->WaterAmountUsed = this->WaterUsage * ReportingConstant;
2725 : }
2726 2 : }
2727 :
2728 5 : void EvapFluidCoolerSpecs::oneTimeInit(EnergyPlusData &state)
2729 : {
2730 5 : bool ErrorsFound(false); // Flag if input data errors are found
2731 :
2732 5 : if (this->MyOneTimeFlag) {
2733 :
2734 2 : this->setupOutputVars(state);
2735 :
2736 2 : this->glycol = state.dataPlnt->PlantLoop(state.dataSize->CurLoopNum).glycol;
2737 2 : std::string const &FluidName = this->glycol->Name;
2738 :
2739 2 : if (Util::SameString(this->PerformanceInputMethod, "STANDARDDESIGNCAPACITY")) {
2740 0 : this->PerformanceInputMethod_Num = PIM::StandardDesignCapacity;
2741 0 : if (FluidName != "WATER") {
2742 0 : ShowSevereError(state,
2743 0 : format("{} = \"{}{}",
2744 0 : state.dataIPShortCut->cCurrentModuleObject,
2745 0 : this->Name,
2746 : R"(". StandardDesignCapacity performance input method is only valid for fluid type = "Water".)"));
2747 0 : ShowContinueError(state,
2748 0 : format("Currently, Fluid Type = {} in CondenserLoop = {}",
2749 : FluidName,
2750 0 : state.dataPlnt->PlantLoop(state.dataSize->CurLoopNum).Name));
2751 0 : ErrorsFound = true;
2752 : }
2753 : }
2754 :
2755 2 : this->MyOneTimeFlag = false;
2756 : }
2757 :
2758 5 : if (this->OneTimeFlagForEachEvapFluidCooler) {
2759 : // Locate the tower on the plant loops for later usage
2760 2 : PlantUtilities::ScanPlantLoopsForObject(state, this->Name, this->Type, this->plantLoc, ErrorsFound, _, _, _, _, _);
2761 :
2762 2 : if (ErrorsFound) {
2763 0 : ShowFatalError(state, "InitEvapFluidCooler: Program terminated due to previous condition(s).");
2764 : }
2765 :
2766 2 : if (this->Type == DataPlant::PlantEquipmentType::EvapFluidCooler_TwoSpd) {
2767 1 : if (this->DesignWaterFlowRate > 0.0) {
2768 0 : if (this->HighSpeedAirFlowRate <= this->LowSpeedAirFlowRate) {
2769 0 : ShowSevereError(
2770 : state,
2771 0 : format("EvaporativeFluidCooler:TwoSpeed \"{}\". Low speed air flow rate must be less than the high speed air flow rate.",
2772 0 : this->Name));
2773 0 : ErrorsFound = true;
2774 : }
2775 0 : if ((this->HighSpeedEvapFluidCoolerUA > 0.0) && (this->LowSpeedEvapFluidCoolerUA > 0.0) &&
2776 0 : (this->HighSpeedEvapFluidCoolerUA <= this->LowSpeedEvapFluidCoolerUA)) {
2777 0 : ShowSevereError(state,
2778 0 : format("EvaporativeFluidCooler:TwoSpeed \"{}\". Evaporative fluid cooler UA at low fan speed must be less "
2779 : "than the evaporative fluid cooler UA at high fan speed.",
2780 0 : this->Name));
2781 0 : ErrorsFound = true;
2782 : }
2783 : }
2784 : }
2785 :
2786 2 : if (ErrorsFound) {
2787 0 : ShowFatalError(state, "InitEvapFluidCooler: Program terminated due to previous condition(s).");
2788 : }
2789 :
2790 2 : this->OneTimeFlagForEachEvapFluidCooler = false;
2791 : }
2792 5 : }
2793 :
2794 : } // namespace EvaporativeFluidCoolers
2795 :
2796 : } // namespace EnergyPlus
|