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