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/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 291607 : 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 291607 : if (state.dataCoolTower->GetInputFlag) {
109 109 : GetCoolTower(state);
110 109 : state.dataCoolTower->GetInputFlag = false;
111 : }
112 :
113 291607 : if ((int)state.dataCoolTower->CoolTowerSys.size() == 0) return;
114 :
115 1 : CalcCoolTower(state);
116 :
117 1 : UpdateCoolTower(state);
118 :
119 1 : ReportCoolTower(state);
120 : }
121 :
122 109 : 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 : static constexpr std::string_view routineName = "GetCoolTower";
135 :
136 311 : static std::string const CurrentModuleObject("ZoneCoolTower:Shower");
137 109 : Real64 constexpr MaximumWaterFlowRate(0.016667); // Maximum limit of water flow rate in m3/s (1000 l/min)
138 109 : Real64 constexpr MinimumWaterFlowRate(0.0); // Minimum limit of water flow rate
139 109 : Real64 constexpr MaxHeight(30.0); // Maximum effective tower height in m
140 109 : Real64 constexpr MinHeight(1.0); // Minimum effective tower height in m
141 109 : Real64 constexpr MaxValue(100.0); // Maximum limit of outlet area, airflow, and temperature
142 109 : Real64 constexpr MinValue(0.0); // Minimum limit of outlet area, airflow, and temperature
143 109 : Real64 constexpr MaxFrac(1.0); // Maximum fraction
144 109 : Real64 constexpr MinFrac(0.0); // Minimum fraction
145 :
146 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
147 109 : bool ErrorsFound(false); // If errors detected in input
148 : int NumAlphas; // Number of Alphas for each GetobjectItem call
149 : int NumNumbers; // Number of Numbers for each GetobjectItem call
150 : int NumArgs;
151 : int IOStat;
152 109 : Array1D_string cAlphaArgs; // Alpha input items for object
153 109 : Array1D_string cAlphaFields; // Alpha field names
154 109 : Array1D_string cNumericFields; // Numeric field names
155 109 : Array1D<Real64> rNumericArgs; // Numeric input items for object
156 109 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
157 109 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
158 :
159 : // Initializations and allocations
160 109 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, NumArgs, NumAlphas, NumNumbers);
161 109 : cAlphaArgs.allocate(NumAlphas);
162 109 : cAlphaFields.allocate(NumAlphas);
163 109 : cNumericFields.allocate(NumNumbers);
164 109 : rNumericArgs.dimension(NumNumbers, 0.0);
165 109 : lAlphaBlanks.dimension(NumAlphas, true);
166 109 : lNumericBlanks.dimension(NumNumbers, true);
167 :
168 109 : auto &Zone(state.dataHeatBal->Zone);
169 :
170 109 : auto &s_ipsc = state.dataIPShortCut;
171 :
172 109 : int NumCoolTowers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
173 :
174 109 : state.dataCoolTower->CoolTowerSys.allocate(NumCoolTowers);
175 :
176 : // Obtain inputs
177 110 : for (int CoolTowerNum = 1; CoolTowerNum <= NumCoolTowers; ++CoolTowerNum) {
178 :
179 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
180 : CurrentModuleObject,
181 : CoolTowerNum,
182 1 : s_ipsc->cAlphaArgs,
183 : NumAlphas,
184 1 : s_ipsc->rNumericArgs,
185 : NumNumbers,
186 : IOStat,
187 : lNumericBlanks,
188 : lAlphaBlanks,
189 : cAlphaFields,
190 : cNumericFields);
191 :
192 1 : ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
193 :
194 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).Name = s_ipsc->cAlphaArgs(1); // Name of cooltower
195 1 : if (lAlphaBlanks(2)) {
196 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).availSched = Sched::GetScheduleAlwaysOn(state);
197 0 : } else if ((state.dataCoolTower->CoolTowerSys(CoolTowerNum).availSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(2))) == nullptr) {
198 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(2), s_ipsc->cAlphaArgs(2));
199 0 : ErrorsFound = true;
200 : }
201 :
202 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr = Util::FindItemInList(s_ipsc->cAlphaArgs(3), Zone);
203 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr = Util::FindItemInList(s_ipsc->cAlphaArgs(3), state.dataHeatBal->space);
204 1 : if ((state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr == 0) && (state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr == 0)) {
205 0 : if (lAlphaBlanks(3)) {
206 0 : ShowSevereError(
207 : state,
208 0 : format("{}=\"{}\" invalid {} is required but input is blank.", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cAlphaFields(3)));
209 : } else {
210 0 : ShowSevereError(state,
211 0 : format("{}=\"{}\" invalid {}=\"{}\" not found.",
212 : CurrentModuleObject,
213 0 : s_ipsc->cAlphaArgs(1),
214 : cAlphaFields(3),
215 0 : s_ipsc->cAlphaArgs(3)));
216 : }
217 0 : ErrorsFound = true;
218 1 : } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr == 0) {
219 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr =
220 0 : state.dataHeatBal->space(state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr).zoneNum;
221 : }
222 :
223 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyName = s_ipsc->cAlphaArgs(4); // Name of water storage tank
224 1 : if (lAlphaBlanks(4)) {
225 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode = WaterSupplyMode::FromMains;
226 0 : } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
227 0 : WaterManager::SetupTankDemandComponent(state,
228 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).Name,
229 : CurrentModuleObject,
230 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyName,
231 : ErrorsFound,
232 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupTankID,
233 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterTankDemandARRID);
234 : }
235 :
236 : {
237 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType =
238 1 : static_cast<FlowCtrl>(getEnumValue(FlowCtrlNamesUC, s_ipsc->cAlphaArgs(5))); // Type of flow control
239 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType == FlowCtrl::Invalid) {
240 0 : ShowSevereError(
241 : state,
242 0 : format("{}=\"{}\" invalid {}=\"{}\".", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cAlphaFields(5), s_ipsc->cAlphaArgs(5)));
243 0 : ErrorsFound = true;
244 : }
245 : }
246 :
247 1 : if ((state.dataCoolTower->CoolTowerSys(CoolTowerNum).pumpSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(6))) == nullptr) {
248 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(6), s_ipsc->cAlphaArgs(6));
249 0 : ErrorsFound = true;
250 : }
251 :
252 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate = s_ipsc->rNumericArgs(1); // Maximum limit of water supply
253 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate > MaximumWaterFlowRate) {
254 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate = MaximumWaterFlowRate;
255 0 : ShowWarningError(
256 : state,
257 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(1), s_ipsc->rNumericArgs(1)));
258 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaximumWaterFlowRate));
259 : }
260 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate < MinimumWaterFlowRate) {
261 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate = MinimumWaterFlowRate;
262 0 : ShowWarningError(
263 : state,
264 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(1), s_ipsc->rNumericArgs(1)));
265 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinimumWaterFlowRate));
266 : }
267 :
268 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight = s_ipsc->rNumericArgs(2); // Get effctive tower height
269 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight > MaxHeight) {
270 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight = MaxHeight;
271 0 : ShowWarningError(
272 : state,
273 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(2), s_ipsc->rNumericArgs(2)));
274 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxHeight));
275 : }
276 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight < MinHeight) {
277 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight = MinHeight;
278 0 : ShowWarningError(
279 : state,
280 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(2), s_ipsc->rNumericArgs(2)));
281 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinHeight));
282 : }
283 :
284 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea = s_ipsc->rNumericArgs(3); // Get outlet area
285 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea > MaxValue) {
286 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea = MaxValue;
287 0 : ShowWarningError(
288 : state,
289 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(3), s_ipsc->rNumericArgs(3)));
290 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxValue));
291 : }
292 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea < MinValue) {
293 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea = MinValue;
294 0 : ShowWarningError(
295 : state,
296 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(3), s_ipsc->rNumericArgs(3)));
297 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinValue));
298 : }
299 :
300 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate = s_ipsc->rNumericArgs(4); // Maximum limit of air flow to the space
301 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate > MaxValue) {
302 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate = MaxValue;
303 0 : ShowWarningError(
304 : state,
305 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(4), s_ipsc->rNumericArgs(4)));
306 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxValue));
307 : }
308 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate < MinValue) {
309 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate = MinValue;
310 0 : ShowWarningError(
311 : state,
312 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(4), s_ipsc->rNumericArgs(4)));
313 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinValue));
314 : }
315 :
316 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp =
317 1 : s_ipsc->rNumericArgs(5); // Get minimum temp limit which gets this cooltower off
318 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp > MaxValue) {
319 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp = MaxValue;
320 0 : ShowWarningError(
321 : state,
322 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(5), s_ipsc->rNumericArgs(5)));
323 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxValue));
324 : }
325 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp < MinValue) {
326 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp = MinValue;
327 0 : ShowWarningError(
328 : state,
329 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(5), s_ipsc->rNumericArgs(5)));
330 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinValue));
331 : }
332 :
333 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss = s_ipsc->rNumericArgs(6); // Fraction of water loss
334 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss > MaxFrac) {
335 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss = MaxFrac;
336 0 : ShowWarningError(
337 : state,
338 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(6), s_ipsc->rNumericArgs(6)));
339 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxFrac));
340 : }
341 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss < MinFrac) {
342 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss = MinFrac;
343 0 : ShowWarningError(
344 : state,
345 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(6), s_ipsc->rNumericArgs(6)));
346 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinFrac));
347 : }
348 :
349 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched = s_ipsc->rNumericArgs(7); // Fraction of loss of air flow
350 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched > MaxFrac) {
351 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched = MaxFrac;
352 0 : ShowWarningError(
353 : state,
354 0 : format("{}=\"{}\" invalid {}=[{:.2R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(7), s_ipsc->rNumericArgs(7)));
355 0 : ShowContinueError(state, format("...Maximum Allowable=[{:.2R}].", MaxFrac));
356 : }
357 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched < MinFrac) {
358 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched = MinFrac;
359 0 : ShowWarningError(
360 : state,
361 0 : format("{}=\"{}\" invalid {}=[{:.5R}].", CurrentModuleObject, s_ipsc->cAlphaArgs(1), cNumericFields(7), s_ipsc->rNumericArgs(7)));
362 0 : ShowContinueError(state, format("...Minimum Allowable=[{:.2R}].", MinFrac));
363 : }
364 :
365 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).RatedPumpPower = s_ipsc->rNumericArgs(8); // Get rated pump power
366 : }
367 :
368 109 : cAlphaArgs.deallocate();
369 109 : cAlphaFields.deallocate();
370 109 : cNumericFields.deallocate();
371 109 : rNumericArgs.deallocate();
372 109 : lAlphaBlanks.deallocate();
373 109 : lNumericBlanks.deallocate();
374 :
375 109 : if (ErrorsFound) ShowFatalError(state, format("{} errors occurred in input. Program terminates.", CurrentModuleObject));
376 :
377 110 : for (int CoolTowerNum = 1; CoolTowerNum <= NumCoolTowers; ++CoolTowerNum) {
378 2 : SetupOutputVariable(state,
379 : "Zone Cooltower Sensible Heat Loss Energy",
380 : Constant::Units::J,
381 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatLoss,
382 : OutputProcessor::TimeStepType::System,
383 : OutputProcessor::StoreType::Sum,
384 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
385 2 : SetupOutputVariable(state,
386 : "Zone Cooltower Sensible Heat Loss Rate",
387 : Constant::Units::W,
388 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower,
389 : OutputProcessor::TimeStepType::System,
390 : OutputProcessor::StoreType::Average,
391 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
392 2 : SetupOutputVariable(state,
393 : "Zone Cooltower Latent Heat Loss Energy",
394 : Constant::Units::J,
395 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatLoss,
396 : OutputProcessor::TimeStepType::System,
397 : OutputProcessor::StoreType::Sum,
398 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
399 2 : SetupOutputVariable(state,
400 : "Zone Cooltower Latent Heat Loss Rate",
401 : Constant::Units::W,
402 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower,
403 : OutputProcessor::TimeStepType::System,
404 : OutputProcessor::StoreType::Average,
405 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
406 2 : SetupOutputVariable(state,
407 : "Zone Cooltower Air Volume",
408 : Constant::Units::m3,
409 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirVol,
410 : OutputProcessor::TimeStepType::System,
411 : OutputProcessor::StoreType::Sum,
412 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
413 2 : SetupOutputVariable(state,
414 : "Zone Cooltower Current Density Air Volume Flow Rate",
415 : Constant::Units::m3_s,
416 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate,
417 : OutputProcessor::TimeStepType::System,
418 : OutputProcessor::StoreType::Average,
419 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
420 2 : SetupOutputVariable(state,
421 : "Zone Cooltower Standard Density Air Volume Flow Rate",
422 : Constant::Units::m3_s,
423 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRateStd,
424 : OutputProcessor::TimeStepType::System,
425 : OutputProcessor::StoreType::Average,
426 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
427 2 : SetupOutputVariable(state,
428 : "Zone Cooltower Air Mass",
429 : Constant::Units::kg,
430 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirMass,
431 : OutputProcessor::TimeStepType::System,
432 : OutputProcessor::StoreType::Sum,
433 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
434 2 : SetupOutputVariable(state,
435 : "Zone Cooltower Air Mass Flow Rate",
436 : Constant::Units::kg_s,
437 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate,
438 : OutputProcessor::TimeStepType::System,
439 : OutputProcessor::StoreType::Average,
440 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
441 2 : SetupOutputVariable(state,
442 : "Zone Cooltower Air Inlet Temperature",
443 : Constant::Units::C,
444 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletDBTemp,
445 : OutputProcessor::TimeStepType::System,
446 : OutputProcessor::StoreType::Average,
447 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
448 2 : SetupOutputVariable(state,
449 : "Zone Cooltower Air Inlet Humidity Ratio",
450 : Constant::Units::kgWater_kgDryAir,
451 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletHumRat,
452 : OutputProcessor::TimeStepType::System,
453 : OutputProcessor::StoreType::Average,
454 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
455 2 : SetupOutputVariable(state,
456 : "Zone Cooltower Air Outlet Temperature",
457 : Constant::Units::C,
458 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletTemp,
459 : OutputProcessor::TimeStepType::System,
460 : OutputProcessor::StoreType::Average,
461 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
462 2 : SetupOutputVariable(state,
463 : "Zone Cooltower Air Outlet Humidity Ratio",
464 : Constant::Units::kgWater_kgDryAir,
465 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletHumRat,
466 : OutputProcessor::TimeStepType::System,
467 : OutputProcessor::StoreType::Average,
468 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
469 2 : SetupOutputVariable(state,
470 : "Zone Cooltower Pump Electricity Rate",
471 : Constant::Units::W,
472 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower,
473 : OutputProcessor::TimeStepType::System,
474 : OutputProcessor::StoreType::Average,
475 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
476 2 : SetupOutputVariable(state,
477 : "Zone Cooltower Pump Electricity Energy",
478 : Constant::Units::J,
479 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecConsump,
480 : OutputProcessor::TimeStepType::System,
481 : OutputProcessor::StoreType::Sum,
482 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name,
483 : Constant::eResource::Electricity,
484 : OutputProcessor::Group::HVAC, // System
485 : OutputProcessor::EndUseCat::Cooling);
486 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromMains) {
487 2 : SetupOutputVariable(state,
488 : "Zone Cooltower Water Volume",
489 : Constant::Units::m3,
490 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
491 : OutputProcessor::TimeStepType::System,
492 : OutputProcessor::StoreType::Sum,
493 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
494 2 : SetupOutputVariable(state,
495 : "Zone Cooltower Mains Water Volume",
496 : Constant::Units::m3,
497 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
498 : OutputProcessor::TimeStepType::System,
499 : OutputProcessor::StoreType::Sum,
500 1 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name,
501 : Constant::eResource::MainsWater,
502 : OutputProcessor::Group::HVAC, // System
503 : OutputProcessor::EndUseCat::Cooling);
504 0 : } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
505 0 : SetupOutputVariable(state,
506 : "Zone Cooltower Water Volume",
507 : Constant::Units::m3,
508 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
509 : OutputProcessor::TimeStepType::System,
510 : OutputProcessor::StoreType::Sum,
511 0 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
512 0 : SetupOutputVariable(state,
513 : "Zone Cooltower Storage Tank Water Volume",
514 : Constant::Units::m3,
515 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump,
516 : OutputProcessor::TimeStepType::System,
517 : OutputProcessor::StoreType::Sum,
518 0 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name);
519 0 : SetupOutputVariable(state,
520 : "Zone Cooltower Starved Mains Water Volume",
521 : Constant::Units::m3,
522 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeup,
523 : OutputProcessor::TimeStepType::System,
524 : OutputProcessor::StoreType::Sum,
525 0 : Zone(state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr).Name,
526 : Constant::eResource::MainsWater,
527 : OutputProcessor::Group::HVAC, // System
528 : OutputProcessor::EndUseCat::Cooling);
529 : }
530 : }
531 109 : }
532 :
533 1 : void CalcCoolTower(EnergyPlusData &state)
534 : {
535 :
536 : // SUBROUTINE INFORMATION:
537 : // AUTHOR Daeho Kang
538 : // DATE WRITTEN Aug 2008
539 :
540 : // REFERENCES:
541 : // Baruch Givoni. 1994. Passive and Low Energy Cooling of Buildings. Chapter 5: Evaporative Cooling Systems.
542 : // John Wiley & Sons, Inc.
543 :
544 : // SUBROUTINE PARAMETER DEFINITIONS:
545 1 : Real64 constexpr MinWindSpeed(0.1); // Minimum limit of outdoor air wind speed in m/s
546 1 : Real64 constexpr MaxWindSpeed(30.0); // Maximum limit of outdoor air wind speed in m/s
547 1 : Real64 constexpr UCFactor(60000.0); // Unit conversion factor m3/s to l/min
548 :
549 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
550 : Real64 CVF_ZoneNum; // Design flow rate in m3/s
551 : Real64 AirMassFlowRate; // Actual air mass flow rate in kg/s
552 : Real64 AirSpecHeat; // Specific heat of air
553 : Real64 AirDensity; // Density of air
554 : Real64 RhoWater; // Density of water
555 : Real64 PumpPartLoadRat; // Pump part load ratio (based on user schedule, or 1.0 for no schedule)
556 1 : Real64 WaterFlowRate = 0.0; // Calculated water flow rate in m3/s
557 1 : Real64 AirVolFlowRate = 0.0; // Calculated air volume flow rate in m3/s
558 : Real64 InletHumRat; // Humidity ratio of outdoor air
559 : Real64 OutletHumRat; // Humidity ratio of air at the cooltower outlet
560 1 : Real64 OutletTemp = 0.0; // Dry bulb temperature of air at the cooltower outlet
561 : Real64 IntHumRat; // Humidity ratio of initialized air
562 :
563 1 : auto &Zone(state.dataHeatBal->Zone);
564 :
565 2 : for (int CoolTowerNum = 1; CoolTowerNum <= (int)state.dataCoolTower->CoolTowerSys.size(); ++CoolTowerNum) {
566 1 : int const ZoneNum = state.dataCoolTower->CoolTowerSys(CoolTowerNum).ZonePtr;
567 1 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
568 1 : thisZoneHB.MCPTC = 0.0;
569 1 : thisZoneHB.MCPC = 0.0;
570 1 : thisZoneHB.CTMFL = 0.0;
571 1 : if ((state.dataHeatBal->doSpaceHeatBalance) && (state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr > 0)) {
572 0 : auto &thisSpaceHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr);
573 0 : thisSpaceHB.MCPTC = 0.0;
574 0 : thisSpaceHB.MCPC = 0.0;
575 0 : thisSpaceHB.CTMFL = 0.0;
576 : }
577 :
578 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).availSched->getCurrentVal() > 0.0) {
579 : // check component operation
580 1 : if (state.dataEnvrn->WindSpeed < MinWindSpeed || state.dataEnvrn->WindSpeed > MaxWindSpeed) continue;
581 1 : if (state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT < state.dataCoolTower->CoolTowerSys(CoolTowerNum).MinZoneTemp)
582 0 : continue;
583 :
584 : // Unit is on and simulate this component
585 : // Determine the temperature and air flow rate at the cooltower outlet
586 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType == FlowCtrl::WindDriven) {
587 1 : Real64 const height_sqrt(std::sqrt(state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight));
588 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletVelocity = 0.7 * height_sqrt + 0.47 * (state.dataEnvrn->WindSpeed - 1.0);
589 1 : AirVolFlowRate =
590 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletArea * state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletVelocity;
591 1 : AirVolFlowRate = min(AirVolFlowRate, state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate);
592 1 : WaterFlowRate = (AirVolFlowRate / (0.0125 * height_sqrt));
593 1 : if (WaterFlowRate > state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor) {
594 1 : WaterFlowRate = state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor;
595 1 : AirVolFlowRate = 0.0125 * WaterFlowRate * height_sqrt;
596 1 : AirVolFlowRate = min(AirVolFlowRate, state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate);
597 : }
598 1 : WaterFlowRate = min(WaterFlowRate, (state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor));
599 1 : OutletTemp =
600 1 : state.dataEnvrn->OutDryBulbTemp - (state.dataEnvrn->OutDryBulbTemp - state.dataEnvrn->OutWetBulbTemp) *
601 1 : (1.0 - std::exp(-0.8 * state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight)) *
602 1 : (1.0 - std::exp(-0.15 * WaterFlowRate));
603 0 : } else if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FlowCtrlType == FlowCtrl::FlowSchedule) {
604 0 : WaterFlowRate = state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxWaterFlowRate * UCFactor;
605 0 : AirVolFlowRate = 0.0125 * WaterFlowRate * std::sqrt(state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight);
606 0 : AirVolFlowRate = min(AirVolFlowRate, state.dataCoolTower->CoolTowerSys(CoolTowerNum).MaxAirVolFlowRate);
607 0 : OutletTemp =
608 0 : state.dataEnvrn->OutDryBulbTemp - (state.dataEnvrn->OutDryBulbTemp - state.dataEnvrn->OutWetBulbTemp) *
609 0 : (1.0 - std::exp(-0.8 * state.dataCoolTower->CoolTowerSys(CoolTowerNum).TowerHeight)) *
610 0 : (1.0 - std::exp(-0.15 * WaterFlowRate));
611 : }
612 :
613 1 : if (OutletTemp < state.dataEnvrn->OutWetBulbTemp) {
614 0 : ShowSevereError(state, "Cooltower outlet temperature exceed the outdoor wet bulb temperature reset to input values");
615 0 : ShowContinueError(state, format("Occurs in Cooltower ={}", state.dataCoolTower->CoolTowerSys(CoolTowerNum).Name));
616 : }
617 :
618 1 : WaterFlowRate /= UCFactor;
619 : // Determine actual water flow rate
620 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss > 0.0) {
621 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualWaterFlowRate =
622 1 : WaterFlowRate * (1.0 + state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracWaterLoss);
623 : } else {
624 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualWaterFlowRate = WaterFlowRate;
625 : }
626 :
627 : // Determine actual air flow rate
628 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched > 0.0) {
629 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate =
630 1 : AirVolFlowRate * (1.0 - state.dataCoolTower->CoolTowerSys(CoolTowerNum).FracFlowSched);
631 : } else {
632 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate = AirVolFlowRate;
633 : }
634 :
635 : // Determine pump power
636 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).pumpSched->getCurrentVal() > 0) {
637 0 : PumpPartLoadRat = state.dataCoolTower->CoolTowerSys(CoolTowerNum).pumpSched->getCurrentVal();
638 : } else {
639 1 : PumpPartLoadRat = 1.0;
640 : }
641 :
642 : // Determine air mass flow rate and volume flow rate
643 2 : InletHumRat = Psychrometrics::PsyWFnTdbTwbPb(
644 1 : state, state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutWetBulbTemp, state.dataEnvrn->OutBaroPress);
645 : // Assume no pressure drops and no changes in enthalpy between inlet and outlet air
646 1 : IntHumRat = Psychrometrics::PsyWFnTdbH(state, OutletTemp, state.dataEnvrn->OutEnthalpy); // Initialized humidity ratio
647 1 : AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, OutletTemp, IntHumRat);
648 1 : AirMassFlowRate = AirDensity * state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate;
649 : // From the mass balance W_in*(m_air + m_water) = W_out*m_air
650 1 : RhoWater = Psychrometrics::RhoH2O(OutletTemp); // Assume T_water = T_outlet
651 1 : OutletHumRat = (InletHumRat * (AirMassFlowRate + (state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualWaterFlowRate * RhoWater))) /
652 : AirMassFlowRate;
653 1 : AirSpecHeat = Psychrometrics::PsyCpAirFnW(OutletHumRat);
654 1 : AirDensity = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, OutletTemp, OutletHumRat); // Outlet air density
655 1 : CVF_ZoneNum = state.dataCoolTower->CoolTowerSys(CoolTowerNum).ActualAirVolFlowRate *
656 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).availSched->getCurrentVal();
657 1 : Real64 thisMCPC = CVF_ZoneNum * AirDensity * AirSpecHeat;
658 1 : Real64 thisMCPTC = thisMCPC * OutletTemp;
659 1 : Real64 thisCTMFL = thisMCPC / AirSpecHeat;
660 1 : Real64 thisZT = thisZoneHB.ZT;
661 1 : Real64 thisAirHumRat = thisZoneHB.airHumRat;
662 1 : thisZoneHB.MCPC = thisMCPC;
663 1 : thisZoneHB.MCPTC = thisMCPTC;
664 1 : thisZoneHB.CTMFL = thisCTMFL;
665 1 : if ((state.dataHeatBal->doSpaceHeatBalance) && (state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr > 0)) {
666 : auto &thisSpaceHB =
667 0 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataCoolTower->CoolTowerSys(CoolTowerNum).spacePtr);
668 0 : thisSpaceHB.MCPC = thisMCPC;
669 0 : thisSpaceHB.MCPTC = thisMCPTC;
670 0 : thisSpaceHB.CTMFL = thisCTMFL;
671 0 : thisZT = thisSpaceHB.ZT;
672 0 : thisAirHumRat = thisSpaceHB.airHumRat;
673 : }
674 :
675 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower = thisMCPC * std::abs(thisZT - OutletTemp);
676 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower = CVF_ZoneNum * std::abs(thisAirHumRat - OutletHumRat);
677 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletTemp = OutletTemp;
678 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletHumRat = OutletHumRat;
679 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate = CVF_ZoneNum;
680 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate = thisCTMFL;
681 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRateStd = thisCTMFL / state.dataEnvrn->StdRhoAir;
682 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletDBTemp = Zone(ZoneNum).OutDryBulbTemp;
683 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletWBTemp = Zone(ZoneNum).OutWetBulbTemp;
684 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletHumRat = state.dataEnvrn->OutHumRat;
685 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate = (std::abs(InletHumRat - OutletHumRat) * thisCTMFL) / RhoWater;
686 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate = 0.0; // initialize -- calc in update
687 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower =
688 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).RatedPumpPower * PumpPartLoadRat;
689 : } else { // Unit is off
690 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower = 0.0;
691 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower = 0.0;
692 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletTemp = 0.0;
693 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).OutletHumRat = 0.0;
694 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate = 0.0;
695 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate = 0.0;
696 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRateStd = 0.0;
697 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletDBTemp = 0.0;
698 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).InletHumRat = 0.0;
699 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower = 0.0;
700 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate = 0.0;
701 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate = 0.0;
702 : }
703 : }
704 1 : }
705 :
706 1 : void UpdateCoolTower(EnergyPlusData &state)
707 : {
708 :
709 : // SUBROUTINE INFORMATION:
710 : // AUTHOR Richard J. Liesen
711 : // DATE WRITTEN October 2000
712 : // MODIFIED Aug 2008 Daeho Kang
713 :
714 2 : for (int CoolTowerNum = 1; CoolTowerNum <= (int)state.dataCoolTower->CoolTowerSys.size(); ++CoolTowerNum) {
715 :
716 : // Set the demand request for supply water from water storage tank (if needed)
717 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
718 0 : state.dataWaterData->WaterStorage(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupTankID)
719 0 : .VdotRequestDemand(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterTankDemandARRID) =
720 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate;
721 : }
722 :
723 : // check if should be starved by restricted flow from tank
724 1 : if (state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupplyMode == WaterSupplyMode::FromTank) {
725 0 : Real64 AvailWaterRate = state.dataWaterData->WaterStorage(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterSupTankID)
726 0 : .VdotAvailDemand(state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterTankDemandARRID);
727 0 : if (AvailWaterRate < state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate) {
728 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate =
729 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate - AvailWaterRate;
730 0 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate = AvailWaterRate;
731 : }
732 : }
733 : }
734 1 : }
735 :
736 1 : void ReportCoolTower(EnergyPlusData &state)
737 : {
738 :
739 : // SUBROUTINE INFORMATION:
740 : // AUTHOR Daeho Kang
741 : // DATE WRITTEN Aut 2008
742 :
743 1 : Real64 const TSMult = state.dataHVACGlobal->TimeStepSysSec;
744 :
745 2 : for (int CoolTowerNum = 1; CoolTowerNum <= (int)state.dataCoolTower->CoolTowerSys.size(); ++CoolTowerNum) {
746 :
747 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirVol = state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirVolFlowRate * TSMult;
748 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTAirMass = state.dataCoolTower->CoolTowerSys(CoolTowerNum).AirMassFlowRate * TSMult;
749 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatLoss = state.dataCoolTower->CoolTowerSys(CoolTowerNum).SenHeatPower * TSMult;
750 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatLoss = state.dataCoolTower->CoolTowerSys(CoolTowerNum).LatHeatPower * TSMult;
751 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecConsump = state.dataCoolTower->CoolTowerSys(CoolTowerNum).PumpElecPower * TSMult;
752 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsump =
753 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterConsumpRate * TSMult;
754 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeup =
755 1 : state.dataCoolTower->CoolTowerSys(CoolTowerNum).CoolTWaterStarvMakeupRate * TSMult;
756 : }
757 1 : }
758 :
759 : } // namespace CoolTower
760 :
761 : } // namespace EnergyPlus
|