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 : // EnergyPlus Headers
52 : #include <EnergyPlus/Data/EnergyPlusData.hh>
53 : #include <EnergyPlus/DataEnvironment.hh>
54 : #include <EnergyPlus/DataHVACGlobals.hh>
55 : #include <EnergyPlus/DataHeatBalSurface.hh>
56 : #include <EnergyPlus/DataHeatBalance.hh>
57 : #include <EnergyPlus/DataIPShortCuts.hh>
58 : #include <EnergyPlus/DataSurfaces.hh>
59 : #include <EnergyPlus/EMSManager.hh>
60 : #include <EnergyPlus/General.hh>
61 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
62 : #include <EnergyPlus/OutputProcessor.hh>
63 : #include <EnergyPlus/Psychrometrics.hh>
64 : #include <EnergyPlus/ScheduleManager.hh>
65 : #include <EnergyPlus/ThermalChimney.hh>
66 : #include <EnergyPlus/UtilityRoutines.hh>
67 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
68 :
69 : namespace EnergyPlus {
70 :
71 : namespace ThermalChimney {
72 : // Module containing the data for Thermal Chimney system
73 :
74 : // MODULE INFORMATION:
75 : // AUTHOR Kwang Ho Lee
76 : // DATE WRITTEN April 2008
77 : // MODIFIED na
78 : // RE-ENGINEERED na
79 :
80 : // PURPOSE OF THIS MODULE:
81 : // To encapsulate the data and algorithyms required to manage the ThermalChimney System Component
82 :
83 : // METHODOLOGY EMPLOYED:
84 : // na
85 :
86 : // REFERENCES:
87 : // 1. N. K. Bansal, R. Mathur and M. S. Bhandari, "Solar Chimney for Enhanced Stack Ventilation",
88 : // Building and Environment, 28, pp. 373-377, 1993
89 : // 2. K. S. Ong, "A Mathematical Model of a Solar Chimney", Renewable Energy, 28, pp. 1047-1060, 2003
90 : // 3. J. Marti-Herrero and M. R. Heras-Celemin, "Dynamic Physical Model for a Solar Chimney",
91 : // Solar Energy, 81, pp. 614-622, 2007
92 :
93 : // OTHER NOTES: none
94 :
95 : // Using/Aliasing
96 : using namespace DataEnvironment;
97 : using namespace DataHeatBalance;
98 : using namespace DataSurfaces;
99 : using namespace DataHeatBalSurface;
100 :
101 : // Use statements for access to subroutines in other modules
102 : using namespace Psychrometrics;
103 :
104 291606 : void ManageThermalChimney(EnergyPlusData &state)
105 : {
106 :
107 : // SUBROUTINE INFORMATION:
108 : // AUTHOR Kwang Ho Lee
109 : // DATE WRITTEN April 2008
110 : // MODIFIED na
111 : // RE-ENGINEERED na
112 :
113 : // PURPOSE OF THIS SUBROUTINE:
114 : // This subroutine manages the simulation of ThermalChimney unit.
115 : // This driver manages the calls to all of
116 : // the other drivers and simulation algorithms.
117 :
118 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
119 291606 : bool ErrorsFound(false);
120 :
121 : // Obtains and Allocates heat balance related parameters from input file
122 291606 : if (state.dataThermalChimneys->ThermalChimneyGetInputFlag) {
123 108 : GetThermalChimney(state, ErrorsFound);
124 108 : state.dataThermalChimneys->ThermalChimneyGetInputFlag = false;
125 : }
126 :
127 291606 : if (state.dataThermalChimneys->TotThermalChimney == 0) return;
128 :
129 0 : CalcThermalChimney(state);
130 :
131 0 : ReportThermalChimney(state);
132 : }
133 :
134 109 : void GetThermalChimney(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
135 : {
136 :
137 : // SUBROUTINE INFORMATION:
138 : // AUTHOR Kwang Ho Lee
139 : // DATE WRITTEN April 2008
140 : // MODIFIED na
141 : // RE-ENGINEERED na
142 :
143 : // PURPOSE OF THIS SUBROUTINE:
144 : // This subroutine obtains input data for ThermalChimney units and
145 : // stores it in the ThermalChimney data structure.
146 :
147 : static constexpr std::string_view routineName = "GetThermalChimney";
148 : // SUBROUTINE PARAMETER DEFINITIONS:
149 109 : Real64 constexpr FlowFractionTolerance(0.0001); // Smallest deviation from unity for the sum of all fractions
150 :
151 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
152 : int NumAlpha;
153 : int NumNumber;
154 : Real64 AllRatiosSummed;
155 : int TCZoneNum; // Thermal chimney zone counter
156 : int TCZoneNum1; // Thermal chimney zone counter
157 : int IOStat;
158 : int Loop;
159 : int Loop1;
160 109 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
161 :
162 : // Following used for reporting
163 109 : state.dataThermalChimneys->ZnRptThermChim.allocate(state.dataGlobal->NumOfZones);
164 :
165 109 : cCurrentModuleObject = "ZoneThermalChimney";
166 109 : state.dataThermalChimneys->TotThermalChimney = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
167 :
168 109 : state.dataThermalChimneys->ThermalChimneySys.allocate(state.dataThermalChimneys->TotThermalChimney);
169 109 : state.dataThermalChimneys->ThermalChimneyReport.allocate(state.dataThermalChimneys->TotThermalChimney);
170 :
171 111 : for (Loop = 1; Loop <= state.dataThermalChimneys->TotThermalChimney; ++Loop) {
172 :
173 4 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
174 : cCurrentModuleObject,
175 : Loop,
176 2 : state.dataIPShortCut->cAlphaArgs,
177 : NumAlpha,
178 2 : state.dataIPShortCut->rNumericArgs,
179 : NumNumber,
180 : IOStat,
181 2 : state.dataIPShortCut->lNumericFieldBlanks,
182 2 : state.dataIPShortCut->lAlphaFieldBlanks,
183 2 : state.dataIPShortCut->cAlphaFieldNames,
184 2 : state.dataIPShortCut->cNumericFieldNames);
185 :
186 2 : ErrorObjectHeader eoh{routineName, state.dataIPShortCut->cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)};
187 :
188 2 : if (Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound)) {
189 0 : continue;
190 : }
191 :
192 : // First Alpha is Thermal Chimney Name
193 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).Name = state.dataIPShortCut->cAlphaArgs(1);
194 :
195 : // Second Alpha is Zone Name
196 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).RealZonePtr =
197 2 : Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataHeatBal->Zone);
198 2 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).RealZonePtr == 0) {
199 0 : ShowSevereError(state, format("{}=\"{} invalid Zone", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
200 0 : ShowContinueError(
201 0 : state, format("invalid - not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
202 0 : ErrorsFound = true;
203 2 : } else if (!state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).RealZonePtr).HasWindow) {
204 0 : ShowSevereError(state, format("{}=\"{} invalid Zone", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
205 0 : ShowContinueError(state,
206 0 : format("...invalid - no window(s) in {}=\"{}\".",
207 0 : state.dataIPShortCut->cAlphaFieldNames(2),
208 0 : state.dataIPShortCut->cAlphaArgs(2)));
209 0 : ShowContinueError(state, "...thermal chimney zones must have window(s).");
210 0 : ErrorsFound = true;
211 : }
212 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).RealZoneName = state.dataIPShortCut->cAlphaArgs(2);
213 :
214 2 : if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
215 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).availSched = Sched::GetScheduleAlwaysOn(state);
216 2 : } else if ((state.dataThermalChimneys->ThermalChimneySys(Loop).availSched =
217 4 : Sched::GetSchedule(state, state.dataIPShortCut->cAlphaArgs(3))) == nullptr) {
218 0 : ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3));
219 0 : ErrorsFound = true;
220 : }
221 :
222 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).AbsorberWallWidth = state.dataIPShortCut->rNumericArgs(1);
223 2 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).AbsorberWallWidth < 0.0) {
224 0 : ShowSevereError(state,
225 0 : format("{}=\"{} invalid {} must be >= 0, entered value=[{:.2R}].",
226 : cCurrentModuleObject,
227 0 : state.dataIPShortCut->cAlphaArgs(1),
228 0 : state.dataIPShortCut->cNumericFieldNames(1),
229 0 : state.dataIPShortCut->rNumericArgs(1)));
230 0 : ErrorsFound = true;
231 : }
232 :
233 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).AirOutletCrossArea = state.dataIPShortCut->rNumericArgs(2);
234 2 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).AirOutletCrossArea < 0.0) {
235 0 : ShowSevereError(state,
236 0 : format("{}=\"{} invalid {} must be >= 0, entered value=[{:.2R}].",
237 : cCurrentModuleObject,
238 0 : state.dataIPShortCut->cAlphaArgs(1),
239 0 : state.dataIPShortCut->cNumericFieldNames(2),
240 0 : state.dataIPShortCut->rNumericArgs(2)));
241 0 : ErrorsFound = true;
242 : }
243 :
244 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).DischargeCoeff = state.dataIPShortCut->rNumericArgs(3);
245 4 : if ((state.dataThermalChimneys->ThermalChimneySys(Loop).DischargeCoeff <= 0.0) ||
246 2 : (state.dataThermalChimneys->ThermalChimneySys(Loop).DischargeCoeff > 1.0)) {
247 0 : ShowSevereError(state,
248 0 : format("{}=\"{} invalid {} must be > 0 and <=1.0, entered value=[{:.2R}].",
249 : cCurrentModuleObject,
250 0 : state.dataIPShortCut->cAlphaArgs(1),
251 0 : state.dataIPShortCut->cNumericFieldNames(3),
252 0 : state.dataIPShortCut->rNumericArgs(3)));
253 0 : ErrorsFound = true;
254 : }
255 :
256 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib = NumAlpha - 3;
257 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr.allocate(state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
258 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr.allocate(state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
259 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName.allocate(state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
260 4 : state.dataThermalChimneys->ThermalChimneySys(Loop).DistanceThermChimInlet.allocate(
261 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
262 4 : state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow.allocate(
263 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
264 4 : state.dataThermalChimneys->ThermalChimneySys(Loop).EachAirInletCrossArea.allocate(
265 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
266 :
267 2 : AllRatiosSummed = 0.0;
268 4 : for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
269 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum) = state.dataIPShortCut->cAlphaArgs(TCZoneNum + 3);
270 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) =
271 2 : Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(TCZoneNum + 3), state.dataHeatBal->Zone);
272 2 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) == 0) {
273 0 : int spaceNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(TCZoneNum + 3), state.dataHeatBal->space);
274 0 : if (spaceNum > 0) {
275 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr(TCZoneNum) = spaceNum;
276 0 : int zoneNum = state.dataHeatBal->space(spaceNum).zoneNum;
277 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) = zoneNum;
278 : }
279 : }
280 :
281 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).DistanceThermChimInlet(TCZoneNum) =
282 2 : state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 1);
283 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) =
284 2 : state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 2);
285 2 : if (state.dataIPShortCut->lNumericFieldBlanks(3 * TCZoneNum + 2))
286 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) = 1.0;
287 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).EachAirInletCrossArea(TCZoneNum) =
288 2 : state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 3);
289 :
290 : //!! Error trap for zones that do not exist or zones not in the zone the thermal chimney is in
291 2 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) == 0) {
292 0 : ShowSevereError(state,
293 0 : format("{}=\"{} invalid {}=\"{}\" not found.",
294 : cCurrentModuleObject,
295 0 : state.dataIPShortCut->cAlphaArgs(1),
296 0 : state.dataIPShortCut->cAlphaFieldNames(TCZoneNum + 3),
297 0 : state.dataIPShortCut->cAlphaArgs(TCZoneNum + 3)));
298 0 : ErrorsFound = true;
299 2 : } else if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
300 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).RealZonePtr) {
301 0 : ShowSevereError(state,
302 0 : format("{}=\"{} invalid reference {}=\"{}",
303 : cCurrentModuleObject,
304 0 : state.dataIPShortCut->cAlphaArgs(1),
305 0 : state.dataIPShortCut->cAlphaFieldNames(2),
306 0 : state.dataIPShortCut->cAlphaArgs(2)));
307 0 : ShowContinueError(state,
308 0 : format("...must not have same zone as reference= {}=\"{}\".",
309 0 : state.dataIPShortCut->cAlphaFieldNames(TCZoneNum + 3),
310 0 : state.dataIPShortCut->cAlphaArgs(TCZoneNum + 3)));
311 0 : ErrorsFound = true;
312 : }
313 :
314 2 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).DistanceThermChimInlet(TCZoneNum) < 0.0) {
315 0 : ShowSevereError(state,
316 0 : format("{}=\"{} invalid {} must be >= 0, entered value=[{:.2R}].",
317 : cCurrentModuleObject,
318 0 : state.dataIPShortCut->cAlphaArgs(1),
319 0 : state.dataIPShortCut->cNumericFieldNames(3 * TCZoneNum + 1),
320 0 : state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 1)));
321 0 : ErrorsFound = true;
322 : }
323 :
324 4 : if ((state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) <= 0.0) ||
325 2 : (state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) > 1.0)) {
326 0 : ShowSevereError(state,
327 0 : format("{}=\"{} invalid {} must be > 0 and <=1.0, entered value=[{:.2R}].",
328 : cCurrentModuleObject,
329 0 : state.dataIPShortCut->cAlphaArgs(1),
330 0 : state.dataIPShortCut->cNumericFieldNames(3 * TCZoneNum + 2),
331 0 : state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 2)));
332 0 : ErrorsFound = true;
333 : }
334 :
335 2 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).EachAirInletCrossArea(TCZoneNum) < 0.0) {
336 0 : ShowSevereError(state,
337 0 : format("{}=\"{} invalid {} must be >= 0, entered value=[{:.2R}].",
338 : cCurrentModuleObject,
339 0 : state.dataIPShortCut->cAlphaArgs(1),
340 0 : state.dataIPShortCut->cNumericFieldNames(3 * TCZoneNum + 3),
341 0 : state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 3)));
342 0 : ErrorsFound = true;
343 : }
344 :
345 2 : AllRatiosSummed += state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum);
346 :
347 : } // DO TCZoneNum = 1, ThermalChimneySys(Loop)%TotZoneToDistrib
348 :
349 : // Error trap if the sum of fractions is not equal to 1.0
350 2 : if (std::abs(AllRatiosSummed - 1.0) > FlowFractionTolerance) {
351 0 : ShowSevereError(state,
352 0 : format("{}=\"{} invalid sum of fractions, must be =1.0, entered value (summed from entries)=[{:.4R}].",
353 : cCurrentModuleObject,
354 0 : state.dataIPShortCut->cAlphaArgs(1),
355 : AllRatiosSummed));
356 0 : ErrorsFound = true;
357 : }
358 :
359 : } // DO Loop=1, TotThermalChimney
360 :
361 : // check infiltration output
362 : // setup zone-level infiltration reports
363 109 : Array1D_bool RepVarSet;
364 109 : RepVarSet.dimension(state.dataGlobal->NumOfZones, true);
365 144 : for (Loop = 1; Loop <= state.dataHeatBal->TotInfiltration; ++Loop) {
366 35 : int zoneNum = state.dataHeatBal->Infiltration(Loop).ZonePtr;
367 35 : if (zoneNum > 0 && !state.dataHeatBal->Zone(zoneNum).zoneOAQuadratureSum) {
368 35 : RepVarSet(zoneNum) = false;
369 : }
370 : }
371 : // Set up the output variables for thermal chimneys
372 111 : for (Loop = 1; Loop <= state.dataThermalChimneys->TotThermalChimney; ++Loop) {
373 4 : SetupOutputVariable(state,
374 : "Zone Thermal Chimney Current Density Air Volume Flow Rate",
375 : Constant::Units::m3_s,
376 2 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlow,
377 : OutputProcessor::TimeStepType::System,
378 : OutputProcessor::StoreType::Average,
379 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).Name);
380 4 : SetupOutputVariable(state,
381 : "Zone Thermal Chimney Standard Density Air Volume Flow Rate",
382 : Constant::Units::m3_s,
383 2 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlowStd,
384 : OutputProcessor::TimeStepType::System,
385 : OutputProcessor::StoreType::Average,
386 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).Name);
387 4 : SetupOutputVariable(state,
388 : "Zone Thermal Chimney Mass Flow Rate",
389 : Constant::Units::kg_s,
390 2 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCMassFlow,
391 : OutputProcessor::TimeStepType::System,
392 : OutputProcessor::StoreType::Average,
393 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).Name);
394 4 : SetupOutputVariable(state,
395 : "Zone Thermal Chimney Outlet Temperature",
396 : Constant::Units::C,
397 2 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OutletAirTempThermalChim,
398 : OutputProcessor::TimeStepType::System,
399 : OutputProcessor::StoreType::Average,
400 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).Name);
401 :
402 2 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
403 4 : SetupEMSActuator(state,
404 : "Zone Thermal Chimney",
405 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).Name,
406 : "Air Exchange Flow Rate",
407 : "[m3/s]",
408 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).EMSOverrideOn,
409 2 : state.dataThermalChimneys->ThermalChimneySys(Loop).EMSAirFlowRateValue);
410 : }
411 :
412 4 : for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
413 4 : SetupOutputVariable(state,
414 : "Zone Thermal Chimney Heat Loss Energy",
415 : Constant::Units::J,
416 2 : state.dataThermalChimneys->ZnRptThermChim(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))
417 2 : .ThermalChimneyHeatLoss,
418 : OutputProcessor::TimeStepType::System,
419 : OutputProcessor::StoreType::Sum,
420 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
421 4 : SetupOutputVariable(state,
422 : "Zone Thermal Chimney Heat Gain Energy",
423 : Constant::Units::J,
424 2 : state.dataThermalChimneys->ZnRptThermChim(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))
425 2 : .ThermalChimneyHeatGain,
426 : OutputProcessor::TimeStepType::System,
427 : OutputProcessor::StoreType::Sum,
428 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
429 4 : SetupOutputVariable(state,
430 : "Zone Thermal Chimney Volume",
431 : Constant::Units::m3,
432 2 : state.dataThermalChimneys->ZnRptThermChim(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))
433 2 : .ThermalChimneyVolume,
434 : OutputProcessor::TimeStepType::System,
435 : OutputProcessor::StoreType::Sum,
436 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
437 4 : SetupOutputVariable(state,
438 : "Zone Thermal Chimney Mass",
439 : Constant::Units::kg,
440 2 : state.dataThermalChimneys->ZnRptThermChim(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))
441 2 : .ThermalChimneyMass,
442 : OutputProcessor::TimeStepType::System,
443 : OutputProcessor::StoreType::Sum,
444 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
445 2 : if (RepVarSet(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))) {
446 4 : SetupOutputVariable(
447 : state,
448 : "Zone Infiltration Sensible Heat Loss Energy",
449 : Constant::Units::J,
450 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilHeatLoss,
451 : OutputProcessor::TimeStepType::System,
452 : OutputProcessor::StoreType::Sum,
453 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
454 4 : SetupOutputVariable(
455 : state,
456 : "Zone Infiltration Sensible Heat Gain Energy",
457 : Constant::Units::J,
458 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilHeatGain,
459 : OutputProcessor::TimeStepType::System,
460 : OutputProcessor::StoreType::Sum,
461 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
462 4 : SetupOutputVariable(
463 : state,
464 : "Zone Infiltration Latent Heat Loss Energy",
465 : Constant::Units::J,
466 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilLatentLoss,
467 : OutputProcessor::TimeStepType::System,
468 : OutputProcessor::StoreType::Sum,
469 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
470 4 : SetupOutputVariable(
471 : state,
472 : "Zone Infiltration Latent Heat Gain Energy",
473 : Constant::Units::J,
474 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilLatentGain,
475 : OutputProcessor::TimeStepType::System,
476 : OutputProcessor::StoreType::Sum,
477 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
478 4 : SetupOutputVariable(
479 : state,
480 : "Zone Infiltration Total Heat Loss Energy",
481 : Constant::Units::J,
482 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilTotalLoss,
483 : OutputProcessor::TimeStepType::System,
484 : OutputProcessor::StoreType::Sum,
485 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
486 4 : SetupOutputVariable(
487 : state,
488 : "Zone Infiltration Total Heat Gain Energy",
489 : Constant::Units::J,
490 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilTotalGain,
491 : OutputProcessor::TimeStepType::System,
492 : OutputProcessor::StoreType::Sum,
493 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
494 4 : SetupOutputVariable(
495 : state,
496 : "Zone Infiltration Current Density Volume Flow Rate",
497 : Constant::Units::m3_s,
498 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilVdotCurDensity,
499 : OutputProcessor::TimeStepType::System,
500 : OutputProcessor::StoreType::Average,
501 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
502 4 : SetupOutputVariable(
503 : state,
504 : "Zone Infiltration Standard Density Volume Flow Rate",
505 : Constant::Units::m3_s,
506 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilVdotStdDensity,
507 : OutputProcessor::TimeStepType::System,
508 : OutputProcessor::StoreType::Average,
509 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
510 4 : SetupOutputVariable(
511 : state,
512 : "Zone Infiltration Outdoor Density Volume Flow Rate",
513 : Constant::Units::m3_s,
514 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilVdotOutDensity,
515 : OutputProcessor::TimeStepType::System,
516 : OutputProcessor::StoreType::Average,
517 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
518 4 : SetupOutputVariable(
519 : state,
520 : "Zone Infiltration Current Density Volume",
521 : Constant::Units::m3,
522 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilVolumeCurDensity,
523 : OutputProcessor::TimeStepType::System,
524 : OutputProcessor::StoreType::Sum,
525 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
526 4 : SetupOutputVariable(
527 : state,
528 : "Zone Infiltration Standard Density Volume",
529 : Constant::Units::m3,
530 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilVolumeStdDensity,
531 : OutputProcessor::TimeStepType::System,
532 : OutputProcessor::StoreType::Sum,
533 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
534 4 : SetupOutputVariable(state,
535 : "Zone Infiltration Mass",
536 : Constant::Units::kg,
537 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilMass,
538 : OutputProcessor::TimeStepType::System,
539 : OutputProcessor::StoreType::Sum,
540 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
541 4 : SetupOutputVariable(state,
542 : "Zone Infiltration Mass Flow Rate",
543 : Constant::Units::kg_s,
544 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilMdot,
545 : OutputProcessor::TimeStepType::System,
546 : OutputProcessor::StoreType::Average,
547 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
548 4 : SetupOutputVariable(state,
549 : "Zone Infiltration Current Density Air Change Rate",
550 : Constant::Units::ach,
551 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))
552 2 : .InfilAirChangeRateCurDensity,
553 : OutputProcessor::TimeStepType::System,
554 : OutputProcessor::StoreType::Average,
555 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
556 4 : SetupOutputVariable(state,
557 : "Zone Infiltration Standard Density Air Change Rate",
558 : Constant::Units::ach,
559 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))
560 2 : .InfilAirChangeRateStdDensity,
561 : OutputProcessor::TimeStepType::System,
562 : OutputProcessor::StoreType::Average,
563 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
564 4 : SetupOutputVariable(state,
565 : "Zone Infiltration Outdoor Density Air Change Rate",
566 : Constant::Units::ach,
567 2 : state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))
568 2 : .InfilAirChangeRateOutDensity,
569 : OutputProcessor::TimeStepType::System,
570 : OutputProcessor::StoreType::Average,
571 2 : state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
572 2 : RepVarSet(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)) = false;
573 : }
574 : } // DO TCZoneNum = 1, ThermalChimneySys(Loop)%TotZoneToDistrib
575 : } // DO Loop=1, TotThermalChimney
576 :
577 : //! LKL-more renaming effort and code review might be possible here
578 : // Check to make sure there is only one thermal chimney statement per zone
579 111 : for (Loop = 1; Loop <= state.dataThermalChimneys->TotThermalChimney; ++Loop) {
580 2 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib > 1) {
581 0 : for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
582 :
583 0 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib >= (TCZoneNum + 1)) {
584 0 : for (TCZoneNum1 = TCZoneNum + 1; TCZoneNum1 <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib;
585 : ++TCZoneNum1) {
586 0 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
587 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum1)) {
588 0 : ShowSevereError(state,
589 0 : format("Only one ZoneThermalChimney object allowed per zone but zone {} has two ZoneThermalChimney "
590 : "objects associated with it",
591 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
592 0 : ErrorsFound = true;
593 : }
594 : }
595 0 : for (TCZoneNum1 = 1; TCZoneNum1 <= TCZoneNum - 1; ++TCZoneNum1) {
596 0 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
597 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum1)) {
598 0 : ShowSevereError(state,
599 0 : format("Only one ZoneThermalChimney object allowed per zone but zone {} has two ZoneThermalChimney "
600 : "objects associated with it",
601 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
602 0 : ErrorsFound = true;
603 : }
604 : }
605 : } else { // IF ( ThermalChimneySys(Loop)%TotZoneToDistrib >= (TCZoneNum+1) ) THEN
606 0 : for (TCZoneNum1 = 1; TCZoneNum1 <= TCZoneNum - 1; ++TCZoneNum1) {
607 0 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
608 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum1)) {
609 0 : ShowSevereError(state,
610 0 : format("Only one ZoneThermalChimney object allowed per zone but zone {} has two ZoneThermalChimney "
611 : "objects associated with it",
612 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
613 0 : ErrorsFound = true;
614 : }
615 : }
616 : } // IF ( ThermalChimneySys(Loop)%TotZoneToDistrib >= (TCZoneNum+1) ) THEN
617 :
618 : } // DO TCZoneNum = 1, ThermalChimneySys(Loop)%TotZoneToDistrib
619 : } // IF (ThermalChimneySys(Loop)%TotZoneToDistrib > 1) THEN
620 : } // DO Loop = 1, TotThermalChimney
621 :
622 : // Check to make sure there is only one thermal chimney statement per zone
623 109 : if (state.dataThermalChimneys->TotThermalChimney > 1) {
624 3 : for (Loop = 1; Loop <= state.dataThermalChimneys->TotThermalChimney; ++Loop) {
625 :
626 2 : if (state.dataThermalChimneys->TotThermalChimney >= (Loop + 1)) {
627 2 : for (Loop1 = Loop + 1; Loop1 <= state.dataThermalChimneys->TotThermalChimney; ++Loop1) {
628 2 : for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
629 2 : for (TCZoneNum1 = 1; TCZoneNum1 <= state.dataThermalChimneys->ThermalChimneySys(Loop1).TotZoneToDistrib; ++TCZoneNum1) {
630 1 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
631 1 : state.dataThermalChimneys->ThermalChimneySys(Loop1).ZonePtr(TCZoneNum1)) {
632 0 : ShowSevereError(state,
633 0 : format("Only one ZoneThermalChimney object allowed per zone but zone {} has two "
634 : "ZoneThermalChimney objects associated with it",
635 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
636 0 : ErrorsFound = true;
637 : }
638 : }
639 : }
640 : }
641 1 : for (Loop1 = 1; Loop1 <= Loop - 1; ++Loop1) {
642 0 : for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
643 0 : for (TCZoneNum1 = 1; TCZoneNum1 <= state.dataThermalChimneys->ThermalChimneySys(Loop1).TotZoneToDistrib; ++TCZoneNum1) {
644 0 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
645 0 : state.dataThermalChimneys->ThermalChimneySys(Loop1).ZonePtr(TCZoneNum1)) {
646 0 : ShowSevereError(state,
647 0 : format("Only one ZoneThermalChimney object allowed per zone but zone {} has two "
648 : "ZoneThermalChimney objects associated with it",
649 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
650 0 : ErrorsFound = true;
651 : }
652 : }
653 : }
654 : }
655 : } else { // IF ( TotThermalChimney >= (Loop+1) ) THEN
656 2 : for (Loop1 = 1; Loop1 <= Loop - 1; ++Loop1) {
657 2 : for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
658 2 : for (TCZoneNum1 = 1; TCZoneNum1 <= state.dataThermalChimneys->ThermalChimneySys(Loop1).TotZoneToDistrib; ++TCZoneNum1) {
659 1 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
660 1 : state.dataThermalChimneys->ThermalChimneySys(Loop1).ZonePtr(TCZoneNum1)) {
661 0 : ShowSevereError(state,
662 0 : format("Only one ZoneThermalChimney object allowed per zone but zone {} has two "
663 : "ZoneThermalChimney objects associated with it",
664 0 : state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
665 0 : ErrorsFound = true;
666 : }
667 : }
668 : }
669 : }
670 : } // IF ( TotThermalChimney >= (Loop+1) ) THEN
671 :
672 : } // DO Loop = 1, TotThermalChimney
673 : } // IF (TotThermalChimney > 1) THEN
674 :
675 109 : if (ErrorsFound) {
676 0 : ShowFatalError(state, format("{} Errors found in input. Preceding condition(s) cause termination.", cCurrentModuleObject));
677 : }
678 109 : }
679 :
680 2 : void CalcThermalChimney(EnergyPlusData &state)
681 : {
682 :
683 : // SUBROUTINE INFORMATION:
684 : // AUTHOR Kwang Ho Lee
685 : // DATE WRITTEN April 2008
686 : // MODIFIED na
687 : // RE-ENGINEERED na
688 :
689 : // PURPOSE OF THIS SUBROUTINE:
690 : // This subroutine simulates the components making up the ThermalChimney.
691 :
692 2 : int constexpr NTC(15); // Number of subregions in thermal chimney air channel for FINITE DIFFERENCE
693 :
694 : // To be obtained from other modules and subroutines
695 : Real64 SurfTempAbsorberWall; // Absorber wall surface temperature (K)
696 : Real64 SurfTempGlassCover; // Glass cover surface temperature (K)
697 : Real64 ConvTransCoeffWallFluid; // Absorber wall convection trasnfer coefficient
698 : Real64 ConvTransCoeffGlassFluid; // Glass cover convection trasnfer coefficient
699 :
700 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
701 : // Real local vaiables
702 : Real64 minorW; // width of enclosure (narrow dimension)
703 : Real64 majorW; // width of major surface
704 : Real64 TempmajorW;
705 :
706 : Real64 RoomAirTemp;
707 : Real64 AirSpecHeatThermalChim; // (J/kg*C) or (J/kg*K)
708 : Real64 AbsorberWallWidthTC;
709 : Real64 TCVolumeAirFlowRate; // (m^3/s)
710 : Real64 TCMassAirFlowRate; // (kg/s)
711 : Real64 DischargeCoeffTC;
712 : Real64 AirOutletCrossAreaTC;
713 : Real64 AirInletCrossArea;
714 : Real64 AirRelativeCrossArea;
715 : // REAL(r64) :: OutletAirTempThermalChim
716 : Real64 OverallThermalChimLength;
717 : Real64 ThermChimTolerance;
718 2 : Array1D<Real64> TempTCMassAirFlowRate(10); // Temporary Value of Thermal Chimney Mass Flow Rate ()
719 2 : Array1D<Real64> TempTCVolumeAirFlowRate(10); // Temporary Value of Thermal Chimney Volume Flow Rate ()
720 : int IterationLoop;
721 : Real64 Process1; // Temporary Variable Used in the Middle of the Calculation
722 : Real64 Process2; // Temporary Variable Used in the Middle of the Calculation
723 : Real64 Process3; // Temporary Variable Used in the Middle of the Calculation
724 : // unused1208 REAL(r64) :: Process4 ! Temporary Variable Used in the Middle of the Calculation
725 : Real64 AirDensityThermalChim; // (kg/m^3)
726 : Real64 AirDensity; // (kg/m^3)
727 : Real64 CpAir;
728 : Real64 TemporaryWallSurfTemp;
729 :
730 : Real64 DeltaL; // OverallThermalChimLength / NTC
731 : int ThermChimLoop1;
732 : int ThermChimLoop2;
733 2 : Array2D<Real64> EquaCoef(NTC, NTC); // Coefficients in Linear Algebraic Euqation for FINITE DIFFERENCE
734 2 : Array1D<Real64> EquaConst(NTC); // Constants in Linear Algebraic Equation for FINITE DIFFERENCE
735 2 : Array1D<Real64> ThermChimSubTemp(NTC); // Air temperature of each thermal chimney air channel subregion
736 :
737 6 : for (int Loop = 1; Loop <= state.dataThermalChimneys->TotThermalChimney; ++Loop) {
738 :
739 4 : int ZoneNum = state.dataThermalChimneys->ThermalChimneySys(Loop).RealZonePtr;
740 4 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
741 : // start off with first surface in zone widths
742 4 : int firstSpaceHTSurfaceFirst = state.dataHeatBal->space(state.dataHeatBal->Zone(ZoneNum).spaceIndexes(1)).HTSurfaceFirst;
743 4 : majorW = state.dataSurface->Surface(firstSpaceHTSurfaceFirst).Width;
744 4 : minorW = majorW;
745 4 : TempmajorW = 0.0;
746 4 : TemporaryWallSurfTemp = -10000.0;
747 :
748 : // determine major width and minor width
749 8 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
750 4 : auto const &thisSpace = state.dataHeatBal->space(spaceNum);
751 36 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
752 32 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall) continue;
753 :
754 20 : if (state.dataSurface->Surface(SurfNum).Width > majorW) {
755 0 : majorW = state.dataSurface->Surface(SurfNum).Width;
756 : }
757 :
758 20 : if (state.dataSurface->Surface(SurfNum).Width < minorW) {
759 4 : minorW = state.dataSurface->Surface(SurfNum).Width;
760 : }
761 : }
762 :
763 36 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
764 32 : if (state.dataSurface->Surface(SurfNum).Width == majorW) {
765 16 : if (state.dataHeatBalSurf->SurfTempIn(SurfNum) > TemporaryWallSurfTemp) {
766 6 : TemporaryWallSurfTemp = state.dataHeatBalSurf->SurfTempIn(SurfNum);
767 6 : ConvTransCoeffWallFluid = state.dataHeatBalSurf->SurfHConvInt(SurfNum);
768 6 : SurfTempAbsorberWall = state.dataHeatBalSurf->SurfTempIn(SurfNum) + Constant::Kelvin;
769 : }
770 : }
771 : }
772 :
773 36 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
774 32 : if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Window) {
775 4 : if (state.dataSurface->Surface(SurfNum).Width > TempmajorW) {
776 4 : TempmajorW = state.dataSurface->Surface(SurfNum).Width;
777 4 : ConvTransCoeffGlassFluid = state.dataHeatBalSurf->SurfHConvInt(SurfNum);
778 4 : SurfTempGlassCover = state.dataHeatBalSurf->SurfTempIn(SurfNum) + Constant::Kelvin;
779 : }
780 : }
781 : }
782 : }
783 :
784 4 : AbsorberWallWidthTC = majorW;
785 4 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).AbsorberWallWidth != majorW) {
786 4 : AbsorberWallWidthTC = state.dataThermalChimneys->ThermalChimneySys(Loop).AbsorberWallWidth;
787 : }
788 :
789 4 : AirDensityThermalChim = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisZoneHB.MAT, thisZoneHB.airHumRat);
790 4 : AirSpecHeatThermalChim = PsyCpAirFnW(thisZoneHB.airHumRat);
791 4 : AirOutletCrossAreaTC = state.dataThermalChimneys->ThermalChimneySys(Loop).AirOutletCrossArea;
792 4 : DischargeCoeffTC = state.dataThermalChimneys->ThermalChimneySys(Loop).DischargeCoeff;
793 :
794 4 : AirInletCrossArea = 0.0;
795 8 : for (int TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
796 4 : AirInletCrossArea += state.dataThermalChimneys->ThermalChimneySys(Loop).EachAirInletCrossArea(TCZoneNum);
797 : }
798 :
799 4 : RoomAirTemp = 0.0;
800 8 : for (int TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
801 4 : int tcSpacePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr(TCZoneNum);
802 4 : if ((state.dataHeatBal->doSpaceHeatBalance) && (tcSpacePtr > 0)) {
803 0 : RoomAirTemp += state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) *
804 0 : state.dataZoneTempPredictorCorrector->spaceHeatBalance(tcSpacePtr).MAT;
805 : } else {
806 4 : int tcZonePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum);
807 4 : RoomAirTemp += state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) *
808 4 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(tcZonePtr).MAT;
809 : }
810 : }
811 4 : RoomAirTemp += Constant::Kelvin;
812 :
813 4 : Process1 = 0.0;
814 4 : Process2 = 0.0;
815 8 : for (int TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
816 4 : int tcZonePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum);
817 4 : auto const &thisTCZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(tcZonePtr);
818 4 : Real64 tcZoneMAT = thisTCZoneHB.MAT;
819 4 : Real64 tcZoneHumRat = thisTCZoneHB.airHumRat;
820 4 : int tcSpacePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr(TCZoneNum);
821 4 : if ((state.dataHeatBal->doSpaceHeatBalance) && (tcSpacePtr > 0)) {
822 0 : auto const &thisTCspaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(tcSpacePtr);
823 0 : tcZoneMAT = thisTCspaceHB.MAT;
824 0 : tcZoneHumRat = thisTCspaceHB.airHumRat;
825 : }
826 4 : Real64 tcZoneEnth = PsyHFnTdbW(tcZoneMAT, tcZoneHumRat);
827 4 : Process1 += tcZoneEnth * state.dataThermalChimneys->ThermalChimneySys(Loop).DistanceThermChimInlet(TCZoneNum) *
828 4 : state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum);
829 4 : Process2 += state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) * tcZoneEnth;
830 : }
831 4 : OverallThermalChimLength = Process1 / Process2;
832 :
833 4 : DeltaL = OverallThermalChimLength / NTC;
834 :
835 : // Starting the iteration for mass and volumetric flow rate calculation
836 4 : ThermChimTolerance = 10000000.0; // An impossibly big tolerance
837 44 : for (IterationLoop = 1; IterationLoop <= 10; ++IterationLoop) {
838 :
839 40 : if (IterationLoop == 1) {
840 4 : TempTCMassAirFlowRate(IterationLoop) = 0.05; // Inital Guess
841 :
842 : } else {
843 36 : TempTCMassAirFlowRate(IterationLoop) = TempTCVolumeAirFlowRate(IterationLoop - 1) * AirDensityThermalChim;
844 :
845 36 : if (std::abs(TempTCMassAirFlowRate(IterationLoop) - TempTCMassAirFlowRate(IterationLoop - 1)) < ThermChimTolerance) {
846 36 : ThermChimTolerance = std::abs(TempTCMassAirFlowRate(IterationLoop) - TempTCMassAirFlowRate(IterationLoop - 1));
847 36 : TCMassAirFlowRate = TempTCMassAirFlowRate(IterationLoop);
848 36 : TCVolumeAirFlowRate = TempTCVolumeAirFlowRate(IterationLoop);
849 : }
850 :
851 : } // IF (IterationLoop == 1) THEN
852 :
853 : // Calculation of Thermal Chimney Discharge Air Temperature
854 80 : Process1 = AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid + AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid -
855 40 : 2.0 * TempTCMassAirFlowRate(IterationLoop) * AirSpecHeatThermalChim;
856 80 : Process2 = AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid + AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid +
857 40 : 2.0 * TempTCMassAirFlowRate(IterationLoop) * AirSpecHeatThermalChim;
858 40 : Process3 = 2.0 * AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid * SurfTempGlassCover +
859 40 : 2.0 * AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid * SurfTempAbsorberWall;
860 :
861 640 : for (ThermChimLoop1 = 1; ThermChimLoop1 <= NTC; ++ThermChimLoop1) {
862 9600 : for (ThermChimLoop2 = 1; ThermChimLoop2 <= NTC; ++ThermChimLoop2) {
863 9000 : EquaCoef(ThermChimLoop2, ThermChimLoop1) = 0.0;
864 : }
865 : }
866 :
867 40 : EquaCoef(1, 1) = Process2;
868 40 : EquaConst(1) = Process3 - Process1 * RoomAirTemp;
869 600 : for (ThermChimLoop1 = 2; ThermChimLoop1 <= NTC; ++ThermChimLoop1) {
870 560 : EquaCoef((ThermChimLoop1 - 1), ThermChimLoop1) = Process1;
871 560 : EquaCoef(ThermChimLoop1, ThermChimLoop1) = Process2;
872 560 : EquaConst(ThermChimLoop1) = Process3;
873 : }
874 :
875 40 : GaussElimination(EquaCoef, EquaConst, ThermChimSubTemp, NTC);
876 :
877 40 : AirRelativeCrossArea = AirOutletCrossAreaTC / AirInletCrossArea;
878 40 : if (ThermChimSubTemp(NTC) <= RoomAirTemp) {
879 0 : TempTCVolumeAirFlowRate(IterationLoop) = 0.0;
880 : } else {
881 40 : TempTCVolumeAirFlowRate(IterationLoop) = DischargeCoeffTC * AirOutletCrossAreaTC *
882 80 : std::sqrt(2.0 * ((ThermChimSubTemp(NTC) - RoomAirTemp) / RoomAirTemp) * 9.8 *
883 40 : OverallThermalChimLength / pow_2(1.0 + AirRelativeCrossArea));
884 : }
885 :
886 : } // DO IterationLoop = 1,10
887 :
888 : // Calculation of Thermal Chimney Discharge Temperature
889 4 : Process1 = AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid + AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid -
890 4 : 2.0 * TCMassAirFlowRate * AirSpecHeatThermalChim;
891 4 : Process2 = AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid + AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid +
892 4 : 2.0 * TCMassAirFlowRate * AirSpecHeatThermalChim;
893 4 : Process3 = 2.0 * AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid * SurfTempGlassCover +
894 4 : 2.0 * AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid * SurfTempAbsorberWall;
895 :
896 64 : for (ThermChimLoop1 = 1; ThermChimLoop1 <= NTC; ++ThermChimLoop1) {
897 960 : for (ThermChimLoop2 = 1; ThermChimLoop2 <= NTC; ++ThermChimLoop2) {
898 900 : EquaCoef(ThermChimLoop2, ThermChimLoop1) = 0.0;
899 : }
900 : }
901 :
902 4 : EquaCoef(1, 1) = Process2;
903 4 : EquaConst(1) = Process3 - Process1 * RoomAirTemp;
904 60 : for (ThermChimLoop1 = 2; ThermChimLoop1 <= NTC; ++ThermChimLoop1) {
905 56 : EquaCoef((ThermChimLoop1 - 1), ThermChimLoop1) = Process1;
906 56 : EquaCoef(ThermChimLoop1, ThermChimLoop1) = Process2;
907 56 : EquaConst(ThermChimLoop1) = Process3;
908 : }
909 :
910 4 : GaussElimination(EquaCoef, EquaConst, ThermChimSubTemp, NTC);
911 :
912 4 : AirRelativeCrossArea = AirOutletCrossAreaTC / AirInletCrossArea;
913 4 : if (ThermChimSubTemp(NTC) <= RoomAirTemp) {
914 0 : TCVolumeAirFlowRate = 0.0;
915 : } else {
916 8 : TCVolumeAirFlowRate = DischargeCoeffTC * AirOutletCrossAreaTC *
917 4 : std::sqrt(2.0 * ((ThermChimSubTemp(NTC) - RoomAirTemp) / RoomAirTemp) * 9.8 * OverallThermalChimLength /
918 4 : pow_2(1.0 + AirRelativeCrossArea));
919 4 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).EMSOverrideOn) {
920 1 : TCVolumeAirFlowRate = state.dataThermalChimneys->ThermalChimneySys(Loop).EMSAirFlowRateValue;
921 : }
922 : }
923 :
924 : // Now assignment of the overall mass flow rate into each zone
925 8 : for (int TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
926 4 : int tcZonePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum);
927 4 : auto &thisTCZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(tcZonePtr);
928 4 : Real64 tcZoneMAT = thisTCZoneHB.MAT;
929 4 : Real64 tcZoneHumRat = thisTCZoneHB.airHumRat;
930 4 : int tcSpacePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr(TCZoneNum);
931 4 : if ((state.dataHeatBal->doSpaceHeatBalance) && (tcSpacePtr > 0)) {
932 0 : auto const &thisTCSpaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(tcSpacePtr);
933 0 : tcZoneMAT = thisTCSpaceHB.MAT;
934 0 : tcZoneHumRat = thisTCSpaceHB.airHumRat;
935 : }
936 : // ToDo - Let this persist to avoid diffs, but should be local
937 4 : AirDensity = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, tcZoneMAT, tcZoneHumRat);
938 4 : CpAir = PsyCpAirFnW(tcZoneHumRat);
939 : Real64 thisMCPThermChim =
940 4 : TCVolumeAirFlowRate * AirDensity * CpAir * state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum);
941 4 : if (thisMCPThermChim <= 0.0) {
942 0 : thisMCPThermChim = 0.0;
943 : }
944 4 : Real64 thisThermChimAMFL = thisMCPThermChim / CpAir;
945 4 : Real64 thisMCPTThermChim = thisMCPThermChim * state.dataHeatBal->Zone(tcZonePtr).OutDryBulbTemp; // Only zones have an ODB temp value
946 4 : thisTCZoneHB.MCPThermChim = thisMCPThermChim;
947 4 : thisTCZoneHB.ThermChimAMFL = thisThermChimAMFL;
948 4 : thisTCZoneHB.MCPTThermChim = thisMCPTThermChim;
949 4 : if ((state.dataHeatBal->doSpaceHeatBalance) && (tcSpacePtr > 0)) {
950 0 : auto &thisTCSpaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(tcSpacePtr);
951 0 : thisTCSpaceHB.MCPThermChim = thisMCPThermChim;
952 0 : thisTCSpaceHB.ThermChimAMFL = thisThermChimAMFL;
953 0 : thisTCSpaceHB.MCPTThermChim = thisMCPTThermChim;
954 : }
955 : }
956 :
957 : // ToDo - This should probably be using AirDensityThermalChim here instead of AirDensity which is leftover from the last inlet zone
958 4 : thisZoneHB.MCPThermChim = TCVolumeAirFlowRate * AirDensity * CpAir;
959 4 : if (thisZoneHB.MCPThermChim <= 0.0) {
960 0 : thisZoneHB.MCPThermChim = 0.0;
961 : }
962 4 : thisZoneHB.ThermChimAMFL = thisZoneHB.MCPThermChim / CpAir;
963 4 : thisZoneHB.MCPTThermChim = thisZoneHB.MCPThermChim * state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp;
964 :
965 4 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlow = TCVolumeAirFlowRate;
966 4 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCMassFlow = TCMassAirFlowRate;
967 4 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlowStd = TCMassAirFlowRate / state.dataEnvrn->StdRhoAir;
968 4 : if (state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCMassFlow != (TCVolumeAirFlowRate * AirDensityThermalChim)) {
969 4 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCMassFlow =
970 4 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlow * AirDensityThermalChim;
971 : }
972 4 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OutletAirTempThermalChim = ThermChimSubTemp(NTC) - Constant::Kelvin;
973 :
974 4 : if (state.dataThermalChimneys->ThermalChimneySys(Loop).availSched->getCurrentVal() <= 0.0) {
975 4 : for (int TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
976 2 : int tcZonePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum);
977 2 : auto &thisTCZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(tcZonePtr);
978 2 : thisTCZoneHB.MCPThermChim = 0.0;
979 2 : thisTCZoneHB.ThermChimAMFL = 0.0;
980 2 : thisTCZoneHB.MCPTThermChim = 0.0;
981 2 : int tcSpacePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr(TCZoneNum);
982 2 : if ((state.dataHeatBal->doSpaceHeatBalance) && (tcSpacePtr > 0)) {
983 0 : auto &thisTCSpaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(tcSpacePtr);
984 0 : thisTCSpaceHB.MCPThermChim = 0.0;
985 0 : thisTCSpaceHB.ThermChimAMFL = 0.0;
986 0 : thisTCSpaceHB.MCPTThermChim = 0.0;
987 : }
988 : }
989 2 : thisZoneHB.MCPThermChim = 0.0;
990 2 : thisZoneHB.ThermChimAMFL = 0.0;
991 2 : thisZoneHB.MCPTThermChim = 0.0;
992 2 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlow = 0.0;
993 2 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlowStd = 0.0;
994 2 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCMassFlow = 0.0;
995 2 : state.dataThermalChimneys->ThermalChimneyReport(Loop).OutletAirTempThermalChim =
996 2 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
997 : }
998 :
999 : } // DO Loop=1, TotThermalChimney
1000 2 : }
1001 :
1002 0 : void ReportThermalChimney(EnergyPlusData &state)
1003 : {
1004 :
1005 : // SUBROUTINE INFORMATION:
1006 : // AUTHOR Kwang Ho Lee
1007 : // DATE WRITTEN April 2008
1008 : // MODIFIED na
1009 : // RE-ENGINEERED na
1010 :
1011 : // PURPOSE OF THIS SUBROUTINE:
1012 : // This subroutine fills remaining report variables.
1013 :
1014 0 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
1015 :
1016 : int ZoneLoop; // Counter for the # of zones (nz)
1017 : Real64 AirDensity;
1018 : Real64 CpAir;
1019 :
1020 0 : for (ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) { // Start of zone loads report variable update loop ...
1021 0 : auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop);
1022 :
1023 : // Break the infiltration load into heat gain and loss components.
1024 0 : AirDensity = PsyRhoAirFnPbTdbW(
1025 0 : state, state.dataEnvrn->OutBaroPress, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop).MAT, thisZoneHB.airHumRat);
1026 0 : CpAir = PsyCpAirFnW(thisZoneHB.airHumRat);
1027 0 : state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyVolume =
1028 0 : (thisZoneHB.MCPThermChim / CpAir / AirDensity) * TimeStepSysSec;
1029 0 : state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyMass = (thisZoneHB.MCPThermChim / CpAir) * TimeStepSysSec;
1030 :
1031 0 : state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatLoss = 0.0;
1032 0 : state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatGain = 0.0;
1033 :
1034 0 : if (state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop).ZT > state.dataHeatBal->Zone(ZoneLoop).OutDryBulbTemp) {
1035 :
1036 0 : state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatLoss =
1037 0 : thisZoneHB.MCPThermChim *
1038 0 : (state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop).ZT - state.dataHeatBal->Zone(ZoneLoop).OutDryBulbTemp) *
1039 : TimeStepSysSec;
1040 0 : state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatGain = 0.0;
1041 :
1042 0 : } else if (state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop).ZT <= state.dataHeatBal->Zone(ZoneLoop).OutDryBulbTemp) {
1043 :
1044 0 : state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatGain =
1045 0 : thisZoneHB.MCPThermChim *
1046 0 : (state.dataHeatBal->Zone(ZoneLoop).OutDryBulbTemp - state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop).ZT) *
1047 : TimeStepSysSec;
1048 0 : state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatLoss = 0.0;
1049 : }
1050 :
1051 : } // ... end of zone loads report variable update loop.
1052 0 : }
1053 :
1054 44 : void GaussElimination(Array2A<Real64> EquaCoef, Array1D<Real64> &EquaConst, Array1D<Real64> &ThermChimSubTemp, int const NTC)
1055 : {
1056 : // PURPOSE OF THIS SUBROUTINE:
1057 : // This subroutine sovles linear algebraic equations using Gauss Elimination Method.
1058 :
1059 44 : EquaCoef.dim(NTC, NTC);
1060 44 : EP_SIZE_CHECK(EquaConst, NTC);
1061 44 : EP_SIZE_CHECK(ThermChimSubTemp, NTC);
1062 :
1063 44 : Array1D<Real64> tempor(NTC);
1064 : Real64 tempb;
1065 : Real64 TCvalue;
1066 : Real64 TCcoefficient;
1067 : int pivot;
1068 : Real64 ThermalChimSum;
1069 : int ThermChimLoop1;
1070 : int ThermChimLoop2;
1071 : int ThermChimLoop3;
1072 :
1073 704 : for (ThermChimLoop1 = 1; ThermChimLoop1 <= NTC; ++ThermChimLoop1) {
1074 :
1075 660 : TCvalue = std::abs(EquaCoef(ThermChimLoop1, ThermChimLoop1));
1076 660 : pivot = ThermChimLoop1;
1077 5280 : for (ThermChimLoop2 = ThermChimLoop1 + 1; ThermChimLoop2 <= NTC; ++ThermChimLoop2) {
1078 4620 : if (std::abs(EquaCoef(ThermChimLoop1, ThermChimLoop2)) > TCvalue) {
1079 0 : TCvalue = std::abs(EquaCoef(ThermChimLoop1, ThermChimLoop2));
1080 0 : pivot = ThermChimLoop2;
1081 : }
1082 : }
1083 :
1084 660 : if (pivot != ThermChimLoop1) {
1085 0 : tempor({ThermChimLoop1, NTC}) = EquaCoef({ThermChimLoop1, NTC}, ThermChimLoop1);
1086 0 : tempb = EquaConst(ThermChimLoop1);
1087 0 : EquaCoef({ThermChimLoop1, NTC}, ThermChimLoop1) = EquaCoef({ThermChimLoop1, NTC}, pivot);
1088 0 : EquaConst(ThermChimLoop1) = EquaConst(pivot);
1089 0 : EquaCoef({ThermChimLoop1, NTC}, pivot) = tempor({ThermChimLoop1, NTC});
1090 0 : EquaConst(pivot) = tempb;
1091 : }
1092 :
1093 5280 : for (ThermChimLoop2 = ThermChimLoop1 + 1; ThermChimLoop2 <= NTC; ++ThermChimLoop2) {
1094 4620 : TCcoefficient = -EquaCoef(ThermChimLoop1, ThermChimLoop2) / EquaCoef(ThermChimLoop1, ThermChimLoop1);
1095 4620 : EquaCoef({ThermChimLoop1, NTC}, ThermChimLoop2) += TCcoefficient * EquaCoef({ThermChimLoop1, NTC}, ThermChimLoop1);
1096 4620 : EquaConst(ThermChimLoop2) += TCcoefficient * EquaConst(ThermChimLoop1);
1097 : }
1098 : }
1099 :
1100 44 : ThermChimSubTemp(NTC) = EquaConst(NTC) / EquaCoef(NTC, NTC);
1101 660 : for (ThermChimLoop2 = NTC - 1; ThermChimLoop2 >= 1; --ThermChimLoop2) {
1102 616 : ThermalChimSum = 0.0;
1103 5236 : for (ThermChimLoop3 = ThermChimLoop2 + 1; ThermChimLoop3 <= NTC; ++ThermChimLoop3) {
1104 4620 : ThermalChimSum += EquaCoef(ThermChimLoop3, ThermChimLoop2) * ThermChimSubTemp(ThermChimLoop3);
1105 : }
1106 616 : ThermChimSubTemp(ThermChimLoop2) = (EquaConst(ThermChimLoop2) - ThermalChimSum) / EquaCoef(ThermChimLoop2, ThermChimLoop2);
1107 : }
1108 44 : }
1109 :
1110 : // End of Module Subroutines for ThermalChimney
1111 :
1112 : //*****************************************************************************************
1113 :
1114 : } // namespace ThermalChimney
1115 :
1116 : } // namespace EnergyPlus
|