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