Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 :
54 : // EnergyPlus Headers
55 : #include <EnergyPlus/BranchNodeConnections.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/DataLoopNode.hh>
62 : #include <EnergyPlus/DataWater.hh>
63 : #include <EnergyPlus/FluidProperties.hh>
64 : #include <EnergyPlus/HeatBalanceInternalHeatGains.hh>
65 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
66 : #include <EnergyPlus/NodeInputManager.hh>
67 : #include <EnergyPlus/OutputProcessor.hh>
68 : #include <EnergyPlus/Plant/DataPlant.hh>
69 : #include <EnergyPlus/PlantUtilities.hh>
70 : #include <EnergyPlus/Psychrometrics.hh>
71 : #include <EnergyPlus/ScheduleManager.hh>
72 : #include <EnergyPlus/UtilityRoutines.hh>
73 : #include <EnergyPlus/WaterManager.hh>
74 : #include <EnergyPlus/WaterUse.hh>
75 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
76 :
77 : namespace EnergyPlus {
78 :
79 : namespace WaterUse {
80 :
81 : // MODULE INFORMATION:
82 : // AUTHOR Peter Graham Ellis
83 : // DATE WRITTEN August 2006
84 : // MODIFIED Brent Griffith, plant upgrade
85 :
86 6770236 : void SimulateWaterUse(EnergyPlusData &state, bool FirstHVACIteration)
87 : {
88 :
89 : // SUBROUTINE INFORMATION:
90 : // AUTHOR Peter Graham Ellis
91 : // DATE WRITTEN August 2006
92 : // MODIFIED Brent Griffith, March 2010, separated plant connected to different sim routine
93 :
94 : // PURPOSE OF THIS SUBROUTINE:
95 : // This routine is called from non zone equipment manager and serves to call
96 : // water use and connections that are not connected to a full plant loop
97 :
98 6770236 : int constexpr MaxIterations(100);
99 6770236 : Real64 constexpr Tolerance(0.1); // Make input?
100 :
101 6770236 : if (state.dataWaterUse->getWaterUseInputFlag) {
102 683 : GetWaterUseInput(state);
103 683 : state.dataWaterUse->getWaterUseInputFlag = false;
104 : }
105 :
106 6770236 : if (state.dataGlobal->BeginEnvrnFlag && state.dataWaterUse->MyEnvrnFlagLocal) {
107 6496 : if (state.dataWaterUse->numWaterEquipment > 0) {
108 13245 : for (auto &e : state.dataWaterUse->WaterEquipment) {
109 12043 : e.SensibleRate = 0.0;
110 12043 : e.SensibleEnergy = 0.0;
111 12043 : e.LatentRate = 0.0;
112 12043 : e.LatentEnergy = 0.0;
113 12043 : e.MixedTemp = 0.0;
114 12043 : e.TotalMassFlowRate = 0.0;
115 12043 : e.DrainTemp = 0.0;
116 1202 : }
117 : }
118 :
119 6496 : if (state.dataWaterUse->numWaterConnections > 0) {
120 12946 : for (auto &e : state.dataWaterUse->WaterConnections) {
121 11780 : e.TotalMassFlowRate = 0.0;
122 1166 : }
123 : }
124 :
125 6496 : state.dataWaterUse->MyEnvrnFlagLocal = false;
126 : }
127 :
128 6770236 : if (!state.dataGlobal->BeginEnvrnFlag) {
129 6739886 : state.dataWaterUse->MyEnvrnFlagLocal = true;
130 : }
131 :
132 : // Simulate all unconnected WATER USE EQUIPMENT objects
133 18503262 : for (auto &waterEquipment : state.dataWaterUse->WaterEquipment) {
134 11733026 : if (waterEquipment.Connections == 0) {
135 104562 : waterEquipment.CalcEquipmentFlowRates(state);
136 104562 : waterEquipment.CalcEquipmentDrainTemp(state);
137 : }
138 6770236 : } // WaterEquipNum
139 :
140 6770236 : ReportStandAloneWaterUse(state);
141 :
142 : // Simulate WATER USE CONNECTIONS objects and connected WATER USE EQUIPMENT objects
143 18301986 : for (auto &waterConnection : state.dataWaterUse->WaterConnections) {
144 :
145 11531750 : if (!waterConnection.StandAlone) {
146 11531750 : continue; // only model non plant connections here
147 : }
148 :
149 0 : waterConnection.InitConnections(state);
150 :
151 0 : int NumIteration = 0;
152 :
153 : while (true) {
154 0 : ++NumIteration;
155 :
156 0 : waterConnection.CalcConnectionsFlowRates(state, FirstHVACIteration);
157 0 : waterConnection.CalcConnectionsDrainTemp(state);
158 0 : waterConnection.CalcConnectionsHeatRecovery(state);
159 :
160 0 : if (waterConnection.TempError < Tolerance) {
161 0 : break;
162 0 : } else if (NumIteration > MaxIterations) {
163 0 : if (!state.dataGlobal->WarmupFlag) {
164 0 : if (waterConnection.MaxIterationsErrorIndex == 0) {
165 0 : ShowWarningError(state,
166 0 : format("WaterUse:Connections = {}: Heat recovery temperature did not converge", waterConnection.Name));
167 0 : ShowContinueErrorTimeStamp(state, "");
168 : }
169 0 : ShowRecurringWarningErrorAtEnd(state,
170 0 : "WaterUse:Connections = " + waterConnection.Name +
171 : ": Heat recovery temperature did not converge",
172 0 : waterConnection.MaxIterationsErrorIndex);
173 : }
174 0 : break;
175 : }
176 :
177 : } // WHILE
178 :
179 0 : waterConnection.UpdateWaterConnections(state);
180 0 : waterConnection.ReportWaterUse(state);
181 :
182 6770236 : } // WaterConnNum
183 6770236 : }
184 :
185 1050 : PlantComponent *WaterConnectionsType::factory(EnergyPlusData &state, std::string const &objectName)
186 : {
187 : // Process the input data
188 1050 : if (state.dataWaterUse->getWaterUseInputFlag) {
189 118 : GetWaterUseInput(state);
190 118 : state.dataWaterUse->getWaterUseInputFlag = false;
191 : }
192 :
193 : // Now look for this particular object in the list
194 35803 : for (auto &thisWC : state.dataWaterUse->WaterConnections) {
195 35803 : if (thisWC.Name == objectName) {
196 1050 : return &thisWC;
197 : }
198 2100 : }
199 : // If we didn't find it, fatal
200 : ShowFatalError(state, format("LocalWaterUseConnectionFactory: Error getting inputs for object named: {}", objectName)); // LCOV_EXCL_LINE
201 : // Shut up the compiler
202 : return nullptr; // LCOV_EXCL_LINE
203 : }
204 :
205 41586463 : void WaterConnectionsType::simulate(EnergyPlusData &state,
206 : [[maybe_unused]] const PlantLocation &calledFromLocation,
207 : bool FirstHVACIteration,
208 : [[maybe_unused]] Real64 &CurLoad,
209 : [[maybe_unused]] bool RunFlag)
210 : {
211 :
212 : // SUBROUTINE INFORMATION:
213 : // AUTHOR Brent Griffith March 2010, Demand Side Update
214 : // DATE WRITTEN August 2006
215 :
216 : // PURPOSE OF THIS SUBROUTINE:
217 : // Plant sim call for plant loop connected water use and connections
218 :
219 41586463 : int constexpr MaxIterations(100);
220 41586463 : Real64 constexpr Tolerance(0.1); // Make input?
221 :
222 41586463 : if (state.dataGlobal->BeginEnvrnFlag && this->MyEnvrnFlag) {
223 6850 : if (state.dataWaterUse->numWaterEquipment > 0) {
224 489865 : for (auto &waterEquipment : state.dataWaterUse->WaterEquipment) {
225 483015 : waterEquipment.reset();
226 483015 : if (waterEquipment.setupMyOutputVars) {
227 1068 : waterEquipment.setupOutputVars(state);
228 1068 : waterEquipment.setupMyOutputVars = false;
229 : }
230 6850 : }
231 : }
232 :
233 6850 : if (state.dataWaterUse->numWaterConnections > 0) {
234 489674 : for (auto &waterConnections : state.dataWaterUse->WaterConnections) {
235 482824 : waterConnections.TotalMassFlowRate = 0.0;
236 6850 : }
237 : }
238 :
239 6850 : this->MyEnvrnFlag = false;
240 : }
241 :
242 41586463 : if (!state.dataGlobal->BeginEnvrnFlag) {
243 41228300 : this->MyEnvrnFlag = true;
244 : }
245 :
246 41586463 : this->InitConnections(state);
247 :
248 41586463 : int NumIteration = 0;
249 :
250 : while (true) {
251 41586463 : ++NumIteration;
252 :
253 41586463 : this->CalcConnectionsFlowRates(state, FirstHVACIteration);
254 41586463 : this->CalcConnectionsDrainTemp(state);
255 41586463 : this->CalcConnectionsHeatRecovery(state);
256 :
257 41586463 : if (this->TempError < Tolerance) {
258 41586463 : break;
259 0 : } else if (NumIteration > MaxIterations) {
260 0 : if (!state.dataGlobal->WarmupFlag) {
261 0 : if (this->MaxIterationsErrorIndex == 0) {
262 0 : ShowWarningError(state, format("WaterUse:Connections = {}: Heat recovery temperature did not converge", this->Name));
263 0 : ShowContinueErrorTimeStamp(state, "");
264 : }
265 0 : ShowRecurringWarningErrorAtEnd(state,
266 0 : "WaterUse:Connections = " + this->Name + ": Heat recovery temperature did not converge",
267 0 : this->MaxIterationsErrorIndex);
268 : }
269 0 : break;
270 : }
271 : } // WHILE
272 :
273 41586463 : this->UpdateWaterConnections(state);
274 41586463 : this->ReportWaterUse(state);
275 41586463 : }
276 :
277 801 : void GetWaterUseInput(EnergyPlusData &state)
278 : {
279 :
280 : // SUBROUTINE INFORMATION:
281 : // AUTHOR Peter Graham Ellis
282 : // DATE WRITTEN August 2006
283 :
284 : static constexpr std::string_view routineName = "GetWaterUseInput";
285 :
286 801 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
287 : int IOStatus; // Used in GetObjectItem
288 : int NumAlphas; // Number of Alphas for each GetObjectItem call
289 : int NumNumbers; // Number of Numbers for each GetObjectItem call
290 :
291 801 : constexpr std::array<std::string_view, static_cast<int>(HeatRecovHX::Num)> HeatRecoverHXNamesUC{"IDEAL", "COUNTERFLOW", "CROSSFLOW"};
292 :
293 801 : constexpr std::array<std::string_view, static_cast<int>(HeatRecovConfig::Num)> HeatRecoveryConfigNamesUC{
294 : "PLANT", "EQUIPMENT", "PLANTANDEQUIPMENT"};
295 :
296 801 : state.dataIPShortCut->cCurrentModuleObject = "WaterUse:Equipment";
297 1602 : state.dataWaterUse->numWaterEquipment =
298 801 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
299 :
300 801 : if (state.dataWaterUse->numWaterEquipment > 0) {
301 122 : state.dataWaterUse->WaterEquipment.allocate(state.dataWaterUse->numWaterEquipment);
302 :
303 1209 : for (int WaterEquipNum = 1; WaterEquipNum <= state.dataWaterUse->numWaterEquipment; ++WaterEquipNum) {
304 1087 : auto &thisWEq = state.dataWaterUse->WaterEquipment(WaterEquipNum);
305 3261 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
306 1087 : state.dataIPShortCut->cCurrentModuleObject,
307 : WaterEquipNum,
308 1087 : state.dataIPShortCut->cAlphaArgs,
309 : NumAlphas,
310 1087 : state.dataIPShortCut->rNumericArgs,
311 : NumNumbers,
312 : IOStatus,
313 : _,
314 1087 : state.dataIPShortCut->lAlphaFieldBlanks,
315 1087 : state.dataIPShortCut->cAlphaFieldNames,
316 1087 : state.dataIPShortCut->cNumericFieldNames);
317 :
318 1087 : ErrorObjectHeader eoh{routineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
319 1087 : Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
320 1087 : thisWEq.Name = state.dataIPShortCut->cAlphaArgs(1);
321 :
322 1087 : thisWEq.EndUseSubcatName = state.dataIPShortCut->cAlphaArgs(2);
323 :
324 1087 : thisWEq.PeakVolFlowRate = state.dataIPShortCut->rNumericArgs(1);
325 :
326 1087 : if ((NumAlphas <= 2) || (state.dataIPShortCut->lAlphaFieldBlanks(3))) {
327 1087 : } else if ((thisWEq.flowRateFracSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(3))) == nullptr) {
328 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3));
329 0 : ErrorsFound = true;
330 : }
331 :
332 1087 : if ((NumAlphas <= 3) || (state.dataIPShortCut->lAlphaFieldBlanks(4))) {
333 819 : } else if ((thisWEq.targetTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(4))) == nullptr) {
334 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(4), state.dataIPShortCut->cAlphaArgs(4));
335 0 : ErrorsFound = true;
336 : }
337 :
338 1087 : if ((NumAlphas <= 4) || (state.dataIPShortCut->lAlphaFieldBlanks(5))) {
339 959 : } else if ((thisWEq.hotTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(5))) == nullptr) {
340 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(5), state.dataIPShortCut->cAlphaArgs(5));
341 0 : ErrorsFound = true;
342 : }
343 :
344 1087 : if ((NumAlphas <= 5) || (state.dataIPShortCut->lAlphaFieldBlanks(6))) {
345 0 : } else if ((thisWEq.coldTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(6))) == nullptr) {
346 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(6), state.dataIPShortCut->cAlphaArgs(6));
347 0 : ErrorsFound = true;
348 : }
349 :
350 1087 : if ((NumAlphas <= 6) || (state.dataIPShortCut->lAlphaFieldBlanks(7))) {
351 1019 : } else if ((thisWEq.Zone = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(7), state.dataHeatBal->Zone)) == 0) {
352 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(7), state.dataIPShortCut->cAlphaArgs(7));
353 0 : ErrorsFound = true;
354 : }
355 :
356 1087 : if ((NumAlphas <= 7) || (state.dataIPShortCut->lAlphaFieldBlanks(8))) {
357 1019 : } else if ((thisWEq.sensibleFracSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(8))) == nullptr) {
358 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(8), state.dataIPShortCut->cAlphaArgs(8));
359 0 : ErrorsFound = true;
360 : }
361 :
362 1087 : if ((NumAlphas <= 8) || (state.dataIPShortCut->lAlphaFieldBlanks(9))) {
363 1013 : } else if ((thisWEq.latentFracSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(9))) == nullptr) {
364 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(9), state.dataIPShortCut->cAlphaArgs(9));
365 0 : ErrorsFound = true;
366 : }
367 :
368 : } // WaterEquipNum
369 :
370 122 : if (ErrorsFound) {
371 0 : ShowFatalError(state, format("Errors found in processing input for {}", state.dataIPShortCut->cCurrentModuleObject));
372 : }
373 : }
374 :
375 801 : state.dataIPShortCut->cCurrentModuleObject = "WaterUse:Connections";
376 1602 : state.dataWaterUse->numWaterConnections =
377 801 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataIPShortCut->cCurrentModuleObject);
378 :
379 801 : if (state.dataWaterUse->numWaterConnections > 0) {
380 118 : state.dataWaterUse->WaterConnections.allocate(state.dataWaterUse->numWaterConnections);
381 :
382 1168 : for (int WaterConnNum = 1; WaterConnNum <= state.dataWaterUse->numWaterConnections; ++WaterConnNum) {
383 3150 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
384 1050 : state.dataIPShortCut->cCurrentModuleObject,
385 : WaterConnNum,
386 1050 : state.dataIPShortCut->cAlphaArgs,
387 : NumAlphas,
388 1050 : state.dataIPShortCut->rNumericArgs,
389 : NumNumbers,
390 : IOStatus,
391 : _,
392 1050 : state.dataIPShortCut->lAlphaFieldBlanks,
393 1050 : state.dataIPShortCut->cAlphaFieldNames,
394 1050 : state.dataIPShortCut->cNumericFieldNames);
395 :
396 1050 : ErrorObjectHeader eoh{routineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
397 :
398 1050 : Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
399 1050 : auto &waterConnection = state.dataWaterUse->WaterConnections(WaterConnNum);
400 1050 : waterConnection.Name = state.dataIPShortCut->cAlphaArgs(1);
401 :
402 1050 : if ((!state.dataIPShortCut->lAlphaFieldBlanks(2)) || (!state.dataIPShortCut->lAlphaFieldBlanks(3))) {
403 1050 : waterConnection.InletNode = NodeInputManager::GetOnlySingleNode(state,
404 1050 : state.dataIPShortCut->cAlphaArgs(2),
405 : ErrorsFound,
406 : DataLoopNode::ConnectionObjectType::WaterUseConnections,
407 1050 : waterConnection.Name,
408 : DataLoopNode::NodeFluidType::Water,
409 : DataLoopNode::ConnectionType::Inlet,
410 : NodeInputManager::CompFluidStream::Primary,
411 : DataLoopNode::ObjectIsNotParent);
412 2100 : waterConnection.OutletNode = NodeInputManager::GetOnlySingleNode(state,
413 1050 : state.dataIPShortCut->cAlphaArgs(3),
414 : ErrorsFound,
415 : DataLoopNode::ConnectionObjectType::WaterUseConnections,
416 1050 : waterConnection.Name,
417 : DataLoopNode::NodeFluidType::Water,
418 : DataLoopNode::ConnectionType::Outlet,
419 : NodeInputManager::CompFluidStream::Primary,
420 : DataLoopNode::ObjectIsNotParent);
421 :
422 : // Check plant connections
423 3150 : BranchNodeConnections::TestCompSet(state,
424 1050 : state.dataIPShortCut->cCurrentModuleObject,
425 : waterConnection.Name,
426 1050 : state.dataIPShortCut->cAlphaArgs(2),
427 1050 : state.dataIPShortCut->cAlphaArgs(3),
428 : "DHW Nodes");
429 : } else {
430 : // If no plant nodes are connected, simulate in stand-alone mode.
431 0 : waterConnection.StandAlone = true;
432 : }
433 :
434 1050 : if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) {
435 0 : WaterManager::SetupTankDemandComponent(state,
436 : waterConnection.Name,
437 0 : state.dataIPShortCut->cCurrentModuleObject,
438 0 : state.dataIPShortCut->cAlphaArgs(4),
439 : ErrorsFound,
440 0 : waterConnection.SupplyTankNum,
441 0 : waterConnection.TankDemandID);
442 : }
443 :
444 1050 : if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) {
445 0 : WaterManager::SetupTankSupplyComponent(state,
446 : waterConnection.Name,
447 0 : state.dataIPShortCut->cCurrentModuleObject,
448 0 : state.dataIPShortCut->cAlphaArgs(5),
449 : ErrorsFound,
450 0 : waterConnection.RecoveryTankNum,
451 0 : waterConnection.TankSupplyID);
452 : }
453 :
454 1050 : if (state.dataIPShortCut->lAlphaFieldBlanks(6)) {
455 0 : } else if ((waterConnection.hotTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(6))) == nullptr) {
456 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(6), state.dataIPShortCut->cAlphaArgs(6));
457 0 : ErrorsFound = true;
458 : }
459 :
460 1050 : if (state.dataIPShortCut->lAlphaFieldBlanks(7)) {
461 3 : } else if ((waterConnection.coldTempSched = Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(7))) == nullptr) {
462 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(7), state.dataIPShortCut->cAlphaArgs(7));
463 0 : ErrorsFound = true;
464 : }
465 :
466 1050 : if ((!state.dataIPShortCut->lAlphaFieldBlanks(8)) && (state.dataIPShortCut->cAlphaArgs(8) != "NONE")) {
467 0 : waterConnection.HeatRecovery = true;
468 0 : waterConnection.HeatRecoveryHX =
469 0 : static_cast<HeatRecovHX>(getEnumValue(HeatRecoverHXNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(8))));
470 0 : if (waterConnection.HeatRecoveryHX == HeatRecovHX::Invalid) {
471 0 : ShowSevereError(state,
472 0 : format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(8), state.dataIPShortCut->cAlphaArgs(8)));
473 0 : ShowContinueError(state, format("Entered in {} = {}", state.dataIPShortCut->cCurrentModuleObject, waterConnection.Name));
474 0 : ErrorsFound = true;
475 : }
476 :
477 0 : waterConnection.HeatRecoveryConfig =
478 0 : static_cast<HeatRecovConfig>(getEnumValue(HeatRecoveryConfigNamesUC, Util::makeUPPER(state.dataIPShortCut->cAlphaArgs(9))));
479 0 : if (waterConnection.HeatRecoveryConfig == HeatRecovConfig::Invalid) {
480 0 : ShowSevereError(state,
481 0 : format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(9), state.dataIPShortCut->cAlphaArgs(9)));
482 0 : ShowContinueError(state, format("Entered in {} = {}", state.dataIPShortCut->cCurrentModuleObject, waterConnection.Name));
483 0 : ErrorsFound = true;
484 : }
485 : }
486 :
487 1050 : waterConnection.HXUA = state.dataIPShortCut->rNumericArgs(1);
488 :
489 1050 : waterConnection.myWaterEquipArr.allocate(NumAlphas - 9);
490 :
491 2119 : for (int AlphaNum = 10; AlphaNum <= NumAlphas; ++AlphaNum) {
492 1069 : int WaterEquipNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(AlphaNum), state.dataWaterUse->WaterEquipment);
493 :
494 1069 : if (WaterEquipNum == 0) {
495 0 : ShowSevereError(
496 : state,
497 0 : format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(AlphaNum), state.dataIPShortCut->cAlphaArgs(AlphaNum)));
498 0 : ShowContinueError(state, format("Entered in {} = {}", state.dataIPShortCut->cCurrentModuleObject, waterConnection.Name));
499 0 : ErrorsFound = true;
500 : } else {
501 1069 : if (state.dataWaterUse->WaterEquipment(WaterEquipNum).Connections > 0) {
502 0 : ShowSevereError(state,
503 0 : format("{} = {}: WaterUse:Equipment = {} is already referenced by another object.",
504 0 : state.dataIPShortCut->cCurrentModuleObject,
505 0 : waterConnection.Name,
506 0 : state.dataIPShortCut->cAlphaArgs(AlphaNum)));
507 0 : ErrorsFound = true;
508 : } else {
509 1069 : state.dataWaterUse->WaterEquipment(WaterEquipNum).Connections = WaterConnNum;
510 :
511 1069 : ++waterConnection.NumWaterEquipment;
512 1069 : waterConnection.myWaterEquipArr(waterConnection.NumWaterEquipment) = WaterEquipNum;
513 :
514 1069 : waterConnection.PeakVolFlowRate +=
515 1069 : state.dataWaterUse->WaterEquipment(WaterEquipNum).PeakVolFlowRate; // this does not include possible multipliers
516 : }
517 : }
518 : }
519 :
520 : } // WaterConnNum
521 :
522 118 : if (ErrorsFound) {
523 0 : ShowFatalError(state, format("Errors found in processing input for {}", state.dataIPShortCut->cCurrentModuleObject));
524 : }
525 :
526 118 : if (state.dataWaterUse->numWaterConnections > 0) {
527 118 : state.dataWaterUse->CheckEquipName.allocate(state.dataWaterUse->numWaterConnections);
528 118 : state.dataWaterUse->CheckEquipName = true;
529 : }
530 : }
531 :
532 : // determine connection's peak mass flow rates.
533 801 : if (state.dataWaterUse->numWaterConnections > 0) {
534 1168 : for (int WaterConnNum = 1; WaterConnNum <= state.dataWaterUse->numWaterConnections; ++WaterConnNum) {
535 1050 : auto &waterConnection = state.dataWaterUse->WaterConnections(WaterConnNum);
536 1050 : waterConnection.PeakMassFlowRate = 0.0;
537 2119 : for (int WaterEquipNum = 1; WaterEquipNum <= waterConnection.NumWaterEquipment; ++WaterEquipNum) {
538 1069 : auto &thisWEq = state.dataWaterUse->WaterEquipment(waterConnection.myWaterEquipArr(WaterEquipNum));
539 1069 : if (thisWEq.Zone > 0) {
540 1019 : waterConnection.PeakMassFlowRate += thisWEq.PeakVolFlowRate * calcH2ODensity(state) *
541 1019 : state.dataHeatBal->Zone(thisWEq.Zone).Multiplier *
542 1019 : state.dataHeatBal->Zone(thisWEq.Zone).ListMultiplier;
543 : } else { // can't have multipliers
544 50 : waterConnection.PeakMassFlowRate += thisWEq.PeakVolFlowRate * calcH2ODensity(state);
545 : }
546 : }
547 1050 : PlantUtilities::RegisterPlantCompDesignFlow(
548 1050 : state, waterConnection.InletNode, waterConnection.PeakMassFlowRate / calcH2ODensity(state));
549 : }
550 : }
551 : // need a good place to set a bool to calculate WaterUse hot and cold flow rates in CalcEquipmentFlowRates
552 : // WaterUse can be used with or without WaterUse:Connections, with or without WaterUse:Equipment hot temp schedule
553 1888 : for (auto &waterEquipment : state.dataWaterUse->WaterEquipment) {
554 : // set logical if either hot water temp or target temp schedule are missing (will use cold water otherwise)
555 : // if a connections object is used then don't need to hot temp schedule
556 1087 : waterEquipment.allowHotControl =
557 1087 : (waterEquipment.targetTempSched != nullptr && waterEquipment.hotTempSched != nullptr) || waterEquipment.Connections;
558 801 : }
559 801 : }
560 :
561 1086 : void WaterEquipmentType::setupOutputVars(EnergyPlusData &state)
562 : {
563 2172 : SetupOutputVariable(state,
564 : "Water Use Equipment Hot Water Mass Flow Rate",
565 : Constant::Units::kg_s,
566 1086 : this->HotMassFlowRate,
567 : OutputProcessor::TimeStepType::System,
568 : OutputProcessor::StoreType::Average,
569 1086 : this->Name);
570 :
571 2172 : SetupOutputVariable(state,
572 : "Water Use Equipment Cold Water Mass Flow Rate",
573 : Constant::Units::kg_s,
574 1086 : this->ColdMassFlowRate,
575 : OutputProcessor::TimeStepType::System,
576 : OutputProcessor::StoreType::Average,
577 1086 : this->Name);
578 :
579 2172 : SetupOutputVariable(state,
580 : "Water Use Equipment Total Mass Flow Rate",
581 : Constant::Units::kg_s,
582 1086 : this->TotalMassFlowRate,
583 : OutputProcessor::TimeStepType::System,
584 : OutputProcessor::StoreType::Average,
585 1086 : this->Name);
586 :
587 2172 : SetupOutputVariable(state,
588 : "Water Use Equipment Hot Water Volume Flow Rate",
589 : Constant::Units::m3_s,
590 1086 : this->HotVolFlowRate,
591 : OutputProcessor::TimeStepType::System,
592 : OutputProcessor::StoreType::Average,
593 1086 : this->Name);
594 :
595 2172 : SetupOutputVariable(state,
596 : "Water Use Equipment Cold Water Volume Flow Rate",
597 : Constant::Units::m3_s,
598 1086 : this->ColdVolFlowRate,
599 : OutputProcessor::TimeStepType::System,
600 : OutputProcessor::StoreType::Average,
601 1086 : this->Name);
602 :
603 2172 : SetupOutputVariable(state,
604 : "Water Use Equipment Total Volume Flow Rate",
605 : Constant::Units::m3_s,
606 1086 : this->TotalVolFlowRate,
607 : OutputProcessor::TimeStepType::System,
608 : OutputProcessor::StoreType::Average,
609 1086 : this->Name);
610 :
611 2172 : SetupOutputVariable(state,
612 : "Water Use Equipment Hot Water Volume",
613 : Constant::Units::m3,
614 1086 : this->HotVolume,
615 : OutputProcessor::TimeStepType::System,
616 : OutputProcessor::StoreType::Sum,
617 1086 : this->Name);
618 :
619 2172 : SetupOutputVariable(state,
620 : "Water Use Equipment Cold Water Volume",
621 : Constant::Units::m3,
622 1086 : this->ColdVolume,
623 : OutputProcessor::TimeStepType::System,
624 : OutputProcessor::StoreType::Sum,
625 1086 : this->Name);
626 :
627 2172 : SetupOutputVariable(state,
628 : "Water Use Equipment Total Volume",
629 : Constant::Units::m3,
630 1086 : this->TotalVolume,
631 : OutputProcessor::TimeStepType::System,
632 : OutputProcessor::StoreType::Sum,
633 1086 : this->Name,
634 : Constant::eResource::Water,
635 : OutputProcessor::Group::Plant,
636 : OutputProcessor::EndUseCat::WaterSystem,
637 : this->EndUseSubcatName);
638 2172 : SetupOutputVariable(state,
639 : "Water Use Equipment Mains Water Volume",
640 : Constant::Units::m3,
641 1086 : this->TotalVolume,
642 : OutputProcessor::TimeStepType::System,
643 : OutputProcessor::StoreType::Sum,
644 1086 : this->Name,
645 : Constant::eResource::MainsWater,
646 : OutputProcessor::Group::Plant,
647 : OutputProcessor::EndUseCat::WaterSystem,
648 : this->EndUseSubcatName);
649 :
650 2172 : SetupOutputVariable(state,
651 : "Water Use Equipment Hot Water Temperature",
652 : Constant::Units::C,
653 1086 : this->HotTemp,
654 : OutputProcessor::TimeStepType::System,
655 : OutputProcessor::StoreType::Average,
656 1086 : this->Name);
657 :
658 2172 : SetupOutputVariable(state,
659 : "Water Use Equipment Cold Water Temperature",
660 : Constant::Units::C,
661 1086 : this->ColdTemp,
662 : OutputProcessor::TimeStepType::System,
663 : OutputProcessor::StoreType::Average,
664 1086 : this->Name);
665 :
666 2172 : SetupOutputVariable(state,
667 : "Water Use Equipment Target Water Temperature",
668 : Constant::Units::C,
669 1086 : this->TargetTemp,
670 : OutputProcessor::TimeStepType::System,
671 : OutputProcessor::StoreType::Average,
672 1086 : this->Name);
673 :
674 2172 : SetupOutputVariable(state,
675 : "Water Use Equipment Mixed Water Temperature",
676 : Constant::Units::C,
677 1086 : this->MixedTemp,
678 : OutputProcessor::TimeStepType::System,
679 : OutputProcessor::StoreType::Average,
680 1086 : this->Name);
681 :
682 2172 : SetupOutputVariable(state,
683 : "Water Use Equipment Drain Water Temperature",
684 : Constant::Units::C,
685 1086 : this->DrainTemp,
686 : OutputProcessor::TimeStepType::System,
687 : OutputProcessor::StoreType::Average,
688 1086 : this->Name);
689 :
690 2172 : SetupOutputVariable(state,
691 : "Water Use Equipment Heating Rate",
692 : Constant::Units::W,
693 1086 : this->Power,
694 : OutputProcessor::TimeStepType::System,
695 : OutputProcessor::StoreType::Average,
696 1086 : this->Name);
697 :
698 1086 : if (this->Connections == 0) {
699 36 : SetupOutputVariable(state,
700 : "Water Use Equipment Heating Energy",
701 : Constant::Units::J,
702 18 : this->Energy,
703 : OutputProcessor::TimeStepType::System,
704 : OutputProcessor::StoreType::Sum,
705 18 : this->Name,
706 : Constant::eResource::DistrictHeatingWater,
707 : OutputProcessor::Group::Plant,
708 : OutputProcessor::EndUseCat::WaterSystem,
709 : this->EndUseSubcatName);
710 :
711 1068 : } else if (state.dataWaterUse->WaterConnections(this->Connections).StandAlone) {
712 0 : SetupOutputVariable(state,
713 : "Water Use Equipment Heating Energy",
714 : Constant::Units::J,
715 0 : this->Energy,
716 : OutputProcessor::TimeStepType::System,
717 : OutputProcessor::StoreType::Sum,
718 0 : this->Name,
719 : Constant::eResource::DistrictHeatingWater,
720 : OutputProcessor::Group::Plant,
721 : OutputProcessor::EndUseCat::WaterSystem,
722 : this->EndUseSubcatName);
723 :
724 : } else { // The EQUIPMENT is coupled to a plant loop via a CONNECTIONS object
725 2136 : SetupOutputVariable(state,
726 : "Water Use Equipment Heating Energy",
727 : Constant::Units::J,
728 1068 : this->Energy,
729 : OutputProcessor::TimeStepType::System,
730 : OutputProcessor::StoreType::Sum,
731 1068 : this->Name,
732 : Constant::eResource::EnergyTransfer,
733 : OutputProcessor::Group::Plant,
734 : OutputProcessor::EndUseCat::WaterSystem,
735 : this->EndUseSubcatName);
736 : }
737 :
738 1086 : if (this->Zone > 0) {
739 2036 : SetupOutputVariable(state,
740 : "Water Use Equipment Zone Sensible Heat Gain Rate",
741 : Constant::Units::W,
742 1018 : this->SensibleRate,
743 : OutputProcessor::TimeStepType::System,
744 : OutputProcessor::StoreType::Average,
745 1018 : this->Name);
746 2036 : SetupOutputVariable(state,
747 : "Water Use Equipment Zone Sensible Heat Gain Energy",
748 : Constant::Units::J,
749 1018 : this->SensibleEnergy,
750 : OutputProcessor::TimeStepType::System,
751 : OutputProcessor::StoreType::Sum,
752 1018 : this->Name);
753 :
754 2036 : SetupOutputVariable(state,
755 : "Water Use Equipment Zone Latent Gain Rate",
756 : Constant::Units::W,
757 1018 : this->LatentRate,
758 : OutputProcessor::TimeStepType::System,
759 : OutputProcessor::StoreType::Average,
760 1018 : this->Name);
761 2036 : SetupOutputVariable(state,
762 : "Water Use Equipment Zone Latent Gain Energy",
763 : Constant::Units::J,
764 1018 : this->LatentEnergy,
765 : OutputProcessor::TimeStepType::System,
766 : OutputProcessor::StoreType::Sum,
767 1018 : this->Name);
768 :
769 2036 : SetupOutputVariable(state,
770 : "Water Use Equipment Zone Moisture Gain Mass Flow Rate",
771 : Constant::Units::kg_s,
772 1018 : this->MoistureRate,
773 : OutputProcessor::TimeStepType::System,
774 : OutputProcessor::StoreType::Average,
775 1018 : this->Name);
776 2036 : SetupOutputVariable(state,
777 : "Water Use Equipment Zone Moisture Gain Mass",
778 : Constant::Units::kg,
779 1018 : this->MoistureMass,
780 : OutputProcessor::TimeStepType::System,
781 : OutputProcessor::StoreType::Sum,
782 1018 : this->Name);
783 :
784 1018 : SetupZoneInternalGain(state,
785 : this->Zone,
786 : this->Name,
787 : DataHeatBalance::IntGainType::WaterUseEquipment,
788 : &this->SensibleRateNoMultiplier,
789 : nullptr,
790 : nullptr,
791 : &this->LatentRateNoMultiplier);
792 : }
793 1086 : }
794 :
795 1050 : void WaterConnectionsType::setupOutputVars(EnergyPlusData &state)
796 : {
797 2100 : SetupOutputVariable(state,
798 : "Water Use Connections Hot Water Mass Flow Rate",
799 : Constant::Units::kg_s,
800 1050 : this->HotMassFlowRate,
801 : OutputProcessor::TimeStepType::System,
802 : OutputProcessor::StoreType::Average,
803 1050 : this->Name);
804 :
805 2100 : SetupOutputVariable(state,
806 : "Water Use Connections Cold Water Mass Flow Rate",
807 : Constant::Units::kg_s,
808 1050 : this->ColdMassFlowRate,
809 : OutputProcessor::TimeStepType::System,
810 : OutputProcessor::StoreType::Average,
811 1050 : this->Name);
812 :
813 2100 : SetupOutputVariable(state,
814 : "Water Use Connections Total Mass Flow Rate",
815 : Constant::Units::kg_s,
816 1050 : this->TotalMassFlowRate,
817 : OutputProcessor::TimeStepType::System,
818 : OutputProcessor::StoreType::Average,
819 1050 : this->Name);
820 :
821 2100 : SetupOutputVariable(state,
822 : "Water Use Connections Drain Water Mass Flow Rate",
823 : Constant::Units::kg_s,
824 1050 : this->DrainMassFlowRate,
825 : OutputProcessor::TimeStepType::System,
826 : OutputProcessor::StoreType::Average,
827 1050 : this->Name);
828 :
829 2100 : SetupOutputVariable(state,
830 : "Water Use Connections Heat Recovery Mass Flow Rate",
831 : Constant::Units::kg_s,
832 1050 : this->RecoveryMassFlowRate,
833 : OutputProcessor::TimeStepType::System,
834 : OutputProcessor::StoreType::Average,
835 1050 : this->Name);
836 :
837 2100 : SetupOutputVariable(state,
838 : "Water Use Connections Hot Water Volume Flow Rate",
839 : Constant::Units::m3_s,
840 1050 : this->HotVolFlowRate,
841 : OutputProcessor::TimeStepType::System,
842 : OutputProcessor::StoreType::Average,
843 1050 : this->Name);
844 :
845 2100 : SetupOutputVariable(state,
846 : "Water Use Connections Cold Water Volume Flow Rate",
847 : Constant::Units::m3_s,
848 1050 : this->ColdVolFlowRate,
849 : OutputProcessor::TimeStepType::System,
850 : OutputProcessor::StoreType::Average,
851 1050 : this->Name);
852 :
853 2100 : SetupOutputVariable(state,
854 : "Water Use Connections Total Volume Flow Rate",
855 : Constant::Units::m3_s,
856 1050 : this->TotalVolFlowRate,
857 : OutputProcessor::TimeStepType::System,
858 : OutputProcessor::StoreType::Average,
859 1050 : this->Name);
860 :
861 2100 : SetupOutputVariable(state,
862 : "Water Use Connections Hot Water Volume",
863 : Constant::Units::m3,
864 1050 : this->HotVolume,
865 : OutputProcessor::TimeStepType::System,
866 : OutputProcessor::StoreType::Sum,
867 1050 : this->Name);
868 :
869 2100 : SetupOutputVariable(state,
870 : "Water Use Connections Cold Water Volume",
871 : Constant::Units::m3,
872 1050 : this->ColdVolume,
873 : OutputProcessor::TimeStepType::System,
874 : OutputProcessor::StoreType::Sum,
875 1050 : this->Name);
876 :
877 2100 : SetupOutputVariable(state,
878 : "Water Use Connections Total Volume",
879 : Constant::Units::m3,
880 1050 : this->TotalVolume,
881 : OutputProcessor::TimeStepType::System,
882 : OutputProcessor::StoreType::Sum,
883 1050 : this->Name); //, &
884 : // ResourceTypeKey='Water', EndUseKey='DHW', EndUseSubKey=EndUseSubcategoryName, GroupKey='Plant')
885 : // tHIS WAS double counting
886 :
887 2100 : SetupOutputVariable(state,
888 : "Water Use Connections Hot Water Temperature",
889 : Constant::Units::C,
890 1050 : this->HotTemp,
891 : OutputProcessor::TimeStepType::System,
892 : OutputProcessor::StoreType::Average,
893 1050 : this->Name);
894 :
895 2100 : SetupOutputVariable(state,
896 : "Water Use Connections Cold Water Temperature",
897 : Constant::Units::C,
898 1050 : this->ColdTemp,
899 : OutputProcessor::TimeStepType::System,
900 : OutputProcessor::StoreType::Average,
901 1050 : this->Name);
902 :
903 2100 : SetupOutputVariable(state,
904 : "Water Use Connections Drain Water Temperature",
905 : Constant::Units::C,
906 1050 : this->DrainTemp,
907 : OutputProcessor::TimeStepType::System,
908 : OutputProcessor::StoreType::Average,
909 1050 : this->Name);
910 :
911 2100 : SetupOutputVariable(state,
912 : "Water Use Connections Return Water Temperature",
913 : Constant::Units::C,
914 1050 : this->ReturnTemp,
915 : OutputProcessor::TimeStepType::System,
916 : OutputProcessor::StoreType::Average,
917 1050 : this->Name);
918 :
919 2100 : SetupOutputVariable(state,
920 : "Water Use Connections Waste Water Temperature",
921 : Constant::Units::C,
922 1050 : this->WasteTemp,
923 : OutputProcessor::TimeStepType::System,
924 : OutputProcessor::StoreType::Average,
925 1050 : this->Name);
926 :
927 2100 : SetupOutputVariable(state,
928 : "Water Use Connections Heat Recovery Water Temperature",
929 : Constant::Units::C,
930 1050 : this->RecoveryTemp,
931 : OutputProcessor::TimeStepType::System,
932 : OutputProcessor::StoreType::Average,
933 1050 : this->Name);
934 :
935 2100 : SetupOutputVariable(state,
936 : "Water Use Connections Heat Recovery Effectiveness",
937 : Constant::Units::None,
938 1050 : this->Effectiveness,
939 : OutputProcessor::TimeStepType::System,
940 : OutputProcessor::StoreType::Average,
941 1050 : this->Name);
942 :
943 2100 : SetupOutputVariable(state,
944 : "Water Use Connections Heat Recovery Rate",
945 : Constant::Units::W,
946 1050 : this->RecoveryRate,
947 : OutputProcessor::TimeStepType::System,
948 : OutputProcessor::StoreType::Average,
949 1050 : this->Name);
950 2100 : SetupOutputVariable(state,
951 : "Water Use Connections Heat Recovery Energy",
952 : Constant::Units::J,
953 1050 : this->RecoveryEnergy,
954 : OutputProcessor::TimeStepType::System,
955 : OutputProcessor::StoreType::Sum,
956 1050 : this->Name);
957 : // Does this go on a meter?
958 :
959 : // To do: Add report variable for starved flow when tank can't deliver?
960 :
961 1050 : if (!this->StandAlone) {
962 2100 : SetupOutputVariable(state,
963 : "Water Use Connections Plant Hot Water Energy",
964 : Constant::Units::J,
965 1050 : this->Energy,
966 : OutputProcessor::TimeStepType::System,
967 : OutputProcessor::StoreType::Sum,
968 1050 : this->Name,
969 : Constant::eResource::PlantLoopHeatingDemand,
970 : OutputProcessor::Group::Plant,
971 : OutputProcessor::EndUseCat::WaterSystem);
972 : }
973 1050 : }
974 :
975 42087518 : void WaterEquipmentType::CalcEquipmentFlowRates(EnergyPlusData &state)
976 : {
977 :
978 : // SUBROUTINE INFORMATION:
979 : // AUTHOR Peter Graham Ellis
980 : // DATE WRITTEN August 2006
981 :
982 : // PURPOSE OF THIS SUBROUTINE:
983 : // Calculate desired hot and cold water flow rates
984 :
985 : Real64 TempDiff;
986 42087518 : Real64 constexpr EPSILON(1.e-3);
987 :
988 42087518 : if (this->setupMyOutputVars) {
989 18 : this->setupOutputVars(state);
990 18 : this->setupMyOutputVars = false;
991 : }
992 :
993 42087518 : if (this->Connections > 0) {
994 : // Get water temperature conditions from the CONNECTIONS object
995 41982956 : this->ColdTemp = state.dataWaterUse->WaterConnections(this->Connections).ColdTemp;
996 41982956 : this->HotTemp = state.dataWaterUse->WaterConnections(this->Connections).HotTemp;
997 :
998 : } else {
999 : // Get water temperature conditions from the WATER USE EQUIPMENT schedules
1000 104562 : this->ColdTemp = (this->coldTempSched != nullptr) ? this->coldTempSched->getCurrentVal() : state.dataEnvrn->WaterMainsTemp;
1001 104562 : this->HotTemp = (this->hotTempSched != nullptr) ? this->hotTempSched->getCurrentVal() : this->ColdTemp;
1002 : }
1003 :
1004 42087518 : if (this->targetTempSched != nullptr) {
1005 35566428 : this->TargetTemp = this->targetTempSched->getCurrentVal();
1006 6521090 : } else if (this->allowHotControl) { // If no TargetTempSchedule, but allowHotControl is set, use all hot water if applicable
1007 6521090 : this->TargetTemp = this->HotTemp;
1008 : } else { // If no TargetTempSchedule, use all cold water
1009 0 : this->TargetTemp = this->ColdTemp;
1010 : }
1011 :
1012 : // Get the requested total flow rate
1013 42087518 : this->TotalVolFlowRate = this->PeakVolFlowRate;
1014 42087518 : if (this->Zone > 0) {
1015 40750354 : this->TotalVolFlowRate *= state.dataHeatBal->Zone(this->Zone).Multiplier * state.dataHeatBal->Zone(this->Zone).ListMultiplier;
1016 : }
1017 42087518 : if (this->flowRateFracSched != nullptr) {
1018 42087518 : this->TotalVolFlowRate *= this->flowRateFracSched->getCurrentVal();
1019 : }
1020 :
1021 42087518 : this->TotalMassFlowRate = this->TotalVolFlowRate * calcH2ODensity(state);
1022 :
1023 : // Calculate hot and cold water mixing at the tap
1024 42087518 : if (this->TotalMassFlowRate > 0.0 && this->allowHotControl) {
1025 : // Calculate the flow rates needed to meet the target temperature
1026 27639398 : if (this->TargetTemp <= this->ColdTemp + EPSILON) {
1027 : // don't need to mix (use cold) or hot water flow would be very small if within EPSILON above cold temp (use cold)
1028 55648 : this->HotMassFlowRate = 0.0;
1029 55648 : if (!state.dataGlobal->WarmupFlag && this->TargetTemp < this->ColdTemp) {
1030 : // print error for variables of target water temperature
1031 872 : ++this->TargetCWTempErrorCount;
1032 872 : TempDiff = this->ColdTemp - this->TargetTemp;
1033 872 : if (this->TargetCWTempErrorCount < 2) {
1034 2 : ShowWarningError(
1035 : state,
1036 2 : format("CalcEquipmentFlowRates: \"{}\" - Target water temperature is less than the cold water temperature by ({:.2R} C)",
1037 1 : this->Name,
1038 : TempDiff));
1039 2 : ShowContinueErrorTimeStamp(state, "");
1040 1 : ShowContinueError(state, format("...target water temperature = {:.2R} C", this->TargetTemp));
1041 1 : ShowContinueError(state, format("...cold water temperature = {:.2R} C", this->ColdTemp));
1042 3 : ShowContinueError(state,
1043 : "...Target water temperature should be greater than or equal to the cold water temperature. "
1044 : "Verify temperature setpoints and schedules.");
1045 : } else {
1046 6968 : ShowRecurringWarningErrorAtEnd(
1047 : state,
1048 1742 : format(
1049 : "\"{}\" - Target water temperature should be greater than or equal to the cold water temperature error continues...",
1050 871 : this->Name),
1051 871 : this->TargetCWTempErrIndex,
1052 : TempDiff,
1053 : TempDiff);
1054 : }
1055 : }
1056 27583750 : } else if (this->TargetTemp >= this->HotTemp) {
1057 : // don't need to mix (use hot), or need to purge stagnant hot water temps (use hot)
1058 5678618 : this->HotMassFlowRate = this->TotalMassFlowRate;
1059 5678618 : if (!state.dataGlobal->WarmupFlag) {
1060 : // print error for variables of target water temperature
1061 770942 : if (this->ColdTemp > (this->HotTemp + EPSILON)) {
1062 : // print error for variables of hot water temperature
1063 0 : ++this->CWHWTempErrorCount;
1064 0 : TempDiff = this->ColdTemp - this->HotTemp;
1065 0 : if (this->CWHWTempErrorCount < 2) {
1066 0 : ShowWarningError(
1067 : state,
1068 0 : format("CalcEquipmentFlowRates: \"{}\" - Hot water temperature is less than the cold water temperature by ({:.2R} C)",
1069 0 : this->Name,
1070 : TempDiff));
1071 0 : ShowContinueErrorTimeStamp(state, "");
1072 0 : ShowContinueError(state, format("...hot water temperature = {:.2R} C", this->HotTemp));
1073 0 : ShowContinueError(state, format("...cold water temperature = {:.2R} C", this->ColdTemp));
1074 0 : ShowContinueError(state,
1075 : "...Hot water temperature should be greater than or equal to the cold water temperature. "
1076 : "Verify temperature setpoints and schedules.");
1077 : } else {
1078 0 : ShowRecurringWarningErrorAtEnd(
1079 : state,
1080 0 : format("\"{}\" - Hot water temperature should be greater than the cold water temperature error continues... ",
1081 0 : this->Name),
1082 0 : this->CWHWTempErrIndex,
1083 : TempDiff,
1084 : TempDiff);
1085 : }
1086 770942 : } else if (this->TargetTemp > this->HotTemp) {
1087 11566 : TempDiff = this->TargetTemp - this->HotTemp;
1088 11566 : ++this->TargetHWTempErrorCount;
1089 11566 : if (this->TargetHWTempErrorCount < 2) {
1090 8 : ShowWarningError(state,
1091 8 : format("CalcEquipmentFlowRates: \"{}\" - Target water temperature is greater than the hot water "
1092 : "temperature by ({:.2R} C)",
1093 4 : this->Name,
1094 : TempDiff));
1095 8 : ShowContinueErrorTimeStamp(state, "");
1096 4 : ShowContinueError(state, format("...target water temperature = {:.2R} C", this->TargetTemp));
1097 4 : ShowContinueError(state, format("...hot water temperature = {:.2R} C", this->HotTemp));
1098 12 : ShowContinueError(state,
1099 : "...Target water temperature should be less than or equal to the hot water temperature. "
1100 : "Verify temperature setpoints and schedules.");
1101 : } else {
1102 92496 : ShowRecurringWarningErrorAtEnd(state,
1103 23124 : format("\"{}\" - Target water temperature should be less than or equal to the hot "
1104 : "water temperature error continues...",
1105 11562 : this->Name),
1106 11562 : this->TargetHWTempErrIndex,
1107 : TempDiff,
1108 : TempDiff);
1109 : }
1110 : }
1111 : }
1112 : } else {
1113 : // Check hot less than cold temp, else calculate hot flow.
1114 21905132 : if (this->HotTemp <= this->ColdTemp + EPSILON) {
1115 : // will need to avoid divide by 0 and stagnant region. Target temp is greater than ColdTemp so use hot water
1116 : // continue using hot water until hot water temp is EPSILON C above cold water temp (i.e., avoid very small denominator)
1117 0 : this->HotMassFlowRate = this->TotalMassFlowRate;
1118 0 : if (!state.dataGlobal->WarmupFlag && this->HotTemp < this->ColdTemp) {
1119 : // print error for variables of hot water temperature
1120 0 : ++this->CWHWTempErrorCount;
1121 0 : TempDiff = this->ColdTemp - this->HotTemp;
1122 0 : if (this->CWHWTempErrorCount < 2) {
1123 0 : ShowWarningError(state,
1124 0 : format("CalcEquipmentFlowRates: \"{}\" - Hot water temperature is less than the cold water "
1125 : "temperature by ({:.2R} C)",
1126 0 : this->Name,
1127 : TempDiff));
1128 0 : ShowContinueErrorTimeStamp(state, "");
1129 0 : ShowContinueError(state, format("...hot water temperature = {:.2R} C", this->HotTemp));
1130 0 : ShowContinueError(state, format("...cold water temperature = {:.2R} C", this->ColdTemp));
1131 0 : ShowContinueError(state,
1132 : "...Hot water temperature should be greater than or equal to the cold water temperature. "
1133 : "Verify temperature setpoints and schedules.");
1134 : } else {
1135 0 : ShowRecurringWarningErrorAtEnd(
1136 : state,
1137 0 : format("\"{}\" - Hot water temperature should be greater than the cold water temperature error continues... ",
1138 0 : this->Name),
1139 0 : this->CWHWTempErrIndex,
1140 : TempDiff,
1141 : TempDiff);
1142 : }
1143 : }
1144 : } else {
1145 : // HotMassFlowRate should always be between 0 and TotalMassFlowRate
1146 21905132 : this->HotMassFlowRate = this->TotalMassFlowRate * (this->TargetTemp - this->ColdTemp) / (this->HotTemp - this->ColdTemp);
1147 : }
1148 : }
1149 :
1150 27639398 : this->ColdMassFlowRate = this->TotalMassFlowRate - this->HotMassFlowRate;
1151 27639398 : this->MixedTemp = (this->ColdMassFlowRate * this->ColdTemp + this->HotMassFlowRate * this->HotTemp) / this->TotalMassFlowRate;
1152 : // there should be no out of bounds results
1153 27639398 : assert(this->ColdMassFlowRate >= 0.0 && this->ColdMassFlowRate <= this->TotalMassFlowRate);
1154 27639398 : assert(this->HotMassFlowRate >= 0.0 && this->HotMassFlowRate <= this->TotalMassFlowRate);
1155 27639398 : assert(std::abs(this->HotMassFlowRate + this->ColdMassFlowRate - this->TotalMassFlowRate) < EPSILON);
1156 : } else {
1157 14448120 : this->HotMassFlowRate = 0.0;
1158 14448120 : this->ColdMassFlowRate = this->TotalMassFlowRate;
1159 14448120 : this->MixedTemp = this->TargetTemp;
1160 : }
1161 42087518 : }
1162 :
1163 42087518 : void WaterEquipmentType::CalcEquipmentDrainTemp(EnergyPlusData &state)
1164 : {
1165 :
1166 : // SUBROUTINE INFORMATION:
1167 : // AUTHOR Peter Graham Ellis
1168 : // DATE WRITTEN August 2006
1169 :
1170 : // PURPOSE OF THIS SUBROUTINE:
1171 : // Calculate drainwater temperature and heat and moisture gains to zone.
1172 :
1173 : static constexpr std::string_view RoutineName("CalcEquipmentDrainTemp");
1174 :
1175 42087518 : this->SensibleRate = 0.0;
1176 42087518 : this->SensibleEnergy = 0.0;
1177 42087518 : this->LatentRate = 0.0;
1178 42087518 : this->LatentEnergy = 0.0;
1179 :
1180 42087518 : if ((this->Zone == 0) || (this->TotalMassFlowRate == 0.0)) {
1181 15442850 : this->DrainTemp = this->MixedTemp;
1182 15442850 : this->DrainMassFlowRate = this->TotalMassFlowRate;
1183 :
1184 : } else {
1185 26644668 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(this->Zone);
1186 :
1187 26644668 : if (this->sensibleFracSched == nullptr) {
1188 0 : this->SensibleRate = 0.0;
1189 0 : this->SensibleEnergy = 0.0;
1190 : } else {
1191 26644668 : this->SensibleRate = this->sensibleFracSched->getCurrentVal() * this->TotalMassFlowRate *
1192 26644668 : Psychrometrics::CPHW(Constant::InitConvTemp) * (this->MixedTemp - thisZoneHB.MAT);
1193 26644668 : this->SensibleEnergy = this->SensibleRate * state.dataHVACGlobal->TimeStepSysSec;
1194 : }
1195 :
1196 26644668 : if (this->latentFracSched == nullptr) {
1197 60120 : this->LatentRate = 0.0;
1198 60120 : this->LatentEnergy = 0.0;
1199 : } else {
1200 26584548 : Real64 ZoneHumRat = thisZoneHB.airHumRat;
1201 26584548 : Real64 ZoneHumRatSat = Psychrometrics::PsyWFnTdbRhPb(state,
1202 : thisZoneHB.MAT,
1203 : 1.0,
1204 26584548 : state.dataEnvrn->OutBaroPress,
1205 : RoutineName); // Humidratio at 100% relative humidity
1206 26584548 : Real64 RhoAirDry = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisZoneHB.MAT, 0.0);
1207 : Real64 ZoneMassMax =
1208 26584548 : (ZoneHumRatSat - ZoneHumRat) * RhoAirDry * state.dataHeatBal->Zone(this->Zone).Volume; // Max water that can be evaporated to zone
1209 26584548 : Real64 FlowMassMax = this->TotalMassFlowRate * state.dataHVACGlobal->TimeStepSysSec; // Max water in flow
1210 26584548 : Real64 MoistureMassMax = min(ZoneMassMax, FlowMassMax);
1211 :
1212 26584548 : this->MoistureMass = this->latentFracSched->getCurrentVal() * MoistureMassMax;
1213 26584548 : this->MoistureRate = this->MoistureMass / (state.dataHVACGlobal->TimeStepSysSec);
1214 :
1215 26584548 : this->LatentRate = this->MoistureRate * Psychrometrics::PsyHfgAirFnWTdb(ZoneHumRat, thisZoneHB.MAT);
1216 26584548 : this->LatentEnergy = this->LatentRate * state.dataHVACGlobal->TimeStepSysSec;
1217 : }
1218 :
1219 26644668 : this->DrainMassFlowRate = this->TotalMassFlowRate - this->MoistureRate;
1220 :
1221 26644668 : if (this->DrainMassFlowRate == 0.0) {
1222 0 : this->DrainTemp = this->MixedTemp;
1223 : } else {
1224 26644668 : this->DrainTemp = (this->TotalMassFlowRate * Psychrometrics::CPHW(Constant::InitConvTemp) * this->MixedTemp - this->SensibleRate -
1225 53289336 : this->LatentRate) /
1226 26644668 : (this->DrainMassFlowRate * Psychrometrics::CPHW(Constant::InitConvTemp));
1227 : }
1228 : }
1229 42087518 : }
1230 :
1231 41586463 : void WaterConnectionsType::InitConnections(EnergyPlusData &state)
1232 : {
1233 :
1234 : // SUBROUTINE INFORMATION:
1235 : // AUTHOR Peter Graham Ellis
1236 : // DATE WRITTEN August 2006
1237 : // MODIFIED Brent Griffith 2010, demand side update
1238 :
1239 : // Set the cold water temperature
1240 41586463 : if (this->SupplyTankNum > 0) {
1241 0 : this->ColdSupplyTemp = state.dataWaterData->WaterStorage(this->SupplyTankNum).Twater;
1242 :
1243 41586463 : } else if (this->coldTempSched != nullptr) {
1244 105307 : this->ColdSupplyTemp = this->coldTempSched->getCurrentVal();
1245 :
1246 : } else {
1247 41481156 : this->ColdSupplyTemp = state.dataEnvrn->WaterMainsTemp;
1248 : }
1249 :
1250 : // Initially set ColdTemp to the ColdSupplyTemp; with heat recovery, ColdTemp will change during iteration
1251 41586463 : this->ColdTemp = this->ColdSupplyTemp;
1252 :
1253 : // Set the hot water temperature
1254 41586463 : if (this->StandAlone) {
1255 0 : this->HotTemp = (this->hotTempSched != nullptr) ? this->hotTempSched->getCurrentVal() : this->ColdTemp;
1256 : } else {
1257 :
1258 41586463 : if (state.dataGlobal->BeginEnvrnFlag && this->Init) {
1259 : // Clear node initial conditions
1260 6850 : if (this->InletNode > 0 && this->OutletNode > 0) {
1261 6850 : PlantUtilities::InitComponentNodes(state, 0.0, this->PeakMassFlowRate, this->InletNode, this->OutletNode);
1262 :
1263 6850 : this->ReturnTemp = state.dataLoopNodes->Node(this->InletNode).Temp;
1264 : }
1265 :
1266 6850 : this->Init = false;
1267 : }
1268 :
1269 41586463 : if (!state.dataGlobal->BeginEnvrnFlag) {
1270 41228300 : this->Init = true;
1271 : }
1272 :
1273 41586463 : if (this->InletNode > 0) {
1274 41586463 : if (!state.dataGlobal->DoingSizing) {
1275 41586463 : this->HotTemp = state.dataLoopNodes->Node(this->InletNode).Temp;
1276 : } else {
1277 : // plant loop will not be running so need a value here.
1278 : // should change to use tank setpoint but water use connections don't have knowledge of the tank they are fed by
1279 0 : this->HotTemp = 60.0;
1280 : }
1281 : }
1282 : }
1283 41586463 : }
1284 :
1285 41586463 : void WaterConnectionsType::CalcConnectionsFlowRates(EnergyPlusData &state, bool FirstHVACIteration)
1286 : {
1287 :
1288 : // SUBROUTINE INFORMATION:
1289 : // AUTHOR Peter Graham Ellis
1290 : // DATE WRITTEN August 2006
1291 :
1292 : // PURPOSE OF THIS SUBROUTINE:
1293 : // Calculate summed values for WATER USE CONNECTIONS (to prepare to request flow from plant, and for reporting).
1294 :
1295 41586463 : this->ColdMassFlowRate = 0.0;
1296 41586463 : this->HotMassFlowRate = 0.0;
1297 :
1298 83569419 : for (int Loop = 1; Loop <= this->NumWaterEquipment; ++Loop) {
1299 41982956 : auto &thisWEq = state.dataWaterUse->WaterEquipment(this->myWaterEquipArr(Loop));
1300 :
1301 41982956 : thisWEq.CalcEquipmentFlowRates(state);
1302 :
1303 41982956 : this->ColdMassFlowRate += thisWEq.ColdMassFlowRate;
1304 41982956 : this->HotMassFlowRate += thisWEq.HotMassFlowRate;
1305 : } // Loop
1306 :
1307 41586463 : this->TotalMassFlowRate = this->ColdMassFlowRate + this->HotMassFlowRate;
1308 :
1309 41586463 : if (!this->StandAlone) { // Interact with the plant loop
1310 41586463 : if (this->InletNode > 0) {
1311 41586463 : if (FirstHVACIteration) {
1312 : // Request the mass flow rate from the demand side manager
1313 18224041 : PlantUtilities::SetComponentFlowRate(state, this->HotMassFlowRate, this->InletNode, this->OutletNode, this->plantLoc);
1314 :
1315 : } else {
1316 23362422 : Real64 DesiredHotWaterMassFlow = this->HotMassFlowRate;
1317 23362422 : PlantUtilities::SetComponentFlowRate(state, DesiredHotWaterMassFlow, this->InletNode, this->OutletNode, this->plantLoc);
1318 : // readjust if more than actual available mass flow rate determined by the demand side manager
1319 23362422 : if ((this->HotMassFlowRate != DesiredHotWaterMassFlow) && (this->HotMassFlowRate > 0.0)) { // plant didn't give what was asked for
1320 :
1321 3379526 : Real64 AvailableFraction = DesiredHotWaterMassFlow / this->HotMassFlowRate;
1322 :
1323 3379526 : this->ColdMassFlowRate = this->TotalMassFlowRate - this->HotMassFlowRate; // Preserve the total mass flow rate
1324 :
1325 : // Proportionally reduce hot water and increase cold water for all WATER USE EQUIPMENT
1326 6802870 : for (int Loop = 1; Loop <= this->NumWaterEquipment; ++Loop) {
1327 3423344 : auto &thisWEq = state.dataWaterUse->WaterEquipment(this->myWaterEquipArr(Loop));
1328 :
1329 : // Recalculate flow rates for water equipment within connection
1330 3423344 : thisWEq.HotMassFlowRate *= AvailableFraction;
1331 3423344 : thisWEq.ColdMassFlowRate = thisWEq.TotalMassFlowRate - thisWEq.HotMassFlowRate;
1332 :
1333 : // Recalculate mixed water temperature
1334 3423344 : if (thisWEq.TotalMassFlowRate > 0.0) {
1335 3417961 : thisWEq.MixedTemp = (thisWEq.ColdMassFlowRate * thisWEq.ColdTemp + thisWEq.HotMassFlowRate * thisWEq.HotTemp) /
1336 3417961 : thisWEq.TotalMassFlowRate;
1337 : } else {
1338 5383 : thisWEq.MixedTemp = thisWEq.TargetTemp;
1339 : }
1340 : } // Loop
1341 : }
1342 : }
1343 : }
1344 : }
1345 :
1346 41586463 : if (this->SupplyTankNum > 0) {
1347 : // Set the demand request for supply water from water storage tank
1348 0 : this->ColdVolFlowRate = this->ColdMassFlowRate / calcH2ODensity(state);
1349 0 : state.dataWaterData->WaterStorage(this->SupplyTankNum).VdotRequestDemand(this->TankDemandID) = this->ColdVolFlowRate;
1350 :
1351 : // Check if cold flow rate should be starved by restricted flow from tank
1352 : // Currently, the tank flow is not really starved--water continues to flow at the tank water temperature
1353 : // But the user can see the error by comparing report variables for TankVolFlowRate < ColdVolFlowRate
1354 0 : this->TankVolFlowRate = state.dataWaterData->WaterStorage(this->SupplyTankNum).VdotAvailDemand(this->TankDemandID);
1355 0 : this->TankMassFlowRate = this->TankVolFlowRate * calcH2ODensity(state);
1356 : }
1357 41586463 : }
1358 :
1359 41586463 : void WaterConnectionsType::CalcConnectionsDrainTemp(EnergyPlusData &state)
1360 : {
1361 :
1362 : // SUBROUTINE INFORMATION:
1363 : // AUTHOR Peter Graham Ellis
1364 : // DATE WRITTEN August 2006
1365 :
1366 41586463 : Real64 MassFlowTempSum = 0.0;
1367 41586463 : this->DrainMassFlowRate = 0.0;
1368 :
1369 83569419 : for (int Loop = 1; Loop <= this->NumWaterEquipment; ++Loop) {
1370 41982956 : auto &thisWEq = state.dataWaterUse->WaterEquipment(this->myWaterEquipArr(Loop));
1371 :
1372 41982956 : thisWEq.CalcEquipmentDrainTemp(state);
1373 :
1374 41982956 : this->DrainMassFlowRate += thisWEq.DrainMassFlowRate;
1375 41982956 : MassFlowTempSum += thisWEq.DrainMassFlowRate * thisWEq.DrainTemp;
1376 : } // Loop
1377 :
1378 41586463 : if (this->DrainMassFlowRate > 0.0) {
1379 27341387 : this->DrainTemp = MassFlowTempSum / this->DrainMassFlowRate;
1380 : } else {
1381 14245076 : this->DrainTemp = this->HotTemp;
1382 : }
1383 :
1384 41586463 : this->DrainVolFlowRate = this->DrainMassFlowRate * calcH2ODensity(state);
1385 41586463 : }
1386 :
1387 41586463 : void WaterConnectionsType::CalcConnectionsHeatRecovery(EnergyPlusData &state)
1388 : {
1389 :
1390 : // SUBROUTINE INFORMATION:
1391 : // AUTHOR Peter Graham Ellis
1392 : // DATE WRITTEN August 2006
1393 :
1394 : // PURPOSE OF THIS SUBROUTINE:
1395 : // Calculate drainwater heat recovery
1396 :
1397 41586463 : if (!this->HeatRecovery) {
1398 41586463 : this->RecoveryTemp = this->ColdSupplyTemp;
1399 41586463 : this->ReturnTemp = this->ColdSupplyTemp;
1400 41586463 : this->WasteTemp = this->DrainTemp;
1401 :
1402 0 : } else if (this->TotalMassFlowRate == 0.0) {
1403 0 : this->Effectiveness = 0.0;
1404 0 : this->RecoveryRate = 0.0;
1405 0 : this->RecoveryTemp = this->ColdSupplyTemp;
1406 0 : this->ReturnTemp = this->ColdSupplyTemp;
1407 0 : this->WasteTemp = this->DrainTemp;
1408 :
1409 : } else { // WaterConnections(WaterConnNum)%TotalMassFlowRate > 0.0
1410 :
1411 0 : switch (this->HeatRecoveryConfig) {
1412 0 : case HeatRecovConfig::Plant: {
1413 0 : this->RecoveryMassFlowRate = this->HotMassFlowRate;
1414 0 : } break;
1415 0 : case HeatRecovConfig::Equipment: {
1416 0 : this->RecoveryMassFlowRate = this->ColdMassFlowRate;
1417 0 : } break;
1418 0 : case HeatRecovConfig::PlantAndEquip: {
1419 0 : this->RecoveryMassFlowRate = this->TotalMassFlowRate;
1420 0 : } break;
1421 0 : default:
1422 0 : break;
1423 : }
1424 :
1425 0 : Real64 HXCapacityRate = Psychrometrics::CPHW(Constant::InitConvTemp) * this->RecoveryMassFlowRate;
1426 0 : Real64 DrainCapacityRate = Psychrometrics::CPHW(Constant::InitConvTemp) * this->DrainMassFlowRate;
1427 0 : Real64 MinCapacityRate = min(DrainCapacityRate, HXCapacityRate);
1428 :
1429 0 : switch (this->HeatRecoveryHX) {
1430 0 : case HeatRecovHX::Ideal: {
1431 0 : this->Effectiveness = 1.0;
1432 0 : } break;
1433 0 : case HeatRecovHX::CounterFlow: { // Unmixed
1434 0 : Real64 CapacityRatio = MinCapacityRate / max(DrainCapacityRate, HXCapacityRate);
1435 0 : Real64 NTU = this->HXUA / MinCapacityRate;
1436 0 : if (CapacityRatio == 1.0) {
1437 0 : this->Effectiveness = NTU / (1.0 + NTU);
1438 : } else {
1439 0 : Real64 ExpVal = std::exp(-NTU * (1.0 - CapacityRatio));
1440 0 : this->Effectiveness = (1.0 - ExpVal) / (1.0 - CapacityRatio * ExpVal);
1441 : }
1442 0 : } break;
1443 0 : case HeatRecovHX::CrossFlow: { // Unmixed
1444 0 : Real64 CapacityRatio = MinCapacityRate / max(DrainCapacityRate, HXCapacityRate);
1445 0 : Real64 NTU = this->HXUA / MinCapacityRate;
1446 0 : this->Effectiveness = 1.0 - std::exp((std::pow(NTU, 0.22) / CapacityRatio) * (std::exp(-CapacityRatio * std::pow(NTU, 0.78)) - 1.0));
1447 0 : } break;
1448 0 : default:
1449 0 : break;
1450 : }
1451 :
1452 0 : this->RecoveryRate = this->Effectiveness * MinCapacityRate * (this->DrainTemp - this->ColdSupplyTemp);
1453 0 : this->RecoveryTemp = this->ColdSupplyTemp + this->RecoveryRate / (Psychrometrics::CPHW(Constant::InitConvTemp) * this->TotalMassFlowRate);
1454 0 : this->WasteTemp = this->DrainTemp - this->RecoveryRate / (Psychrometrics::CPHW(Constant::InitConvTemp) * this->TotalMassFlowRate);
1455 :
1456 0 : if (this->RecoveryTankNum > 0) {
1457 0 : state.dataWaterData->WaterStorage(this->RecoveryTankNum).VdotAvailSupply(this->TankSupplyID) = this->DrainVolFlowRate;
1458 0 : state.dataWaterData->WaterStorage(this->RecoveryTankNum).TwaterSupply(this->TankSupplyID) = this->WasteTemp;
1459 : }
1460 :
1461 0 : switch (this->HeatRecoveryConfig) {
1462 0 : case HeatRecovConfig::Plant: {
1463 0 : this->TempError = 0.0; // No feedback back to the cold supply
1464 0 : this->ReturnTemp = this->RecoveryTemp;
1465 0 : } break;
1466 0 : case HeatRecovConfig::Equipment: {
1467 0 : this->TempError = std::abs(this->ColdTemp - this->RecoveryTemp);
1468 :
1469 0 : this->ColdTemp = this->RecoveryTemp;
1470 0 : this->ReturnTemp = this->ColdSupplyTemp;
1471 0 : } break;
1472 0 : case HeatRecovConfig::PlantAndEquip: {
1473 0 : this->TempError = std::abs(this->ColdTemp - this->RecoveryTemp);
1474 :
1475 0 : this->ColdTemp = this->RecoveryTemp;
1476 0 : this->ReturnTemp = this->RecoveryTemp;
1477 0 : } break;
1478 0 : default:
1479 0 : break;
1480 : }
1481 : }
1482 41586463 : }
1483 :
1484 41586463 : void WaterConnectionsType::UpdateWaterConnections(EnergyPlusData &state)
1485 : {
1486 :
1487 : // SUBROUTINE INFORMATION:
1488 : // AUTHOR Peter Graham Ellis
1489 : // DATE WRITTEN August 2006
1490 :
1491 : // PURPOSE OF THIS SUBROUTINE:
1492 : // Updates the node variables with local variables.
1493 :
1494 41586463 : if (this->InletNode > 0 && this->OutletNode > 0) {
1495 : // Pass all variables from inlet to outlet node
1496 41586463 : PlantUtilities::SafeCopyPlantNode(state, this->InletNode, this->OutletNode, this->plantLoc.loopNum);
1497 :
1498 : // Set outlet node variables that are possibly changed
1499 41586463 : state.dataLoopNodes->Node(this->OutletNode).Temp = this->ReturnTemp;
1500 : // should add enthalpy update to return?
1501 : }
1502 41586463 : }
1503 :
1504 6770236 : void ReportStandAloneWaterUse(EnergyPlusData &state)
1505 : {
1506 :
1507 : // SUBROUTINE INFORMATION:
1508 : // AUTHOR B. Griffith, Peter Graham Ellis
1509 : // DATE WRITTEN Nov. 2011
1510 : // MODIFIED Brent Griffith, March 2010 added argument
1511 :
1512 : // PURPOSE OF THIS SUBROUTINE:
1513 : // Calculates report variables for stand alone water use
1514 :
1515 18503262 : for (int WaterEquipNum = 1; WaterEquipNum <= state.dataWaterUse->numWaterEquipment; ++WaterEquipNum) {
1516 11733026 : auto &thisWEq = state.dataWaterUse->WaterEquipment(WaterEquipNum);
1517 11733026 : thisWEq.ColdVolFlowRate = thisWEq.ColdMassFlowRate / calcH2ODensity(state);
1518 11733026 : thisWEq.HotVolFlowRate = thisWEq.HotMassFlowRate / calcH2ODensity(state);
1519 11733026 : thisWEq.TotalVolFlowRate = thisWEq.ColdVolFlowRate + thisWEq.HotVolFlowRate;
1520 :
1521 11733026 : thisWEq.ColdVolume = thisWEq.ColdVolFlowRate * state.dataHVACGlobal->TimeStepSysSec;
1522 11733026 : thisWEq.HotVolume = thisWEq.HotVolFlowRate * state.dataHVACGlobal->TimeStepSysSec;
1523 11733026 : thisWEq.TotalVolume = thisWEq.TotalVolFlowRate * state.dataHVACGlobal->TimeStepSysSec;
1524 :
1525 11733026 : if (thisWEq.Connections == 0) {
1526 104562 : thisWEq.Power = thisWEq.HotMassFlowRate * Psychrometrics::CPHW(Constant::InitConvTemp) * (thisWEq.HotTemp - thisWEq.ColdTemp);
1527 : } else {
1528 11628464 : thisWEq.Power = thisWEq.HotMassFlowRate * Psychrometrics::CPHW(Constant::InitConvTemp) *
1529 11628464 : (thisWEq.HotTemp - state.dataWaterUse->WaterConnections(thisWEq.Connections).ReturnTemp);
1530 : }
1531 :
1532 11733026 : thisWEq.Energy = thisWEq.Power * state.dataHVACGlobal->TimeStepSysSec;
1533 : }
1534 6770236 : }
1535 :
1536 41586463 : void WaterConnectionsType::ReportWaterUse(EnergyPlusData &state)
1537 : {
1538 :
1539 : // SUBROUTINE INFORMATION:
1540 : // AUTHOR Peter Graham Ellis
1541 : // DATE WRITTEN August 2006
1542 : // MODIFIED Brent Griffith, March 2010 added argument
1543 :
1544 : // PURPOSE OF THIS SUBROUTINE:
1545 : // Calculates report variables.
1546 :
1547 83569419 : for (int Loop = 1; Loop <= this->NumWaterEquipment; ++Loop) {
1548 :
1549 41982956 : auto &thisWEq = state.dataWaterUse->WaterEquipment(this->myWaterEquipArr(Loop));
1550 :
1551 41982956 : thisWEq.ColdVolFlowRate = thisWEq.ColdMassFlowRate / calcH2ODensity(state);
1552 41982956 : thisWEq.HotVolFlowRate = thisWEq.HotMassFlowRate / calcH2ODensity(state);
1553 41982956 : thisWEq.TotalVolFlowRate = thisWEq.ColdVolFlowRate + thisWEq.HotVolFlowRate;
1554 41982956 : thisWEq.ColdVolume = thisWEq.ColdVolFlowRate * state.dataHVACGlobal->TimeStepSysSec;
1555 41982956 : thisWEq.HotVolume = thisWEq.HotVolFlowRate * state.dataHVACGlobal->TimeStepSysSec;
1556 41982956 : thisWEq.TotalVolume = thisWEq.TotalVolFlowRate * state.dataHVACGlobal->TimeStepSysSec;
1557 :
1558 41982956 : if (thisWEq.Connections == 0) {
1559 0 : thisWEq.Power = thisWEq.HotMassFlowRate * Psychrometrics::CPHW(Constant::InitConvTemp) * (thisWEq.HotTemp - thisWEq.ColdTemp);
1560 : } else {
1561 41982956 : thisWEq.Power = thisWEq.HotMassFlowRate * Psychrometrics::CPHW(Constant::InitConvTemp) *
1562 41982956 : (thisWEq.HotTemp - state.dataWaterUse->WaterConnections(thisWEq.Connections).ReturnTemp);
1563 : }
1564 :
1565 41982956 : thisWEq.Energy = thisWEq.Power * state.dataHVACGlobal->TimeStepSysSec;
1566 : }
1567 :
1568 41586463 : this->ColdVolFlowRate = this->ColdMassFlowRate / calcH2ODensity(state);
1569 41586463 : this->HotVolFlowRate = this->HotMassFlowRate / calcH2ODensity(state);
1570 41586463 : this->TotalVolFlowRate = this->ColdVolFlowRate + this->HotVolFlowRate;
1571 41586463 : this->ColdVolume = this->ColdVolFlowRate * state.dataHVACGlobal->TimeStepSysSec;
1572 41586463 : this->HotVolume = this->HotVolFlowRate * state.dataHVACGlobal->TimeStepSysSec;
1573 41586463 : this->TotalVolume = this->TotalVolFlowRate * state.dataHVACGlobal->TimeStepSysSec;
1574 41586463 : this->Power = this->HotMassFlowRate * Psychrometrics::CPHW(Constant::InitConvTemp) * (this->HotTemp - this->ReturnTemp);
1575 41586463 : this->Energy = this->Power * state.dataHVACGlobal->TimeStepSysSec;
1576 41586463 : this->RecoveryEnergy = this->RecoveryRate * state.dataHVACGlobal->TimeStepSysSec;
1577 41586463 : }
1578 1050 : void WaterConnectionsType::oneTimeInit_new(EnergyPlusData &state)
1579 : {
1580 :
1581 1050 : this->setupOutputVars(state);
1582 :
1583 1050 : if (allocated(state.dataPlnt->PlantLoop) && !this->StandAlone) {
1584 1050 : bool errFlag = false;
1585 2100 : PlantUtilities::ScanPlantLoopsForObject(
1586 1050 : state, this->Name, DataPlant::PlantEquipmentType::WaterUseConnection, this->plantLoc, errFlag, _, _, _, _, _);
1587 1050 : if (errFlag) {
1588 0 : ShowFatalError(state, "InitConnections: Program terminated due to previous condition(s).");
1589 : }
1590 : }
1591 1050 : }
1592 0 : void WaterConnectionsType::oneTimeInit([[maybe_unused]] EnergyPlusData &state)
1593 : {
1594 0 : }
1595 :
1596 2828408 : void CalcWaterUseZoneGains(EnergyPlusData &state)
1597 : {
1598 :
1599 : // SUBROUTINE INFORMATION:
1600 : // AUTHOR Peter Graham Ellis
1601 : // DATE WRITTEN August 2006
1602 :
1603 : // PURPOSE OF THIS SUBROUTINE:
1604 : // Calculates the zone internal gains due to water use sensible and latent loads.
1605 :
1606 : static bool MyEnvrnFlagLocal = true;
1607 :
1608 2828408 : if (state.dataWaterUse->numWaterEquipment == 0) {
1609 2368599 : return;
1610 : }
1611 :
1612 459809 : if (state.dataGlobal->BeginEnvrnFlag && MyEnvrnFlagLocal) {
1613 12036 : for (auto &e : state.dataWaterUse->WaterEquipment) {
1614 10956 : e.SensibleRate = 0.0;
1615 10956 : e.SensibleEnergy = 0.0;
1616 10956 : e.SensibleRateNoMultiplier = 0.0;
1617 10956 : e.LatentRate = 0.0;
1618 10956 : e.LatentEnergy = 0.0;
1619 10956 : e.LatentRateNoMultiplier = 0.0;
1620 10956 : e.MixedTemp = 0.0;
1621 10956 : e.TotalMassFlowRate = 0.0;
1622 10956 : e.DrainTemp = 0.0;
1623 10956 : e.ColdVolFlowRate = 0.0;
1624 10956 : e.HotVolFlowRate = 0.0;
1625 10956 : e.TotalVolFlowRate = 0.0;
1626 10956 : e.ColdMassFlowRate = 0.0;
1627 10956 : e.HotMassFlowRate = 0.0;
1628 1080 : }
1629 1080 : MyEnvrnFlagLocal = false;
1630 : }
1631 :
1632 459809 : if (!state.dataGlobal->BeginEnvrnFlag) {
1633 458729 : MyEnvrnFlagLocal = true;
1634 : }
1635 :
1636 5205953 : for (int WaterEquipNum = 1; WaterEquipNum <= state.dataWaterUse->numWaterEquipment; ++WaterEquipNum) {
1637 4746144 : if (state.dataWaterUse->WaterEquipment(WaterEquipNum).Zone == 0) {
1638 196267 : continue;
1639 : }
1640 4549877 : int ZoneNum = state.dataWaterUse->WaterEquipment(WaterEquipNum).Zone;
1641 4549877 : state.dataWaterUse->WaterEquipment(WaterEquipNum).SensibleRateNoMultiplier =
1642 4549877 : state.dataWaterUse->WaterEquipment(WaterEquipNum).SensibleRate /
1643 4549877 : (state.dataHeatBal->Zone(ZoneNum).Multiplier * state.dataHeatBal->Zone(ZoneNum).ListMultiplier);
1644 4549877 : state.dataWaterUse->WaterEquipment(WaterEquipNum).LatentRateNoMultiplier =
1645 4549877 : state.dataWaterUse->WaterEquipment(WaterEquipNum).LatentRate /
1646 4549877 : (state.dataHeatBal->Zone(ZoneNum).Multiplier * state.dataHeatBal->Zone(ZoneNum).ListMultiplier);
1647 : }
1648 : }
1649 :
1650 274280990 : Real64 calcH2ODensity(EnergyPlusData &state)
1651 : {
1652 : static constexpr std::string_view RoutineName{"calcH2ODensity"};
1653 :
1654 274280990 : if (state.dataWaterUse->calcRhoH2O) {
1655 122 : state.dataWaterUse->rhoH2OStd = Fluid::GetWater(state)->getDensity(state, Constant::InitConvTemp, RoutineName);
1656 122 : state.dataWaterUse->calcRhoH2O = false;
1657 : }
1658 274280990 : return state.dataWaterUse->rhoH2OStd;
1659 : }
1660 :
1661 : } // namespace WaterUse
1662 : } // namespace EnergyPlus
|