Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Fmath.hh>
53 :
54 : // EnergyPlus Headers
55 : #include <EnergyPlus/CoolTower.hh>
56 : #include <EnergyPlus/Data/EnergyPlusData.hh>
57 : #include <EnergyPlus/DataEnvironment.hh>
58 : #include <EnergyPlus/DataHVACGlobals.hh>
59 : #include <EnergyPlus/DataHeatBalance.hh>
60 : #include <EnergyPlus/DataIPShortCuts.hh>
61 : #include <EnergyPlus/DataWater.hh>
62 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
63 : #include <EnergyPlus/OutputProcessor.hh>
64 : #include <EnergyPlus/Psychrometrics.hh>
65 : #include <EnergyPlus/ScheduleManager.hh>
66 : #include <EnergyPlus/UtilityRoutines.hh>
67 : #include <EnergyPlus/WaterManager.hh>
68 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
69 :
70 : namespace EnergyPlus {
71 :
72 : namespace CoolTower {
73 : // Module containing the data for cooltower system
74 :
75 : // MODULE INFORMATION:
76 : // AUTHOR Daeho Kang
77 : // DATE WRITTEN Aug 2008
78 : // MODIFIED na
79 : // RE-ENGINEERED na
80 :
81 : // PURPOSE OF THIS MODULE:
82 : // To encapsulate the data and algorithms required to manage the cooltower component.
83 :
84 : // REFERENCES:
85 : // Baruch Givoni. 1994. Passive and Low Energy Cooling of Buildings. Chapter 5: Evaporative Cooling Systems.
86 : // John Wiley & Sons, Inc.
87 : // OTHER NOTES: none
88 :
89 : // Using/Aliasing
90 : using namespace DataHeatBalance;
91 :
92 : constexpr std::array<std::string_view, static_cast<int>(FlowCtrl::Num)> FlowCtrlNamesUC{"WATERFLOWSCHEDULE", "WINDDRIVENFLOW"};
93 :
94 3728073 : void ManageCoolTower(EnergyPlusData &state)
95 : {
96 :
97 : // SUBROUTINE INFORMATION:
98 : // AUTHOR Daeho Kang
99 : // DATE WRITTEN Aug 2008
100 :
101 : // PURPOSE OF THIS SUBROUTINE:
102 : // This subroutine manages the simulation of Cooltower component.
103 : // This driver manages the calls to all of the other drivers and simulation algorithms.
104 :
105 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
106 :
107 : // Obtains and allocates heat balance related parameters from input
108 3728073 : if (state.dataCoolTower->GetInputFlag) {
109 763 : GetCoolTower(state);
110 763 : state.dataCoolTower->GetInputFlag = false;
111 : }
112 :
113 3728073 : if ((int)state.dataCoolTower->CoolTowerSys.size() == 0) return;
114 :
115 3580 : CalcCoolTower(state);
116 :
117 3580 : UpdateCoolTower(state);
118 :
119 3580 : ReportCoolTower(state);
120 : }
121 :
122 763 : void GetCoolTower(EnergyPlusData &state)
123 : {
124 :
125 : // SUBROUTINE INFORMATION:
126 : // AUTHOR Daeho Kang
127 : // DATE WRITTEN Aug 2008
128 :
129 : // PURPOSE OF THIS SUBROUTINE:
130 : // This subroutine gets input data for cooltower components
131 : // and stores it in the Cooltower data structure.
132 :
133 : // SUBROUTINE PARAMETER DEFINITIONS:
134 763 : static std::string const CurrentModuleObject("ZoneCoolTower:Shower");
135 763 : Real64 constexpr MaximumWaterFlowRate(0.016667); // Maximum limit of water flow rate in m3/s (1000 l/min)
136 763 : Real64 constexpr MinimumWaterFlowRate(0.0); // Minimum limit of water flow rate
137 763 : Real64 constexpr MaxHeight(30.0); // Maximum effective tower height in m
138 763 : Real64 constexpr MinHeight(1.0); // Minimum effective tower height in m
139 763 : Real64 constexpr MaxValue(100.0); // Maximum limit of outlet area, airflow, and temperature
140 763 : Real64 constexpr MinValue(0.0); // Minimum limit of outlet area, airflow, and temperature
141 763 : Real64 constexpr MaxFrac(1.0); // Maximum fraction
142 763 : Real64 constexpr MinFrac(0.0); // Minimum fraction
143 :
144 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
145 763 : bool ErrorsFound(false); // If errors detected in input
146 : int NumAlphas; // Number of Alphas for each GetobjectItem call
147 : int NumNumbers; // Number of Numbers for each GetobjectItem call
148 : int NumArgs;
149 : int IOStat;
150 763 : Array1D_string cAlphaArgs; // Alpha input items for object
151 763 : Array1D_string cAlphaFields; // Alpha field names
152 763 : Array1D_string cNumericFields; // Numeric field names
153 763 : Array1D<Real64> rNumericArgs; // Numeric input items for object
154 763 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
155 763 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
156 :
157 : // Initializations and allocations
158 763 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumArgs, NumAlphas, NumNumbers);
159 763 : cAlphaArgs.allocate(NumAlphas);
160 763 : cAlphaFields.allocate(NumAlphas);
161 763 : cNumericFields.allocate(NumNumbers);
162 763 : rNumericArgs.dimension(NumNumbers, 0.0);
163 763 : lAlphaBlanks.dimension(NumAlphas, true);
164 763 : lNumericBlanks.dimension(NumNumbers, true);
165 :
166 763 : auto &Zone(state.dataHeatBal->Zone);
167 :
168 763 : int NumCoolTowers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
169 :
170 763 : state.dataCoolTower->CoolTowerSys.allocate(NumCoolTowers);
171 :
172 : // Obtain inputs
173 768 : for (int CoolTowerNum = 1; CoolTowerNum <= NumCoolTowers; ++CoolTowerNum) {
174 :
175 10 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
176 : CurrentModuleObject,
177 : CoolTowerNum,
178 5 : state.dataIPShortCut->cAlphaArgs,
179 : NumAlphas,
180 5 : state.dataIPShortCut->rNumericArgs,
181 : NumNumbers,
182 : IOStat,
183 : lNumericBlanks,
184 : lAlphaBlanks,
185 : cAlphaFields,
186 : cNumericFields);
187 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).Name = state.dataIPShortCut->cAlphaArgs(1); // Name of cooltower
188 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).Schedule = state.dataIPShortCut->cAlphaArgs(2); // Get schedule
189 5 : if (lAlphaBlanks(2)) {
190 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SchedPtr = ScheduleManager::ScheduleAlwaysOn;
191 : } else {
192 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SchedPtr =
193 5 : ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
194 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).SchedPtr == 0) {
195 0 : ShowSevereError(state, format("{}=\"{}\" invalid data", CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
196 0 : ShowContinueError(state, format("Invalid-Schedule not found {}=\"{}\".", cAlphaFields(2), state.dataIPShortCut->cAlphaArgs(2)));
197 0 : ErrorsFound = true;
198 : }
199 : }
200 :
201 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), Zone);
202 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr =
203 5 : Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->space);
204 5 : if ((state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr == 0) && (state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr == 0)) {
205 0 : if (lAlphaBlanks(3)) {
206 0 : ShowSevereError(state,
207 0 : format("{}=\"{}\" invalid {} is required but input is blank.",
208 : CurrentModuleObject,
209 0 : state.dataIPShortCut->cAlphaArgs(1),
210 : cAlphaFields(3)));
211 : } else {
212 0 : ShowSevereError(state,
213 0 : format("{}=\"{}\" invalid {}=\"{}\" not found.",
214 : CurrentModuleObject,
215 0 : state.dataIPShortCut->cAlphaArgs(1),
216 : cAlphaFields(3),
217 0 : state.dataIPShortCut->cAlphaArgs(3)));
218 : }
219 0 : ErrorsFound = true;
220 5 : } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr == 0) {
221 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr =
222 0 : state.dataHeatBal->space(state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr).zoneNum;
223 : }
224 :
225 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyName = state.dataIPShortCut->cAlphaArgs(4); // Name of water storage tank
226 5 : if (lAlphaBlanks(4)) {
227 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode = WaterSupplyMode::FromMains;
228 0 : } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
229 0 : WaterManager::SetupTankDemandComponent(state,
230 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).Name,
231 : CurrentModuleObject,
232 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyName,
233 : ErrorsFound,
234 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupTankID,
235 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterTankDemandARRID);
236 : }
237 :
238 : {
239 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType =
240 5 : static_cast<FlowCtrl>(getEnumValue(FlowCtrlNamesUC, state.dataIPShortCut->cAlphaArgs(5))); // Type of flow control
241 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType == FlowCtrl::Invalid) {
242 0 : ShowSevereError(state,
243 0 : format("{}=\"{}\" invalid {}=\"{}\".",
244 : CurrentModuleObject,
245 0 : state.dataIPShortCut->cAlphaArgs(1),
246 : cAlphaFields(5),
247 0 : state.dataIPShortCut->cAlphaArgs(5)));
248 0 : ErrorsFound = true;
249 : }
250 : }
251 :
252 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpSchedPtr =
253 5 : ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6));
254 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpSchedPtr == 0) {
255 0 : if (lAlphaBlanks(6)) {
256 0 : ShowSevereError(state,
257 0 : format("{}=\"{}\" invalid {} is required but input is blank.",
258 : CurrentModuleObject,
259 0 : state.dataIPShortCut->cAlphaArgs(1),
260 : cAlphaFields(6)));
261 : } else {
262 0 : ShowSevereError(state,
263 0 : format("{}=\"{}\" invalid {}=\"{}\" not found.",
264 : CurrentModuleObject,
265 0 : state.dataIPShortCut->cAlphaArgs(1),
266 : cAlphaFields(6),
267 0 : state.dataIPShortCut->cAlphaArgs(6)));
268 : }
269 0 : ErrorsFound = true;
270 : }
271 :
272 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate = state.dataIPShortCut->rNumericArgs(1); // Maximum limit of water supply
273 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate > MaximumWaterFlowRate) {
274 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate = MaximumWaterFlowRate;
275 0 : ShowWarningError(state,
276 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
277 : CurrentModuleObject,
278 0 : state.dataIPShortCut->cAlphaArgs(1),
279 : cNumericFields(1),
280 0 : state.dataIPShortCut->rNumericArgs(1)));
281 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaximumWaterFlowRate));
282 : }
283 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate < MinimumWaterFlowRate) {
284 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate = MinimumWaterFlowRate;
285 0 : ShowWarningError(state,
286 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
287 : CurrentModuleObject,
288 0 : state.dataIPShortCut->cAlphaArgs(1),
289 : cNumericFields(1),
290 0 : state.dataIPShortCut->rNumericArgs(1)));
291 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinimumWaterFlowRate));
292 : }
293 :
294 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight = state.dataIPShortCut->rNumericArgs(2); // Get effctive tower height
295 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight > MaxHeight) {
296 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight = MaxHeight;
297 0 : ShowWarningError(state,
298 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
299 : CurrentModuleObject,
300 0 : state.dataIPShortCut->cAlphaArgs(1),
301 : cNumericFields(2),
302 0 : state.dataIPShortCut->rNumericArgs(2)));
303 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxHeight));
304 : }
305 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight < MinHeight) {
306 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight = MinHeight;
307 0 : ShowWarningError(state,
308 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
309 : CurrentModuleObject,
310 0 : state.dataIPShortCut->cAlphaArgs(1),
311 : cNumericFields(2),
312 0 : state.dataIPShortCut->rNumericArgs(2)));
313 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinHeight));
314 : }
315 :
316 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea = state.dataIPShortCut->rNumericArgs(3); // Get outlet area
317 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea > MaxValue) {
318 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea = MaxValue;
319 0 : ShowWarningError(state,
320 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
321 : CurrentModuleObject,
322 0 : state.dataIPShortCut->cAlphaArgs(1),
323 : cNumericFields(3),
324 0 : state.dataIPShortCut->rNumericArgs(3)));
325 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxValue));
326 : }
327 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea < MinValue) {
328 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea = MinValue;
329 0 : ShowWarningError(state,
330 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
331 : CurrentModuleObject,
332 0 : state.dataIPShortCut->cAlphaArgs(1),
333 : cNumericFields(3),
334 0 : state.dataIPShortCut->rNumericArgs(3)));
335 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinValue));
336 : }
337 :
338 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate =
339 5 : state.dataIPShortCut->rNumericArgs(4); // Maximum limit of air flow to the space
340 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate > MaxValue) {
341 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate = MaxValue;
342 0 : ShowWarningError(state,
343 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
344 : CurrentModuleObject,
345 0 : state.dataIPShortCut->cAlphaArgs(1),
346 : cNumericFields(4),
347 0 : state.dataIPShortCut->rNumericArgs(4)));
348 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxValue));
349 : }
350 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate < MinValue) {
351 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate = MinValue;
352 0 : ShowWarningError(state,
353 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
354 : CurrentModuleObject,
355 0 : state.dataIPShortCut->cAlphaArgs(1),
356 : cNumericFields(4),
357 0 : state.dataIPShortCut->rNumericArgs(4)));
358 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinValue));
359 : }
360 :
361 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp =
362 5 : state.dataIPShortCut->rNumericArgs(5); // Get minimum temp limit which gets this cooltower off
363 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp > MaxValue) {
364 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp = MaxValue;
365 0 : ShowWarningError(state,
366 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
367 : CurrentModuleObject,
368 0 : state.dataIPShortCut->cAlphaArgs(1),
369 : cNumericFields(5),
370 0 : state.dataIPShortCut->rNumericArgs(5)));
371 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxValue));
372 : }
373 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp < MinValue) {
374 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp = MinValue;
375 0 : ShowWarningError(state,
376 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
377 : CurrentModuleObject,
378 0 : state.dataIPShortCut->cAlphaArgs(1),
379 : cNumericFields(5),
380 0 : state.dataIPShortCut->rNumericArgs(5)));
381 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinValue));
382 : }
383 :
384 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss = state.dataIPShortCut->rNumericArgs(6); // Fraction of water loss
385 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss > MaxFrac) {
386 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss = MaxFrac;
387 0 : ShowWarningError(state,
388 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
389 : CurrentModuleObject,
390 0 : state.dataIPShortCut->cAlphaArgs(1),
391 : cNumericFields(6),
392 0 : state.dataIPShortCut->rNumericArgs(6)));
393 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxFrac));
394 : }
395 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss < MinFrac) {
396 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss = MinFrac;
397 0 : ShowWarningError(state,
398 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
399 : CurrentModuleObject,
400 0 : state.dataIPShortCut->cAlphaArgs(1),
401 : cNumericFields(6),
402 0 : state.dataIPShortCut->rNumericArgs(6)));
403 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinFrac));
404 : }
405 :
406 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched = state.dataIPShortCut->rNumericArgs(7); // Fraction of loss of air flow
407 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched > MaxFrac) {
408 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched = MaxFrac;
409 0 : ShowWarningError(state,
410 0 : format("{}=\"{}\" invalid {}=[{:.2R}].",
411 : CurrentModuleObject,
412 0 : state.dataIPShortCut->cAlphaArgs(1),
413 : cNumericFields(7),
414 0 : state.dataIPShortCut->rNumericArgs(7)));
415 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxFrac));
416 : }
417 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched < MinFrac) {
418 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched = MinFrac;
419 0 : ShowWarningError(state,
420 0 : format("{}=\"{}\" invalid {}=[{:.5R}].",
421 : CurrentModuleObject,
422 0 : state.dataIPShortCut->cAlphaArgs(1),
423 : cNumericFields(7),
424 0 : state.dataIPShortCut->rNumericArgs(7)));
425 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinFrac));
426 : }
427 :
428 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).RatedPumpPower = state.dataIPShortCut->rNumericArgs(8); // Get rated pump power
429 : }
430 :
431 763 : cAlphaArgs.deallocate();
432 763 : cAlphaFields.deallocate();
433 763 : cNumericFields.deallocate();
434 763 : rNumericArgs.deallocate();
435 763 : lAlphaBlanks.deallocate();
436 763 : lNumericBlanks.deallocate();
437 :
438 763 : if (ErrorsFound) ShowFatalError(state, format("{} errors occurred in input. Program terminates.", CurrentModuleObject));
439 :
440 768 : for (int CoolTowerNum = 1; CoolTowerNum <= NumCoolTowers; ++CoolTowerNum) {
441 10 : SetupOutputVariable(state,
442 : "Zone Cooltower Sensible Heat Loss Energy",
443 : Constant::Units::J,
444 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatLoss,
445 : OutputProcessor::TimeStepType::System,
446 : OutputProcessor::StoreType::Sum,
447 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
448 10 : SetupOutputVariable(state,
449 : "Zone Cooltower Sensible Heat Loss Rate",
450 : Constant::Units::W,
451 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower,
452 : OutputProcessor::TimeStepType::System,
453 : OutputProcessor::StoreType::Average,
454 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
455 10 : SetupOutputVariable(state,
456 : "Zone Cooltower Latent Heat Loss Energy",
457 : Constant::Units::J,
458 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatLoss,
459 : OutputProcessor::TimeStepType::System,
460 : OutputProcessor::StoreType::Sum,
461 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
462 10 : SetupOutputVariable(state,
463 : "Zone Cooltower Latent Heat Loss Rate",
464 : Constant::Units::W,
465 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower,
466 : OutputProcessor::TimeStepType::System,
467 : OutputProcessor::StoreType::Average,
468 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
469 10 : SetupOutputVariable(state,
470 : "Zone Cooltower Air Volume",
471 : Constant::Units::m3,
472 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirVol,
473 : OutputProcessor::TimeStepType::System,
474 : OutputProcessor::StoreType::Sum,
475 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
476 10 : SetupOutputVariable(state,
477 : "Zone Cooltower Current Density Air Volume Flow Rate",
478 : Constant::Units::m3_s,
479 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate,
480 : OutputProcessor::TimeStepType::System,
481 : OutputProcessor::StoreType::Average,
482 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
483 10 : SetupOutputVariable(state,
484 : "Zone Cooltower Standard Density Air Volume Flow Rate",
485 : Constant::Units::m3_s,
486 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRateStd,
487 : OutputProcessor::TimeStepType::System,
488 : OutputProcessor::StoreType::Average,
489 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
490 10 : SetupOutputVariable(state,
491 : "Zone Cooltower Air Mass",
492 : Constant::Units::kg,
493 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirMass,
494 : OutputProcessor::TimeStepType::System,
495 : OutputProcessor::StoreType::Sum,
496 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
497 10 : SetupOutputVariable(state,
498 : "Zone Cooltower Air Mass Flow Rate",
499 : Constant::Units::kg_s,
500 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate,
501 : OutputProcessor::TimeStepType::System,
502 : OutputProcessor::StoreType::Average,
503 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
504 10 : SetupOutputVariable(state,
505 : "Zone Cooltower Air Inlet Temperature",
506 : Constant::Units::C,
507 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletDBTemp,
508 : OutputProcessor::TimeStepType::System,
509 : OutputProcessor::StoreType::Average,
510 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
511 10 : SetupOutputVariable(state,
512 : "Zone Cooltower Air Inlet Humidity Ratio",
513 : Constant::Units::kgWater_kgDryAir,
514 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletHumRat,
515 : OutputProcessor::TimeStepType::System,
516 : OutputProcessor::StoreType::Average,
517 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
518 10 : SetupOutputVariable(state,
519 : "Zone Cooltower Air Outlet Temperature",
520 : Constant::Units::C,
521 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletTemp,
522 : OutputProcessor::TimeStepType::System,
523 : OutputProcessor::StoreType::Average,
524 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
525 10 : SetupOutputVariable(state,
526 : "Zone Cooltower Air Outlet Humidity Ratio",
527 : Constant::Units::kgWater_kgDryAir,
528 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletHumRat,
529 : OutputProcessor::TimeStepType::System,
530 : OutputProcessor::StoreType::Average,
531 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
532 10 : SetupOutputVariable(state,
533 : "Zone Cooltower Pump Electricity Rate",
534 : Constant::Units::W,
535 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower,
536 : OutputProcessor::TimeStepType::System,
537 : OutputProcessor::StoreType::Average,
538 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
539 10 : SetupOutputVariable(state,
540 : "Zone Cooltower Pump Electricity Energy",
541 : Constant::Units::J,
542 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecConsump,
543 : OutputProcessor::TimeStepType::System,
544 : OutputProcessor::StoreType::Sum,
545 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name,
546 : Constant::eResource::Electricity,
547 : OutputProcessor::Group::HVAC, // System
548 : OutputProcessor::EndUseCat::Cooling);
549 5 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromMains) {
550 10 : SetupOutputVariable(state,
551 : "Zone Cooltower Water Volume",
552 : Constant::Units::m3,
553 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
554 : OutputProcessor::TimeStepType::System,
555 : OutputProcessor::StoreType::Sum,
556 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
557 10 : SetupOutputVariable(state,
558 : "Zone Cooltower Mains Water Volume",
559 : Constant::Units::m3,
560 5 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
561 : OutputProcessor::TimeStepType::System,
562 : OutputProcessor::StoreType::Sum,
563 5 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name,
564 : Constant::eResource::MainsWater,
565 : OutputProcessor::Group::HVAC, // System
566 : OutputProcessor::EndUseCat::Cooling);
567 0 : } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
568 0 : SetupOutputVariable(state,
569 : "Zone Cooltower Water Volume",
570 : Constant::Units::m3,
571 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
572 : OutputProcessor::TimeStepType::System,
573 : OutputProcessor::StoreType::Sum,
574 0 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
575 0 : SetupOutputVariable(state,
576 : "Zone Cooltower Storage Tank Water Volume",
577 : Constant::Units::m3,
578 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
579 : OutputProcessor::TimeStepType::System,
580 : OutputProcessor::StoreType::Sum,
581 0 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
582 0 : SetupOutputVariable(state,
583 : "Zone Cooltower Starved Mains Water Volume",
584 : Constant::Units::m3,
585 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeup,
586 : OutputProcessor::TimeStepType::System,
587 : OutputProcessor::StoreType::Sum,
588 0 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name,
589 : Constant::eResource::MainsWater,
590 : OutputProcessor::Group::HVAC, // System
591 : OutputProcessor::EndUseCat::Cooling);
592 : }
593 : }
594 763 : }
595 :
596 3580 : void CalcCoolTower(EnergyPlusData &state)
597 : {
598 :
599 : // SUBROUTINE INFORMATION:
600 : // AUTHOR Daeho Kang
601 : // DATE WRITTEN Aug 2008
602 :
603 : // REFERENCES:
604 : // Baruch Givoni. 1994. Passive and Low Energy Cooling of Buildings. Chapter 5: Evaporative Cooling Systems.
605 : // John Wiley & Sons, Inc.
606 :
607 : // SUBROUTINE PARAMETER DEFINITIONS:
608 3580 : Real64 constexpr MinWindSpeed(0.1); // Minimum limit of outdoor air wind speed in m/s
609 3580 : Real64 constexpr MaxWindSpeed(30.0); // Maximum limit of outdoor air wind speed in m/s
610 3580 : Real64 constexpr UCFactor(60000.0); // Unit conversion factor m3/s to l/min
611 :
612 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
613 : Real64 CVF_ZoneNum; // Design flow rate in m3/s
614 : Real64 AirMassFlowRate; // Actual air mass flow rate in kg/s
615 : Real64 AirSpecHeat; // Specific heat of air
616 : Real64 AirDensity; // Density of air
617 : Real64 RhoWater; // Density of water
618 : Real64 PumpPartLoadRat; // Pump part load ratio (based on user schedule, or 1.0 for no schedule)
619 3580 : Real64 WaterFlowRate = 0.0; // Calculated water flow rate in m3/s
620 3580 : Real64 AirVolFlowRate = 0.0; // Calculated air volume flow rate in m3/s
621 : Real64 InletHumRat; // Humidity ratio of outdoor air
622 : Real64 OutletHumRat; // Humidity ratio of air at the cooltower outlet
623 3580 : Real64 OutletTemp = 0.0; // Dry bulb temperature of air at the cooltower outlet
624 : Real64 IntHumRat; // Humidity ratio of initialized air
625 :
626 3580 : auto &Zone(state.dataHeatBal->Zone);
627 :
628 12501 : for (int CoolTowerNum = 1; CoolTowerNum <= (int)state.dataCoolTower->CoolTowerSys.size(); ++CoolTowerNum) {
629 8921 : int const ZoneNum = state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr;
630 8921 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
631 8921 : thisZoneHB.MCPTC = 0.0;
632 8921 : thisZoneHB.MCPC = 0.0;
633 8921 : thisZoneHB.CTMFL = 0.0;
634 8921 : if ((state.dataHeatBal->doSpaceHeatBalance) && (state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr > 0)) {
635 0 : auto &thisSpaceHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr);
636 0 : thisSpaceHB.MCPTC = 0.0;
637 0 : thisSpaceHB.MCPC = 0.0;
638 0 : thisSpaceHB.CTMFL = 0.0;
639 : }
640 8921 : if (ScheduleManager::GetCurrentScheduleValue(state, state.dataCoolTower->CoolTowerSys(CoolTowerNum).SchedPtr) > 0.0) {
641 : // check component operation
642 6365 : if (state.dataEnvrn->WindSpeed < MinWindSpeed || state.dataEnvrn->WindSpeed > MaxWindSpeed) continue;
643 6365 : if (state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT < state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp)
644 2920 : continue;
645 :
646 : // Unit is on and simulate this component
647 : // Determine the temperature and air flow rate at the cooltower outlet
648 3445 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType == FlowCtrl::WindDriven) {
649 2785 : Real64 const height_sqrt(std::sqrt(state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight));
650 2785 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletVelocity = 0.7 * height_sqrt + 0.47 * (state.dataEnvrn->WindSpeed - 1.0);
651 2785 : AirVolFlowRate =
652 2785 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea * state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletVelocity;
653 2785 : AirVolFlowRate = min(AirVolFlowRate, state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate);
654 2785 : WaterFlowRate = (AirVolFlowRate / (0.0125 * height_sqrt));
655 2785 : if (WaterFlowRate > state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor) {
656 2049 : WaterFlowRate = state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor;
657 2049 : AirVolFlowRate = 0.0125 * WaterFlowRate * height_sqrt;
658 2049 : AirVolFlowRate = min(AirVolFlowRate, state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate);
659 : }
660 2785 : WaterFlowRate = min(WaterFlowRate, (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor));
661 2785 : OutletTemp =
662 2785 : state.dataEnvrn->OutDryBulbTemp - (state.dataEnvrn->OutDryBulbTemp - state.dataEnvrn->OutWetBulbTemp) *
663 2785 : (1.0 - std::exp(-0.8 * state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight)) *
664 2785 : (1.0 - std::exp(-0.15 * WaterFlowRate));
665 660 : } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType == FlowCtrl::FlowSchedule) {
666 660 : WaterFlowRate = state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor;
667 660 : AirVolFlowRate = 0.0125 * WaterFlowRate * std::sqrt(state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight);
668 660 : AirVolFlowRate = min(AirVolFlowRate, state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate);
669 660 : OutletTemp =
670 660 : state.dataEnvrn->OutDryBulbTemp - (state.dataEnvrn->OutDryBulbTemp - state.dataEnvrn->OutWetBulbTemp) *
671 660 : (1.0 - std::exp(-0.8 * state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight)) *
672 660 : (1.0 - std::exp(-0.15 * WaterFlowRate));
673 : }
674 :
675 3445 : if (OutletTemp < state.dataEnvrn->OutWetBulbTemp) {
676 0 : ShowSevereError(state, "Cooltower outlet temperature exceed the outdoor wet bulb temperature reset to input values");
677 0 : ShowContinueError(state, format("Occurs in Cooltower ={}", state.dataCoolTower->CoolTowerSys(CoolTowerNum).Name));
678 : }
679 :
680 3445 : WaterFlowRate /= UCFactor;
681 : // Determine actual water flow rate
682 3445 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss > 0.0) {
683 2782 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualWaterFlowRate =
684 2782 : WaterFlowRate * (1.0 + state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss);
685 : } else {
686 663 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualWaterFlowRate = WaterFlowRate;
687 : }
688 :
689 : // Determine actual air flow rate
690 3445 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched > 0.0) {
691 2782 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate =
692 2782 : AirVolFlowRate * (1.0 - state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched);
693 : } else {
694 663 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate = AirVolFlowRate;
695 : }
696 :
697 : // Determine pump power
698 3445 : if (ScheduleManager::GetCurrentScheduleValue(state, state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpSchedPtr) > 0) {
699 3445 : PumpPartLoadRat = ScheduleManager::GetCurrentScheduleValue(state, state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpSchedPtr);
700 : } else {
701 0 : PumpPartLoadRat = 1.0;
702 : }
703 :
704 : // Determine air mass flow rate and volume flow rate
705 6890 : InletHumRat = Psychrometrics::PsyWFnTdbTwbPb(
706 3445 : state, state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutWetBulbTemp, state.dataEnvrn->OutBaroPress);
707 : // Assume no pressure drops and no changes in enthalpy between inlet and outlet air
708 3445 : IntHumRat = Psychrometrics::PsyWFnTdbH(state, OutletTemp, state.dataEnvrn->OutEnthalpy); // Initialized humidity ratio
709 3445 : AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, OutletTemp, IntHumRat);
710 3445 : AirMassFlowRate = AirDensity * state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate;
711 : // From the mass balance W_in*(m_air + m_water) = W_out*m_air
712 3445 : RhoWater = Psychrometrics::RhoH2O(OutletTemp); // Assume T_water = T_outlet
713 3445 : OutletHumRat = (InletHumRat * (AirMassFlowRate + (state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualWaterFlowRate * RhoWater))) /
714 : AirMassFlowRate;
715 3445 : AirSpecHeat = Psychrometrics::PsyCpAirFnW(OutletHumRat);
716 3445 : AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, OutletTemp, OutletHumRat); // Outlet air density
717 3445 : CVF_ZoneNum = state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate *
718 3445 : ScheduleManager::GetCurrentScheduleValue(state, state.dataCoolTower->CoolTowerSys(CoolTowerNum).SchedPtr);
719 3445 : Real64 thisMCPC = CVF_ZoneNum * AirDensity * AirSpecHeat;
720 3445 : Real64 thisMCPTC = thisMCPC * OutletTemp;
721 3445 : Real64 thisCTMFL = thisMCPC / AirSpecHeat;
722 3445 : Real64 thisZT = thisZoneHB.ZT;
723 3445 : Real64 thisAirHumRat = thisZoneHB.airHumRat;
724 3445 : thisZoneHB.MCPC = thisMCPC;
725 3445 : thisZoneHB.MCPTC = thisMCPTC;
726 3445 : thisZoneHB.CTMFL = thisCTMFL;
727 3445 : if ((state.dataHeatBal->doSpaceHeatBalance) && (state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr > 0)) {
728 : auto &thisSpaceHB =
729 0 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr);
730 0 : thisSpaceHB.MCPC = thisMCPC;
731 0 : thisSpaceHB.MCPTC = thisMCPTC;
732 0 : thisSpaceHB.CTMFL = thisCTMFL;
733 0 : thisZT = thisSpaceHB.ZT;
734 0 : thisAirHumRat = thisSpaceHB.airHumRat;
735 : }
736 :
737 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower = thisMCPC * std::abs(thisZT - OutletTemp);
738 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower = CVF_ZoneNum * std::abs(thisAirHumRat - OutletHumRat);
739 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletTemp = OutletTemp;
740 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletHumRat = OutletHumRat;
741 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate = CVF_ZoneNum;
742 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate = thisCTMFL;
743 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRateStd = thisCTMFL / state.dataEnvrn->StdRhoAir;
744 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletDBTemp = Zone(ZoneNum).OutDryBulbTemp;
745 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletWBTemp = Zone(ZoneNum).OutWetBulbTemp;
746 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletHumRat = state.dataEnvrn->OutHumRat;
747 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate = (std::abs(InletHumRat - OutletHumRat) * thisCTMFL) / RhoWater;
748 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate = 0.0; // initialize -- calc in update
749 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower =
750 3445 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).RatedPumpPower * PumpPartLoadRat;
751 : } else { // Unit is off
752 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower = 0.0;
753 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower = 0.0;
754 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletTemp = 0.0;
755 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletHumRat = 0.0;
756 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate = 0.0;
757 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate = 0.0;
758 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRateStd = 0.0;
759 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletDBTemp = 0.0;
760 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletHumRat = 0.0;
761 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower = 0.0;
762 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate = 0.0;
763 2556 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate = 0.0;
764 : }
765 : }
766 3580 : }
767 :
768 3580 : void UpdateCoolTower(EnergyPlusData &state)
769 : {
770 :
771 : // SUBROUTINE INFORMATION:
772 : // AUTHOR Richard J. Liesen
773 : // DATE WRITTEN October 2000
774 : // MODIFIED Aug 2008 Daeho Kang
775 :
776 12501 : for (int CoolTowerNum = 1; CoolTowerNum <= (int)state.dataCoolTower->CoolTowerSys.size(); ++CoolTowerNum) {
777 :
778 : // Set the demand request for supply water from water storage tank (if needed)
779 8921 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
780 0 : state.dataWaterData->WaterStorage(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupTankID)
781 0 : .VdotRequestDemand(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterTankDemandARRID) =
782 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate;
783 : }
784 :
785 : // check if should be starved by restricted flow from tank
786 8921 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
787 0 : Real64 AvailWaterRate = state.dataWaterData->WaterStorage(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupTankID)
788 0 : .VdotAvailDemand(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterTankDemandARRID);
789 0 : if (AvailWaterRate < state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate) {
790 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate =
791 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate - AvailWaterRate;
792 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate = AvailWaterRate;
793 : }
794 : }
795 : }
796 3580 : }
797 :
798 3580 : void ReportCoolTower(EnergyPlusData &state)
799 : {
800 :
801 : // SUBROUTINE INFORMATION:
802 : // AUTHOR Daeho Kang
803 : // DATE WRITTEN Aut 2008
804 :
805 3580 : Real64 const TSMult = state.dataHVACGlobal->TimeStepSysSec;
806 :
807 12501 : for (int CoolTowerNum = 1; CoolTowerNum <= (int)state.dataCoolTower->CoolTowerSys.size(); ++CoolTowerNum) {
808 :
809 8921 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirVol = state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate * TSMult;
810 8921 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirMass = state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate * TSMult;
811 8921 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatLoss = state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower * TSMult;
812 8921 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatLoss = state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower * TSMult;
813 8921 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecConsump = state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower * TSMult;
814 8921 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump =
815 8921 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate * TSMult;
816 8921 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeup =
817 8921 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate * TSMult;
818 : }
819 3580 : }
820 :
821 : } // namespace CoolTower
822 :
823 : } // namespace EnergyPlus
|