Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/BranchNodeConnections.hh>
57 : #include <EnergyPlus/Construction.hh>
58 : #include <EnergyPlus/Data/EnergyPlusData.hh>
59 : #include <EnergyPlus/DataConversions.hh>
60 : #include <EnergyPlus/DataEnvironment.hh>
61 : #include <EnergyPlus/DataHVACGlobals.hh>
62 : #include <EnergyPlus/DataHeatBalFanSys.hh>
63 : #include <EnergyPlus/DataHeatBalSurface.hh>
64 : #include <EnergyPlus/DataHeatBalance.hh>
65 : #include <EnergyPlus/DataLoopNode.hh>
66 : #include <EnergyPlus/DataSizing.hh>
67 : #include <EnergyPlus/DataSurfaceLists.hh>
68 : #include <EnergyPlus/DataSurfaces.hh>
69 : #include <EnergyPlus/FluidProperties.hh>
70 : #include <EnergyPlus/General.hh>
71 : #include <EnergyPlus/GeneralRoutines.hh>
72 : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
73 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
74 : #include <EnergyPlus/NodeInputManager.hh>
75 : #include <EnergyPlus/OutputProcessor.hh>
76 : #include <EnergyPlus/Plant/DataPlant.hh>
77 : #include <EnergyPlus/Plant/PlantLocation.hh>
78 : #include <EnergyPlus/PlantUtilities.hh>
79 : #include <EnergyPlus/Psychrometrics.hh>
80 : #include <EnergyPlus/ScheduleManager.hh>
81 : #include <EnergyPlus/SwimmingPool.hh>
82 : #include <EnergyPlus/UtilityRoutines.hh>
83 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
84 :
85 : namespace EnergyPlus::SwimmingPool {
86 :
87 : // MODULE INFORMATION:
88 : // AUTHOR Rick Strand, Ho-Sung Kim
89 : // DATE WRITTEN June 2012 (F90) and October 2014 (C++)
90 :
91 : // PURPOSE OF THIS MODULE:
92 : // The purpose of this module is to encapsulate the data and algorithms required
93 : // to manage the SwimmingPool System Component.
94 :
95 : // METHODOLOGY EMPLOYED:
96 : // The swimming pool acts as a surface within the heat balance and then connects
97 : // to the plant via a water loop.
98 :
99 : // REFERENCES:
100 : // 1. ASHRAE (2011). 2011 ASHRAE Handbook - HVAC Applications. Atlanta: American Society of Heating,
101 : // Refrigerating and Air-Conditioning Engineers, Inc., p.5.6-5.9.
102 : // 2. Janis, R. and W. Tao (2005). Mechanical and Electrical Systems in Buildings. 3rd ed. Upper
103 : // Saddle River, NJ: Pearson Education, Inc., p.246.
104 : // 3. Kittler, R. (1989). Indoor Natatorium Design and Energy Recycling. ASHRAE Transactions 95(1), p.521-526.
105 : // 4. Smith, C., R. Jones, and G. Lof (1993). Energy Requirements and Potential Savings for Heated
106 : // Indoor Swimming Pools. ASHRAE Transactions 99(2), p.864-874.
107 :
108 2 : SwimmingPoolData *SwimmingPoolData::factory(EnergyPlusData &state, std::string const &objectName)
109 : {
110 2 : if (state.dataSwimmingPools->getSwimmingPoolInput) {
111 2 : GetSwimmingPool(state);
112 2 : state.dataSwimmingPools->getSwimmingPoolInput = false;
113 : }
114 : // Now look for this particular swimming pool in the list
115 2 : for (auto &pool : state.dataSwimmingPools->Pool) {
116 2 : if (pool.Name == objectName) {
117 2 : return &pool;
118 : }
119 : }
120 : // If we didn't find it, fatal
121 0 : ShowFatalError(state,
122 : format("LocalSwimmingPoolFactory: Error getting inputs or index for swimming pool named: {}", objectName)); // LCOV_EXCL_LINE
123 : // Shut up the compiler
124 : return nullptr; // LCOV_EXCL_LINE
125 : }
126 :
127 32734 : void SwimmingPoolData::simulate(EnergyPlusData &state,
128 : [[maybe_unused]] const PlantLocation &calledFromLocation,
129 : bool FirstHVACIteration,
130 : [[maybe_unused]] Real64 &CurLoad,
131 : [[maybe_unused]] bool RunFlag)
132 : {
133 32734 : state.dataHeatBalFanSys->SumConvPool(this->ZonePtr) = 0.0;
134 32734 : state.dataHeatBalFanSys->SumLatentPool(this->ZonePtr) = 0.0;
135 :
136 32734 : CurLoad = 0.0;
137 32734 : RunFlag = true;
138 :
139 32734 : this->initialize(state, FirstHVACIteration);
140 :
141 32734 : this->calculate(state);
142 :
143 32734 : this->update(state);
144 :
145 32734 : if (state.dataSwimmingPools->NumSwimmingPools > 0) HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state);
146 :
147 32734 : this->report(state);
148 32734 : }
149 :
150 2 : void GetSwimmingPool(EnergyPlusData &state)
151 : {
152 : // SUBROUTINE INFORMATION:
153 : // AUTHOR Rick Strand, Ho-Sung Kim
154 : // DATE WRITTEN October 2014
155 :
156 : // PURPOSE OF THIS SUBROUTINE:
157 : // This subroutine reads the input for all swimming pools present in
158 : // the user input file. This will contain all of the information needed
159 : // to simulate a swimming pool.
160 :
161 : // SUBROUTINE PARAMETER DEFINITIONS:
162 : static constexpr std::string_view RoutineName("GetSwimmingPool: "); // include trailing blank space
163 2 : Real64 constexpr MinCoverFactor(0.0); // minimum value for cover factors
164 2 : Real64 constexpr MaxCoverFactor(1.0); // maximum value for cover factors
165 2 : Real64 constexpr MinDepth(0.05); // minimum average pool depth (to avoid obvious input errors)
166 2 : Real64 constexpr MaxDepth(10.0); // maximum average pool depth (to avoid obvious input errors)
167 2 : Real64 constexpr MinPowerFactor(0.0); // minimum power factor for miscellaneous equipment
168 :
169 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
170 2 : bool ErrorsFound(false); // Set to true if something goes wrong
171 2 : std::string CurrentModuleObject; // for ease in getting objects
172 2 : Array1D_string Alphas; // Alpha items for object
173 2 : Array1D_string cAlphaFields; // Alpha field names
174 2 : Array1D_string cNumericFields; // Numeric field names
175 2 : int IOStatus = 0; // Used in GetObjectItem
176 2 : Array1D<Real64> Numbers; // Numeric items for object
177 2 : int NumAlphas = 0; // Number of Alphas for each GetObjectItem call
178 2 : int NumArgs = 0; // Unused variable that is part of a subroutine call
179 2 : int NumNumbers = 0; // Number of Numbers for each GetObjectItem call
180 2 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
181 2 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
182 :
183 : // Initializations and allocations
184 2 : int MaxAlphas = 0; // Maximum number of alphas for these input keywords
185 2 : int MaxNumbers = 0; // Maximum number of numbers for these input keywords
186 :
187 2 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "SwimmingPool:Indoor", NumArgs, NumAlphas, NumNumbers);
188 2 : MaxAlphas = max(MaxAlphas, NumAlphas);
189 2 : MaxNumbers = max(MaxNumbers, NumNumbers);
190 :
191 2 : Alphas.allocate(MaxAlphas);
192 2 : Alphas = "";
193 2 : Numbers.allocate(MaxNumbers);
194 2 : Numbers = 0.0;
195 2 : cAlphaFields.allocate(MaxAlphas);
196 2 : cAlphaFields = "";
197 2 : cNumericFields.allocate(MaxNumbers);
198 2 : cNumericFields = "";
199 2 : lAlphaBlanks.allocate(MaxAlphas);
200 2 : lAlphaBlanks = true;
201 2 : lNumericBlanks.allocate(MaxNumbers);
202 2 : lNumericBlanks = true;
203 :
204 2 : state.dataSwimmingPools->NumSwimmingPools = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "SwimmingPool:Indoor");
205 2 : state.dataSwimmingPools->CheckEquipName.allocate(state.dataSwimmingPools->NumSwimmingPools);
206 2 : state.dataSwimmingPools->CheckEquipName = true;
207 :
208 2 : state.dataSwimmingPools->Pool.allocate(state.dataSwimmingPools->NumSwimmingPools);
209 :
210 : // Obtain all of the user data related to indoor swimming pools...
211 2 : CurrentModuleObject = "SwimmingPool:Indoor";
212 4 : for (int Item = 1; Item <= state.dataSwimmingPools->NumSwimmingPools; ++Item) {
213 :
214 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
215 : CurrentModuleObject,
216 : Item,
217 : Alphas,
218 : NumAlphas,
219 : Numbers,
220 : NumNumbers,
221 : IOStatus,
222 : lNumericBlanks,
223 : lAlphaBlanks,
224 : cAlphaFields,
225 : cNumericFields);
226 2 : Util::IsNameEmpty(state, Alphas(1), CurrentModuleObject, ErrorsFound);
227 2 : state.dataSwimmingPools->Pool(Item).Name = Alphas(1);
228 :
229 2 : state.dataSwimmingPools->Pool(Item).SurfaceName = Alphas(2);
230 2 : state.dataSwimmingPools->Pool(Item).SurfacePtr = 0;
231 38 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
232 38 : if (Util::SameString(state.dataSurface->Surface(SurfNum).Name, state.dataSwimmingPools->Pool(Item).SurfaceName)) {
233 2 : state.dataSwimmingPools->Pool(Item).SurfacePtr = SurfNum;
234 2 : break;
235 : }
236 : }
237 :
238 2 : state.dataSwimmingPools->Pool(Item).ErrorCheckSetupPoolSurface(state, Alphas(1), Alphas(2), cAlphaFields(2), ErrorsFound);
239 :
240 2 : state.dataSwimmingPools->Pool(Item).AvgDepth = Numbers(1);
241 2 : if (state.dataSwimmingPools->Pool(Item).AvgDepth < MinDepth) {
242 0 : ShowWarningError(state, format("{}{}=\"{} has an average depth that is too small.", RoutineName, CurrentModuleObject, Alphas(1)));
243 0 : ShowContinueError(state, "The pool average depth has been reset to the minimum allowed depth.");
244 2 : } else if (state.dataSwimmingPools->Pool(Item).AvgDepth > MaxDepth) {
245 0 : ShowSevereError(state, format("{}{}=\"{} has an average depth that is too large.", RoutineName, CurrentModuleObject, Alphas(1)));
246 0 : ShowContinueError(state, "The pool depth must be less than the maximum average depth of 10 meters.");
247 0 : ErrorsFound = true;
248 : }
249 :
250 2 : state.dataSwimmingPools->Pool(Item).ActivityFactorSchedName = Alphas(3);
251 2 : state.dataSwimmingPools->Pool(Item).ActivityFactorSchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(3));
252 2 : if ((state.dataSwimmingPools->Pool(Item).ActivityFactorSchedPtr == 0) && (!lAlphaBlanks(3))) {
253 0 : ShowSevereError(state, format("{} not found: {}", cAlphaFields(3), Alphas(3)));
254 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
255 0 : ErrorsFound = true;
256 : }
257 :
258 2 : state.dataSwimmingPools->Pool(Item).MakeupWaterSupplySchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(4));
259 2 : if ((state.dataSwimmingPools->Pool(Item).MakeupWaterSupplySchedPtr == 0) && (!lAlphaBlanks(4))) {
260 0 : ShowSevereError(state, format("{} not found: {}", cAlphaFields(4), Alphas(4)));
261 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
262 0 : ErrorsFound = true;
263 : }
264 :
265 2 : state.dataSwimmingPools->Pool(Item).CoverSchedName = Alphas(5);
266 2 : state.dataSwimmingPools->Pool(Item).CoverSchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(5));
267 2 : if ((state.dataSwimmingPools->Pool(Item).CoverSchedPtr == 0) && (!lAlphaBlanks(5))) {
268 0 : ShowSevereError(state, format("{} not found: {}", cAlphaFields(5), Alphas(5)));
269 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
270 0 : ErrorsFound = true;
271 : }
272 :
273 2 : state.dataSwimmingPools->Pool(Item).CoverEvapFactor = Numbers(2);
274 2 : if (state.dataSwimmingPools->Pool(Item).CoverEvapFactor < MinCoverFactor) {
275 0 : ShowWarningError(state, format("{}{}=\"{} has an evaporation cover factor less than zero.", RoutineName, CurrentModuleObject, Alphas(1)));
276 0 : ShowContinueError(state, "The evaporation cover factor has been reset to zero.");
277 0 : state.dataSwimmingPools->Pool(Item).CoverEvapFactor = MinCoverFactor;
278 2 : } else if (state.dataSwimmingPools->Pool(Item).CoverEvapFactor > MaxCoverFactor) {
279 0 : ShowWarningError(state,
280 0 : format("{}{}=\"{} has an evaporation cover factor greater than one.", RoutineName, CurrentModuleObject, Alphas(1)));
281 0 : ShowContinueError(state, "The evaporation cover factor has been reset to one.");
282 0 : state.dataSwimmingPools->Pool(Item).CoverEvapFactor = MaxCoverFactor;
283 : }
284 :
285 2 : state.dataSwimmingPools->Pool(Item).CoverConvFactor = Numbers(3);
286 2 : if (state.dataSwimmingPools->Pool(Item).CoverConvFactor < MinCoverFactor) {
287 0 : ShowWarningError(state, format("{}{}=\"{} has a convection cover factor less than zero.", RoutineName, CurrentModuleObject, Alphas(1)));
288 0 : ShowContinueError(state, "The convection cover factor has been reset to zero.");
289 0 : state.dataSwimmingPools->Pool(Item).CoverConvFactor = MinCoverFactor;
290 2 : } else if (state.dataSwimmingPools->Pool(Item).CoverConvFactor > MaxCoverFactor) {
291 0 : ShowWarningError(state, format("{}{}=\"{} has a convection cover factor greater than one.", RoutineName, CurrentModuleObject, Alphas(1)));
292 0 : ShowContinueError(state, "The convection cover factor has been reset to one.");
293 0 : state.dataSwimmingPools->Pool(Item).CoverConvFactor = MaxCoverFactor;
294 : }
295 :
296 2 : state.dataSwimmingPools->Pool(Item).CoverSWRadFactor = Numbers(4);
297 2 : if (state.dataSwimmingPools->Pool(Item).CoverSWRadFactor < MinCoverFactor) {
298 0 : ShowWarningError(
299 : state,
300 0 : format("{}{}=\"{} has a short-wavelength radiation cover factor less than zero.", RoutineName, CurrentModuleObject, Alphas(1)));
301 0 : ShowContinueError(state, "The short-wavelength radiation cover factor has been reset to zero.");
302 0 : state.dataSwimmingPools->Pool(Item).CoverSWRadFactor = MinCoverFactor;
303 2 : } else if (state.dataSwimmingPools->Pool(Item).CoverSWRadFactor > MaxCoverFactor) {
304 0 : ShowWarningError(
305 : state,
306 0 : format("{}{}=\"{} has a short-wavelength radiation cover factor greater than one.", RoutineName, CurrentModuleObject, Alphas(1)));
307 0 : ShowContinueError(state, "The short-wavelength radiation cover factor has been reset to one.");
308 0 : state.dataSwimmingPools->Pool(Item).CoverSWRadFactor = MaxCoverFactor;
309 : }
310 :
311 2 : state.dataSwimmingPools->Pool(Item).CoverLWRadFactor = Numbers(5);
312 2 : if (state.dataSwimmingPools->Pool(Item).CoverLWRadFactor < MinCoverFactor) {
313 0 : ShowWarningError(
314 0 : state, format("{}{}=\"{} has a long-wavelength radiation cover factor less than zero.", RoutineName, CurrentModuleObject, Alphas(1)));
315 0 : ShowContinueError(state, "The long-wavelength radiation cover factor has been reset to zero.");
316 0 : state.dataSwimmingPools->Pool(Item).CoverLWRadFactor = MinCoverFactor;
317 2 : } else if (state.dataSwimmingPools->Pool(Item).CoverLWRadFactor > MaxCoverFactor) {
318 0 : ShowWarningError(
319 : state,
320 0 : format("{}{}=\"{} has a long-wavelength radiation cover factor greater than one.", RoutineName, CurrentModuleObject, Alphas(1)));
321 0 : ShowContinueError(state, "The long-wavelength radiation cover factor has been reset to one.");
322 0 : state.dataSwimmingPools->Pool(Item).CoverLWRadFactor = MaxCoverFactor;
323 : }
324 :
325 2 : state.dataSwimmingPools->Pool(Item).WaterInletNodeName = Alphas(6);
326 2 : state.dataSwimmingPools->Pool(Item).WaterOutletNodeName = Alphas(7);
327 2 : state.dataSwimmingPools->Pool(Item).WaterInletNode =
328 4 : NodeInputManager::GetOnlySingleNode(state,
329 2 : Alphas(6),
330 : ErrorsFound,
331 : DataLoopNode::ConnectionObjectType::SwimmingPoolIndoor,
332 2 : Alphas(1),
333 : DataLoopNode::NodeFluidType::Water,
334 : DataLoopNode::ConnectionType::Inlet,
335 : NodeInputManager::CompFluidStream::Primary,
336 : DataLoopNode::ObjectIsNotParent);
337 2 : state.dataSwimmingPools->Pool(Item).WaterOutletNode =
338 4 : NodeInputManager::GetOnlySingleNode(state,
339 2 : Alphas(7),
340 : ErrorsFound,
341 : DataLoopNode::ConnectionObjectType::SwimmingPoolIndoor,
342 2 : Alphas(1),
343 : DataLoopNode::NodeFluidType::Water,
344 : DataLoopNode::ConnectionType::Outlet,
345 : NodeInputManager::CompFluidStream::Primary,
346 : DataLoopNode::ObjectIsNotParent);
347 2 : if ((!lAlphaBlanks(6)) || (!lAlphaBlanks(7))) {
348 2 : BranchNodeConnections::TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(6), Alphas(7), "Hot Water Nodes");
349 : }
350 2 : state.dataSwimmingPools->Pool(Item).WaterVolFlowMax = Numbers(6);
351 2 : state.dataSwimmingPools->Pool(Item).MiscPowerFactor = Numbers(7);
352 2 : if (state.dataSwimmingPools->Pool(Item).MiscPowerFactor < MinPowerFactor) {
353 0 : ShowWarningError(state,
354 0 : format("{}{}=\"{} has a miscellaneous power factor less than zero.", RoutineName, CurrentModuleObject, Alphas(1)));
355 0 : ShowContinueError(state, "The miscellaneous power factor has been reset to zero.");
356 0 : state.dataSwimmingPools->Pool(Item).MiscPowerFactor = MinPowerFactor;
357 : }
358 :
359 2 : state.dataSwimmingPools->Pool(Item).SetPtTempSchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(8));
360 2 : if ((state.dataSwimmingPools->Pool(Item).SetPtTempSchedPtr == 0) && (!lAlphaBlanks(8))) {
361 0 : ShowSevereError(state, format("{} not found: {}", cAlphaFields(8), Alphas(8)));
362 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
363 0 : ErrorsFound = true;
364 : }
365 2 : if (lAlphaBlanks(8)) {
366 0 : ShowSevereError(state,
367 0 : format("{} left blank. This is NOT allowed as there must be a pool water setpoint temperature.", cAlphaFields(8)));
368 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
369 0 : ErrorsFound = true;
370 : }
371 :
372 2 : state.dataSwimmingPools->Pool(Item).MaxNumOfPeople = Numbers(8);
373 2 : if (state.dataSwimmingPools->Pool(Item).MaxNumOfPeople < 0.0) {
374 0 : ShowWarningError(
375 0 : state, format("{}{}=\"{} was entered with negative people. This is not allowed.", RoutineName, CurrentModuleObject, Alphas(1)));
376 0 : ShowContinueError(state, "The number of people has been reset to zero.");
377 0 : state.dataSwimmingPools->Pool(Item).MaxNumOfPeople = 0.0;
378 : }
379 :
380 2 : state.dataSwimmingPools->Pool(Item).PeopleSchedName = Alphas(9);
381 2 : state.dataSwimmingPools->Pool(Item).PeopleSchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(9));
382 2 : if ((state.dataSwimmingPools->Pool(Item).PeopleSchedPtr == 0) && (!lAlphaBlanks(9))) {
383 0 : ShowSevereError(state, format("{} not found: {}", cAlphaFields(9), Alphas(9)));
384 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
385 0 : ErrorsFound = true;
386 : }
387 :
388 2 : state.dataSwimmingPools->Pool(Item).PeopleHeatGainSchedName = Alphas(10);
389 2 : state.dataSwimmingPools->Pool(Item).PeopleHeatGainSchedPtr = ScheduleManager::GetScheduleIndex(state, Alphas(10));
390 2 : if ((state.dataSwimmingPools->Pool(Item).PeopleHeatGainSchedPtr == 0) && (!lAlphaBlanks(10))) {
391 0 : ShowSevereError(state, format("{} not found: {}", cAlphaFields(10), Alphas(10)));
392 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
393 0 : ErrorsFound = true;
394 : }
395 : }
396 :
397 2 : Alphas.deallocate();
398 2 : Numbers.deallocate();
399 2 : cAlphaFields.deallocate();
400 2 : cNumericFields.deallocate();
401 2 : lAlphaBlanks.deallocate();
402 2 : lNumericBlanks.deallocate();
403 :
404 2 : if (ErrorsFound) {
405 0 : ShowFatalError(state, format("{}Errors found in swimming pool input. Preceding conditions cause termination.", RoutineName));
406 : }
407 2 : }
408 :
409 2 : void SwimmingPoolData::ErrorCheckSetupPoolSurface(
410 : EnergyPlusData &state, std::string_view Alpha1, std::string_view Alpha2, std::string_view cAlphaField2, bool &ErrorsFound)
411 : {
412 :
413 : static constexpr std::string_view RoutineName("ErrorCheckSetupPoolSurface: "); // include trailing blank space
414 : static constexpr std::string_view CurrentModuleObject("SwimmingPool:Indoor");
415 :
416 2 : if (this->SurfacePtr <= 0) {
417 0 : ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaField2, Alpha2));
418 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alpha1));
419 0 : ErrorsFound = true;
420 2 : } else if (state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(this->SurfacePtr)) {
421 0 : ShowSevereError(state, format("{}{}=\"{}\", Invalid Surface", RoutineName, CurrentModuleObject, Alpha1));
422 0 : ShowContinueError(state, format("{}=\"{}\" has been used in another radiant system, ventilated slab, or pool.", cAlphaField2, Alpha2));
423 0 : ShowContinueError(state,
424 : "A single surface can only be a radiant system, a ventilated slab, or a pool. It CANNOT be more than one of these.");
425 0 : ErrorsFound = true;
426 : // Something present that is not allowed for a swimming pool (non-CTF algorithm, movable insulation, or radiant source/sink
427 2 : } else if (state.dataSurface->Surface(this->SurfacePtr).HeatTransferAlgorithm != DataSurfaces::HeatTransferModel::CTF) {
428 0 : ShowSevereError(state,
429 0 : format("{} is a pool and is attempting to use a non-CTF solution algorithm. This is not allowed. Use the CTF solution "
430 : "algorithm for this surface.",
431 0 : state.dataSurface->Surface(this->SurfacePtr).Name));
432 0 : ErrorsFound = true;
433 :
434 2 : } else if (state.dataSurface->Surface(this->SurfacePtr).Class == DataSurfaces::SurfaceClass::Window) {
435 0 : ShowSevereError(state,
436 0 : format("{} is a pool and is defined as a window. This is not allowed. A pool must be a floor that is NOT a window.",
437 0 : state.dataSurface->Surface(this->SurfacePtr).Name));
438 0 : ErrorsFound = true;
439 2 : } else if (state.dataSurface->SurfMaterialMovInsulInt(this->SurfacePtr) > 0) {
440 0 : ShowSevereError(state,
441 0 : format("{} is a pool and has movable insulation. This is not allowed. Remove the movable insulation for this surface.",
442 0 : state.dataSurface->Surface(this->SurfacePtr).Name));
443 0 : ErrorsFound = true;
444 2 : } else if (state.dataConstruction->Construct(state.dataSurface->Surface(this->SurfacePtr).Construction).SourceSinkPresent) {
445 0 : ShowSevereError(
446 : state,
447 0 : format("{} is a pool and uses a construction with a source/sink. This is not allowed. Use a standard construction for this surface.",
448 0 : state.dataSurface->Surface(this->SurfacePtr).Name));
449 0 : ErrorsFound = true;
450 : } else { // ( Pool( Item ).SurfacePtr > 0 )
451 2 : state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(this->SurfacePtr) = true;
452 2 : state.dataSurface->SurfIsPool(this->SurfacePtr) = true;
453 2 : this->ZonePtr = state.dataSurface->Surface(this->SurfacePtr).Zone;
454 : // Check to make sure pool surface is a floor
455 2 : if (state.dataSurface->Surface(this->SurfacePtr).Class != DataSurfaces::SurfaceClass::Floor) {
456 0 : ShowSevereError(state, format("{}{}=\"{} contains a surface name that is NOT a floor.", RoutineName, CurrentModuleObject, Alpha1));
457 0 : ShowContinueError(
458 : state, "A swimming pool must be associated with a surface that is a FLOOR. Association with other surface types is not permitted.");
459 0 : ErrorsFound = true;
460 : }
461 : }
462 2 : }
463 :
464 32734 : void SwimmingPoolData::initialize(EnergyPlusData &state, bool const FirstHVACIteration // true during the first HVAC iteration
465 : )
466 : {
467 : // SUBROUTINE INFORMATION:
468 : // AUTHOR Rick Strand, Ho-Sung Kim
469 : // DATE WRITTEN October 2014
470 :
471 : // PURPOSE OF THIS SUBROUTINE:
472 : // This subroutine initializes variables relating to indoor swimming pools.
473 :
474 : // SUBROUTINE PARAMETER DEFINITIONS:
475 : static constexpr std::string_view RoutineName("InitSwimmingPool");
476 32734 : Real64 constexpr MinActivityFactor = 0.0; // Minimum value for activity factor
477 32734 : Real64 constexpr MaxActivityFactor = 10.0; // Maximum value for activity factor (realistically)
478 :
479 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
480 32734 : Real64 HeatGainPerPerson = ScheduleManager::GetCurrentScheduleValue(state, this->PeopleHeatGainSchedPtr);
481 32734 : Real64 PeopleModifier = ScheduleManager::GetCurrentScheduleValue(state, this->PeopleSchedPtr);
482 :
483 32734 : if (this->MyOneTimeFlag) {
484 2 : this->setupOutputVars(state); // Set up the output variables once here
485 2 : this->MyOneTimeFlag = false;
486 : }
487 :
488 32734 : SwimmingPoolData::initSwimmingPoolPlantLoopIndex(state);
489 :
490 32734 : if (state.dataGlobal->BeginEnvrnFlag && this->MyEnvrnFlagGeneral) {
491 10 : this->ZeroPoolSourceSumHATsurf = 0.0;
492 10 : this->QPoolSrcAvg = 0.0;
493 10 : this->HeatTransCoefsAvg = 0.0;
494 10 : this->LastQPoolSrc = 0.0;
495 10 : this->LastHeatTransCoefs = 0.0;
496 10 : this->LastSysTimeElapsed = 0.0;
497 10 : this->LastTimeStepSys = 0.0;
498 10 : this->MyEnvrnFlagGeneral = false;
499 : }
500 :
501 32734 : if (!state.dataGlobal->BeginEnvrnFlag) this->MyEnvrnFlagGeneral = true;
502 :
503 32734 : if (state.dataGlobal->BeginEnvrnFlag) {
504 238 : this->PoolWaterTemp = 23.0;
505 238 : this->HeatPower = 0.0;
506 238 : this->HeatEnergy = 0.0;
507 238 : this->MiscEquipPower = 0.0;
508 238 : this->MiscEquipEnergy = 0.0;
509 238 : this->WaterInletTemp = 0.0;
510 238 : this->WaterOutletTemp = 0.0;
511 238 : this->WaterMassFlowRate = 0.0;
512 238 : this->PeopleHeatGain = 0.0;
513 238 : Real64 Density = FluidProperties::GetDensityGlycol(state, "WATER", this->PoolWaterTemp, this->GlycolIndex, RoutineName);
514 238 : this->WaterMass = state.dataSurface->Surface(this->SurfacePtr).Area * this->AvgDepth * Density;
515 238 : this->WaterMassFlowRateMax = this->WaterVolFlowMax * Density;
516 238 : this->initSwimmingPoolPlantNodeFlow(state);
517 : }
518 :
519 32734 : if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) { // This is the first pass through in a particular time step
520 :
521 16242 : int ZoneNum = this->ZonePtr;
522 16242 : this->ZeroPoolSourceSumHATsurf =
523 16242 : state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state); // Set this to figure what the impact of the swimming pool on all zone surfaces
524 16242 : this->QPoolSrcAvg = 0.0; // Initialize this variable to zero (pool parameters "off")
525 16242 : this->HeatTransCoefsAvg = 0.0; // Initialize this variable to zero (pool parameters "off")
526 16242 : this->LastQPoolSrc = 0.0; // At the start of a time step, reset to zero so average calculation can begin again
527 16242 : this->LastSysTimeElapsed = 0.0; // At the start of a time step, reset to zero so average calculation can begin again
528 16242 : this->LastTimeStepSys = 0.0; // At the start of a time step, reset to zero so average calculation can begin again
529 : }
530 :
531 : // initialize the flow rate for the component on the plant side (this follows standard procedure for other components like low temperature
532 : // radiant systems)
533 32734 : Real64 mdot = 0.0;
534 32734 : PlantUtilities::SetComponentFlowRate(state, mdot, this->WaterInletNode, this->WaterOutletNode, this->HWplantLoc);
535 32734 : this->WaterInletTemp = state.dataLoopNodes->Node(this->WaterInletNode).Temp;
536 :
537 : // get the schedule values for different scheduled parameters
538 32734 : if (this->ActivityFactorSchedPtr > 0) {
539 32734 : this->CurActivityFactor = ScheduleManager::GetCurrentScheduleValue(state, this->ActivityFactorSchedPtr);
540 32734 : if (this->CurActivityFactor < MinActivityFactor) {
541 0 : this->CurActivityFactor = MinActivityFactor;
542 0 : ShowWarningError(state,
543 0 : format("{}: Swimming Pool =\"{} Activity Factor Schedule =\"{} has a negative value. This is not allowed.",
544 : RoutineName,
545 0 : this->Name,
546 0 : this->ActivityFactorSchedName));
547 0 : ShowContinueError(state, "The activity factor has been reset to zero.");
548 : }
549 32734 : if (this->CurActivityFactor > MaxActivityFactor) {
550 0 : this->CurActivityFactor = 1.0;
551 0 : ShowWarningError(state,
552 0 : format("{}: Swimming Pool =\"{} Activity Factor Schedule =\"{} has a value larger than 10. This is not allowed.",
553 : RoutineName,
554 0 : this->Name,
555 0 : this->ActivityFactorSchedName));
556 0 : ShowContinueError(state, "The activity factor has been reset to unity.");
557 : }
558 : } else {
559 : // default is activity factor of 1.0
560 0 : this->CurActivityFactor = 1.0;
561 : }
562 :
563 32734 : this->CurSetPtTemp = ScheduleManager::GetCurrentScheduleValue(state, this->SetPtTempSchedPtr);
564 :
565 32734 : if (this->MakeupWaterSupplySchedPtr > 0) {
566 32734 : this->CurMakeupWaterTemp = ScheduleManager::GetCurrentScheduleValue(state, this->MakeupWaterSupplySchedPtr);
567 : } else {
568 : // use water main temperaure if no schedule present in input
569 0 : this->CurMakeupWaterTemp = state.dataEnvrn->WaterMainsTemp;
570 : }
571 :
572 : // determine the current heat gain from people
573 32734 : if (this->PeopleHeatGainSchedPtr > 0) {
574 32734 : if (HeatGainPerPerson < 0.0) {
575 0 : ShowWarningError(state,
576 0 : format("{}: Swimming Pool =\"{} Heat Gain Schedule =\"{} has a negative value. This is not allowed.",
577 : RoutineName,
578 0 : this->Name,
579 0 : this->PeopleHeatGainSchedName));
580 0 : ShowContinueError(state, "The heat gain per person has been reset to zero.");
581 0 : HeatGainPerPerson = 0.0;
582 : }
583 32734 : if (this->PeopleSchedPtr > 0) {
584 32734 : if (PeopleModifier < 0.0) {
585 0 : ShowWarningError(state,
586 0 : format("{}: Swimming Pool =\"{} People Schedule =\"{} has a negative value. This is not allowed.",
587 : RoutineName,
588 0 : this->Name,
589 0 : this->PeopleSchedName));
590 0 : ShowContinueError(state, "The number of people has been reset to zero.");
591 0 : PeopleModifier = 0.0;
592 : }
593 : } else { // no people schedule entered--assume that full number always present
594 0 : PeopleModifier = 1.0;
595 : }
596 : } else { // no heat gain schedule added--assume a zero value for Heat Gain per Person and no people present
597 0 : HeatGainPerPerson = 0.0;
598 0 : PeopleModifier = 0.0;
599 : }
600 32734 : this->PeopleHeatGain = PeopleModifier * HeatGainPerPerson * this->MaxNumOfPeople;
601 :
602 : // once cover schedule value is established, define the current values of the cover heat transfer factors
603 32734 : if (this->CoverSchedPtr > 0) {
604 32734 : this->CurCoverSchedVal = ScheduleManager::GetCurrentScheduleValue(state, this->CoverSchedPtr);
605 32734 : if (this->CurCoverSchedVal > 1.0) {
606 0 : ShowWarningError(state,
607 0 : format("{}: Swimming Pool =\"{} Cover Schedule =\"{} has a value greater than 1.0 (100%). This is not allowed.",
608 : RoutineName,
609 0 : this->Name,
610 0 : this->CoverSchedName));
611 0 : ShowContinueError(state, "The cover has been reset to one or fully covered.");
612 0 : this->CurCoverSchedVal = 1.0;
613 32734 : } else if (this->CurCoverSchedVal < 0.0) {
614 0 : ShowWarningError(state,
615 0 : format("{}: Swimming Pool =\"{} Cover Schedule =\"{} has a negative value. This is not allowed.",
616 : RoutineName,
617 0 : this->Name,
618 0 : this->CoverSchedName));
619 0 : ShowContinueError(state, "The cover has been reset to zero or uncovered.");
620 0 : this->CurCoverSchedVal = 0.0;
621 : }
622 : } else {
623 : // default is NO pool cover
624 0 : this->CurCoverSchedVal = 0.0;
625 : }
626 : // for the current cover factors, a value of 1.0 means that the pool is open (not covered)
627 : // the user input values determine the amount the pool cover degrades one of the factors
628 : // for example, if the cover reduces convection by 50% and the pool is half covered, then
629 : // the reduction factor for convection is 25% or 75% of the normal value. this establishes
630 : // the following relationships and how they are used in other parts of the code.
631 : // note that for the radiation factors, the reduction in absorption of radiation caused by
632 : // the cover will result in a net imbalance if this energy which is no longer accounted for
633 : // in the surface heat balance is not accounted for elsewhere. thus, these terms will dump
634 : // any reduced radiation into the air heat balance as an additional convective gain to avoid
635 : // any loss of energy in the overall heat balance.
636 32734 : this->CurCoverEvapFac = 1.0 - (this->CurCoverSchedVal * this->CoverEvapFactor);
637 32734 : this->CurCoverConvFac = 1.0 - (this->CurCoverSchedVal * this->CoverConvFactor);
638 32734 : this->CurCoverSWRadFac = 1.0 - (this->CurCoverSchedVal * this->CoverSWRadFactor);
639 32734 : this->CurCoverLWRadFac = 1.0 - (this->CurCoverSchedVal * this->CoverLWRadFactor);
640 32734 : }
641 :
642 2 : void SwimmingPoolData::setupOutputVars(EnergyPlusData &state)
643 : {
644 4 : SetupOutputVariable(state,
645 : "Indoor Pool Makeup Water Rate",
646 : Constant::Units::m3_s,
647 2 : this->MakeUpWaterVolFlowRate,
648 : OutputProcessor::TimeStepType::System,
649 : OutputProcessor::StoreType::Average,
650 2 : this->Name);
651 4 : SetupOutputVariable(state,
652 : "Indoor Pool Makeup Water Volume",
653 : Constant::Units::m3,
654 2 : this->MakeUpWaterVol,
655 : OutputProcessor::TimeStepType::System,
656 : OutputProcessor::StoreType::Sum,
657 2 : this->Name,
658 : Constant::eResource::MainsWater,
659 : OutputProcessor::Group::HVAC,
660 : OutputProcessor::EndUseCat::Heating);
661 4 : SetupOutputVariable(state,
662 : "Indoor Pool Makeup Water Temperature",
663 : Constant::Units::C,
664 2 : this->CurMakeupWaterTemp,
665 : OutputProcessor::TimeStepType::System,
666 : OutputProcessor::StoreType::Average,
667 2 : this->Name);
668 4 : SetupOutputVariable(state,
669 : "Indoor Pool Water Temperature",
670 : Constant::Units::C,
671 2 : this->PoolWaterTemp,
672 : OutputProcessor::TimeStepType::System,
673 : OutputProcessor::StoreType::Average,
674 2 : this->Name);
675 4 : SetupOutputVariable(state,
676 : "Indoor Pool Inlet Water Temperature",
677 : Constant::Units::C,
678 2 : this->WaterInletTemp,
679 : OutputProcessor::TimeStepType::System,
680 : OutputProcessor::StoreType::Average,
681 2 : this->Name);
682 4 : SetupOutputVariable(state,
683 : "Indoor Pool Inlet Water Mass Flow Rate",
684 : Constant::Units::kg_s,
685 2 : this->WaterMassFlowRate,
686 : OutputProcessor::TimeStepType::System,
687 : OutputProcessor::StoreType::Average,
688 2 : this->Name);
689 4 : SetupOutputVariable(state,
690 : "Indoor Pool Miscellaneous Equipment Power",
691 : Constant::Units::W,
692 2 : this->MiscEquipPower,
693 : OutputProcessor::TimeStepType::System,
694 : OutputProcessor::StoreType::Average,
695 2 : this->Name);
696 4 : SetupOutputVariable(state,
697 : "Indoor Pool Miscellaneous Equipment Energy",
698 : Constant::Units::J,
699 2 : this->MiscEquipEnergy,
700 : OutputProcessor::TimeStepType::System,
701 : OutputProcessor::StoreType::Sum,
702 2 : this->Name);
703 4 : SetupOutputVariable(state,
704 : "Indoor Pool Water Heating Rate",
705 : Constant::Units::W,
706 2 : this->HeatPower,
707 : OutputProcessor::TimeStepType::System,
708 : OutputProcessor::StoreType::Average,
709 2 : this->Name);
710 4 : SetupOutputVariable(state,
711 : "Indoor Pool Water Heating Energy",
712 : Constant::Units::J,
713 2 : this->HeatEnergy,
714 : OutputProcessor::TimeStepType::System,
715 : OutputProcessor::StoreType::Sum,
716 2 : this->Name,
717 : Constant::eResource::EnergyTransfer,
718 : OutputProcessor::Group::HVAC,
719 : OutputProcessor::EndUseCat::HeatingCoils);
720 4 : SetupOutputVariable(state,
721 : "Indoor Pool Radiant to Convection by Cover",
722 : Constant::Units::W,
723 2 : this->RadConvertToConvect,
724 : OutputProcessor::TimeStepType::System,
725 : OutputProcessor::StoreType::Average,
726 2 : this->Name);
727 4 : SetupOutputVariable(state,
728 : "Indoor Pool People Heat Gain",
729 : Constant::Units::W,
730 2 : this->PeopleHeatGain,
731 : OutputProcessor::TimeStepType::System,
732 : OutputProcessor::StoreType::Average,
733 2 : this->Name);
734 4 : SetupOutputVariable(state,
735 : "Indoor Pool Current Activity Factor",
736 : Constant::Units::None,
737 2 : this->CurActivityFactor,
738 : OutputProcessor::TimeStepType::System,
739 : OutputProcessor::StoreType::Average,
740 2 : this->Name);
741 4 : SetupOutputVariable(state,
742 : "Indoor Pool Current Cover Factor",
743 : Constant::Units::None,
744 2 : this->CurCoverSchedVal,
745 : OutputProcessor::TimeStepType::System,
746 : OutputProcessor::StoreType::Average,
747 2 : this->Name);
748 4 : SetupOutputVariable(state,
749 : "Indoor Pool Evaporative Heat Loss Rate",
750 : Constant::Units::W,
751 2 : this->EvapHeatLossRate,
752 : OutputProcessor::TimeStepType::System,
753 : OutputProcessor::StoreType::Average,
754 2 : this->Name);
755 4 : SetupOutputVariable(state,
756 : "Indoor Pool Evaporative Heat Loss Energy",
757 : Constant::Units::J,
758 2 : this->EvapEnergyLoss,
759 : OutputProcessor::TimeStepType::System,
760 : OutputProcessor::StoreType::Sum,
761 2 : this->Name);
762 4 : SetupOutputVariable(state,
763 : "Indoor Pool Saturation Pressure at Pool Temperature",
764 : Constant::Units::Pa,
765 2 : this->SatPressPoolWaterTemp,
766 : OutputProcessor::TimeStepType::System,
767 : OutputProcessor::StoreType::Average,
768 2 : this->Name);
769 4 : SetupOutputVariable(state,
770 : "Indoor Pool Partial Pressure of Water Vapor in Air",
771 : Constant::Units::Pa,
772 2 : this->PartPressZoneAirTemp,
773 : OutputProcessor::TimeStepType::System,
774 : OutputProcessor::StoreType::Average,
775 2 : this->Name);
776 4 : SetupOutputVariable(state,
777 : "Indoor Pool Current Cover Evaporation Factor",
778 : Constant::Units::None,
779 2 : this->CurCoverEvapFac,
780 : OutputProcessor::TimeStepType::System,
781 : OutputProcessor::StoreType::Average,
782 2 : this->Name);
783 4 : SetupOutputVariable(state,
784 : "Indoor Pool Current Cover Convective Factor",
785 : Constant::Units::None,
786 2 : this->CurCoverConvFac,
787 : OutputProcessor::TimeStepType::System,
788 : OutputProcessor::StoreType::Average,
789 2 : this->Name);
790 4 : SetupOutputVariable(state,
791 : "Indoor Pool Current Cover SW Radiation Factor",
792 : Constant::Units::None,
793 2 : this->CurCoverSWRadFac,
794 : OutputProcessor::TimeStepType::System,
795 : OutputProcessor::StoreType::Average,
796 2 : this->Name);
797 4 : SetupOutputVariable(state,
798 : "Indoor Pool Current Cover LW Radiation Factor",
799 : Constant::Units::None,
800 2 : this->CurCoverLWRadFac,
801 : OutputProcessor::TimeStepType::System,
802 : OutputProcessor::StoreType::Average,
803 2 : this->Name);
804 2 : }
805 :
806 32734 : void SwimmingPoolData::initSwimmingPoolPlantLoopIndex(EnergyPlusData &state)
807 : {
808 : // SUBROUTINE INFORMATION:
809 : // AUTHOR Rick Strand
810 : // DATE WRITTEN June 2017
811 :
812 : static constexpr std::string_view RoutineName("InitSwimmingPoolPlantLoopIndex");
813 :
814 32734 : if (this->MyPlantScanFlagPool && allocated(state.dataPlnt->PlantLoop)) {
815 2 : bool errFlag = false;
816 2 : if (this->WaterInletNode > 0) {
817 6 : PlantUtilities::ScanPlantLoopsForObject(
818 4 : state, this->Name, DataPlant::PlantEquipmentType::SwimmingPool_Indoor, this->HWplantLoc, errFlag, _, _, _, this->WaterInletNode, _);
819 2 : if (errFlag) {
820 0 : ShowFatalError(state, format("{}: Program terminated due to previous condition(s).", RoutineName));
821 : }
822 : }
823 2 : this->MyPlantScanFlagPool = false;
824 32732 : } else if (this->MyPlantScanFlagPool && !state.dataGlobal->AnyPlantInModel) {
825 0 : this->MyPlantScanFlagPool = false;
826 : }
827 32734 : }
828 :
829 238 : void SwimmingPoolData::initSwimmingPoolPlantNodeFlow(EnergyPlusData &state) const
830 : {
831 :
832 238 : if (!this->MyPlantScanFlagPool) {
833 238 : if (this->WaterInletNode > 0) {
834 238 : PlantUtilities::InitComponentNodes(state, 0.0, this->WaterMassFlowRateMax, this->WaterInletNode, this->WaterOutletNode);
835 238 : PlantUtilities::RegisterPlantCompDesignFlow(state, this->WaterInletNode, this->WaterVolFlowMax);
836 : }
837 : }
838 238 : }
839 :
840 32734 : void SwimmingPoolData::calculate(EnergyPlusData &state)
841 : {
842 : // SUBROUTINE INFORMATION:
843 : // AUTHOR Rick Strand, Ho-Sung Kim
844 : // DATE WRITTEN October 2014
845 :
846 : // PURPOSE OF THIS SUBROUTINE:
847 : // This subroutine simulates the components making up the Indoor Swimming Pool model.
848 :
849 : // METHODOLOGY EMPLOYED:
850 : // The swimming pool is modeled as a SURFACE to get access to all of the existing
851 : // surface related algorithms. This subroutine mainly models the components of the
852 : // swimming pool so that information can be used in a standard surface heat balance.
853 : // The pool is assumed to be located at the inside surface face with a possible cover
854 : // affecting the heat balance. The pool model takes the form of an equation solving
855 : // for the inside surface temperature which is assumed to be the same as the pool
856 : // water temperature.
857 : // Standard Heat Balance Equation:
858 : // SurfTempInTmp( SurfNum ) = ( SurfCTFConstInPart( SurfNum ) + SurfQRadThermInAbs( SurfNum ) + SurfOpaqQRadSWInAbs( SurfNum ) + HConvIn(
859 : // SurfNum
860 : //)
861 : //* RefAirTemp( SurfNum ) + SurfNetLWRadToSurf( SurfNum ) + Construct( ConstrNum ).CTFSourceIn( 0 ) * SurfQsrcHist( 1, SurfNum ) +
862 : // SurfQdotRadHVACInPerArea( SurfNum ) + IterDampConst * SurfTempInsOld(
863 : // SurfNum ) + Construct( ConstrNum ).CTFCross( 0 ) * TH11 ) / ( Construct( ConstrNum ).CTFInside( 0 ) + HConvIn( SurfNum ) + IterDampConst );
864 : //// Constant part of conduction eq (history terms) | LW radiation from internal sources | SW radiation from internal sources | Convection
865 : // from surface to zone air | Net radiant exchange with other zone surfaces | Heat source/sink term for radiant systems | (if there is one
866 : // present) | Radiant flux from high temp radiant heater | Radiant flux from a hot water baseboard heater | Radiant flux from a steam
867 : // baseboard heater | Radiant flux from an electric baseboard heater | Iterative damping term (for stability) | Current conduction from | the
868 : // outside surface | Coefficient for conduction (current time) | Convection and damping term
869 : // That equation is modified to include pool specific terms and removes the IterDampConst
870 : // term which is for iterations within the inside surface heat balance. Then, the resulting
871 : // equation is solved for the plant loop mass flow rate. It also assigns the appropriate
872 : // terms for use in the actual heat balance routine.
873 :
874 : // REFERENCES:
875 : // 1. ASHRAE (2011). 2011 ASHRAE Handbook - HVAC Applications. Atlanta: American Society of Heating,
876 : // Refrigerating and Air-Conditioning Engineers, Inc., p.5.6-5.9.
877 : // 2. Janis, R. and W. Tao (2005). Mechanical and Electrical Systems in Buildings. 3rd ed. Upper
878 : // Saddle River, NJ: Pearson Education, Inc., p.246.
879 : // 3. Kittler, R. (1989). Indoor Natatorium Design and Energy Recycling. ASHRAE Transactions 95(1), p.521-526.
880 : // 4. Smith, C., R. Jones, and G. Lof (1993). Energy Requirements and Potential Savings for Heated
881 : // Indoor Swimming Pools. ASHRAE Transactions 99(2), p.864-874.
882 :
883 : // SUBROUTINE PARAMETER DEFINITIONS:
884 : static constexpr std::string_view RoutineName("CalcSwimmingPool");
885 :
886 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
887 32734 : Real64 EvapRate = 0.0; // evaporation rate for pool in kg/s
888 :
889 : // initialize local variables
890 32734 : int SurfNum = this->SurfacePtr; // surface number of floor that is the pool
891 32734 : int ZoneNum = state.dataSurface->Surface(SurfNum).Zone; // index to zone array
892 32734 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
893 :
894 : // Convection coefficient calculation
895 : Real64 HConvIn =
896 32734 : 0.22 * std::pow(std::abs(this->PoolWaterTemp - thisZoneHB.MAT), 1.0 / 3.0) * this->CurCoverConvFac; // convection coefficient for pool
897 32734 : calcSwimmingPoolEvap(state, EvapRate, SurfNum, thisZoneHB.MAT, thisZoneHB.airHumRat);
898 32734 : this->MakeUpWaterMassFlowRate = EvapRate;
899 65468 : Real64 EvapEnergyLossPerArea = -EvapRate *
900 32734 : Psychrometrics::PsyHfgAirFnWTdb(thisZoneHB.airHumRat,
901 : thisZoneHB.MAT) /
902 32734 : state.dataSurface->Surface(SurfNum).Area; // energy effect of evaporation rate per unit area in W/m2
903 32734 : this->EvapHeatLossRate = EvapEnergyLossPerArea * state.dataSurface->Surface(SurfNum).Area;
904 : // LW and SW radiation term modification: any "excess" radiation blocked by the cover gets convected
905 : // to the air directly and added to the zone air heat balance
906 32734 : Real64 LWsum = (state.dataHeatBal->SurfQdotRadIntGainsInPerArea(SurfNum) + state.dataHeatBalSurf->SurfQdotRadNetLWInPerArea(SurfNum) +
907 32734 : state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(SurfNum)); // summation of all long-wavelenth radiation going to surface
908 32734 : Real64 LWtotal = this->CurCoverLWRadFac * LWsum; // total flux from long-wavelength radiation to surface
909 : Real64 SWtotal =
910 32734 : this->CurCoverSWRadFac * state.dataHeatBalSurf->SurfOpaqQRadSWInAbs(SurfNum); // total flux from short-wavelength radiation to surface
911 32734 : this->RadConvertToConvect =
912 32734 : ((1.0 - this->CurCoverLWRadFac) * LWsum) + ((1.0 - this->CurCoverSWRadFac) * state.dataHeatBalSurf->SurfOpaqQRadSWInAbs(SurfNum));
913 :
914 : // Heat gain from people (assumed to be all convective to pool water)
915 : Real64 PeopleGain =
916 32734 : this->PeopleHeatGain / state.dataSurface->Surface(SurfNum).Area; // heat gain from people in pool (assumed to be all convective)
917 :
918 : // Get an estimate of the pool water specific heat
919 : Real64 Cp =
920 32734 : FluidProperties::GetSpecificHeatGlycol(state, "WATER", this->PoolWaterTemp, this->GlycolIndex, RoutineName); // specific heat of pool water
921 :
922 32734 : Real64 TH22 = state.dataHeatBalSurf->SurfInsideTempHist(2)(
923 32734 : SurfNum); // inside surface temperature at the previous time step equals the old pool water temperature
924 32734 : Real64 Tmuw = this->CurMakeupWaterTemp; // Inlet makeup water temperature
925 32734 : Real64 TLoopInletTemp = state.dataLoopNodes->Node(this->WaterInletNode).Temp; // Inlet water temperature from the plant loop
926 32734 : this->WaterInletTemp = TLoopInletTemp;
927 :
928 : Real64 MassFlowRate;
929 32734 : this->calcMassFlowRate(state, MassFlowRate, TH22, TLoopInletTemp);
930 :
931 32734 : PlantUtilities::SetComponentFlowRate(state, MassFlowRate, this->WaterInletNode, this->WaterOutletNode, this->HWplantLoc);
932 32734 : this->WaterMassFlowRate = MassFlowRate;
933 :
934 : // We now have a flow rate so we can assemble the terms needed for the surface heat balance that is solved for the inside face temperature
935 32734 : state.dataHeatBalFanSys->QPoolSurfNumerator(SurfNum) =
936 65468 : SWtotal + LWtotal + PeopleGain + EvapEnergyLossPerArea + HConvIn * thisZoneHB.MAT +
937 32734 : (EvapRate * Tmuw + MassFlowRate * TLoopInletTemp + (this->WaterMass * TH22 / state.dataGlobal->TimeStepZoneSec)) * Cp /
938 32734 : state.dataSurface->Surface(SurfNum).Area;
939 32734 : state.dataHeatBalFanSys->PoolHeatTransCoefs(SurfNum) =
940 32734 : HConvIn + (EvapRate + MassFlowRate + (this->WaterMass / state.dataGlobal->TimeStepZoneSec)) * Cp / state.dataSurface->Surface(SurfNum).Area;
941 :
942 : // Finally take care of the latent and convective gains resulting from the pool
943 32734 : state.dataHeatBalFanSys->SumConvPool(ZoneNum) += this->RadConvertToConvect;
944 32734 : state.dataHeatBalFanSys->SumLatentPool(ZoneNum) += EvapRate * Psychrometrics::PsyHfgAirFnWTdb(thisZoneHB.airHumRat, thisZoneHB.MAT);
945 32734 : }
946 :
947 32734 : void SwimmingPoolData::calcMassFlowRate(EnergyPlusData &state, Real64 &massFlowRate, Real64 TH22, Real64 TLoopInletTemp)
948 : {
949 : // Calculate the mass flow rate to achieve the proper setpoint temperature
950 32734 : if (TLoopInletTemp != this->CurSetPtTemp) {
951 32734 : massFlowRate = this->WaterMass / state.dataHVACGlobal->TimeStepSysSec * (this->CurSetPtTemp - TH22) / (TLoopInletTemp - this->CurSetPtTemp);
952 : } else { // avoid the divide by zero, reset later if necessary
953 0 : massFlowRate = 0.0;
954 : }
955 32734 : if (massFlowRate > this->WaterMassFlowRateMax) {
956 0 : massFlowRate = this->WaterMassFlowRateMax;
957 32734 : } else if (massFlowRate <= 0.0) {
958 : // trap case where loop temperature is lower than the setpoint but could still do heating Defect 10317
959 0 : if (TLoopInletTemp > TH22 && TLoopInletTemp <= this->CurSetPtTemp) {
960 0 : massFlowRate = this->WaterMassFlowRateMax;
961 : } else {
962 0 : massFlowRate = 0.0;
963 : }
964 : }
965 32734 : }
966 :
967 32734 : void SwimmingPoolData::calcSwimmingPoolEvap(EnergyPlusData &state,
968 : Real64 &EvapRate, // evaporation rate of pool
969 : int const SurfNum, // surface index
970 : Real64 const MAT, // mean air temperature
971 : Real64 const HumRat // zone air humidity ratio
972 : )
973 : {
974 : static constexpr std::string_view RoutineName("CalcSwimmingPoolEvap");
975 32734 : Real64 constexpr CFinHg(0.00029613); // Multiple pressure in Pa by this constant to get inches of Hg
976 :
977 : // Evaporation calculation:
978 : // Evaporation Rate (lb/h) = 0.1 * Area (ft2) * Activity Factor * (Psat,pool - Ppar,air) (in Hg)
979 : // So evaporation rate, area, and pressures have to be converted to standard E+ units (kg/s, m2, and Pa, respectively)
980 : // Evaporation Rate per Area = Evaporation Rate * Heat of Vaporization / Area of Surface
981 :
982 32734 : Real64 PSatPool = Psychrometrics::PsyPsatFnTemp(state, this->PoolWaterTemp, RoutineName);
983 : Real64 PParAir =
984 32734 : Psychrometrics::PsyPsatFnTemp(state, MAT, RoutineName) * Psychrometrics::PsyRhFnTdbWPb(state, MAT, HumRat, state.dataEnvrn->OutBaroPress);
985 32734 : if (PSatPool < PParAir) PSatPool = PParAir;
986 32734 : this->SatPressPoolWaterTemp = PSatPool;
987 32734 : this->PartPressZoneAirTemp = PParAir;
988 32734 : EvapRate = (0.1 * (state.dataSurface->Surface(SurfNum).Area / DataConversions::CFA) * this->CurActivityFactor * ((PSatPool - PParAir) * CFinHg)) *
989 32734 : DataConversions::CFMF * this->CurCoverEvapFac;
990 32734 : }
991 :
992 32734 : void SwimmingPoolData::update(EnergyPlusData &state)
993 : {
994 : // SUBROUTINE INFORMATION:
995 : // AUTHOR Rick Strand, Ho-Sung Kim
996 : // DATE WRITTEN October 2014
997 :
998 : // PURPOSE OF THIS SUBROUTINE:
999 : // This subroutine does any updating that needs to be done for the swimming pool model.
1000 :
1001 32734 : int SurfNum = this->SurfacePtr; // surface number/pointer
1002 :
1003 32734 : if (this->LastSysTimeElapsed == state.dataHVACGlobal->SysTimeElapsed) {
1004 : // Still iterating or reducing system time step, so subtract old values which were
1005 : // not valid
1006 32734 : this->QPoolSrcAvg -= this->LastQPoolSrc * this->LastTimeStepSys / state.dataGlobal->TimeStepZone;
1007 32734 : this->HeatTransCoefsAvg -= this->LastHeatTransCoefs * this->LastTimeStepSys / state.dataGlobal->TimeStepZone;
1008 : }
1009 :
1010 : // Update the running average and the "last" values with the current values of the appropriate variables
1011 32734 : this->QPoolSrcAvg += state.dataHeatBalFanSys->QPoolSurfNumerator(SurfNum) * state.dataHVACGlobal->TimeStepSys / state.dataGlobal->TimeStepZone;
1012 32734 : this->HeatTransCoefsAvg +=
1013 32734 : state.dataHeatBalFanSys->PoolHeatTransCoefs(SurfNum) * state.dataHVACGlobal->TimeStepSys / state.dataGlobal->TimeStepZone;
1014 :
1015 32734 : this->LastQPoolSrc = state.dataHeatBalFanSys->QPoolSurfNumerator(SurfNum);
1016 32734 : this->LastHeatTransCoefs = state.dataHeatBalFanSys->PoolHeatTransCoefs(SurfNum);
1017 32734 : this->LastSysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
1018 32734 : this->LastTimeStepSys = state.dataHVACGlobal->TimeStepSys;
1019 :
1020 32734 : PlantUtilities::SafeCopyPlantNode(state, this->WaterInletNode, this->WaterOutletNode);
1021 :
1022 32734 : Real64 WaterMassFlow = state.dataLoopNodes->Node(this->WaterInletNode).MassFlowRate; // water mass flow rate
1023 32734 : if (WaterMassFlow > 0.0) state.dataLoopNodes->Node(this->WaterOutletNode).Temp = this->PoolWaterTemp;
1024 32734 : }
1025 :
1026 2 : void SwimmingPoolData::oneTimeInit_new([[maybe_unused]] EnergyPlusData &state)
1027 : {
1028 2 : }
1029 :
1030 0 : void SwimmingPoolData::oneTimeInit([[maybe_unused]] EnergyPlusData &state)
1031 : {
1032 0 : }
1033 :
1034 32734 : void SwimmingPoolData::report(EnergyPlusData &state)
1035 : {
1036 : // SUBROUTINE INFORMATION:
1037 : // AUTHOR Rick Strand, Ho-Sung Kim
1038 : // DATE WRITTEN October 2014
1039 :
1040 : // PURPOSE OF THIS SUBROUTINE:
1041 : // This subroutine simply produces output for the swimming pool model.
1042 :
1043 : // SUBROUTINE PARAMETER DEFINITIONS:
1044 : static constexpr std::string_view RoutineName("SwimmingPoolData::report");
1045 32734 : Real64 constexpr MinDensity = 1.0; // to avoid a divide by zero
1046 :
1047 32734 : int SurfNum = this->SurfacePtr; // surface number index
1048 :
1049 : // First transfer the surface inside temperature data to the current pool water temperature
1050 32734 : this->PoolWaterTemp = state.dataHeatBalSurf->SurfInsideTempHist(1)(SurfNum);
1051 :
1052 : // Next calculate the amount of heating done by the plant loop
1053 32734 : Real64 Cp = FluidProperties::GetSpecificHeatGlycol(state, "WATER", this->PoolWaterTemp, this->GlycolIndex,
1054 : RoutineName); // specific heat of water
1055 32734 : this->HeatPower = this->WaterMassFlowRate * Cp * (this->WaterInletTemp - this->PoolWaterTemp);
1056 :
1057 : // Now the power consumption of miscellaneous equipment
1058 32734 : Real64 Density = FluidProperties::GetDensityGlycol(state, "WATER", this->PoolWaterTemp, this->GlycolIndex,
1059 : RoutineName); // density of water
1060 32734 : if (Density > MinDensity) {
1061 32734 : this->MiscEquipPower = this->MiscPowerFactor * this->WaterMassFlowRate / Density;
1062 : } else {
1063 0 : this->MiscEquipPower = 0.0;
1064 : }
1065 :
1066 : // Also the radiant exchange converted to convection by the pool cover
1067 32734 : this->RadConvertToConvectRep = this->RadConvertToConvect * state.dataSurface->Surface(SurfNum).Area;
1068 :
1069 : // Finally calculate the summed up report variables
1070 32734 : Real64 thisTimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
1071 32734 : this->MiscEquipEnergy = this->MiscEquipPower * thisTimeStepSysSec;
1072 32734 : this->HeatEnergy = this->HeatPower * thisTimeStepSysSec;
1073 32734 : this->MakeUpWaterMass = this->MakeUpWaterMassFlowRate * thisTimeStepSysSec;
1074 32734 : this->EvapEnergyLoss = this->EvapHeatLossRate * thisTimeStepSysSec;
1075 :
1076 32734 : this->MakeUpWaterVolFlowRate = MakeUpWaterVolFlowFunct(this->MakeUpWaterMassFlowRate, Density);
1077 32734 : this->MakeUpWaterVol = MakeUpWaterVolFunct(this->MakeUpWaterMass, Density);
1078 32734 : }
1079 :
1080 2804482 : void UpdatePoolSourceValAvg(EnergyPlusData &state, bool &SwimmingPoolOn) // .TRUE. if the swimming pool "runs" this zone time step
1081 : {
1082 : // SUBROUTINE INFORMATION:
1083 : // AUTHOR Rick Strand
1084 : // DATE WRITTEN October 2014
1085 :
1086 : // PURPOSE OF THIS SUBROUTINE:
1087 : // To transfer the average value of the pool heat balance term over the entire zone time step back to the heat balance routines so that the
1088 : // heat balance algorithms can simulate one last time with the average source to maintain some reasonable amount of continuity and energy
1089 : // balance in the temperature and flux histories.
1090 :
1091 : // METHODOLOGY EMPLOYED:
1092 : // All of the record keeping for the average term is done in the Update routine so the only other thing that this subroutine does is check to
1093 : // see if the system was even on. If any average term is non-zero, then one or more of the swimming pools was running. Method borrowed from
1094 : // radiant systems.
1095 :
1096 : // SUBROUTINE PARAMETER DEFINITIONS:
1097 2804482 : Real64 constexpr CloseEnough(0.01); // Some arbitrarily small value to avoid zeros and numbers that are almost the same
1098 :
1099 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1100 2804482 : SwimmingPoolOn = false;
1101 :
1102 : // If there are no pools, then just RETURN
1103 :
1104 2804482 : if (state.dataSwimmingPools->NumSwimmingPools == 0) return;
1105 :
1106 16188 : for (int PoolNum = 1; PoolNum <= state.dataSwimmingPools->NumSwimmingPools; ++PoolNum) {
1107 8094 : auto &thisPool = state.dataSwimmingPools->Pool(PoolNum);
1108 8094 : if (thisPool.QPoolSrcAvg != 0.0) SwimmingPoolOn = true;
1109 8094 : int SurfNum = thisPool.SurfacePtr; // surface number index
1110 8094 : state.dataHeatBalFanSys->QPoolSurfNumerator(SurfNum) = thisPool.QPoolSrcAvg;
1111 8094 : state.dataHeatBalFanSys->PoolHeatTransCoefs(SurfNum) = thisPool.HeatTransCoefsAvg;
1112 : }
1113 :
1114 : // For interzone surfaces, QPoolSrcAvg was only updated for the "active" side. The active side
1115 : // would have a non-zero value at this point. If the numbers differ, then we have to manually update.
1116 412794 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
1117 404700 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0 && state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum) {
1118 210444 : if (std::abs(state.dataHeatBalFanSys->QPoolSurfNumerator(SurfNum) -
1119 210444 : state.dataHeatBalFanSys->QPoolSurfNumerator(state.dataSurface->Surface(SurfNum).ExtBoundCond)) >
1120 : CloseEnough) { // numbers differ
1121 0 : if (std::abs(state.dataHeatBalFanSys->QPoolSurfNumerator(SurfNum)) >
1122 0 : std::abs(state.dataHeatBalFanSys->QPoolSurfNumerator(state.dataSurface->Surface(SurfNum).ExtBoundCond))) {
1123 0 : state.dataHeatBalFanSys->QPoolSurfNumerator(state.dataSurface->Surface(SurfNum).ExtBoundCond) =
1124 0 : state.dataHeatBalFanSys->QPoolSurfNumerator(SurfNum);
1125 : } else {
1126 0 : state.dataHeatBalFanSys->QPoolSurfNumerator(SurfNum) =
1127 0 : state.dataHeatBalFanSys->QPoolSurfNumerator(state.dataSurface->Surface(SurfNum).ExtBoundCond);
1128 : }
1129 : }
1130 : }
1131 : }
1132 : // For interzone surfaces, PoolHeatTransCoefs was only updated for the "active" side. The active side
1133 : // would have a non-zero value at this point. If the numbers differ, then we have to manually update.
1134 412794 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
1135 404700 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond > 0 && state.dataSurface->Surface(SurfNum).ExtBoundCond != SurfNum) {
1136 210444 : if (std::abs(state.dataHeatBalFanSys->PoolHeatTransCoefs(SurfNum) -
1137 210444 : state.dataHeatBalFanSys->PoolHeatTransCoefs(state.dataSurface->Surface(SurfNum).ExtBoundCond)) >
1138 : CloseEnough) { // numbers differ
1139 0 : if (std::abs(state.dataHeatBalFanSys->PoolHeatTransCoefs(SurfNum)) >
1140 0 : std::abs(state.dataHeatBalFanSys->PoolHeatTransCoefs(state.dataSurface->Surface(SurfNum).ExtBoundCond))) {
1141 0 : state.dataHeatBalFanSys->PoolHeatTransCoefs(state.dataSurface->Surface(SurfNum).ExtBoundCond) =
1142 0 : state.dataHeatBalFanSys->PoolHeatTransCoefs(SurfNum);
1143 : } else {
1144 0 : state.dataHeatBalFanSys->PoolHeatTransCoefs(SurfNum) =
1145 0 : state.dataHeatBalFanSys->PoolHeatTransCoefs(state.dataSurface->Surface(SurfNum).ExtBoundCond);
1146 : }
1147 : }
1148 : }
1149 : }
1150 : }
1151 :
1152 32734 : Real64 MakeUpWaterVolFlowFunct(Real64 MakeUpWaterMassFlowRate, Real64 Density)
1153 : {
1154 32734 : return MakeUpWaterMassFlowRate / Density;
1155 : }
1156 :
1157 32734 : Real64 MakeUpWaterVolFunct(Real64 MakeUpWaterMass, Real64 Density)
1158 : {
1159 32734 : return MakeUpWaterMass / Density;
1160 : }
1161 :
1162 : } // namespace EnergyPlus::SwimmingPool
|