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