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 : #include "AirflowNetwork/Elements.hpp"
49 : #include "AirflowNetwork/Properties.hpp"
50 : #include "AirflowNetwork/Solver.hpp"
51 :
52 : #include "../../Data/EnergyPlusData.hh"
53 : #include "../../DataAirLoop.hh"
54 : #include "../../DataEnvironment.hh"
55 : #include "../../DataHVACGlobals.hh"
56 : #include "../../DataLoopNode.hh"
57 : #include "../../DataSurfaces.hh"
58 :
59 : namespace EnergyPlus {
60 :
61 : namespace AirflowNetwork {
62 :
63 : // MODULE INFORMATION:
64 : // AUTHOR Lixing Gu, Don Shirey, and Muthusamy V. Swami
65 : // DATE WRITTEN Aug. 2003
66 : // MODIFIED na
67 : // RE-ENGINEERED na
68 :
69 : // PURPOSE OF THIS MODULE:
70 : // This module should contain the information that is needed to simulate
71 : // performance of air distribution system, including pressure, temperature
72 : // and moisture levels at each node, and airflow and sensible and latent energy losses
73 : // at each element
74 :
75 13811441 : static Real64 square(Real64 x)
76 : {
77 13811441 : return x * x;
78 : }
79 :
80 88956763 : int Duct::calculate([[maybe_unused]] EnergyPlusData &state,
81 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
82 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
83 : [[maybe_unused]] int const i, // Linkage number
84 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
85 : [[maybe_unused]] const Real64 control, // Element control signal
86 : const AirState &propN, // Node 1 properties
87 : const AirState &propM, // Node 2 properties
88 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
89 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
90 : )
91 : {
92 :
93 : // SUBROUTINE INFORMATION:
94 : // AUTHOR George Walton
95 : // DATE WRITTEN Extracted from AIRNET
96 : // MODIFIED Lixing Gu, 2/1/04
97 : // Revised the subroutine to meet E+ needs
98 : // MODIFIED Lixing Gu, 6/8/05
99 : // RE-ENGINEERED na
100 :
101 : // PURPOSE OF THIS SUBROUTINE:
102 : // This subroutine solves airflow for a duct/pipe component using Colebrook equation for the
103 : // turbulent friction factor
104 :
105 : // SUBROUTINE PARAMETER DEFINITIONS:
106 88956763 : Real64 constexpr C(0.868589);
107 88956763 : Real64 constexpr EPS(0.001);
108 :
109 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
110 : Real64 A0;
111 : Real64 A1;
112 : Real64 A2;
113 : Real64 B;
114 : Real64 D;
115 : Real64 S2;
116 : Real64 CDM;
117 : Real64 FL; // friction factor for laminar flow.
118 : Real64 FT; // friction factor for turbulent flow.
119 : Real64 FTT;
120 : Real64 RE; // Reynolds number.
121 : Real64 ed;
122 : Real64 ld;
123 : Real64 g;
124 : Real64 AA1;
125 :
126 : // Formats
127 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
128 :
129 : // CompNum = state.afn->AirflowNetworkCompData(j).TypeNum;
130 88956763 : ed = roughness / hydraulicDiameter;
131 88956763 : ld = L / hydraulicDiameter;
132 88956763 : g = 1.14 - 0.868589 * std::log(ed);
133 88956763 : AA1 = g;
134 :
135 88956763 : if (LFLAG) {
136 : // Initialization by linear relation.
137 0 : if (PDROP >= 0.0) {
138 0 : DF[0] = (2.0 * propN.density * A * hydraulicDiameter) / (propN.viscosity * InitLamCoef * ld);
139 : } else {
140 0 : DF[0] = (2.0 * propM.density * A * hydraulicDiameter) / (propM.viscosity * InitLamCoef * ld);
141 : }
142 0 : F[0] = -DF[0] * PDROP;
143 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwi:" << i << InitLamCoef << F[0] << DF[0];
144 : } else {
145 : // Standard calculation.
146 88956763 : if (PDROP >= 0.0) {
147 : // Flow in positive direction.
148 : // Laminar flow coefficient !=0
149 85459708 : if (LamFriCoef >= 0.001) {
150 66758602 : A2 = LamFriCoef / (2.0 * propN.density * A * A);
151 66758602 : A1 = (propN.viscosity * LamDynCoef * ld) / (2.0 * propN.density * A * hydraulicDiameter);
152 66758602 : A0 = -PDROP;
153 66758602 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
154 66758602 : FL = (CDM - A1) / (2.0 * A2);
155 66758602 : CDM = 1.0 / CDM;
156 : } else {
157 18701106 : CDM = (2.0 * propN.density * A * hydraulicDiameter) / (propN.viscosity * LamDynCoef * ld);
158 18701106 : FL = CDM * PDROP;
159 : }
160 85459708 : RE = FL * hydraulicDiameter / (propN.viscosity * A);
161 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwl:" << i << PDROP << FL << CDM << RE;
162 : // Turbulent flow; test when Re>10.
163 85459708 : if (RE >= 10.0) {
164 84785798 : S2 = std::sqrt(2.0 * propN.density * PDROP) * A;
165 84785798 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
166 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << S2 << FTT << g;
167 : while (true) {
168 180445595 : FT = FTT;
169 180445595 : B = (9.3 * propN.viscosity * A) / (FT * roughness);
170 180445595 : D = 1.0 + g * B;
171 180445595 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
172 180445595 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
173 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << B << FTT << g;
174 180445595 : if (std::abs(FTT - FT) / FTT < EPS) {
175 84785798 : break;
176 : }
177 : }
178 84785798 : FT = FTT;
179 : } else {
180 673910 : FT = FL;
181 : }
182 : } else {
183 : // Flow in negative direction.
184 : // Laminar flow coefficient !=0
185 3497055 : if (LamFriCoef >= 0.001) {
186 2308989 : A2 = LamFriCoef / (2.0 * propM.density * A * A);
187 2308989 : A1 = (propM.viscosity * LamDynCoef * ld) / (2.0 * propM.density * A * hydraulicDiameter);
188 2308989 : A0 = PDROP;
189 2308989 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
190 2308989 : FL = -(CDM - A1) / (2.0 * A2);
191 2308989 : CDM = 1.0 / CDM;
192 : } else {
193 1188066 : CDM = (2.0 * propM.density * A * hydraulicDiameter) / (propM.viscosity * LamDynCoef * ld);
194 1188066 : FL = CDM * PDROP;
195 : }
196 3497055 : RE = -FL * hydraulicDiameter / (propM.viscosity * A);
197 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwl:" << i << PDROP << FL << CDM << RE;
198 : // Turbulent flow; test when Re>10.
199 3497055 : if (RE >= 10.0) {
200 2914705 : S2 = std::sqrt(-2.0 * propM.density * PDROP) * A;
201 2914705 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
202 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << S2 << FTT << g;
203 : while (true) {
204 8551777 : FT = FTT;
205 8551777 : B = (9.3 * propM.viscosity * A) / (FT * roughness);
206 8551777 : D = 1.0 + g * B;
207 8551777 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
208 8551777 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
209 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << B << FTT << g;
210 8551777 : if (std::abs(FTT - FT) / FTT < EPS) {
211 2914705 : break;
212 : }
213 : }
214 2914705 : FT = -FTT;
215 : } else {
216 582350 : FT = FL;
217 : }
218 : }
219 : // Select laminar or turbulent flow.
220 88956763 : if (std::abs(FL) <= std::abs(FT)) {
221 2540548 : F[0] = FL;
222 2540548 : DF[0] = CDM;
223 : } else {
224 86416215 : F[0] = FT;
225 86416215 : DF[0] = 0.5 * FT / PDROP;
226 : }
227 : }
228 88956763 : return 1;
229 : }
230 :
231 0 : int Duct::calculate([[maybe_unused]] EnergyPlusData &state,
232 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
233 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
234 : [[maybe_unused]] const Real64 control, // Element control signal
235 : const AirState &propN, // Node 1 properties
236 : const AirState &propM, // Node 2 properties
237 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
238 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
239 : )
240 : {
241 :
242 : // SUBROUTINE INFORMATION:
243 : // AUTHOR George Walton
244 : // DATE WRITTEN Extracted from AIRNET
245 : // MODIFIED Lixing Gu, 2/1/04
246 : // Revised the subroutine to meet E+ needs
247 : // MODIFIED Lixing Gu, 6/8/05
248 : // RE-ENGINEERED na
249 :
250 : // PURPOSE OF THIS SUBROUTINE:
251 : // This subroutine solves airflow for a duct/pipe component using Colebrook equation for the
252 : // turbulent friction factor
253 :
254 : // SUBROUTINE PARAMETER DEFINITIONS:
255 0 : Real64 constexpr C(0.868589);
256 0 : Real64 constexpr EPS(0.001);
257 :
258 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
259 : Real64 A0;
260 : Real64 A1;
261 : Real64 A2;
262 : Real64 B;
263 : Real64 D;
264 : Real64 S2;
265 : Real64 CDM;
266 : Real64 FL; // friction factor for laminar flow.
267 : Real64 FT; // friction factor for turbulent flow.
268 : Real64 FTT;
269 : Real64 RE; // Reynolds number.
270 : Real64 ed;
271 : Real64 ld;
272 : Real64 g;
273 : Real64 AA1;
274 :
275 : // Formats
276 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
277 :
278 : // CompNum = state.afn->AirflowNetworkCompData(j).TypeNum;
279 0 : ed = roughness / hydraulicDiameter;
280 0 : ld = L / hydraulicDiameter;
281 0 : g = 1.14 - 0.868589 * std::log(ed);
282 0 : AA1 = g;
283 :
284 : // Standard calculation.
285 0 : if (PDROP >= 0.0) {
286 : // Flow in positive direction.
287 : // Laminar flow coefficient !=0
288 0 : if (LamFriCoef >= 0.001) {
289 0 : A2 = LamFriCoef / (2.0 * propN.density * A * A);
290 0 : A1 = (propN.viscosity * LamDynCoef * ld) / (2.0 * propN.density * A * hydraulicDiameter);
291 0 : A0 = -PDROP;
292 0 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
293 0 : FL = (CDM - A1) / (2.0 * A2);
294 0 : CDM = 1.0 / CDM;
295 : } else {
296 0 : CDM = (2.0 * propN.density * A * hydraulicDiameter) / (propN.viscosity * LamDynCoef * ld);
297 0 : FL = CDM * PDROP;
298 : }
299 0 : RE = FL * hydraulicDiameter / (propN.viscosity * A);
300 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwl:" << i << PDROP << FL << CDM << RE;
301 : // Turbulent flow; test when Re>10.
302 0 : if (RE >= 10.0) {
303 0 : S2 = std::sqrt(2.0 * propN.density * PDROP) * A;
304 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
305 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << S2 << FTT << g;
306 : while (true) {
307 0 : FT = FTT;
308 0 : B = (9.3 * propN.viscosity * A) / (FT * roughness);
309 0 : D = 1.0 + g * B;
310 0 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
311 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
312 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << B << FTT << g;
313 0 : if (std::abs(FTT - FT) / FTT < EPS) {
314 0 : break;
315 : }
316 : }
317 0 : FT = FTT;
318 : } else {
319 0 : FT = FL;
320 : }
321 : } else {
322 : // Flow in negative direction.
323 : // Laminar flow coefficient !=0
324 0 : if (LamFriCoef >= 0.001) {
325 0 : A2 = LamFriCoef / (2.0 * propM.density * A * A);
326 0 : A1 = (propM.viscosity * LamDynCoef * ld) / (2.0 * propM.density * A * hydraulicDiameter);
327 0 : A0 = PDROP;
328 0 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
329 0 : FL = -(CDM - A1) / (2.0 * A2);
330 0 : CDM = 1.0 / CDM;
331 : } else {
332 0 : CDM = (2.0 * propM.density * A * hydraulicDiameter) / (propM.viscosity * LamDynCoef * ld);
333 0 : FL = CDM * PDROP;
334 : }
335 0 : RE = -FL * hydraulicDiameter / (propM.viscosity * A);
336 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwl:" << i << PDROP << FL << CDM << RE;
337 : // Turbulent flow; test when Re>10.
338 0 : if (RE >= 10.0) {
339 0 : S2 = std::sqrt(-2.0 * propM.density * PDROP) * A;
340 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
341 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << S2 << FTT << g;
342 : while (true) {
343 0 : FT = FTT;
344 0 : B = (9.3 * propM.viscosity * A) / (FT * roughness);
345 0 : D = 1.0 + g * B;
346 0 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
347 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
348 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << B << FTT << g;
349 0 : if (std::abs(FTT - FT) / FTT < EPS) {
350 0 : break;
351 : }
352 : }
353 0 : FT = -FTT;
354 : } else {
355 0 : FT = FL;
356 : }
357 : }
358 : // Select laminar or turbulent flow.
359 0 : if (std::abs(FL) <= std::abs(FT)) {
360 0 : F[0] = FL;
361 0 : DF[0] = CDM;
362 : } else {
363 0 : F[0] = FT;
364 0 : DF[0] = 0.5 * FT / PDROP;
365 : }
366 0 : return 1;
367 : }
368 :
369 64057013 : int SurfaceCrack::calculate([[maybe_unused]] EnergyPlusData &state,
370 : bool const linear, // Initialization flag. If true, use linear relationship
371 : Real64 const pdrop, // Total pressure drop across a component (P1 - P2) [Pa]
372 : [[maybe_unused]] int const i, // Linkage number
373 : const Real64 multiplier, // Element multiplier
374 : const Real64 control, // Element control signal
375 : const AirState &propN, // Node 1 properties
376 : const AirState &propM, // Node 2 properties
377 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
378 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
379 : )
380 : {
381 : // SUBROUTINE INFORMATION:
382 : // AUTHOR George Walton
383 : // DATE WRITTEN Extracted from AIRNET
384 : // MODIFIED Lixing Gu, 2/1/04
385 : // Revised the subroutine to meet E+ needs
386 : // MODIFIED Lixing Gu, 6/8/05
387 : // RE-ENGINEERED Jason DeGraw
388 :
389 : // PURPOSE OF THIS SUBROUTINE:
390 : // This subroutine solves airflow for a surface crack component
391 :
392 : // Real64 rhoz_norm = AIRDENSITY(StandardP, StandardT, StandardW);
393 : // Real64 viscz_norm = 1.71432e-5 + 4.828e-8 * StandardT;
394 :
395 64057013 : Real64 VisAve{0.5 * (propN.viscosity + propM.viscosity)};
396 64057013 : Real64 Tave{0.5 * (propN.temperature + propM.temperature)};
397 :
398 64057013 : Real64 sign{1.0};
399 64057013 : Real64 upwind_temperature{propN.temperature};
400 64057013 : Real64 upwind_density{propN.density};
401 64057013 : Real64 upwind_viscosity{propN.viscosity};
402 64057013 : Real64 upwind_sqrt_density{propN.sqrt_density};
403 64057013 : Real64 abs_pdrop = pdrop;
404 :
405 64057013 : if (pdrop < 0.0) {
406 29175161 : sign = -1.0;
407 29175161 : upwind_temperature = propM.temperature;
408 29175161 : upwind_density = propM.density;
409 29175161 : upwind_viscosity = propM.viscosity;
410 29175161 : upwind_sqrt_density = propM.sqrt_density;
411 29175161 : abs_pdrop = -pdrop;
412 : }
413 :
414 64057013 : Real64 coef = coefficient * control * multiplier / upwind_sqrt_density;
415 :
416 : // Laminar calculation
417 64057013 : Real64 RhoCor{TOKELVIN(upwind_temperature) / TOKELVIN(Tave)};
418 64057013 : Real64 Ctl{std::pow(reference_density / upwind_density / RhoCor, exponent - 1.0) *
419 64057013 : std::pow(reference_viscosity / VisAve, 2.0 * exponent - 1.0)};
420 64057013 : Real64 CDM{coef * upwind_density / upwind_viscosity * Ctl};
421 64057013 : Real64 FL{CDM * pdrop};
422 : Real64 abs_FT;
423 :
424 64057013 : if (linear) {
425 0 : DF[0] = CDM;
426 0 : F[0] = FL;
427 : } else {
428 : // Turbulent flow.
429 64057013 : if (exponent == 0.5) {
430 561104 : abs_FT = coef * upwind_sqrt_density * std::sqrt(abs_pdrop) * Ctl;
431 : } else {
432 63495909 : abs_FT = coef * upwind_sqrt_density * std::pow(abs_pdrop, exponent) * Ctl;
433 : }
434 : // Select linear or turbulent flow.
435 64057013 : if (std::abs(FL) <= abs_FT) {
436 66501 : F[0] = FL;
437 66501 : DF[0] = CDM;
438 : } else {
439 63990512 : F[0] = sign * abs_FT;
440 63990512 : DF[0] = F[0] * exponent / pdrop;
441 : }
442 : }
443 64057013 : return 1;
444 : }
445 :
446 0 : int SurfaceCrack::calculate(EnergyPlusData &state,
447 : Real64 const pdrop, // Total pressure drop across a component (P1 - P2) [Pa]
448 : const Real64 multiplier, // Element multiplier
449 : const Real64 control, // Element control signal
450 : const AirState &propN, // Node 1 properties
451 : const AirState &propM, // Node 2 properties
452 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
453 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
454 : )
455 : {
456 : // SUBROUTINE INFORMATION:
457 : // AUTHOR George Walton
458 : // DATE WRITTEN Extracted from AIRNET
459 : // MODIFIED Lixing Gu, 2/1/04
460 : // Revised the subroutine to meet E+ needs
461 : // MODIFIED Lixing Gu, 6/8/05
462 : // RE-ENGINEERED Jason DeGraw
463 :
464 : // PURPOSE OF THIS SUBROUTINE:
465 : // This subroutine solves airflow for a surface crack component
466 :
467 : // Real64 rhoz_norm = AIRDENSITY(StandardP, StandardT, StandardW);
468 : // Real64 viscz_norm = 1.71432e-5 + 4.828e-8 * StandardT;
469 :
470 0 : Real64 VisAve{0.5 * (propN.viscosity + propM.viscosity)};
471 0 : Real64 Tave{0.5 * (propN.temperature + propM.temperature)};
472 :
473 0 : Real64 sign{1.0};
474 0 : Real64 upwind_temperature{propN.temperature};
475 0 : Real64 upwind_density{propN.density};
476 0 : Real64 upwind_viscosity{propN.viscosity};
477 0 : Real64 upwind_sqrt_density{propN.sqrt_density};
478 0 : Real64 abs_pdrop = pdrop;
479 :
480 0 : if (pdrop < 0.0) {
481 0 : sign = -1.0;
482 0 : upwind_temperature = propM.temperature;
483 0 : upwind_density = propM.density;
484 0 : upwind_viscosity = propM.viscosity;
485 0 : upwind_sqrt_density = propM.sqrt_density;
486 0 : abs_pdrop = -pdrop;
487 : }
488 :
489 0 : Real64 coef = coefficient * control * multiplier / upwind_sqrt_density;
490 :
491 : // Laminar calculation
492 0 : Real64 RhoCor{TOKELVIN(upwind_temperature) / TOKELVIN(Tave)};
493 0 : Real64 Ctl{std::pow(reference_density / upwind_density / RhoCor, exponent - 1.0) *
494 0 : std::pow(reference_viscosity / VisAve, 2.0 * exponent - 1.0)};
495 0 : Real64 CDM{coef * upwind_density / upwind_viscosity * Ctl};
496 0 : Real64 FL{CDM * pdrop};
497 : Real64 abs_FT;
498 :
499 : // Turbulent flow.
500 0 : if (exponent == 0.5) {
501 0 : abs_FT = coef * upwind_sqrt_density * std::sqrt(abs_pdrop) * Ctl;
502 : } else {
503 0 : abs_FT = coef * upwind_sqrt_density * std::pow(abs_pdrop, exponent) * Ctl;
504 : }
505 : // Select linear or turbulent flow.
506 0 : if (std::abs(FL) <= abs_FT) {
507 0 : F[0] = FL;
508 0 : DF[0] = CDM;
509 : } else {
510 0 : F[0] = sign * abs_FT;
511 0 : DF[0] = F[0] * exponent / pdrop;
512 : }
513 :
514 0 : return 1;
515 : }
516 :
517 1959787 : int DuctLeak::calculate(EnergyPlusData &state,
518 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
519 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
520 : [[maybe_unused]] int const i, // Linkage number
521 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
522 : [[maybe_unused]] const Real64 control, // Element control signal
523 : const AirState &propN, // Node 1 properties
524 : const AirState &propM, // Node 2 properties
525 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
526 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
527 : )
528 : {
529 : // SUBROUTINE INFORMATION:
530 : // AUTHOR George Walton
531 : // DATE WRITTEN Extracted from AIRNET
532 : // MODIFIED Lixing Gu, 2/1/04
533 : // Revised the subroutine to meet E+ needs
534 : // MODIFIED Lixing Gu, 6/8/05
535 : // RE-ENGINEERED na
536 :
537 : // PURPOSE OF THIS SUBROUTINE:
538 : // This subroutine solves airflow for a power law resistance airflow component
539 :
540 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
541 : Real64 CDM;
542 : Real64 FL;
543 : Real64 FT;
544 : Real64 Ctl;
545 :
546 : // Formats
547 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
548 :
549 : // Crack standard condition: T=20C, p=101325 Pa and 0 g/kg
550 1959787 : Real64 RhozNorm = state.afn->properties.density(101325.0, 20.0, 0.0);
551 1959787 : Real64 VisczNorm = 1.71432e-5 + 4.828e-8 * 20.0;
552 1959787 : Real64 coef = FlowCoef;
553 :
554 1959787 : if (PDROP >= 0.0) {
555 1903475 : coef /= propN.sqrt_density;
556 : } else {
557 56312 : coef /= propM.sqrt_density;
558 : }
559 :
560 1959787 : if (LFLAG) {
561 : // Initialization by linear relation.
562 0 : if (PDROP >= 0.0) {
563 0 : Ctl = std::pow(RhozNorm / propN.density, FlowExpo - 1.0) * std::pow(VisczNorm / propN.viscosity, 2.0 * FlowExpo - 1.0);
564 0 : DF[0] = coef * propN.density / propN.viscosity * Ctl;
565 : } else {
566 0 : Ctl = std::pow(RhozNorm / propM.density, FlowExpo - 1.0) * std::pow(VisczNorm / propM.viscosity, 2.0 * FlowExpo - 1.0);
567 0 : DF[0] = coef * propM.density / propM.viscosity * Ctl;
568 : }
569 0 : F[0] = -DF[0] * PDROP;
570 : } else {
571 : // Standard calculation.
572 1959787 : if (PDROP >= 0.0) {
573 : // Flow in positive direction for laminar flow.
574 1903475 : Ctl = std::pow(RhozNorm / propN.density, FlowExpo - 1.0) * std::pow(VisczNorm / propN.viscosity, 2.0 * FlowExpo - 1.0);
575 1903475 : CDM = coef * propN.density / propN.viscosity * Ctl;
576 1903475 : FL = CDM * PDROP;
577 : // Flow in positive direction for turbulent flow.
578 1903475 : if (FlowExpo == 0.5) {
579 0 : FT = coef * propN.sqrt_density * std::sqrt(PDROP);
580 : } else {
581 1903475 : FT = coef * propN.sqrt_density * std::pow(PDROP, FlowExpo);
582 : }
583 : } else {
584 : // Flow in negative direction for laminar flow
585 56312 : CDM = coef * propM.density / propM.viscosity;
586 56312 : FL = CDM * PDROP;
587 : // Flow in negative direction for turbulent flow
588 56312 : if (FlowExpo == 0.5) {
589 0 : FT = -coef * propM.sqrt_density * std::sqrt(-PDROP);
590 : } else {
591 56312 : FT = -coef * propM.sqrt_density * std::pow(-PDROP, FlowExpo);
592 : }
593 : }
594 : // Select laminar or turbulent flow.
595 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " plr: " << i << PDROP << FL << FT;
596 1959787 : if (std::abs(FL) <= std::abs(FT)) {
597 89 : F[0] = FL;
598 89 : DF[0] = CDM;
599 : } else {
600 1959698 : F[0] = FT;
601 1959698 : DF[0] = FT * FlowExpo / PDROP;
602 : }
603 : }
604 1959787 : return 1;
605 : }
606 :
607 0 : int DuctLeak::calculate(EnergyPlusData &state,
608 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
609 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
610 : [[maybe_unused]] const Real64 control, // Element control signal
611 : const AirState &propN, // Node 1 properties
612 : const AirState &propM, // Node 2 properties
613 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
614 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
615 : )
616 : {
617 : // SUBROUTINE INFORMATION:
618 : // AUTHOR George Walton
619 : // DATE WRITTEN Extracted from AIRNET
620 : // MODIFIED Lixing Gu, 2/1/04
621 : // Revised the subroutine to meet E+ needs
622 : // MODIFIED Lixing Gu, 6/8/05
623 : // RE-ENGINEERED na
624 :
625 : // PURPOSE OF THIS SUBROUTINE:
626 : // This subroutine solves airflow for a power law resistance airflow component
627 :
628 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
629 : Real64 CDM;
630 : Real64 FL;
631 : Real64 FT;
632 : Real64 Ctl;
633 :
634 : // Formats
635 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
636 :
637 : // Crack standard condition: T=20C, p=101325 Pa and 0 g/kg
638 0 : Real64 RhozNorm = state.afn->properties.density(101325.0, 20.0, 0.0);
639 0 : Real64 VisczNorm = 1.71432e-5 + 4.828e-8 * 20.0;
640 0 : Real64 coef = FlowCoef;
641 :
642 0 : if (PDROP >= 0.0) {
643 0 : coef /= propN.sqrt_density;
644 : } else {
645 0 : coef /= propM.sqrt_density;
646 : }
647 :
648 : // Standard calculation.
649 0 : if (PDROP >= 0.0) {
650 : // Flow in positive direction for laminar flow.
651 0 : Ctl = std::pow(RhozNorm / propN.density, FlowExpo - 1.0) * std::pow(VisczNorm / propN.viscosity, 2.0 * FlowExpo - 1.0);
652 0 : CDM = coef * propN.density / propN.viscosity * Ctl;
653 0 : FL = CDM * PDROP;
654 : // Flow in positive direction for turbulent flow.
655 0 : if (FlowExpo == 0.5) {
656 0 : FT = coef * propN.sqrt_density * std::sqrt(PDROP);
657 : } else {
658 0 : FT = coef * propN.sqrt_density * std::pow(PDROP, FlowExpo);
659 : }
660 : } else {
661 : // Flow in negative direction for laminar flow
662 0 : CDM = coef * propM.density / propM.viscosity;
663 0 : FL = CDM * PDROP;
664 : // Flow in negative direction for turbulent flow
665 0 : if (FlowExpo == 0.5) {
666 0 : FT = -coef * propM.sqrt_density * std::sqrt(-PDROP);
667 : } else {
668 0 : FT = -coef * propM.sqrt_density * std::pow(-PDROP, FlowExpo);
669 : }
670 : }
671 : // Select laminar or turbulent flow.
672 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " plr: " << i << PDROP << FL << FT;
673 0 : if (std::abs(FL) <= std::abs(FT)) {
674 0 : F[0] = FL;
675 0 : DF[0] = CDM;
676 : } else {
677 0 : F[0] = FT;
678 0 : DF[0] = FT * FlowExpo / PDROP;
679 : }
680 0 : return 1;
681 : }
682 :
683 5315176 : int ConstantVolumeFan::calculate(EnergyPlusData &state,
684 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
685 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
686 : int const i, // Linkage number
687 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
688 : [[maybe_unused]] const Real64 control, // Element control signal
689 : const AirState &propN, // Node 1 properties
690 : const AirState &propM, // Node 2 properties
691 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
692 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
693 : )
694 : {
695 :
696 : // SUBROUTINE INFORMATION:
697 : // AUTHOR George Walton
698 : // DATE WRITTEN Extracted from AIRNET
699 : // MODIFIED Lixing Gu, 2/1/04
700 : // Revised the subroutine to meet E+ needs
701 : // MODIFIED Lixing Gu, 6/8/05
702 : // RE-ENGINEERED na
703 :
704 : // PURPOSE OF THIS SUBROUTINE:
705 : // This subroutine solves airflow for a constant flow rate airflow component -- using standard interface.
706 :
707 : // Using/Aliasing
708 5315176 : auto &NumPrimaryAirSys = state.dataHVACGlobal->NumPrimaryAirSys;
709 :
710 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
711 : int k;
712 : int k1;
713 : Real64 SumTermFlow; // Sum of all Terminal flows [kg/s]
714 : Real64 SumFracSuppLeak; // Sum of all supply leaks as a fraction of supply fan flow rate
715 : int Node1;
716 : int Node2;
717 :
718 5315176 : int NF(1);
719 :
720 5315176 : int AirLoopNum = state.afn->AirflowNetworkLinkageData(i).AirLoopNum;
721 :
722 5315176 : if (fanType == HVAC::FanType::OnOff) {
723 6127178 : if (state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopFanOperationMode == HVAC::FanOp::Cycling &&
724 2946089 : state.dataLoopNodes->Node(InletNode).MassFlowRate == 0.0) {
725 12136 : NF = GenericDuct(0.1, 0.001, LFLAG, PDROP, propN, propM, F, DF);
726 6102906 : } else if (state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopFanOperationMode == HVAC::FanOp::Cycling &&
727 2933953 : state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOnMassFlowrate > 0.0) {
728 2933953 : F[0] = state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOnMassFlowrate;
729 : } else {
730 235000 : F[0] = state.dataLoopNodes->Node(InletNode).MassFlowRate * Ctrl;
731 235000 : if (state.afn->MultiSpeedHPIndicator == 2) {
732 0 : F[0] = state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOnMassFlowrate *
733 0 : state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopCompCycRatio +
734 0 : state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOffMassFlowrate *
735 0 : (1.0 - state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopCompCycRatio);
736 : }
737 : }
738 2134087 : } else if (fanType == HVAC::FanType::Constant) {
739 2084943 : if (state.dataLoopNodes->Node(InletNode).MassFlowRate > 0.0) {
740 2084943 : F[0] = FlowRate * Ctrl;
741 0 : } else if (NumPrimaryAirSys > 1 && state.dataLoopNodes->Node(InletNode).MassFlowRate <= 0.0) {
742 0 : NF = GenericDuct(0.1, 0.001, LFLAG, PDROP, propN, propM, F, DF);
743 : }
744 :
745 2084943 : if (state.afn->MultiSpeedHPIndicator == 2) {
746 0 : F[0] = state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopSystemOnMassFlowrate;
747 : }
748 49144 : } else if (fanType == HVAC::FanType::VAV) {
749 : // Check VAV termals with a damper
750 49144 : SumTermFlow = 0.0;
751 49144 : SumFracSuppLeak = 0.0;
752 3046928 : for (k = 1; k <= state.afn->ActualNumOfLinks; ++k) {
753 2997784 : if (state.afn->AirflowNetworkLinkageData(k).VAVTermDamper && state.afn->AirflowNetworkLinkageData(k).AirLoopNum == AirLoopNum) {
754 147432 : k1 = state.afn->AirflowNetworkNodeData(state.afn->AirflowNetworkLinkageData(k).NodeNums[0]).EPlusNodeNum;
755 147432 : if (state.dataLoopNodes->Node(k1).MassFlowRate > 0.0) {
756 147432 : SumTermFlow += state.dataLoopNodes->Node(k1).MassFlowRate;
757 : }
758 : }
759 2997784 : if (state.afn->AirflowNetworkCompData(state.afn->AirflowNetworkLinkageData(k).CompNum).CompTypeNum == iComponentTypeNum::ELR) {
760 : // Calculate supply leak sensible losses
761 344008 : Node1 = state.afn->AirflowNetworkLinkageData(k).NodeNums[0];
762 344008 : Node2 = state.afn->AirflowNetworkLinkageData(k).NodeNums[1];
763 540584 : if ((state.afn->AirflowNetworkNodeData(Node2).EPlusZoneNum > 0) && (state.afn->AirflowNetworkNodeData(Node1).EPlusNodeNum == 0) &&
764 196576 : (state.afn->AirflowNetworkNodeData(Node1).AirLoopNum == AirLoopNum)) {
765 196576 : SumFracSuppLeak +=
766 196576 : state.afn->DisSysCompELRData(state.afn->AirflowNetworkCompData(state.afn->AirflowNetworkLinkageData(k).CompNum).TypeNum)
767 196576 : .ELR;
768 : }
769 : }
770 : }
771 49144 : F[0] = SumTermFlow / (1.0 - SumFracSuppLeak);
772 49144 : state.afn->VAVTerminalRatio = 0.0;
773 49144 : if (F[0] > MaxAirMassFlowRate) {
774 0 : state.afn->VAVTerminalRatio = MaxAirMassFlowRate / F[0];
775 0 : F[0] = MaxAirMassFlowRate;
776 : }
777 : }
778 5315176 : DF[0] = 0.0;
779 5315176 : return NF;
780 : }
781 :
782 0 : int DetailedFan::calculate(EnergyPlusData &state,
783 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
784 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
785 : int const i, // Linkage number
786 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
787 : const Real64 control, // Element control signal
788 : const AirState &propN, // Node 1 properties
789 : const AirState &propM, // Node 2 properties
790 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
791 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
792 : )
793 : {
794 :
795 : // SUBROUTINE INFORMATION:
796 : // AUTHOR George Walton
797 : // DATE WRITTEN Extracted from AIRNET
798 : // MODIFIED Lixing Gu, 2/1/04
799 : // Revised the subroutine to meet E+ needs
800 : // MODIFIED Lixing Gu, 6/8/05
801 : // RE-ENGINEERED na
802 :
803 : // PURPOSE OF THIS SUBROUTINE:
804 : // This subroutine solves airflow for a detailed fan component -- using standard interface.
805 :
806 : // SUBROUTINE PARAMETER DEFINITIONS:
807 0 : Real64 constexpr TOL(0.00001);
808 :
809 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
810 : int j;
811 : int k;
812 : int L;
813 : Real64 DPDF;
814 : Real64 PRISE; // pressure rise (negative of pressure drop) (Pa).
815 : Real64 BX;
816 : Real64 BY;
817 : Real64 CX;
818 : Real64 CY;
819 : Real64 CCY;
820 : Real64 DX;
821 : Real64 DY;
822 :
823 : // Formats
824 : // static gio::Fmt Format_901("(A5,I3,5E14.6)");
825 :
826 0 : int NumCur = n;
827 0 : if (control <= 0.0) {
828 : // Speed = 0; treat fan as resistance.
829 0 : generic_crack(FlowCoef, FlowExpo, LFLAG, PDROP, propN, propM, F, DF);
830 0 : return 1;
831 : }
832 : // Pressure rise at reference fan speed.
833 0 : if (control >= TranRat) {
834 0 : PRISE = -PDROP * (RhoAir / propN.density) / (control * control);
835 : } else {
836 0 : PRISE = -PDROP * (RhoAir / propN.density) / (TranRat * control);
837 : }
838 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " fan:" << i << PDROP << PRISE << AFECTL(i) << DisSysCompDetFanData(CompNum).TranRat;
839 0 : if (LFLAG) {
840 : // Initialization by linear approximation.
841 0 : F[0] = -Qfree * control * (1.0 - PRISE / Pshut);
842 0 : DPDF = -Pshut / Qfree;
843 : // if (LIST >= 4)
844 : // gio::write(Unit21, Format_901) << " fni:" << JA << DisSysCompDetFanData(CompNum).Qfree << DisSysCompDetFanData(CompNum).Pshut;
845 : } else {
846 : // Solution of the fan performance curve.
847 : // Determine curve fit range.
848 0 : j = 1;
849 0 : k = 5 * (j - 1) + 1;
850 0 : BX = Coeff(k);
851 0 : BY = Coeff(k + 1) + BX * (Coeff(k + 2) + BX * (Coeff(k + 3) + BX * Coeff(k + 4))) - PRISE;
852 0 : if (BY < 0.0) {
853 0 : ShowFatalError(state, "Out of range, too low in an AirflowNetwork detailed Fan");
854 : }
855 :
856 : while (true) {
857 0 : DX = Coeff(k + 5);
858 0 : DY = Coeff(k + 1) + DX * (Coeff(k + 2) + DX * (Coeff(k + 3) + DX * Coeff(k + 5))) - PRISE;
859 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " fp0:" << j << BX << BY << DX << DY;
860 0 : if (BY * DY <= 0.0) {
861 0 : break;
862 : }
863 0 : ++j;
864 0 : if (j > NumCur) {
865 0 : ShowFatalError(state, "Out of range, too high (FAN) in ADS simulation");
866 : }
867 0 : k += 5;
868 0 : BX = DX;
869 0 : BY = DY;
870 : }
871 : // Determine reference mass flow rate by false position method.
872 0 : L = 0;
873 0 : CY = 0.0;
874 0 : Label40:;
875 0 : ++L;
876 0 : if (L > 100) {
877 0 : ShowFatalError(state, "Too many iterations (FAN) in AirflowNtework simulation");
878 : }
879 0 : CCY = CY;
880 0 : CX = BX - BY * ((DX - BX) / (DY - BY));
881 0 : CY = Coeff(k + 1) + CX * (Coeff(k + 2) + CX * (Coeff(k + 3) + CX * Coeff(k + 4))) - PRISE;
882 0 : if (BY * CY == 0.0) {
883 0 : goto Label90;
884 : }
885 0 : if (BY * CY > 0.0) {
886 0 : goto Label60;
887 : }
888 0 : DX = CX;
889 0 : DY = CY;
890 0 : if (CY * CCY > 0.0) {
891 0 : BY *= 0.5;
892 : }
893 0 : goto Label70;
894 0 : Label60:;
895 0 : BX = CX;
896 0 : BY = CY;
897 0 : if (CY * CCY > 0.0) {
898 0 : DY *= 0.5;
899 : }
900 0 : Label70:;
901 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " fpi:" << j << BX << CX << DX << BY << DY;
902 0 : if (DX - BX < TOL * CX) {
903 0 : goto Label80;
904 : }
905 0 : if (DX - BX < TOL) {
906 0 : goto Label80;
907 : }
908 0 : goto Label40;
909 0 : Label80:;
910 0 : CX = 0.5 * (BX + DX);
911 0 : Label90:;
912 0 : F[0] = CX;
913 0 : DPDF = Coeff(k + 2) + CX * (2.0 * Coeff(k + 3) + CX * 3.0 * Coeff(k + 4));
914 : }
915 : // Convert to flow at given speed.
916 0 : F[0] *= (propN.density / RhoAir) * control;
917 : // Set derivative w/r pressure drop (-).
918 0 : if (control >= TranRat) {
919 0 : DF[0] = -control / DPDF;
920 : } else {
921 0 : DF[0] = -1.0 / DPDF;
922 : }
923 0 : return 1;
924 : }
925 :
926 0 : int DetailedFan::calculate(EnergyPlusData &state,
927 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
928 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
929 : const Real64 control, // Element control signal
930 : const AirState &propN, // Node 1 properties
931 : const AirState &propM, // Node 2 properties
932 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
933 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
934 : )
935 : {
936 :
937 : // SUBROUTINE INFORMATION:
938 : // AUTHOR George Walton
939 : // DATE WRITTEN Extracted from AIRNET
940 : // MODIFIED Lixing Gu, 2/1/04
941 : // Revised the subroutine to meet E+ needs
942 : // MODIFIED Lixing Gu, 6/8/05
943 : // RE-ENGINEERED na
944 :
945 : // PURPOSE OF THIS SUBROUTINE:
946 : // This subroutine solves airflow for a detailed fan component -- using standard interface.
947 :
948 : // SUBROUTINE PARAMETER DEFINITIONS:
949 0 : Real64 constexpr TOL(0.00001);
950 :
951 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
952 : int j;
953 : int k;
954 : int L;
955 : Real64 DPDF;
956 : Real64 PRISE; // pressure rise (negative of pressure drop) (Pa).
957 : Real64 BX;
958 : Real64 BY;
959 : Real64 CX;
960 : Real64 CY;
961 : Real64 CCY;
962 : Real64 DX;
963 : Real64 DY;
964 :
965 : // Formats
966 : // static gio::Fmt Format_901("(A5,I3,5E14.6)");
967 :
968 0 : int NumCur = n;
969 :
970 0 : if (control <= 0.0) {
971 : // Speed = 0; treat fan as resistance.
972 0 : generic_crack(FlowCoef, FlowExpo, false, PDROP, propN, propM, F, DF);
973 0 : return 1;
974 : }
975 : // Pressure rise at reference fan speed.
976 0 : if (control >= TranRat) {
977 0 : PRISE = -PDROP * (RhoAir / propN.density) / pow_2(control);
978 : } else {
979 0 : PRISE = -PDROP * (RhoAir / propN.density) / (TranRat * control);
980 : }
981 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " fan:" << i << PDROP << PRISE << AFECTL(i) << DisSysCompDetFanData(CompNum).TranRat;
982 : // if (LFLAG) {
983 : // // Initialization by linear approximation.
984 : // F[0] = -Qfree * control * (1.0 - PRISE / Pshut);
985 : // DPDF = -Pshut / Qfree;
986 : // // if (LIST >= 4)
987 : // // gio::write(Unit21, Format_901) << " fni:" << JA << DisSysCompDetFanData(CompNum).Qfree << DisSysCompDetFanData(CompNum).Pshut;
988 : //} else {
989 : // Solution of the fan performance curve.
990 : // Determine curve fit range.
991 0 : j = 1;
992 0 : k = 5 * (j - 1) + 1;
993 0 : BX = Coeff(k);
994 0 : BY = Coeff(k + 1) + BX * (Coeff(k + 2) + BX * (Coeff(k + 3) + BX * Coeff(k + 4))) - PRISE;
995 0 : if (BY < 0.0) {
996 0 : ShowFatalError(state, "Out of range, too low in an AirflowNetwork detailed Fan");
997 : }
998 :
999 : while (true) {
1000 0 : DX = Coeff(k + 5);
1001 0 : DY = Coeff(k + 1) + DX * (Coeff(k + 2) + DX * (Coeff(k + 3) + DX * Coeff(k + 5))) - PRISE;
1002 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " fp0:" << j << BX << BY << DX << DY;
1003 0 : if (BY * DY <= 0.0) {
1004 0 : break;
1005 : }
1006 0 : ++j;
1007 0 : if (j > NumCur) {
1008 0 : ShowFatalError(state, "Out of range, too high (FAN) in ADS simulation");
1009 : }
1010 0 : k += 5;
1011 0 : BX = DX;
1012 0 : BY = DY;
1013 : }
1014 : // Determine reference mass flow rate by false position method.
1015 0 : L = 0;
1016 0 : CY = 0.0;
1017 0 : Label40:;
1018 0 : ++L;
1019 0 : if (L > 100) {
1020 0 : ShowFatalError(state, "Too many iterations (FAN) in AirflowNtework simulation");
1021 : }
1022 0 : CCY = CY;
1023 0 : CX = BX - BY * ((DX - BX) / (DY - BY));
1024 0 : CY = Coeff(k + 1) + CX * (Coeff(k + 2) + CX * (Coeff(k + 3) + CX * Coeff(k + 4))) - PRISE;
1025 0 : if (BY * CY == 0.0) {
1026 0 : goto Label90;
1027 : }
1028 0 : if (BY * CY > 0.0) {
1029 0 : goto Label60;
1030 : }
1031 0 : DX = CX;
1032 0 : DY = CY;
1033 0 : if (CY * CCY > 0.0) {
1034 0 : BY *= 0.5;
1035 : }
1036 0 : goto Label70;
1037 0 : Label60:;
1038 0 : BX = CX;
1039 0 : BY = CY;
1040 0 : if (CY * CCY > 0.0) {
1041 0 : DY *= 0.5;
1042 : }
1043 0 : Label70:;
1044 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " fpi:" << j << BX << CX << DX << BY << DY;
1045 0 : if (DX - BX < TOL * CX) {
1046 0 : goto Label80;
1047 : }
1048 0 : if (DX - BX < TOL) {
1049 0 : goto Label80;
1050 : }
1051 0 : goto Label40;
1052 0 : Label80:;
1053 0 : CX = 0.5 * (BX + DX);
1054 0 : Label90:;
1055 0 : F[0] = CX;
1056 0 : DPDF = Coeff(k + 2) + CX * (2.0 * Coeff(k + 3) + CX * 3.0 * Coeff(k + 4));
1057 :
1058 : // Convert to flow at given speed.
1059 0 : F[0] *= (propN.density / RhoAir) * control;
1060 : // Set derivative w/r pressure drop (-).
1061 0 : if (control >= TranRat) {
1062 0 : DF[0] = -control / DPDF;
1063 : } else {
1064 0 : DF[0] = -1.0 / DPDF;
1065 : }
1066 0 : return 1;
1067 : }
1068 :
1069 0 : int Damper::calculate([[maybe_unused]] EnergyPlusData &state,
1070 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
1071 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
1072 : int const i, // Linkage number
1073 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
1074 : [[maybe_unused]] const Real64 control, // Element control signal
1075 : const AirState &propN, // Node 1 properties
1076 : const AirState &propM, // Node 2 properties
1077 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
1078 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
1079 : )
1080 : {
1081 :
1082 : // SUBROUTINE INFORMATION:
1083 : // AUTHOR George Walton
1084 : // DATE WRITTEN Extracted from AIRNET
1085 : // MODIFIED Lixing Gu, 2/1/04
1086 : // Revised the subroutine to meet E+ needs
1087 : // MODIFIED Lixing Gu, 6/8/05
1088 : // RE-ENGINEERED na
1089 :
1090 : // PURPOSE OF THIS SUBROUTINE:
1091 : // This subroutine solves airflow for a Controlled power law resistance airflow component (damper)
1092 :
1093 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1094 : Real64 C;
1095 :
1096 : // Formats
1097 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
1098 :
1099 0 : C = control;
1100 0 : if (C < FlowMin) {
1101 0 : C = FlowMin;
1102 : }
1103 0 : if (C > FlowMax) {
1104 0 : C = FlowMax;
1105 : }
1106 0 : C = A0 + C * (A1 + C * (A2 + C * A3));
1107 : // if (LIST >= 4)
1108 : // gio::write(Unit21, Format_901) << " Dmp:" << i << AFECTL(i) << DisSysCompDamperData(CompNum).FlowMin
1109 : // << DisSysCompDamperData(CompNum).FlowMax << C;
1110 0 : if (LFLAG || std::abs(PDROP) <= LTP) {
1111 : // Laminar flow.
1112 0 : if (PDROP >= 0.0) {
1113 0 : DF[0] = C * LamFlow * propN.density / propN.viscosity;
1114 : } else {
1115 0 : DF[0] = C * LamFlow * propM.density / propM.viscosity;
1116 : }
1117 0 : F[0] = DF[0] * PDROP;
1118 : } else {
1119 : // Turbulent flow.
1120 0 : if (PDROP >= 0.0) {
1121 0 : F[0] = C * TurFlow * propN.sqrt_density * std::pow(PDROP, FlowExpo);
1122 : } else {
1123 0 : F[0] = -C * TurFlow * propM.sqrt_density * std::pow(-PDROP, FlowExpo);
1124 : }
1125 0 : DF[0] = F[0] * FlowExpo / PDROP;
1126 : }
1127 0 : return 1;
1128 : }
1129 :
1130 0 : int Damper::calculate([[maybe_unused]] EnergyPlusData &state,
1131 : const Real64 PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
1132 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
1133 : const Real64 control, // Element control signal
1134 : const AirState &propN, // Node 1 properties
1135 : const AirState &propM, // Node 2 properties
1136 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
1137 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
1138 : )
1139 : {
1140 :
1141 : // SUBROUTINE INFORMATION:
1142 : // AUTHOR George Walton
1143 : // DATE WRITTEN Extracted from AIRNET
1144 : // MODIFIED Lixing Gu, 2/1/04
1145 : // Revised the subroutine to meet E+ needs
1146 : // MODIFIED Lixing Gu, 6/8/05
1147 : // RE-ENGINEERED na
1148 :
1149 : // PURPOSE OF THIS SUBROUTINE:
1150 : // This subroutine solves airflow for a Controlled power law resistance airflow component (damper)
1151 :
1152 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1153 : Real64 C;
1154 :
1155 : // Formats
1156 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
1157 :
1158 0 : C = control;
1159 0 : if (C < FlowMin) {
1160 0 : C = FlowMin;
1161 : }
1162 0 : if (C > FlowMax) {
1163 0 : C = FlowMax;
1164 : }
1165 0 : C = A0 + C * (A1 + C * (A2 + C * A3));
1166 : // if (LIST >= 4)
1167 : // gio::write(Unit21, Format_901) << " Dmp:" << i << AFECTL(i) << DisSysCompDamperData(CompNum).FlowMin
1168 : // << DisSysCompDamperData(CompNum).FlowMax << C;
1169 0 : if (std::abs(PDROP) <= LTP) {
1170 : // Laminar flow.
1171 0 : if (PDROP >= 0.0) {
1172 0 : DF[0] = C * LamFlow * propN.density / propN.viscosity;
1173 : } else {
1174 0 : DF[0] = C * LamFlow * propM.density / propM.viscosity;
1175 : }
1176 0 : F[0] = DF[0] * PDROP;
1177 : } else {
1178 : // Turbulent flow.
1179 0 : if (PDROP >= 0.0) {
1180 0 : F[0] = C * TurFlow * propN.sqrt_density * std::pow(PDROP, FlowExpo);
1181 : } else {
1182 0 : F[0] = -C * TurFlow * propM.sqrt_density * std::pow(-PDROP, FlowExpo);
1183 : }
1184 0 : DF[0] = F[0] * FlowExpo / PDROP;
1185 : }
1186 0 : return 1;
1187 : }
1188 :
1189 17457999 : int EffectiveLeakageRatio::calculate([[maybe_unused]] EnergyPlusData &state,
1190 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
1191 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
1192 : [[maybe_unused]] int const i, // Linkage number
1193 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
1194 : [[maybe_unused]] const Real64 control, // Element control signal
1195 : const AirState &propN, // Node 1 properties
1196 : const AirState &propM, // Node 2 properties
1197 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
1198 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
1199 : )
1200 : {
1201 :
1202 : // SUBROUTINE INFORMATION:
1203 : // AUTHOR George Walton
1204 : // DATE WRITTEN Extracted from AIRNET
1205 : // MODIFIED Lixing Gu, 2/1/04
1206 : // Revised the subroutine to meet E+ needs
1207 : // MODIFIED Lixing Gu, 6/8/05
1208 : // RE-ENGINEERED na
1209 :
1210 : // PURPOSE OF THIS SUBROUTINE:
1211 : // This subroutine solves airflow for a Effective leakage ratio component
1212 :
1213 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1214 : Real64 CDM;
1215 : Real64 FL;
1216 : Real64 FT;
1217 : Real64 FlowCoef;
1218 :
1219 : // Formats
1220 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
1221 :
1222 : // Get component properties
1223 17457999 : FlowCoef = ELR * FlowRate / propN.density * std::pow(RefPres, -FlowExpo);
1224 :
1225 17457999 : if (LFLAG) {
1226 : // Initialization by linear relation.
1227 0 : if (PDROP >= 0.0) {
1228 0 : DF[0] = FlowCoef * propN.density / propN.viscosity;
1229 : } else {
1230 0 : DF[0] = FlowCoef * propM.density / propM.viscosity;
1231 : }
1232 0 : F[0] = -DF[0] * PDROP;
1233 : } else {
1234 : // Standard calculation.
1235 17457999 : if (PDROP >= 0.0) {
1236 : // Flow in positive direction.
1237 : // Laminar flow.
1238 11749716 : CDM = FlowCoef * propN.density / propN.viscosity;
1239 11749716 : FL = CDM * PDROP;
1240 : // Turbulent flow.
1241 11749716 : if (FlowExpo == 0.5) {
1242 0 : FT = FlowCoef * propN.sqrt_density * std::sqrt(PDROP);
1243 : } else {
1244 11749716 : FT = FlowCoef * propN.sqrt_density * std::pow(PDROP, FlowExpo);
1245 : }
1246 : } else {
1247 : // Flow in negative direction.
1248 : // Laminar flow.
1249 5708283 : CDM = FlowCoef * propM.density / propM.viscosity;
1250 5708283 : FL = CDM * PDROP;
1251 : // Turbulent flow.
1252 5708283 : if (FlowExpo == 0.5) {
1253 0 : FT = -FlowCoef * propM.sqrt_density * std::sqrt(-PDROP);
1254 : } else {
1255 5708283 : FT = -FlowCoef * propM.sqrt_density * std::pow(-PDROP, FlowExpo);
1256 : }
1257 : }
1258 : // Select laminar or turbulent flow.
1259 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " plr: " << i << PDROP << FL << FT;
1260 17457999 : if (std::abs(FL) <= std::abs(FT)) {
1261 343 : F[0] = FL;
1262 343 : DF[0] = CDM;
1263 : } else {
1264 17457656 : F[0] = FT;
1265 17457656 : DF[0] = FT * FlowExpo / PDROP;
1266 : }
1267 : }
1268 17457999 : return 1;
1269 : }
1270 :
1271 0 : int EffectiveLeakageRatio::calculate([[maybe_unused]] EnergyPlusData &state,
1272 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
1273 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
1274 : [[maybe_unused]] const Real64 control, // Element control signal
1275 : const AirState &propN, // Node 1 properties
1276 : const AirState &propM, // Node 2 properties
1277 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
1278 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
1279 : )
1280 : {
1281 :
1282 : // SUBROUTINE INFORMATION:
1283 : // AUTHOR George Walton
1284 : // DATE WRITTEN Extracted from AIRNET
1285 : // MODIFIED Lixing Gu, 2/1/04
1286 : // Revised the subroutine to meet E+ needs
1287 : // MODIFIED Lixing Gu, 6/8/05
1288 : // RE-ENGINEERED na
1289 :
1290 : // PURPOSE OF THIS SUBROUTINE:
1291 : // This subroutine solves airflow for a Effective leakage ratio component
1292 :
1293 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1294 : Real64 CDM;
1295 : Real64 FL;
1296 : Real64 FT;
1297 : Real64 FlowCoef;
1298 :
1299 : // Formats
1300 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
1301 :
1302 : // Get component properties
1303 0 : FlowCoef = ELR * FlowRate / propN.density * std::pow(RefPres, -FlowExpo);
1304 :
1305 : // Standard calculation.
1306 0 : if (PDROP >= 0.0) {
1307 : // Flow in positive direction.
1308 : // Laminar flow.
1309 0 : CDM = FlowCoef * propN.density / propN.viscosity;
1310 0 : FL = CDM * PDROP;
1311 : // Turbulent flow.
1312 0 : if (FlowExpo == 0.5) {
1313 0 : FT = FlowCoef * propN.sqrt_density * std::sqrt(PDROP);
1314 : } else {
1315 0 : FT = FlowCoef * propN.sqrt_density * std::pow(PDROP, FlowExpo);
1316 : }
1317 : } else {
1318 : // Flow in negative direction.
1319 : // Laminar flow.
1320 0 : CDM = FlowCoef * propM.density / propM.viscosity;
1321 0 : FL = CDM * PDROP;
1322 : // Turbulent flow.
1323 0 : if (FlowExpo == 0.5) {
1324 0 : FT = -FlowCoef * propM.sqrt_density * std::sqrt(-PDROP);
1325 : } else {
1326 0 : FT = -FlowCoef * propM.sqrt_density * std::pow(-PDROP, FlowExpo);
1327 : }
1328 : }
1329 : // Select laminar or turbulent flow.
1330 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " plr: " << i << PDROP << FL << FT;
1331 0 : if (std::abs(FL) <= std::abs(FT)) {
1332 0 : F[0] = FL;
1333 0 : DF[0] = CDM;
1334 : } else {
1335 0 : F[0] = FT;
1336 0 : DF[0] = FT * FlowExpo / PDROP;
1337 : }
1338 0 : return 1;
1339 : }
1340 :
1341 6769587 : int DetailedOpening::calculate(EnergyPlusData &state,
1342 : [[maybe_unused]] bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
1343 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
1344 : int const IL, // Linkage number
1345 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
1346 : [[maybe_unused]] const Real64 control, // Element control signal
1347 : [[maybe_unused]] const AirState &propN, // Node 1 properties
1348 : [[maybe_unused]] const AirState &propM, // Node 2 properties
1349 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
1350 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
1351 : )
1352 : {
1353 :
1354 : // SUBROUTINE INFORMATION:
1355 : // AUTHOR Lixing Gu
1356 : // DATE WRITTEN Oct. 2005
1357 : // MODIFIED na
1358 : // RE-ENGINEERED This subroutine is revised based on a vertical large opening subroutine from COMIS
1359 :
1360 : // PURPOSE OF THIS SUBROUTINE:
1361 : // This subroutine simulates airflow and pressure of a detailed large opening component.
1362 :
1363 : // METHODOLOGY EMPLOYED:
1364 : // Purpose: This routine calculates the massflow and its derivative
1365 : // through a large opening in both flow directions. As input
1366 : // the density profiles RhoProfF/T are required aswell as the
1367 : // effective pressure difference profile DpProfNew, which is the
1368 : // sum of the stack pressure difference profile DpProf and the
1369 : // difference of the actual pressures at reference height. The
1370 : // profiles are calculated in the routine PresProfile.
1371 : // The massflow and its derivative are calculated for each
1372 : // interval representing a step of the pressure difference
1373 : // profile. The total flow and derivative are obtained by
1374 : // summation over the whole opening.
1375 : // The calculation is split into different cases representing
1376 : // different situations of the opening:
1377 : // - closed opening (opening factor = 0): summation of top and
1378 : // bottom crack (crack length = lwmax) plus "integration" over
1379 : // a vertically distributed crack of length (2*lhmax+lextra).
1380 : // - type 1: normal rectangular opening: "integration" over NrInt
1381 : // openings with width actlw and height actlh/NrInt
1382 : // - type 2: horizontally pivoted window: flow direction assumed
1383 : // strictly perpendicular to the plane of the opening
1384 : // -> "integration" over normal rectangular openings at top
1385 : // and bottom of LO plus a rectangular opening in series with two
1386 : // triangular openings in the middle of the LO (most general
1387 : // situation). The geometry is defined by the input parameters
1388 : // actlw(=lwmax), actlh, axisheight, opening angle.
1389 : // Assuming the massflow perpendicular to the opening plane in all
1390 : // cases the ownheightfactor has no influence on the massflow.
1391 :
1392 : // REFERENCES:
1393 : // Helmut E. Feustel and Alison Rayner-Hooson, "COMIS Fundamentals," LBL-28560,
1394 : // Lawrence Berkeley National Laboratory, Berkeley, CA, May 1990
1395 :
1396 : // USE STATEMENTS:
1397 : // Locals
1398 : // SUBROUTINE ARGUMENT DEFINITIONS:
1399 :
1400 : // SUBROUTINE PARAMETER DEFINITIONS:
1401 6769587 : Real64 constexpr RealMin(1e-37);
1402 : static Real64 const sqrt_1_2(std::sqrt(1.2));
1403 :
1404 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1405 : static Real64 const sqrt_2(std::sqrt(2.0));
1406 :
1407 : Real64 Width;
1408 : Real64 Height;
1409 :
1410 : Real64 fma12; // massflow in direction "from-to" [kg/s]
1411 : Real64 fma21; // massflow in direction "to-from" [kg/s]
1412 : Real64 dp1fma12; // derivative d fma12 / d Dp [kg/s/Pa]
1413 : Real64 dp1fma21; // derivative d fma21 / d Dp [kg/s/Pa]
1414 6769587 : Array1D<Real64> DpProfNew(NrInt + 2); // Differential pressure profile for Large Openings, taking into account fixed
1415 : // pressures and actual zone pressures at reference height
1416 : Real64 Fact; // Actual opening factor
1417 : Real64 DifLim; // Limit for the pressure difference where laminarization takes place [Pa]
1418 : Real64 Cfact;
1419 : Real64 FvVeloc;
1420 :
1421 : Real64 ActLh;
1422 : Real64 ActLw;
1423 : Real64 Lextra;
1424 : Real64 Axishght;
1425 : Real64 ActCD;
1426 : Real64 Cs;
1427 : Real64 expn;
1428 : Real64 Type;
1429 : Real64 Interval;
1430 : Real64 fmasum;
1431 : Real64 dfmasum;
1432 : Real64 Prefact;
1433 6769587 : Array1D<Real64> EvalHghts(NrInt + 2);
1434 : Real64 h2;
1435 : Real64 h4;
1436 : Real64 alpha;
1437 : Real64 rholink;
1438 : Real64 c1;
1439 : Real64 c2;
1440 : Real64 DpZeroOffset;
1441 : Real64 area;
1442 : Real64 WFact;
1443 : Real64 HFact;
1444 : int i;
1445 : int Loc;
1446 : int iNum;
1447 :
1448 : // Get component properties
1449 6769587 : DifLim = 1.0e-4;
1450 6769587 : Width = state.afn->MultizoneSurfaceData(IL).Width;
1451 6769587 : Height = state.afn->MultizoneSurfaceData(IL).Height;
1452 6769587 : Fact = state.afn->MultizoneSurfaceData(IL).OpenFactor;
1453 6769587 : Loc = (state.afn->AirflowNetworkLinkageData(IL).DetOpenNum - 1) * (NrInt + 2);
1454 6769587 : iNum = NumFac;
1455 6769587 : ActCD = 0.0;
1456 :
1457 6769587 : if (iNum == 2) {
1458 6769587 : if (Fact <= OpenFac2) {
1459 6769587 : WFact = WidthFac1 + (Fact - OpenFac1) / (OpenFac2 - OpenFac1) * (WidthFac2 - WidthFac1);
1460 6769587 : HFact = HeightFac1 + (Fact - OpenFac1) / (OpenFac2 - OpenFac1) * (HeightFac2 - HeightFac1);
1461 6769587 : Cfact = DischCoeff1 + (Fact - OpenFac1) / (OpenFac2 - OpenFac1) * (DischCoeff2 - DischCoeff1);
1462 : } else {
1463 0 : ShowFatalError(
1464 : state,
1465 0 : "Open Factor is above the maximum input range for opening factors in AirflowNetwork:MultiZone:Component:DetailedOpening = " +
1466 0 : name);
1467 : }
1468 : }
1469 :
1470 6769587 : if (iNum == 3) {
1471 0 : if (Fact <= OpenFac2) {
1472 0 : WFact = WidthFac1 + (Fact - OpenFac1) / (OpenFac2 - OpenFac1) * (WidthFac2 - WidthFac1);
1473 0 : HFact = HeightFac1 + (Fact - OpenFac1) / (OpenFac2 - OpenFac1) * (HeightFac2 - HeightFac1);
1474 0 : Cfact = DischCoeff1 + (Fact - OpenFac1) / (OpenFac2 - OpenFac1) * (DischCoeff2 - DischCoeff1);
1475 0 : } else if (Fact <= OpenFac3) {
1476 0 : WFact = WidthFac2 + (Fact - OpenFac2) / (OpenFac3 - OpenFac2) * (WidthFac3 - WidthFac2);
1477 0 : HFact = HeightFac2 + (Fact - OpenFac2) / (OpenFac3 - OpenFac2) * (HeightFac3 - HeightFac2);
1478 0 : Cfact = DischCoeff2 + (Fact - OpenFac2) / (OpenFac3 - OpenFac2) * (DischCoeff3 - DischCoeff2);
1479 : } else {
1480 0 : ShowFatalError(
1481 : state,
1482 0 : "Open Factor is above the maximum input range for opening factors in AirflowNetwork:MultiZone:Component:DetailedOpening = " +
1483 0 : name);
1484 : }
1485 : }
1486 :
1487 6769587 : if (iNum == 4) {
1488 0 : if (Fact <= OpenFac2) {
1489 0 : WFact = WidthFac1 + (Fact - OpenFac1) / (OpenFac2 - OpenFac1) * (WidthFac2 - WidthFac1);
1490 0 : HFact = HeightFac1 + (Fact - OpenFac1) / (OpenFac2 - OpenFac1) * (HeightFac2 - HeightFac1);
1491 0 : Cfact = DischCoeff1 + (Fact - OpenFac1) / (OpenFac2 - OpenFac1) * (DischCoeff2 - DischCoeff1);
1492 0 : } else if (Fact <= OpenFac3) {
1493 0 : WFact = WidthFac2 + (Fact - OpenFac2) / (OpenFac3 - OpenFac2) * (WidthFac3 - WidthFac2);
1494 0 : HFact = HeightFac2 + (Fact - OpenFac2) / (OpenFac3 - OpenFac2) * (HeightFac3 - HeightFac2);
1495 0 : Cfact = DischCoeff2 + (Fact - OpenFac2) / (OpenFac3 - OpenFac2) * (DischCoeff3 - DischCoeff2);
1496 0 : } else if (Fact <= OpenFac4) {
1497 0 : WFact = WidthFac3 + (Fact - OpenFac3) / (OpenFac4 - OpenFac3) * (WidthFac4 - WidthFac3);
1498 0 : HFact = HeightFac3 + (Fact - OpenFac3) / (OpenFac4 - OpenFac3) * (HeightFac4 - HeightFac3);
1499 0 : Cfact = DischCoeff3 + (Fact - OpenFac3) / (OpenFac4 - OpenFac3) * (DischCoeff4 - DischCoeff3);
1500 : } else {
1501 0 : ShowFatalError(
1502 : state,
1503 0 : "Open Factor is above the maximum input range for opening factors in AirflowNetwork:MultiZone:Component:DetailedOpening = " +
1504 0 : name);
1505 : }
1506 : }
1507 :
1508 : // calculate DpProfNew
1509 155700501 : for (i = 1; i <= NrInt + 2; ++i) {
1510 148930914 : DpProfNew(i) = PDROP + state.afn->dos.DpProf(Loc + i) - state.afn->dos.DpL(IL, 1);
1511 : }
1512 :
1513 : // Get opening data based on the opening factor
1514 6769587 : if (Fact == 0) {
1515 5172227 : ActLw = state.afn->MultizoneSurfaceData(IL).Width;
1516 5172227 : ActLh = state.afn->MultizoneSurfaceData(IL).Height;
1517 5172227 : Cfact = 0.0;
1518 : } else {
1519 1597360 : ActLw = state.afn->MultizoneSurfaceData(IL).Width * WFact;
1520 1597360 : ActLh = state.afn->MultizoneSurfaceData(IL).Height * HFact;
1521 1597360 : ActCD = Cfact;
1522 : }
1523 :
1524 6769587 : Cs = FlowCoef;
1525 6769587 : expn = FlowExpo;
1526 6769587 : Type = LVOType;
1527 6769587 : if (Type == 1) {
1528 6769587 : Lextra = LVOValue;
1529 6769587 : Axishght = 0.0;
1530 0 : } else if (Type == 2) {
1531 0 : Lextra = 0.0;
1532 0 : Axishght = LVOValue;
1533 0 : ActLw = state.afn->MultizoneSurfaceData(IL).Width;
1534 0 : ActLh = state.afn->MultizoneSurfaceData(IL).Height;
1535 : }
1536 :
1537 : // Add window multiplier with window close
1538 6769587 : if (state.afn->MultizoneSurfaceData(IL).Multiplier > 1.0) {
1539 0 : Cs *= state.afn->MultizoneSurfaceData(IL).Multiplier;
1540 : }
1541 : // Add window multiplier with window open
1542 6769587 : if (Fact > 0.0) {
1543 1597360 : if (state.afn->MultizoneSurfaceData(IL).Multiplier > 1.0) {
1544 0 : ActLw *= state.afn->MultizoneSurfaceData(IL).Multiplier;
1545 : }
1546 : // Add recurring warnings
1547 1597360 : if (ActLw == 0.0) {
1548 0 : ++WidthErrCount;
1549 0 : if (WidthErrCount < 2) {
1550 0 : ShowWarningError(state, "The actual width of the AirflowNetwork:MultiZone:Component:DetailedOpening of " + name + " is 0.");
1551 0 : ShowContinueError(state, "The actual width is set to 1.0E-6 m.");
1552 0 : ShowContinueErrorTimeStamp(state, "Occurrence info:");
1553 : } else {
1554 0 : ShowRecurringWarningErrorAtEnd(state,
1555 0 : "The actual width of the AirflowNetwork:MultiZone:Component:DetailedOpening of " + name +
1556 : " is 0 error continues.",
1557 0 : WidthErrIndex,
1558 : ActLw,
1559 : ActLw);
1560 : }
1561 0 : ActLw = 1.0e-6;
1562 : }
1563 1597360 : if (ActLh == 0.0) {
1564 0 : ++HeightErrCount;
1565 0 : if (HeightErrCount < 2) {
1566 0 : ShowWarningError(state, "The actual height of the AirflowNetwork:MultiZone:Component:DetailedOpening of " + name + " is 0.");
1567 0 : ShowContinueError(state, "The actual height is set to 1.0E-6 m.");
1568 0 : ShowContinueErrorTimeStamp(state, "Occurrence info:");
1569 : } else {
1570 0 : ShowRecurringWarningErrorAtEnd(state,
1571 0 : "The actual width of the AirflowNetwork:MultiZone:Component:DetailedOpening of " + name +
1572 : " is 0 error continues.",
1573 0 : HeightErrIndex,
1574 : ActLh,
1575 : ActLh);
1576 : }
1577 0 : ActLh = 1.0e-6;
1578 : }
1579 : }
1580 : // Initialization:
1581 6769587 : int NF(1);
1582 6769587 : Interval = ActLh / NrInt;
1583 6769587 : fma12 = 0.0;
1584 6769587 : fma21 = 0.0;
1585 6769587 : dp1fma12 = 0.0;
1586 6769587 : dp1fma21 = 0.0;
1587 :
1588 : // Closed LO
1589 6769587 : if (Cfact == 0) {
1590 5172227 : DpZeroOffset = DifLim;
1591 : // bottom crack
1592 5172227 : if (DpProfNew(1) > 0) {
1593 3484370 : if (std::abs(DpProfNew(1)) <= DpZeroOffset) {
1594 757 : dfmasum = Cs * ActLw * std::pow(DpZeroOffset, expn) / DpZeroOffset;
1595 757 : fmasum = DpProfNew(1) * dfmasum;
1596 : } else {
1597 3483613 : fmasum = Cs * ActLw * std::pow(DpProfNew(1), expn);
1598 3483613 : dfmasum = fmasum * expn / DpProfNew(1);
1599 : }
1600 3484370 : fma12 += fmasum;
1601 3484370 : dp1fma12 += dfmasum;
1602 : } else {
1603 1687857 : if (std::abs(DpProfNew(1)) <= DpZeroOffset) {
1604 1050 : dfmasum = -Cs * ActLw * std::pow(DpZeroOffset, expn) / DpZeroOffset;
1605 1050 : fmasum = DpProfNew(1) * dfmasum;
1606 : } else {
1607 1686807 : fmasum = Cs * ActLw * std::pow(-DpProfNew(1), expn);
1608 1686807 : dfmasum = fmasum * expn / DpProfNew(1);
1609 : }
1610 1687857 : fma21 += fmasum;
1611 1687857 : dp1fma21 += dfmasum;
1612 : }
1613 : // top crack
1614 5172227 : if (DpProfNew(NrInt + 2) > 0) {
1615 3872621 : if (std::abs(DpProfNew(NrInt + 2)) <= DpZeroOffset) {
1616 479 : dfmasum = Cs * ActLw * std::pow(DpZeroOffset, expn) / DpZeroOffset;
1617 479 : fmasum = DpProfNew(NrInt + 2) * dfmasum;
1618 : } else {
1619 3872142 : fmasum = Cs * ActLw * std::pow(DpProfNew(NrInt + 2), expn);
1620 3872142 : dfmasum = fmasum * expn / DpProfNew(NrInt + 2);
1621 : }
1622 3872621 : fma12 += fmasum;
1623 3872621 : dp1fma12 += dfmasum;
1624 : } else {
1625 1299606 : if (std::abs(DpProfNew(NrInt + 2)) <= DpZeroOffset) {
1626 822 : dfmasum = -Cs * ActLw * std::pow(DpZeroOffset, expn) / DpZeroOffset;
1627 822 : fmasum = DpProfNew(NrInt + 2) * dfmasum;
1628 : } else {
1629 1298784 : fmasum = Cs * ActLw * std::pow(-DpProfNew(NrInt + 2), expn);
1630 1298784 : dfmasum = fmasum * expn / DpProfNew(NrInt + 2);
1631 : }
1632 1299606 : fma21 += fmasum;
1633 1299606 : dp1fma21 += dfmasum;
1634 : }
1635 : // side and extra cracks
1636 5172227 : Prefact = Interval * (2 + Lextra / ActLh) * Cs;
1637 108616767 : for (i = 2; i <= NrInt + 1; ++i) {
1638 103444540 : if (DpProfNew(i) > 0) {
1639 77737586 : if (std::abs(DpProfNew(i)) <= DpZeroOffset) {
1640 26939 : dfmasum = Prefact * std::pow(DpZeroOffset, expn) / DpZeroOffset;
1641 26939 : fmasum = DpProfNew(i) * dfmasum;
1642 : } else {
1643 77710647 : fmasum = Prefact * std::pow(DpProfNew(i), expn);
1644 77710647 : dfmasum = fmasum * expn / DpProfNew(i);
1645 : }
1646 77737586 : fma12 += fmasum;
1647 77737586 : dp1fma12 += dfmasum;
1648 : } else {
1649 25706954 : if (std::abs(DpProfNew(i)) <= DpZeroOffset) {
1650 30424 : dfmasum = -Prefact * std::pow(DpZeroOffset, expn) / DpZeroOffset;
1651 30424 : fmasum = DpProfNew(i) * dfmasum;
1652 : } else {
1653 25676530 : fmasum = Prefact * std::pow(-DpProfNew(i), expn);
1654 25676530 : dfmasum = fmasum * expn / DpProfNew(i);
1655 : }
1656 25706954 : fma21 += fmasum;
1657 25706954 : dp1fma21 += dfmasum;
1658 : }
1659 : }
1660 : }
1661 :
1662 : // Open LO, type 1
1663 6769587 : if ((Cfact != 0) && (Type == 1)) {
1664 1597360 : DpZeroOffset = DifLim * 1e-3;
1665 1597360 : Prefact = ActLw * ActCD * Interval * sqrt_2;
1666 33544560 : for (i = 2; i <= NrInt + 1; ++i) {
1667 31947200 : if (DpProfNew(i) > 0) {
1668 17931521 : if (std::abs(DpProfNew(i)) <= DpZeroOffset) {
1669 48 : dfmasum = std::sqrt(state.afn->dos.RhoProfF(Loc + i) * DpZeroOffset) / DpZeroOffset;
1670 48 : fmasum = DpProfNew(i) * dfmasum;
1671 : } else {
1672 17931473 : fmasum = std::sqrt(state.afn->dos.RhoProfF(Loc + i) * DpProfNew(i));
1673 17931473 : dfmasum = 0.5 * fmasum / DpProfNew(i);
1674 : }
1675 17931521 : fma12 += fmasum;
1676 17931521 : dp1fma12 += dfmasum;
1677 : } else {
1678 14015679 : if (std::abs(DpProfNew(i)) <= DpZeroOffset) {
1679 1547 : dfmasum = -std::sqrt(state.afn->dos.RhoProfT(Loc + i) * DpZeroOffset) / DpZeroOffset;
1680 1547 : fmasum = DpProfNew(i) * dfmasum;
1681 : } else {
1682 14014132 : fmasum = std::sqrt(-state.afn->dos.RhoProfT(Loc + i) * DpProfNew(i));
1683 14014132 : dfmasum = 0.5 * fmasum / DpProfNew(i);
1684 : }
1685 14015679 : fma21 += fmasum;
1686 14015679 : dp1fma21 += dfmasum;
1687 : }
1688 : }
1689 :
1690 1597360 : fma12 *= Prefact;
1691 1597360 : fma21 *= Prefact;
1692 1597360 : dp1fma12 *= Prefact;
1693 1597360 : dp1fma21 *= Prefact;
1694 : }
1695 :
1696 : // Open LO, type 2
1697 6769587 : if ((Cfact != 0) && (Type == 2)) {
1698 : // Initialization
1699 0 : DpZeroOffset = DifLim * 1e-3;
1700 : // New definition for opening factors for LVO type 2: opening angle = 90 degrees --> opening factor = 1.0
1701 : // should be PIOvr2 in below?
1702 0 : alpha = Fact * Constant::PiOvr2;
1703 0 : Real64 const cos_alpha(std::cos(alpha));
1704 0 : Real64 const tan_alpha(std::tan(alpha));
1705 0 : h2 = Axishght * (1.0 - cos_alpha);
1706 0 : h4 = Axishght + (ActLh - Axishght) * cos_alpha;
1707 0 : EvalHghts(1) = 0.0;
1708 0 : EvalHghts(NrInt + 2) = ActLh;
1709 : // New definition for opening factors for LVO type 2: pening angle = 90 degrees --> opening factor = 1.0
1710 0 : if (Fact == 1.0) {
1711 0 : h2 = Axishght;
1712 0 : h4 = Axishght;
1713 : }
1714 :
1715 0 : for (i = 2; i <= NrInt + 1; ++i) {
1716 0 : EvalHghts(i) = Interval * (i - 1.5);
1717 : }
1718 :
1719 : // Calculation of massflow and its derivative
1720 0 : for (i = 2; i <= NrInt + 1; ++i) {
1721 0 : if (DpProfNew(i) > 0) {
1722 0 : rholink = state.afn->dos.RhoProfF(Loc + i);
1723 : } else {
1724 0 : rholink = state.afn->dos.RhoProfT(Loc + i);
1725 : }
1726 :
1727 0 : if ((EvalHghts(i) <= h2) || (EvalHghts(i) >= h4)) {
1728 0 : if (std::abs(DpProfNew(i)) <= DpZeroOffset) {
1729 0 : dfmasum = ActCD * ActLw * Interval * std::sqrt(2.0 * rholink * DpZeroOffset) / DpZeroOffset * sign(1, DpProfNew(i));
1730 0 : fmasum = DpProfNew(i) * dfmasum;
1731 : } else {
1732 0 : fmasum = ActCD * ActLw * Interval * std::sqrt(2.0 * rholink * std::abs(DpProfNew(i)));
1733 0 : dfmasum = 0.5 * fmasum / DpProfNew(i);
1734 : }
1735 : } else {
1736 : // triangular opening at the side of LO
1737 0 : c1 = ActCD * ActLw * Interval * std::sqrt(2.0 * rholink);
1738 0 : c2 = 2 * ActCD * std::abs(Axishght - EvalHghts(i)) * tan_alpha * Interval * std::sqrt(2.0 * rholink);
1739 0 : if ((c1 != 0) && (c2 != 0)) {
1740 0 : if (std::abs(DpProfNew(i)) <= DpZeroOffset) {
1741 0 : dfmasum = std::sqrt(DpZeroOffset / (1 / c1 / c1 + 1 / c2 / c2)) / DpZeroOffset * sign(1, DpProfNew(i));
1742 0 : fmasum = DpProfNew(i) * dfmasum;
1743 : } else {
1744 0 : fmasum = std::sqrt(std::abs(DpProfNew(i)) / (1 / c1 / c1 + 1 / c2 / c2));
1745 0 : dfmasum = 0.5 * fmasum / DpProfNew(i);
1746 : }
1747 : } else {
1748 0 : fmasum = 0.0;
1749 0 : dfmasum = 0.0;
1750 : }
1751 : }
1752 :
1753 0 : if (DpProfNew(i) > 0) {
1754 0 : fma12 += fmasum;
1755 0 : dp1fma12 += dfmasum;
1756 : } else {
1757 0 : fma21 += fmasum;
1758 0 : dp1fma21 += dfmasum;
1759 : }
1760 : }
1761 : }
1762 :
1763 : // Calculate some velocity in the large opening
1764 6769587 : area = ActLh * ActLw * ActCD;
1765 6769587 : if (area > (Cs + RealMin)) {
1766 1555622 : if (area > RealMin) {
1767 1555622 : FvVeloc = (fma21 + fma12) / area;
1768 : } else {
1769 0 : FvVeloc = 0.0;
1770 : }
1771 : } else {
1772 : // here the average velocity over the full area, may blow half in half out.
1773 : // velocity= Fva/Nett area=Fma/Rho/(Cm/( (2**N)* SQRT(1.2) ) )
1774 5213965 : if (Cs > 0.0) {
1775 : // get the average Rho for this closed window
1776 109493265 : for (i = 2; i <= NrInt + 1; ++i) {
1777 : // rholink = 0.0;
1778 : // if (DpProfNew(i) > 0) {
1779 : // rholink = state.afn->dos.RhoProfF(Loc + i);
1780 : //} else {
1781 : // rholink = state.afn->dos.RhoProfT(Loc + i);
1782 : //}
1783 : // rholink /= NrInt;
1784 104279300 : rholink = 1.2;
1785 : }
1786 5213965 : FvVeloc = (fma21 + fma12) * std::pow(2.0, expn) * sqrt_1_2 / (rholink * Cs);
1787 : } else {
1788 0 : FvVeloc = 0.0;
1789 : }
1790 : }
1791 :
1792 : // Output mass flow rates and associated derivatives
1793 6769587 : F[0] = fma12 - fma21;
1794 6769587 : DF[0] = dp1fma12 - dp1fma21;
1795 6769587 : F[1] = 0.0;
1796 6769587 : if (fma12 != 0.0 && fma21 != 0.0) {
1797 1649469 : F[1] = fma21;
1798 : }
1799 6769587 : DF[1] = 0.0;
1800 6769587 : return NF;
1801 6769587 : }
1802 :
1803 2499220 : int SimpleOpening::calculate(EnergyPlusData &state,
1804 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
1805 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
1806 : int const i, // Linkage number
1807 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
1808 : [[maybe_unused]] const Real64 control, // Element control signal
1809 : const AirState &propN, // Node 1 properties
1810 : const AirState &propM, // Node 2 properties
1811 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
1812 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
1813 : )
1814 : {
1815 :
1816 : // SUBROUTINE INFORMATION:
1817 : // AUTHOR George Walton
1818 : // DATE WRITTEN Extracted from AIRNET
1819 : // MODIFIED Lixing Gu, 2/1/04
1820 : // Revised the subroutine to meet E+ needs
1821 : // MODIFIED Lixing Gu, 6/8/05
1822 : // RE-ENGINEERED na
1823 :
1824 : // PURPOSE OF THIS SUBROUTINE:
1825 : // This subroutine solves airflow for a Doorway airflow component using standard interface.
1826 : // A doorway may have two-way airflows. Heights measured relative to the bottom of the door.
1827 :
1828 : // SUBROUTINE PARAMETER DEFINITIONS:
1829 : // Replace this with the value from numbers when we have C++20
1830 2499220 : Real64 constexpr SQRT2(1.414213562373095);
1831 :
1832 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1833 : Real64 DPMID; // pressure drop at mid-height of doorway.
1834 : Real64 C;
1835 : Real64 DF0; // derivative factor at the bottom of the door.
1836 : Real64 DFH; // derivative factor at the top of the door.
1837 : Real64 DRHO; // difference in air densities between rooms.
1838 : Real64 GDRHO;
1839 : Real64 F0; // flow factor at the bottom of the door.
1840 : Real64 FH; // flow factor at the top of the door.
1841 : Real64 Y; // height of neutral plane rel. to bottom of door (m).
1842 : Real64 coeff;
1843 : Real64 Width;
1844 : Real64 Height;
1845 : Real64 OpenFactor;
1846 :
1847 2499220 : int NF(1);
1848 :
1849 : // Formats
1850 : // static gio::Fmt Format_900("(A5,9X,4E16.7)");
1851 : // static gio::Fmt Format_903("(A5,3I3,4E16.7)");
1852 :
1853 2499220 : Width = state.afn->MultizoneSurfaceData(i).Width;
1854 2499220 : Height = state.afn->MultizoneSurfaceData(i).Height;
1855 2499220 : coeff = FlowCoef * 2.0 * (Width + Height);
1856 2499220 : OpenFactor = state.afn->MultizoneSurfaceData(i).OpenFactor;
1857 2499220 : if (OpenFactor > 0.0) {
1858 377558 : Width *= OpenFactor;
1859 377558 : if (state.dataSurface->Surface(state.afn->MultizoneSurfaceData(i).SurfNum).Tilt < 90.0) {
1860 0 : Height *= state.dataSurface->Surface(state.afn->MultizoneSurfaceData(i).SurfNum).SinTilt;
1861 : }
1862 : }
1863 :
1864 2499220 : if (PDROP >= 0.0) {
1865 1557765 : coeff /= propN.sqrt_density;
1866 : } else {
1867 941455 : coeff /= propM.sqrt_density;
1868 : }
1869 :
1870 : // Add window multiplier with window close
1871 2499220 : if (state.afn->MultizoneSurfaceData(i).Multiplier > 1.0) {
1872 0 : coeff *= state.afn->MultizoneSurfaceData(i).Multiplier;
1873 : }
1874 : // Add window multiplier with window open
1875 2499220 : if (OpenFactor > 0.0) {
1876 377558 : if (state.afn->MultizoneSurfaceData(i).Multiplier > 1.0) {
1877 0 : Width *= state.afn->MultizoneSurfaceData(i).Multiplier;
1878 : }
1879 : }
1880 :
1881 2499220 : DRHO = propN.density - propM.density;
1882 2499220 : GDRHO = 9.8 * DRHO;
1883 : // if (LIST >= 4) gio::write(Unit21, Format_903) << " DOR:" << i << n << m << PDROP << std::abs(DRHO) << MinRhoDiff;
1884 2499220 : if (OpenFactor == 0.0) {
1885 2121662 : generic_crack(coeff, FlowExpo, LFLAG, PDROP, propN, propM, F, DF);
1886 2121662 : return 1;
1887 : }
1888 377558 : if (std::abs(DRHO) < MinRhoDiff || LFLAG) {
1889 3949 : DPMID = PDROP - 0.5 * Height * GDRHO;
1890 : // Initialization or identical temps: treat as one-way flow.
1891 3949 : NF = 1;
1892 3949 : generic_crack(coeff, FlowExpo, LFLAG, DPMID, propN, propM, F, DF);
1893 : // if (LIST >= 4) gio::write(Unit21, Format_900) << " Drs:" << DPMID << F[0] << DF[0];
1894 : } else {
1895 : // Possible two-way flow:
1896 373609 : Y = PDROP / GDRHO;
1897 : // if (LIST >= 4) gio::write(Unit21, Format_900) << " DrY:" << PDROP << GDRHO << Y;
1898 : // F0 = lower flow, FH = upper flow.
1899 373609 : C = SQRT2 * Width * DischCoeff;
1900 373609 : DF0 = C * std::sqrt(std::abs(PDROP)) / std::abs(GDRHO);
1901 : // F0 = 0.666667d0*C*SQRT(ABS(GDRHO*Y))*ABS(Y)
1902 373609 : F0 = (2.0 / 3.0) * C * std::sqrt(std::abs(GDRHO * Y)) * std::abs(Y);
1903 373609 : DFH = C * std::sqrt(std::abs((Height - Y) / GDRHO));
1904 : // FH = 0.666667d0*DFH*ABS(GDRHO*(Height-Y))
1905 373609 : FH = (2.0 / 3.0) * DFH * std::abs(GDRHO * (Height - Y));
1906 : // if (LIST >= 4) gio::write(Unit21, Format_900) << " DrF:" << F0 << DF0 << FH << DFH;
1907 373609 : if (Y <= 0.0) {
1908 : // One-way flow (negative).
1909 87745 : if (DRHO >= 0.0) {
1910 42261 : F[0] = -propM.sqrt_density * std::abs(FH - F0);
1911 42261 : DF[0] = propM.sqrt_density * std::abs(DFH - DF0);
1912 : } else {
1913 45484 : F[0] = propN.sqrt_density * std::abs(FH - F0);
1914 45484 : DF[0] = propN.sqrt_density * std::abs(DFH - DF0);
1915 : }
1916 : // if (LIST >= 4) gio::write(Unit21, Format_900) << " Dr1:" << C << F[0] << DF[0];
1917 285864 : } else if (Y >= Height) {
1918 : // One-way flow (positive).
1919 253110 : if (DRHO >= 0.0) {
1920 242646 : F[0] = propN.sqrt_density * std::abs(FH - F0);
1921 242646 : DF[0] = propN.sqrt_density * std::abs(DFH - DF0);
1922 : } else {
1923 10464 : F[0] = -propM.sqrt_density * std::abs(FH - F0);
1924 10464 : DF[0] = propM.sqrt_density * std::abs(DFH - DF0);
1925 : }
1926 : // if (LIST >= 4) gio::write(Unit21, Format_900) << " Dr2:" << C << F[0] << DF[0];
1927 : } else {
1928 : // Two-way flow.
1929 32754 : NF = 2;
1930 32754 : if (DRHO >= 0.0) {
1931 7752 : F[0] = -propM.sqrt_density * FH;
1932 7752 : DF[0] = propM.sqrt_density * DFH;
1933 7752 : F[1] = propN.sqrt_density * F0;
1934 7752 : DF[1] = propN.sqrt_density * DF0;
1935 : } else {
1936 25002 : F[0] = propN.sqrt_density * FH;
1937 25002 : DF[0] = propN.sqrt_density * DFH;
1938 25002 : F[1] = -propM.sqrt_density * F0;
1939 25002 : DF[1] = propM.sqrt_density * DF0;
1940 : }
1941 : // if (LIST >= 4) gio::write(Unit21, Format_900) << " Dr3:" << C << F[0] << DF[0];
1942 : // if (LIST >= 4) gio::write(Unit21, Format_900) << " Dr4:" << C << F[1] << DF[1];
1943 : }
1944 : }
1945 377558 : return NF;
1946 : }
1947 :
1948 1822110 : int ConstantPressureDrop::calculate([[maybe_unused]] EnergyPlusData &state,
1949 : [[maybe_unused]] bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
1950 : const Real64 PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
1951 : int const i, // Linkage number
1952 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
1953 : [[maybe_unused]] const Real64 control, // Element control signal
1954 : const AirState &propN, // Node 1 properties
1955 : [[maybe_unused]] const AirState &propM, // Node 2 properties
1956 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
1957 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
1958 : )
1959 : {
1960 :
1961 : // SUBROUTINE INFORMATION:
1962 : // AUTHOR George Walton
1963 : // DATE WRITTEN Extracted from AIRNET
1964 : // MODIFIED Lixing Gu, 2/1/04
1965 : // Revised the subroutine to meet E+ needs
1966 : // MODIFIED Lixing Gu, 6/8/05
1967 :
1968 : // PURPOSE OF THIS SUBROUTINE:
1969 : // This subroutine solves airflow for a Constant pressure drop component
1970 :
1971 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1972 : // Real64 Co;
1973 :
1974 1822110 : int n = state.afn->AirflowNetworkLinkageData(i).NodeNums[0];
1975 1822110 : int m = state.afn->AirflowNetworkLinkageData(i).NodeNums[1];
1976 :
1977 : // Get component properties
1978 : // A = Cross section area [m2]
1979 : // DP = Pressure difference across the element [Pa]
1980 :
1981 1822110 : if (PDROP == 0.0) {
1982 112885 : F[0] = std::sqrt(2.0 * propN.density) * A * std::sqrt(DP);
1983 112885 : DF[0] = 0.5 * F[0] / DP;
1984 : } else {
1985 35143796 : for (int k = 1; k <= state.afn->ActualNumOfLinks; ++k) {
1986 35143796 : if (state.afn->AirflowNetworkLinkageData(k).NodeNums[1] == n) {
1987 1709225 : F[0] = state.afn->AFLOW(k);
1988 1709225 : break;
1989 : }
1990 : }
1991 1709225 : state.afn->PZ(m) = state.afn->PZ(n) - DP;
1992 : // Co = F[0] / DP; // can be deleted since it is not used
1993 1709225 : DF[0] = 10.e10;
1994 : }
1995 1822110 : return 1;
1996 : }
1997 :
1998 22112523 : int EffectiveLeakageArea::calculate([[maybe_unused]] EnergyPlusData &state,
1999 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
2000 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
2001 : [[maybe_unused]] int const i, // Linkage number
2002 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
2003 : [[maybe_unused]] const Real64 control, // Element control signal
2004 : const AirState &propN, // Node 1 properties
2005 : const AirState &propM, // Node 2 properties
2006 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
2007 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
2008 : )
2009 : {
2010 :
2011 : // SUBROUTINE INFORMATION:
2012 : // AUTHOR George Walton
2013 : // DATE WRITTEN Extracted from AIRNET
2014 : // MODIFIED Lixing Gu, 2/1/04
2015 : // Revised the subroutine to meet E+ needs
2016 : // MODIFIED Lixing Gu, 6/8/05
2017 : // RE-ENGINEERED na
2018 :
2019 : // PURPOSE OF THIS SUBROUTINE:
2020 : // This subroutine solves airflow for a Surface effective leakage area component
2021 :
2022 : // SUBROUTINE PARAMETER DEFINITIONS:
2023 : static Real64 const sqrt_2(std::sqrt(2.0));
2024 :
2025 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2026 : Real64 CDM;
2027 : Real64 FL;
2028 : Real64 FT;
2029 : Real64 FlowCoef;
2030 :
2031 : // Formats
2032 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
2033 :
2034 : // Get component properties
2035 22112523 : FlowCoef = ELA * DischCoeff * sqrt_2 * std::pow(RefDeltaP, 0.5 - FlowExpo);
2036 :
2037 22112523 : if (LFLAG) {
2038 : // Initialization by linear relation.
2039 0 : if (PDROP >= 0.0) {
2040 0 : DF[0] = FlowCoef * propN.density / propN.viscosity;
2041 : } else {
2042 0 : DF[0] = FlowCoef * propM.density / propM.viscosity;
2043 : }
2044 0 : F[0] = -DF[0] * PDROP;
2045 : } else {
2046 : // Standard calculation.
2047 22112523 : if (PDROP >= 0.0) {
2048 : // Flow in positive direction.
2049 : // Laminar flow.
2050 11658845 : CDM = FlowCoef * propN.density / propN.viscosity;
2051 11658845 : FL = CDM * PDROP;
2052 : // Turbulent flow.
2053 11658845 : if (FlowExpo == 0.5) {
2054 0 : FT = FlowCoef * propN.sqrt_density * std::sqrt(PDROP);
2055 : } else {
2056 11658845 : FT = FlowCoef * propN.sqrt_density * std::pow(PDROP, FlowExpo);
2057 : }
2058 : } else {
2059 : // Flow in negative direction.
2060 : // Laminar flow.
2061 10453678 : CDM = FlowCoef * propM.density / propM.viscosity;
2062 10453678 : FL = CDM * PDROP;
2063 : // Turbulent flow.
2064 10453678 : if (FlowExpo == 0.5) {
2065 0 : FT = -FlowCoef * propM.sqrt_density * std::sqrt(-PDROP);
2066 : } else {
2067 10453678 : FT = -FlowCoef * propM.sqrt_density * std::pow(-PDROP, FlowExpo);
2068 : }
2069 : }
2070 : // Select laminar or turbulent flow.
2071 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " plr: " << i << PDROP << FL << FT;
2072 22112523 : if (std::abs(FL) <= std::abs(FT)) {
2073 447 : F[0] = FL;
2074 447 : DF[0] = CDM;
2075 : } else {
2076 22112076 : F[0] = FT;
2077 22112076 : DF[0] = FT * FlowExpo / PDROP;
2078 : }
2079 : }
2080 22112523 : return 1;
2081 : }
2082 :
2083 0 : int EffectiveLeakageArea::calculate([[maybe_unused]] EnergyPlusData &state,
2084 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
2085 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
2086 : [[maybe_unused]] const Real64 control, // Element control signal
2087 : const AirState &propN, // Node 1 properties
2088 : const AirState &propM, // Node 2 properties
2089 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
2090 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
2091 : )
2092 : {
2093 :
2094 : // SUBROUTINE INFORMATION:
2095 : // AUTHOR George Walton
2096 : // DATE WRITTEN Extracted from AIRNET
2097 : // MODIFIED Lixing Gu, 2/1/04
2098 : // Revised the subroutine to meet E+ needs
2099 : // MODIFIED Lixing Gu, 6/8/05
2100 : // RE-ENGINEERED na
2101 :
2102 : // PURPOSE OF THIS SUBROUTINE:
2103 : // This subroutine solves airflow for a Surface effective leakage area component
2104 :
2105 : // SUBROUTINE PARAMETER DEFINITIONS:
2106 : static Real64 const sqrt_2(std::sqrt(2.0));
2107 :
2108 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2109 : Real64 CDM;
2110 : Real64 FL;
2111 : Real64 FT;
2112 : Real64 FlowCoef;
2113 :
2114 : // Formats
2115 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
2116 :
2117 : // Get component properties
2118 0 : FlowCoef = ELA * DischCoeff * sqrt_2 * std::pow(RefDeltaP, 0.5 - FlowExpo);
2119 :
2120 : // Standard calculation.
2121 0 : if (PDROP >= 0.0) {
2122 : // Flow in positive direction.
2123 : // Laminar flow.
2124 0 : CDM = FlowCoef * propN.density / propN.viscosity;
2125 0 : FL = CDM * PDROP;
2126 : // Turbulent flow.
2127 0 : if (FlowExpo == 0.5) {
2128 0 : FT = FlowCoef * propN.sqrt_density * std::sqrt(PDROP);
2129 : } else {
2130 0 : FT = FlowCoef * propN.sqrt_density * std::pow(PDROP, FlowExpo);
2131 : }
2132 : } else {
2133 : // Flow in negative direction.
2134 : // Laminar flow.
2135 0 : CDM = FlowCoef * propM.density / propM.viscosity;
2136 0 : FL = CDM * PDROP;
2137 : // Turbulent flow.
2138 0 : if (FlowExpo == 0.5) {
2139 0 : FT = -FlowCoef * propM.sqrt_density * std::sqrt(-PDROP);
2140 : } else {
2141 0 : FT = -FlowCoef * propM.sqrt_density * std::pow(-PDROP, FlowExpo);
2142 : }
2143 : }
2144 : // Select laminar or turbulent flow.
2145 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " plr: " << i << PDROP << FL << FT;
2146 0 : if (std::abs(FL) <= std::abs(FT)) {
2147 0 : F[0] = FL;
2148 0 : DF[0] = CDM;
2149 : } else {
2150 0 : F[0] = FT;
2151 0 : DF[0] = FT * FlowExpo / PDROP;
2152 : }
2153 :
2154 0 : return 1;
2155 : }
2156 :
2157 13811441 : int DisSysCompCoilProp::calculate([[maybe_unused]] EnergyPlusData &state,
2158 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
2159 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
2160 : [[maybe_unused]] int const i, // Linkage number
2161 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
2162 : [[maybe_unused]] const Real64 control, // Element control signal
2163 : const AirState &propN, // Node 1 properties
2164 : const AirState &propM, // Node 2 properties
2165 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
2166 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
2167 : )
2168 : {
2169 :
2170 : // SUBROUTINE INFORMATION:
2171 : // AUTHOR George Walton
2172 : // DATE WRITTEN Extracted from AIRNET
2173 : // MODIFIED Lixing Gu, 2/1/04
2174 : // Revised the subroutine to meet E+ needs
2175 : // MODIFIED Lixing Gu, 6/8/05
2176 : // RE-ENGINEERED na
2177 :
2178 : // PURPOSE OF THIS SUBROUTINE:
2179 : // This subroutine solves airflow for a coil component
2180 :
2181 : // SUBROUTINE PARAMETER DEFINITIONS:
2182 13811441 : Real64 constexpr C(0.868589);
2183 13811441 : Real64 constexpr EPS(0.001);
2184 13811441 : Real64 constexpr Rough(0.0001);
2185 13811441 : Real64 constexpr InitLamCoef(128.0);
2186 13811441 : Real64 constexpr LamDynCoef(64.0);
2187 13811441 : Real64 constexpr LamFriCoef(0.0001);
2188 13811441 : Real64 constexpr TurDynCoef(0.0001);
2189 :
2190 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2191 : Real64 A0;
2192 : Real64 A1;
2193 : Real64 A2;
2194 : Real64 B;
2195 : Real64 D;
2196 : Real64 S2;
2197 : Real64 CDM;
2198 : Real64 FL;
2199 : Real64 FT;
2200 : Real64 FTT;
2201 : Real64 RE;
2202 : Real64 ed;
2203 : Real64 ld;
2204 : Real64 g;
2205 : Real64 AA1;
2206 : Real64 area;
2207 :
2208 : // Formats
2209 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
2210 :
2211 : // Get component properties
2212 : // ed = Rough / DisSysCompCoilData(CompNum).hydraulicDiameter;
2213 13811441 : ed = Rough / hydraulicDiameter;
2214 :
2215 13811441 : area = square(hydraulicDiameter) * Constant::Pi;
2216 13811441 : ld = L / hydraulicDiameter;
2217 13811441 : g = 1.14 - 0.868589 * std::log(ed);
2218 13811441 : AA1 = g;
2219 :
2220 13811441 : if (LFLAG) {
2221 : // Initialization by linear relation.
2222 0 : if (PDROP >= 0.0) {
2223 0 : DF[0] = (2.0 * propN.density * area * hydraulicDiameter) / (propN.viscosity * InitLamCoef * ld);
2224 : } else {
2225 0 : DF[0] = (2.0 * propM.density * area * hydraulicDiameter) / (propM.viscosity * InitLamCoef * ld);
2226 : }
2227 0 : F[0] = -DF[0] * PDROP;
2228 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwi:" << i << InitLamCoef << F[0] << DF[0];
2229 : } else {
2230 : // Standard calculation.
2231 13811441 : if (PDROP >= 0.0) {
2232 : // Flow in positive direction.
2233 : // Laminar flow coefficient !=0
2234 : if (LamFriCoef >= 0.001) {
2235 : A2 = LamFriCoef / (2.0 * propN.density * area * area);
2236 : A1 = (propN.viscosity * LamDynCoef * ld) / (2.0 * propN.density * area * hydraulicDiameter);
2237 : A0 = -PDROP;
2238 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
2239 : FL = (CDM - A1) / (2.0 * A2);
2240 : CDM = 1.0 / CDM;
2241 : } else {
2242 12082105 : CDM = (2.0 * propN.density * area * hydraulicDiameter) / (propN.viscosity * LamDynCoef * ld);
2243 12082105 : FL = CDM * PDROP;
2244 : }
2245 12082105 : RE = FL * hydraulicDiameter / (propN.viscosity * area);
2246 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwl:" << i << PDROP << FL << CDM << RE;
2247 : // Turbulent flow; test when Re>10.
2248 12082105 : if (RE >= 10.0) {
2249 11559961 : S2 = std::sqrt(2.0 * propN.density * PDROP) * area;
2250 11559961 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2251 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << S2 << FTT << g;
2252 : while (true) {
2253 44447844 : FT = FTT;
2254 44447844 : B = (9.3 * propN.viscosity * area) / (FT * Rough);
2255 44447844 : D = 1.0 + g * B;
2256 44447844 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
2257 44447844 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2258 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << B << FTT << g;
2259 44447844 : if (std::abs(FTT - FT) / FTT < EPS) {
2260 11559961 : break;
2261 : }
2262 : }
2263 11559961 : FT = FTT;
2264 : } else {
2265 522144 : FT = FL;
2266 : }
2267 : } else {
2268 : // Flow in negative direction.
2269 : // Laminar flow coefficient !=0
2270 : if (LamFriCoef >= 0.001) {
2271 : A2 = LamFriCoef / (2.0 * propM.density * area * area);
2272 : A1 = (propM.viscosity * LamDynCoef * ld) / (2.0 * propM.density * area * hydraulicDiameter);
2273 : A0 = PDROP;
2274 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
2275 : FL = -(CDM - A1) / (2.0 * A2);
2276 : CDM = 1.0 / CDM;
2277 : } else {
2278 1729336 : CDM = (2.0 * propM.density * area * hydraulicDiameter) / (propM.viscosity * LamDynCoef * ld);
2279 1729336 : FL = CDM * PDROP;
2280 : }
2281 1729336 : RE = -FL * hydraulicDiameter / (propM.viscosity * area);
2282 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwl:" << i << PDROP << FL << CDM << RE;
2283 : // Turbulent flow; test when Re>10.
2284 1729336 : if (RE >= 10.0) {
2285 1702992 : S2 = std::sqrt(-2.0 * propM.density * PDROP) * area;
2286 1702992 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2287 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << S2 << FTT << g;
2288 : while (true) {
2289 4782824 : FT = FTT;
2290 4782824 : B = (9.3 * propM.viscosity * area) / (FT * Rough);
2291 4782824 : D = 1.0 + g * B;
2292 4782824 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
2293 4782824 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2294 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << B << FTT << g;
2295 4782824 : if (std::abs(FTT - FT) / FTT < EPS) {
2296 1702992 : break;
2297 : }
2298 : }
2299 1702992 : FT = -FTT;
2300 : } else {
2301 26344 : FT = FL;
2302 : }
2303 : }
2304 : // Select laminar or turbulent flow.
2305 13811441 : if (std::abs(FL) <= std::abs(FT)) {
2306 556138 : F[0] = FL;
2307 556138 : DF[0] = CDM;
2308 : } else {
2309 13255303 : F[0] = FT;
2310 13255303 : DF[0] = 0.5 * FT / PDROP;
2311 : }
2312 : }
2313 13811441 : return 1;
2314 : }
2315 :
2316 0 : int DisSysCompCoilProp::calculate([[maybe_unused]] EnergyPlusData &state,
2317 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
2318 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
2319 : [[maybe_unused]] const Real64 control, // Element control signal
2320 : const AirState &propN, // Node 1 properties
2321 : const AirState &propM, // Node 2 properties
2322 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
2323 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
2324 : )
2325 : {
2326 :
2327 : // SUBROUTINE INFORMATION:
2328 : // AUTHOR George Walton
2329 : // DATE WRITTEN Extracted from AIRNET
2330 : // MODIFIED Lixing Gu, 2/1/04
2331 : // Revised the subroutine to meet E+ needs
2332 : // MODIFIED Lixing Gu, 6/8/05
2333 : // RE-ENGINEERED na
2334 :
2335 : // PURPOSE OF THIS SUBROUTINE:
2336 : // This subroutine solves airflow for a coil component
2337 :
2338 : // SUBROUTINE PARAMETER DEFINITIONS:
2339 0 : Real64 constexpr C(0.868589);
2340 0 : Real64 constexpr EPS(0.001);
2341 0 : Real64 constexpr Rough(0.0001);
2342 0 : Real64 constexpr LamDynCoef(64.0);
2343 0 : Real64 constexpr LamFriCoef(0.0001);
2344 0 : Real64 constexpr TurDynCoef(0.0001);
2345 :
2346 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2347 : Real64 A0;
2348 : Real64 A1;
2349 : Real64 A2;
2350 : Real64 B;
2351 : Real64 D;
2352 : Real64 S2;
2353 : Real64 CDM;
2354 : Real64 FL;
2355 : Real64 FT;
2356 : Real64 FTT;
2357 : Real64 RE;
2358 : Real64 ed;
2359 : Real64 ld;
2360 : Real64 g;
2361 : Real64 AA1;
2362 : Real64 area;
2363 :
2364 : // Formats
2365 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
2366 :
2367 : // Get component properties
2368 : // ed = Rough / DisSysCompCoilData(CompNum).hydraulicDiameter;
2369 0 : ed = Rough / hydraulicDiameter;
2370 :
2371 0 : area = square(hydraulicDiameter) * Constant::Pi;
2372 0 : ld = L / hydraulicDiameter;
2373 0 : g = 1.14 - 0.868589 * std::log(ed);
2374 0 : AA1 = g;
2375 :
2376 : // Standard calculation.
2377 0 : if (PDROP >= 0.0) {
2378 : // Flow in positive direction.
2379 : // Laminar flow coefficient !=0
2380 : if (LamFriCoef >= 0.001) {
2381 : A2 = LamFriCoef / (2.0 * propN.density * area * area);
2382 : A1 = (propN.viscosity * LamDynCoef * ld) / (2.0 * propN.density * area * hydraulicDiameter);
2383 : A0 = -PDROP;
2384 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
2385 : FL = (CDM - A1) / (2.0 * A2);
2386 : CDM = 1.0 / CDM;
2387 : } else {
2388 0 : CDM = (2.0 * propN.density * area * hydraulicDiameter) / (propN.viscosity * LamDynCoef * ld);
2389 0 : FL = CDM * PDROP;
2390 : }
2391 0 : RE = FL * hydraulicDiameter / (propN.viscosity * area);
2392 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwl:" << i << PDROP << FL << CDM << RE;
2393 : // Turbulent flow; test when Re>10.
2394 0 : if (RE >= 10.0) {
2395 0 : S2 = std::sqrt(2.0 * propN.density * PDROP) * area;
2396 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2397 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << S2 << FTT << g;
2398 : while (true) {
2399 0 : FT = FTT;
2400 0 : B = (9.3 * propN.viscosity * area) / (FT * Rough);
2401 0 : D = 1.0 + g * B;
2402 0 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
2403 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2404 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << B << FTT << g;
2405 0 : if (std::abs(FTT - FT) / FTT < EPS) {
2406 0 : break;
2407 : }
2408 : }
2409 0 : FT = FTT;
2410 : } else {
2411 0 : FT = FL;
2412 : }
2413 : } else {
2414 : // Flow in negative direction.
2415 : // Laminar flow coefficient !=0
2416 : if (LamFriCoef >= 0.001) {
2417 : A2 = LamFriCoef / (2.0 * propM.density * area * area);
2418 : A1 = (propM.viscosity * LamDynCoef * ld) / (2.0 * propM.density * area * hydraulicDiameter);
2419 : A0 = PDROP;
2420 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
2421 : FL = -(CDM - A1) / (2.0 * A2);
2422 : CDM = 1.0 / CDM;
2423 : } else {
2424 0 : CDM = (2.0 * propM.density * area * hydraulicDiameter) / (propM.viscosity * LamDynCoef * ld);
2425 0 : FL = CDM * PDROP;
2426 : }
2427 0 : RE = -FL * hydraulicDiameter / (propM.viscosity * area);
2428 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwl:" << i << PDROP << FL << CDM << RE;
2429 : // Turbulent flow; test when Re>10.
2430 0 : if (RE >= 10.0) {
2431 0 : S2 = std::sqrt(-2.0 * propM.density * PDROP) * area;
2432 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2433 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << S2 << FTT << g;
2434 : while (true) {
2435 0 : FT = FTT;
2436 0 : B = (9.3 * propM.viscosity * area) / (FT * Rough);
2437 0 : D = 1.0 + g * B;
2438 0 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
2439 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2440 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << B << FTT << g;
2441 0 : if (std::abs(FTT - FT) / FTT < EPS) {
2442 0 : break;
2443 : }
2444 : }
2445 0 : FT = -FTT;
2446 : } else {
2447 0 : FT = FL;
2448 : }
2449 : }
2450 : // Select laminar or turbulent flow.
2451 0 : if (std::abs(FL) <= std::abs(FT)) {
2452 0 : F[0] = FL;
2453 0 : DF[0] = CDM;
2454 : } else {
2455 0 : F[0] = FT;
2456 0 : DF[0] = 0.5 * FT / PDROP;
2457 : }
2458 0 : return 1;
2459 : }
2460 :
2461 3053955 : int DisSysCompTermUnitProp::calculate([[maybe_unused]] EnergyPlusData &state,
2462 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
2463 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
2464 : int const i, // Linkage number
2465 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
2466 : [[maybe_unused]] const Real64 control, // Element control signal
2467 : const AirState &propN, // Node 1 properties
2468 : const AirState &propM, // Node 2 properties
2469 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
2470 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
2471 : )
2472 : {
2473 :
2474 : // SUBROUTINE INFORMATION:
2475 : // AUTHOR George Walton
2476 : // DATE WRITTEN Extracted from AIRNET
2477 : // MODIFIED Lixing Gu, 2/1/04
2478 : // Revised the subroutine to meet E+ needs
2479 : // MODIFIED Lixing Gu, 6/8/05
2480 : // RE-ENGINEERED na
2481 :
2482 : // PURPOSE OF THIS SUBROUTINE:
2483 : // This subroutine solves airflow for a terminal unit component
2484 :
2485 : // SUBROUTINE PARAMETER DEFINITIONS:
2486 3053955 : Real64 constexpr C(0.868589);
2487 3053955 : Real64 constexpr EPS(0.001);
2488 3053955 : Real64 constexpr Rough(0.0001);
2489 3053955 : Real64 constexpr InitLamCoef(128.0);
2490 3053955 : Real64 constexpr LamDynCoef(64.0);
2491 3053955 : Real64 constexpr LamFriCoef(0.0001);
2492 3053955 : Real64 constexpr TurDynCoef(0.0001);
2493 :
2494 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2495 : Real64 A0;
2496 : Real64 A1;
2497 : Real64 A2;
2498 : Real64 B;
2499 : Real64 D;
2500 : Real64 S2;
2501 : Real64 CDM;
2502 : Real64 FL;
2503 : Real64 FT;
2504 : Real64 FTT;
2505 : Real64 RE;
2506 : Real64 ed;
2507 : Real64 ld;
2508 : Real64 g;
2509 : Real64 AA1;
2510 : Real64 area;
2511 :
2512 : // Formats
2513 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
2514 :
2515 : // Get component properties
2516 3053955 : ed = Rough / hydraulicDiameter;
2517 3053955 : area = pow_2(hydraulicDiameter) * Constant::Pi;
2518 3053955 : ld = L / hydraulicDiameter;
2519 3053955 : g = 1.14 - 0.868589 * std::log(ed);
2520 3053955 : AA1 = g;
2521 :
2522 3053955 : if (LFLAG) {
2523 : // Initialization by linear relation.
2524 0 : if (PDROP >= 0.0) {
2525 0 : DF[0] = (2.0 * propN.density * area * hydraulicDiameter) / (propN.viscosity * InitLamCoef * ld);
2526 : } else {
2527 0 : DF[0] = (2.0 * propM.density * area * hydraulicDiameter) / (propM.viscosity * InitLamCoef * ld);
2528 : }
2529 0 : F[0] = -DF[0] * PDROP;
2530 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwi:" << i << InitLamCoef << F[0] << DF[0];
2531 : } else {
2532 : // Standard calculation.
2533 3053955 : if (PDROP >= 0.0) {
2534 : // Flow in positive direction.
2535 : // Laminar flow coefficient !=0
2536 : if (LamFriCoef >= 0.001) {
2537 : A2 = LamFriCoef / (2.0 * propN.density * area * area);
2538 : A1 = (propN.viscosity * LamDynCoef * ld) / (2.0 * propN.density * area * hydraulicDiameter);
2539 : A0 = -PDROP;
2540 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
2541 : FL = (CDM - A1) / (2.0 * A2);
2542 : CDM = 1.0 / CDM;
2543 : } else {
2544 2623937 : CDM = (2.0 * propN.density * area * hydraulicDiameter) / (propN.viscosity * LamDynCoef * ld);
2545 2623937 : FL = CDM * PDROP;
2546 : }
2547 2623937 : RE = FL * hydraulicDiameter / (propN.viscosity * area);
2548 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwl:" << i << PDROP << FL << CDM << RE;
2549 : // Turbulent flow; test when Re>10.
2550 2623937 : if (RE >= 10.0) {
2551 2582792 : S2 = std::sqrt(2.0 * propN.density * PDROP) * area;
2552 2582792 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2553 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << S2 << FTT << g;
2554 : while (true) {
2555 10056555 : FT = FTT;
2556 10056555 : B = (9.3 * propN.viscosity * area) / (FT * Rough);
2557 10056555 : D = 1.0 + g * B;
2558 10056555 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
2559 10056555 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2560 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << B << FTT << g;
2561 10056555 : if (std::abs(FTT - FT) / FTT < EPS) {
2562 2582792 : break;
2563 : }
2564 : }
2565 2582792 : FT = FTT;
2566 : } else {
2567 41145 : FT = FL;
2568 : }
2569 : } else {
2570 : // Flow in negative direction.
2571 : // Laminar flow coefficient !=0
2572 : if (LamFriCoef >= 0.001) {
2573 : A2 = LamFriCoef / (2.0 * propM.density * area * area);
2574 : A1 = (propM.viscosity * LamDynCoef * ld) / (2.0 * propM.density * area * hydraulicDiameter);
2575 : A0 = PDROP;
2576 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
2577 : FL = -(CDM - A1) / (2.0 * A2);
2578 : CDM = 1.0 / CDM;
2579 : } else {
2580 430018 : CDM = (2.0 * propM.density * area * hydraulicDiameter) / (propM.viscosity * LamDynCoef * ld);
2581 430018 : FL = CDM * PDROP;
2582 : }
2583 430018 : RE = -FL * hydraulicDiameter / (propM.viscosity * area);
2584 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwl:" << i << PDROP << FL << CDM << RE;
2585 : // Turbulent flow; test when Re>10.
2586 430018 : if (RE >= 10.0) {
2587 366931 : S2 = std::sqrt(-2.0 * propM.density * PDROP) * area;
2588 366931 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2589 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << S2 << FTT << g;
2590 : while (true) {
2591 1214527 : FT = FTT;
2592 1214527 : B = (9.3 * propM.viscosity * area) / (FT * Rough);
2593 1214527 : D = 1.0 + g * B;
2594 1214527 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
2595 1214527 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2596 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " dwt:" << i << B << FTT << g;
2597 1214527 : if (std::abs(FTT - FT) / FTT < EPS) {
2598 366931 : break;
2599 : }
2600 : }
2601 366931 : FT = -FTT;
2602 : } else {
2603 63087 : FT = FL;
2604 : }
2605 : }
2606 : // Select laminar or turbulent flow.
2607 3053955 : if (std::abs(FL) <= std::abs(FT)) {
2608 123274 : F[0] = FL;
2609 123274 : DF[0] = CDM;
2610 : } else {
2611 2930681 : F[0] = FT;
2612 2930681 : DF[0] = 0.5 * FT / PDROP;
2613 : }
2614 : }
2615 : // If damper, setup the airflows from nodal values calculated from terminal
2616 3053955 : if (state.afn->AirflowNetworkLinkageData(i).VAVTermDamper) {
2617 147432 : F[0] = state.dataLoopNodes->Node(DamperInletNode).MassFlowRate;
2618 147432 : if (state.afn->VAVTerminalRatio > 0.0) {
2619 0 : F[0] *= state.afn->VAVTerminalRatio;
2620 : }
2621 147432 : DF[0] = 0.0;
2622 : }
2623 3053955 : return 1;
2624 : }
2625 :
2626 725824 : int DisSysCompHXProp::calculate([[maybe_unused]] EnergyPlusData &state,
2627 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
2628 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
2629 : [[maybe_unused]] int const i, // Linkage number
2630 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
2631 : [[maybe_unused]] const Real64 control, // Element control signal
2632 : const AirState &propN, // Node 1 properties
2633 : const AirState &propM, // Node 2 properties
2634 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
2635 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
2636 : )
2637 : {
2638 :
2639 : // SUBROUTINE INFORMATION:
2640 : // AUTHOR George Walton
2641 : // DATE WRITTEN Extracted from AIRNET
2642 : // MODIFIED Lixing Gu, 2/1/04
2643 : // Revised the subroutine to meet E+ needs
2644 : // MODIFIED Lixing Gu, 1/18/09
2645 : // RE-ENGINEERED na
2646 :
2647 : // PURPOSE OF THIS SUBROUTINE:
2648 : // This subroutine solves airflow for a heat exchanger component
2649 :
2650 : // SUBROUTINE PARAMETER DEFINITIONS:
2651 725824 : Real64 constexpr C(0.868589);
2652 725824 : Real64 constexpr EPS(0.001);
2653 725824 : Real64 constexpr Rough(0.0001);
2654 725824 : Real64 constexpr InitLamCoef(128.0);
2655 725824 : Real64 constexpr LamDynCoef(64.0);
2656 725824 : Real64 constexpr LamFriCoef(0.0001);
2657 725824 : Real64 constexpr TurDynCoef(0.0001);
2658 :
2659 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2660 : Real64 A0;
2661 : Real64 A1;
2662 : Real64 A2;
2663 : Real64 B;
2664 : Real64 D;
2665 : Real64 S2;
2666 : Real64 CDM;
2667 : Real64 FL;
2668 : Real64 FT;
2669 : Real64 FTT;
2670 : Real64 RE;
2671 : Real64 ed;
2672 : Real64 ld;
2673 : Real64 g;
2674 : Real64 AA1;
2675 : Real64 area;
2676 :
2677 : // Get component properties
2678 725824 : ed = Rough / hydraulicDiameter;
2679 725824 : area = pow_2(hydraulicDiameter) * Constant::Pi;
2680 725824 : ld = L / hydraulicDiameter;
2681 725824 : g = 1.14 - 0.868589 * std::log(ed);
2682 725824 : AA1 = g;
2683 :
2684 725824 : if (LFLAG) {
2685 : // Initialization by linear relation.
2686 0 : if (PDROP >= 0.0) {
2687 0 : DF[0] = (2.0 * propN.density * area * hydraulicDiameter) / (propN.viscosity * InitLamCoef * ld);
2688 : } else {
2689 0 : DF[0] = (2.0 * propM.density * area * hydraulicDiameter) / (propM.viscosity * InitLamCoef * ld);
2690 : }
2691 0 : F[0] = -DF[0] * PDROP;
2692 : } else {
2693 : // Standard calculation.
2694 725824 : if (PDROP >= 0.0) {
2695 : // Flow in positive direction.
2696 : // Laminar flow coefficient !=0
2697 : if (LamFriCoef >= 0.001) {
2698 : A2 = LamFriCoef / (2.0 * propN.density * area * area);
2699 : A1 = (propN.viscosity * LamDynCoef * ld) / (2.0 * propN.density * area * hydraulicDiameter);
2700 : A0 = -PDROP;
2701 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
2702 : FL = (CDM - A1) / (2.0 * A2);
2703 : CDM = 1.0 / CDM;
2704 : } else {
2705 659617 : CDM = (2.0 * propN.density * area * hydraulicDiameter) / (propN.viscosity * LamDynCoef * ld);
2706 659617 : FL = CDM * PDROP;
2707 : }
2708 659617 : RE = FL * hydraulicDiameter / (propN.viscosity * area);
2709 : // Turbulent flow; test when Re>10.
2710 659617 : if (RE >= 10.0) {
2711 621585 : S2 = std::sqrt(2.0 * propN.density * PDROP) * area;
2712 621585 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2713 : while (true) {
2714 2425738 : FT = FTT;
2715 2425738 : B = (9.3 * propN.viscosity * area) / (FT * Rough);
2716 2425738 : D = 1.0 + g * B;
2717 2425738 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
2718 2425738 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2719 2425738 : if (std::abs(FTT - FT) / FTT < EPS) {
2720 621585 : break;
2721 : }
2722 : }
2723 621585 : FT = FTT;
2724 : } else {
2725 38032 : FT = FL;
2726 : }
2727 : } else {
2728 : // Flow in negative direction.
2729 : // Laminar flow coefficient !=0
2730 : if (LamFriCoef >= 0.001) {
2731 : A2 = LamFriCoef / (2.0 * propM.density * area * area);
2732 : A1 = (propM.viscosity * LamDynCoef * ld) / (2.0 * propM.density * area * hydraulicDiameter);
2733 : A0 = PDROP;
2734 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
2735 : FL = -(CDM - A1) / (2.0 * A2);
2736 : CDM = 1.0 / CDM;
2737 : } else {
2738 66207 : CDM = (2.0 * propM.density * area * hydraulicDiameter) / (propM.viscosity * LamDynCoef * ld);
2739 66207 : FL = CDM * PDROP;
2740 : }
2741 66207 : RE = -FL * hydraulicDiameter / (propM.viscosity * area);
2742 : // Turbulent flow; test when Re>10.
2743 66207 : if (RE >= 10.0) {
2744 66207 : S2 = std::sqrt(-2.0 * propM.density * PDROP) * area;
2745 66207 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2746 : while (true) {
2747 212024 : FT = FTT;
2748 212024 : B = (9.3 * propM.viscosity * area) / (FT * Rough);
2749 212024 : D = 1.0 + g * B;
2750 212024 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
2751 212024 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2752 212024 : if (std::abs(FTT - FT) / FTT < EPS) {
2753 66207 : break;
2754 : }
2755 : }
2756 66207 : FT = -FTT;
2757 : } else {
2758 0 : FT = FL;
2759 : }
2760 : }
2761 : // Select laminar or turbulent flow.
2762 725824 : if (std::abs(FL) <= std::abs(FT)) {
2763 38032 : F[0] = FL;
2764 38032 : DF[0] = CDM;
2765 : } else {
2766 687792 : F[0] = FT;
2767 687792 : DF[0] = 0.5 * FT / PDROP;
2768 : }
2769 : }
2770 725824 : return 1;
2771 : }
2772 :
2773 0 : int DisSysCompHXProp::calculate([[maybe_unused]] EnergyPlusData &state,
2774 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
2775 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
2776 : [[maybe_unused]] const Real64 control, // Element control signal
2777 : const AirState &propN, // Node 1 properties
2778 : const AirState &propM, // Node 2 properties
2779 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
2780 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
2781 : )
2782 : {
2783 :
2784 : // SUBROUTINE INFORMATION:
2785 : // AUTHOR George Walton
2786 : // DATE WRITTEN Extracted from AIRNET
2787 : // MODIFIED Lixing Gu, 2/1/04
2788 : // Revised the subroutine to meet E+ needs
2789 : // MODIFIED Lixing Gu, 1/18/09
2790 : // RE-ENGINEERED na
2791 :
2792 : // PURPOSE OF THIS SUBROUTINE:
2793 : // This subroutine solves airflow for a heat exchanger component
2794 :
2795 : // SUBROUTINE PARAMETER DEFINITIONS:
2796 0 : Real64 constexpr C(0.868589);
2797 0 : Real64 constexpr EPS(0.001);
2798 0 : Real64 constexpr Rough(0.0001);
2799 0 : Real64 constexpr LamDynCoef(64.0);
2800 0 : Real64 constexpr LamFriCoef(0.0001);
2801 0 : Real64 constexpr TurDynCoef(0.0001);
2802 :
2803 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2804 : Real64 A0;
2805 : Real64 A1;
2806 : Real64 A2;
2807 : Real64 B;
2808 : Real64 D;
2809 : Real64 S2;
2810 : Real64 CDM;
2811 : Real64 FL;
2812 : Real64 FT;
2813 : Real64 FTT;
2814 : Real64 RE;
2815 : Real64 ed;
2816 : Real64 ld;
2817 : Real64 g;
2818 : Real64 AA1;
2819 : Real64 area;
2820 :
2821 : // Get component properties
2822 0 : ed = Rough / hydraulicDiameter;
2823 0 : area = pow_2(hydraulicDiameter) * Constant::Pi;
2824 0 : ld = L / hydraulicDiameter;
2825 0 : g = 1.14 - 0.868589 * std::log(ed);
2826 0 : AA1 = g;
2827 :
2828 : // Standard calculation.
2829 0 : if (PDROP >= 0.0) {
2830 : // Flow in positive direction.
2831 : // Laminar flow coefficient !=0
2832 : if (LamFriCoef >= 0.001) {
2833 : A2 = LamFriCoef / (2.0 * propN.density * area * area);
2834 : A1 = (propN.viscosity * LamDynCoef * ld) / (2.0 * propN.density * area * hydraulicDiameter);
2835 : A0 = -PDROP;
2836 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
2837 : FL = (CDM - A1) / (2.0 * A2);
2838 : CDM = 1.0 / CDM;
2839 : } else {
2840 0 : CDM = (2.0 * propN.density * area * hydraulicDiameter) / (propN.viscosity * LamDynCoef * ld);
2841 0 : FL = CDM * PDROP;
2842 : }
2843 0 : RE = FL * hydraulicDiameter / (propN.viscosity * area);
2844 : // Turbulent flow; test when Re>10.
2845 0 : if (RE >= 10.0) {
2846 0 : S2 = std::sqrt(2.0 * propN.density * PDROP) * area;
2847 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2848 : while (true) {
2849 0 : FT = FTT;
2850 0 : B = (9.3 * propN.viscosity * area) / (FT * Rough);
2851 0 : D = 1.0 + g * B;
2852 0 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
2853 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2854 0 : if (std::abs(FTT - FT) / FTT < EPS) {
2855 0 : break;
2856 : }
2857 : }
2858 0 : FT = FTT;
2859 : } else {
2860 0 : FT = FL;
2861 : }
2862 : } else {
2863 : // Flow in negative direction.
2864 : // Laminar flow coefficient !=0
2865 : if (LamFriCoef >= 0.001) {
2866 : A2 = LamFriCoef / (2.0 * propM.density * area * area);
2867 : A1 = (propM.viscosity * LamDynCoef * ld) / (2.0 * propM.density * area * hydraulicDiameter);
2868 : A0 = PDROP;
2869 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
2870 : FL = -(CDM - A1) / (2.0 * A2);
2871 : CDM = 1.0 / CDM;
2872 : } else {
2873 0 : CDM = (2.0 * propM.density * area * hydraulicDiameter) / (propM.viscosity * LamDynCoef * ld);
2874 0 : FL = CDM * PDROP;
2875 : }
2876 0 : RE = -FL * hydraulicDiameter / (propM.viscosity * area);
2877 : // Turbulent flow; test when Re>10.
2878 0 : if (RE >= 10.0) {
2879 0 : S2 = std::sqrt(-2.0 * propM.density * PDROP) * area;
2880 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2881 : while (true) {
2882 0 : FT = FTT;
2883 0 : B = (9.3 * propM.viscosity * area) / (FT * Rough);
2884 0 : D = 1.0 + g * B;
2885 0 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
2886 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
2887 0 : if (std::abs(FTT - FT) / FTT < EPS) {
2888 0 : break;
2889 : }
2890 : }
2891 0 : FT = -FTT;
2892 : } else {
2893 0 : FT = FL;
2894 : }
2895 : }
2896 : // Select laminar or turbulent flow.
2897 0 : if (std::abs(FL) <= std::abs(FT)) {
2898 0 : F[0] = FL;
2899 0 : DF[0] = CDM;
2900 : } else {
2901 0 : F[0] = FT;
2902 0 : DF[0] = 0.5 * FT / PDROP;
2903 : }
2904 0 : return 1;
2905 : }
2906 :
2907 3950300 : int ZoneExhaustFan::calculate(EnergyPlusData &state,
2908 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
2909 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
2910 : int const i, // Linkage number
2911 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
2912 : [[maybe_unused]] const Real64 control, // Element control signal
2913 : const AirState &propN, // Node 1 properties
2914 : const AirState &propM, // Node 2 properties
2915 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
2916 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
2917 : )
2918 : {
2919 : // SUBROUTINE INFORMATION:
2920 : // AUTHOR George Walton
2921 : // DATE WRITTEN Extracted from AIRNET
2922 : // MODIFIED Lixing Gu, 12/17/06
2923 : // Revised for zone exhaust fan
2924 : // RE-ENGINEERED na
2925 :
2926 : // PURPOSE OF THIS SUBROUTINE:
2927 : // This subroutine solves airflow for a surface crack component
2928 :
2929 : // Using/Aliasing
2930 : using HVAC::VerySmallMassFlow;
2931 :
2932 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2933 : Real64 CDM;
2934 : Real64 FL;
2935 : Real64 FT;
2936 : Real64 RhozNorm;
2937 : Real64 VisczNorm;
2938 : Real64 expn;
2939 : Real64 Ctl;
2940 : Real64 coef;
2941 : Real64 Corr;
2942 : Real64 VisAve;
2943 : Real64 Tave;
2944 : Real64 RhoCor;
2945 : // int InletNode;
2946 :
2947 : // Formats
2948 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
2949 :
2950 3950300 : if (state.dataLoopNodes->Node(InletNode).MassFlowRate > VerySmallMassFlow) {
2951 : // Treat the component as an exhaust fan
2952 3441420 : if (state.afn->PressureSetFlag == PressureCtrlExhaust) {
2953 0 : F[0] = state.afn->ExhaustFanMassFlowRate;
2954 : } else {
2955 3441420 : F[0] = state.dataLoopNodes->Node(InletNode).MassFlowRate;
2956 : }
2957 3441420 : DF[0] = 0.0;
2958 3441420 : return 1;
2959 : } else {
2960 : // Treat the component as a surface crack
2961 : // Crack standard condition from given inputs
2962 508880 : Corr = state.afn->MultizoneSurfaceData(i).Factor;
2963 508880 : RhozNorm = state.afn->properties.density(StandardP, StandardT, StandardW);
2964 508880 : VisczNorm = 1.71432e-5 + 4.828e-8 * StandardT;
2965 :
2966 508880 : expn = FlowExpo;
2967 508880 : VisAve = (propN.viscosity + propM.viscosity) / 2.0;
2968 508880 : Tave = (propN.temperature + propM.temperature) / 2.0;
2969 508880 : if (PDROP >= 0.0) {
2970 231320 : coef = FlowCoef / propN.sqrt_density * Corr;
2971 : } else {
2972 277560 : coef = FlowCoef / propM.sqrt_density * Corr;
2973 : }
2974 :
2975 508880 : if (LFLAG) {
2976 : // Initialization by linear relation.
2977 0 : if (PDROP >= 0.0) {
2978 0 : RhoCor = TOKELVIN(propN.temperature) / TOKELVIN(Tave);
2979 0 : Ctl = std::pow(RhozNorm / propN.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
2980 0 : DF[0] = coef * propN.density / propN.viscosity * Ctl;
2981 : } else {
2982 0 : RhoCor = TOKELVIN(propM.temperature) / TOKELVIN(Tave);
2983 0 : Ctl = std::pow(RhozNorm / propM.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
2984 0 : DF[0] = coef * propM.density / propM.viscosity * Ctl;
2985 : }
2986 0 : F[0] = -DF[0] * PDROP;
2987 : } else {
2988 : // Standard calculation.
2989 508880 : if (PDROP >= 0.0) {
2990 : // Flow in positive direction.
2991 : // Laminar flow.
2992 231320 : RhoCor = TOKELVIN(propN.temperature) / TOKELVIN(Tave);
2993 231320 : Ctl = std::pow(RhozNorm / propN.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
2994 231320 : CDM = coef * propN.density / propN.viscosity * Ctl;
2995 231320 : FL = CDM * PDROP;
2996 : // Turbulent flow.
2997 231320 : if (expn == 0.5) {
2998 0 : FT = coef * propN.sqrt_density * std::sqrt(PDROP) * Ctl;
2999 : } else {
3000 231320 : FT = coef * propN.sqrt_density * std::pow(PDROP, expn) * Ctl;
3001 : }
3002 : } else {
3003 : // Flow in negative direction.
3004 : // Laminar flow.
3005 277560 : RhoCor = TOKELVIN(propM.temperature) / TOKELVIN(Tave);
3006 277560 : Ctl = std::pow(RhozNorm / propM.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
3007 277560 : CDM = coef * propM.density / propM.viscosity * Ctl;
3008 277560 : FL = CDM * PDROP;
3009 : // Turbulent flow.
3010 277560 : if (expn == 0.5) {
3011 0 : FT = -coef * propM.sqrt_density * std::sqrt(-PDROP) * Ctl;
3012 : } else {
3013 277560 : FT = -coef * propM.sqrt_density * std::pow(-PDROP, expn) * Ctl;
3014 : }
3015 : }
3016 : // Select laminar or turbulent flow.
3017 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " scr: " << i << PDROP << FL << FT;
3018 508880 : if (std::abs(FL) <= std::abs(FT)) {
3019 0 : F[0] = FL;
3020 0 : DF[0] = CDM;
3021 : } else {
3022 508880 : F[0] = FT;
3023 508880 : DF[0] = FT * expn / PDROP;
3024 : }
3025 : }
3026 : }
3027 508880 : return 1;
3028 : }
3029 :
3030 0 : int ZoneExhaustFan::calculate(EnergyPlusData &state,
3031 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
3032 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
3033 : const Real64 control, // Element control signal
3034 : const AirState &propN, // Node 1 properties
3035 : const AirState &propM, // Node 2 properties
3036 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
3037 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
3038 : )
3039 : {
3040 : // SUBROUTINE INFORMATION:
3041 : // AUTHOR George Walton
3042 : // DATE WRITTEN Extracted from AIRNET
3043 : // MODIFIED Lixing Gu, 12/17/06
3044 : // Revised for zone exhaust fan
3045 : // RE-ENGINEERED na
3046 :
3047 : // PURPOSE OF THIS SUBROUTINE:
3048 : // This subroutine solves airflow for a surface crack component
3049 :
3050 : // Using/Aliasing
3051 : using HVAC::VerySmallMassFlow;
3052 :
3053 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3054 : Real64 CDM;
3055 : Real64 FL;
3056 : Real64 FT;
3057 : Real64 RhozNorm;
3058 : Real64 VisczNorm;
3059 : Real64 expn;
3060 : Real64 Ctl;
3061 : Real64 coef;
3062 : Real64 VisAve;
3063 : Real64 Tave;
3064 : Real64 RhoCor;
3065 : // int InletNode;
3066 :
3067 : // Formats
3068 : // static gio::Fmt Format_901("(A5,I3,6X,4E16.7)");
3069 :
3070 0 : if (state.dataLoopNodes->Node(InletNode).MassFlowRate > VerySmallMassFlow) {
3071 : // Treat the component as an exhaust fan
3072 0 : if (state.afn->PressureSetFlag == PressureCtrlExhaust) {
3073 0 : F[0] = state.afn->ExhaustFanMassFlowRate;
3074 : } else {
3075 0 : F[0] = state.dataLoopNodes->Node(InletNode).MassFlowRate;
3076 : }
3077 0 : DF[0] = 0.0;
3078 0 : return 1;
3079 : } else {
3080 : // Treat the component as a surface crack
3081 : // Crack standard condition from given inputs
3082 0 : RhozNorm = state.afn->properties.density(StandardP, StandardT, StandardW);
3083 0 : VisczNorm = 1.71432e-5 + 4.828e-8 * StandardT;
3084 :
3085 0 : expn = FlowExpo;
3086 0 : VisAve = (propN.viscosity + propM.viscosity) / 2.0;
3087 0 : Tave = (propN.temperature + propM.temperature) / 2.0;
3088 0 : if (PDROP >= 0.0) {
3089 0 : coef = control * FlowCoef / propN.sqrt_density;
3090 : } else {
3091 0 : coef = control * FlowCoef / propM.sqrt_density;
3092 : }
3093 :
3094 : // Standard calculation.
3095 0 : if (PDROP >= 0.0) {
3096 : // Flow in positive direction.
3097 : // Laminar flow.
3098 0 : RhoCor = TOKELVIN(propN.temperature) / TOKELVIN(Tave);
3099 0 : Ctl = std::pow(RhozNorm / propN.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
3100 0 : CDM = coef * propN.density / propN.viscosity * Ctl;
3101 0 : FL = CDM * PDROP;
3102 : // Turbulent flow.
3103 0 : if (expn == 0.5) {
3104 0 : FT = coef * propN.sqrt_density * std::sqrt(PDROP) * Ctl;
3105 : } else {
3106 0 : FT = coef * propN.sqrt_density * std::pow(PDROP, expn) * Ctl;
3107 : }
3108 : } else {
3109 : // Flow in negative direction.
3110 : // Laminar flow.
3111 0 : RhoCor = TOKELVIN(propM.temperature) / TOKELVIN(Tave);
3112 0 : Ctl = std::pow(RhozNorm / propM.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
3113 0 : CDM = coef * propM.density / propM.viscosity * Ctl;
3114 0 : FL = CDM * PDROP;
3115 : // Turbulent flow.
3116 0 : if (expn == 0.5) {
3117 0 : FT = -coef * propM.sqrt_density * std::sqrt(-PDROP) * Ctl;
3118 : } else {
3119 0 : FT = -coef * propM.sqrt_density * std::pow(-PDROP, expn) * Ctl;
3120 : }
3121 : }
3122 : // Select laminar or turbulent flow.
3123 : // if (LIST >= 4) gio::write(Unit21, Format_901) << " scr: " << i << PDROP << FL << FT;
3124 0 : if (std::abs(FL) <= std::abs(FT)) {
3125 0 : F[0] = FL;
3126 0 : DF[0] = CDM;
3127 : } else {
3128 0 : F[0] = FT;
3129 0 : DF[0] = FT * expn / PDROP;
3130 : }
3131 : }
3132 0 : return 1;
3133 : }
3134 :
3135 110859 : int HorizontalOpening::calculate(EnergyPlusData &state,
3136 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
3137 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
3138 : int const i, // Linkage number
3139 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
3140 : [[maybe_unused]] const Real64 control, // Element control signal
3141 : const AirState &propN, // Node 1 properties
3142 : const AirState &propM, // Node 2 properties
3143 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
3144 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
3145 : )
3146 : {
3147 : // SUBROUTINE INFORMATION:
3148 : // AUTHOR Lixing Gu
3149 : // DATE WRITTEN Apr. 2009
3150 : // MODIFIED na
3151 : // MODIFIED na
3152 : // RE-ENGINEERED na
3153 :
3154 : // PURPOSE OF THIS SUBROUTINE:
3155 : // This subroutine solves airflow for a horizontal opening component. The subroutine was
3156 : // developed based on the subroutine AFEPLR of AIRNET.
3157 :
3158 : // METHODOLOGY EMPLOYED:
3159 : // Combine forced and buyancy airflows together with a cap
3160 :
3161 : // REFERENCES:
3162 : // Cooper, L., 1989, "Calculation of the Flow Through a Horizontal Ceiling/Floor Vent,"
3163 : // NISTIR 89-4052, National Institute of Standards and Technology, Gaithersburg, MD
3164 :
3165 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3166 : Real64 RhozAver;
3167 : Real64 expn;
3168 : Real64 coef;
3169 : Real64 Width; // Opening width
3170 : Real64 Height; // Opening height
3171 : Real64 Fact; // Opening factor
3172 : // Real64 Slope; // Opening slope
3173 : // Real64 DischCoeff; // Discharge coefficient
3174 : Real64 fma12; // massflow in direction "from-to" [kg/s]
3175 : Real64 fma21; // massflow in direction "to-from" [kg/s]
3176 : Real64 dp1fma12; // derivative d fma12 / d Dp [kg/s/Pa]
3177 : Real64 dp1fma21; // derivative d fma21 / d Dp [kg/s/Pa]
3178 : Real64 PurgedP; // Purge pressure [Pa]
3179 : Real64 BuoFlow; // Buoyancy flow rate [Pa]
3180 : Real64 BuoFlowMax; // Maximum buoyancy flow rate [Pa]
3181 : Real64 dPBuoFlow; // Derivative of buoyancy flow rate [kg/s/Pa]
3182 : Real64 DH; // Hydraulic diameter [m]
3183 : Real64 Cshape; // Shape factor [dimensionless]
3184 : Real64 OpenArea; // Opening area [m2]
3185 :
3186 : // Get information on the horizontal opening
3187 110859 : RhozAver = (propN.density + propM.density) / 2.0;
3188 110859 : Width = state.afn->MultizoneSurfaceData(i).Width;
3189 110859 : Height = state.afn->MultizoneSurfaceData(i).Height;
3190 110859 : Fact = state.afn->MultizoneSurfaceData(i).OpenFactor;
3191 110859 : expn = FlowExpo;
3192 110859 : coef = FlowCoef;
3193 : // Slope = MultizoneCompHorOpeningData(CompNum).Slope;
3194 : // DischCoeff = MultizoneCompHorOpeningData(CompNum).DischCoeff;
3195 110859 : Cshape = 0.942 * Width / Height;
3196 110859 : OpenArea = Width * Height * Fact * std::sin(Slope * Constant::Pi / 180.0) * (1.0 + std::cos(Slope * Constant::Pi / 180.0));
3197 110859 : DH = 4.0 * (Width * Height) / 2.0 / (Width + Height) * Fact;
3198 :
3199 : // Check which zone is higher
3200 110859 : if (Fact == 0.0) {
3201 0 : generic_crack(coef, expn, LFLAG, PDROP, propN, propM, F, DF);
3202 0 : return 1;
3203 : }
3204 :
3205 110859 : fma12 = 0.0;
3206 110859 : fma21 = 0.0;
3207 110859 : dp1fma12 = 0.0;
3208 110859 : dp1fma21 = 0.0;
3209 110859 : BuoFlow = 0.0;
3210 110859 : dPBuoFlow = 0.0;
3211 :
3212 110859 : if (state.afn->AirflowNetworkLinkageData(i).NodeHeights[0] > state.afn->AirflowNetworkLinkageData(i).NodeHeights[1]) {
3213 : // Node N is upper zone
3214 110859 : if (propN.density > propM.density) {
3215 80284 : BuoFlowMax = RhozAver * 0.055 * std::sqrt(9.81 * std::abs(propN.density - propM.density) * pow_5(DH) / RhozAver);
3216 80284 : PurgedP = Cshape * Cshape * 9.81 * std::abs(propN.density - propM.density) * pow_5(DH) / (2.0 * pow_2(OpenArea));
3217 80284 : if (std::abs(PDROP) <= PurgedP) {
3218 80281 : BuoFlow = BuoFlowMax * (1.0 - std::abs(PDROP) / PurgedP);
3219 80281 : dPBuoFlow = BuoFlowMax / PurgedP;
3220 : }
3221 : }
3222 : } else {
3223 : // Node M is upper zone
3224 0 : if (propN.density < propM.density) {
3225 0 : BuoFlowMax = RhozAver * 0.055 * std::sqrt(9.81 * std::abs(propN.density - propM.density) * pow_5(DH) / RhozAver);
3226 0 : PurgedP = Cshape * Cshape * 9.81 * std::abs(propN.density - propM.density) * pow_5(DH) / (2.0 * pow_2(OpenArea));
3227 0 : if (std::abs(PDROP) <= PurgedP) {
3228 0 : BuoFlow = BuoFlowMax * (1.0 - std::abs(PDROP) / PurgedP);
3229 0 : dPBuoFlow = BuoFlowMax / PurgedP;
3230 : }
3231 : }
3232 : }
3233 :
3234 110859 : if (PDROP == 0.0) {
3235 0 : fma12 = BuoFlow;
3236 0 : fma21 = BuoFlow;
3237 0 : dp1fma12 = 0.0;
3238 0 : dp1fma21 = 0.0;
3239 110859 : } else if (PDROP > 0.0) {
3240 42038 : fma12 = propN.density * OpenArea * Fact * DischCoeff * std::sqrt(2.0 * PDROP / RhozAver) + BuoFlow;
3241 42038 : dp1fma12 = propN.density * OpenArea * DischCoeff / std::sqrt(2.0 * PDROP * RhozAver) + dPBuoFlow;
3242 42038 : if (BuoFlow > 0.0) {
3243 27914 : fma21 = BuoFlow;
3244 27914 : dp1fma21 = dPBuoFlow;
3245 : }
3246 : } else { // PDROP.LT.0.0
3247 68821 : fma21 = propM.density * OpenArea * Fact * DischCoeff * std::sqrt(2.0 * std::abs(PDROP) / RhozAver) + BuoFlow;
3248 68821 : dp1fma21 = -propM.density * OpenArea * DischCoeff / std::sqrt(2.0 * std::abs(PDROP) * RhozAver) + dPBuoFlow;
3249 68821 : if (BuoFlow > 0.0) {
3250 52367 : fma12 = BuoFlow;
3251 52367 : dp1fma12 = dPBuoFlow;
3252 : }
3253 : }
3254 :
3255 110859 : F[0] = fma12 - fma21;
3256 110859 : DF[0] = dp1fma12 - dp1fma21;
3257 110859 : F[1] = 0.0;
3258 110859 : if (fma12 != 0.0 && fma21 != 0.0) {
3259 80281 : F[1] = BuoFlow;
3260 : }
3261 110859 : DF[1] = 0.0;
3262 :
3263 110859 : return 1;
3264 : }
3265 :
3266 105624 : int SpecifiedMassFlow::calculate([[maybe_unused]] EnergyPlusData &state,
3267 : [[maybe_unused]] bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
3268 : [[maybe_unused]] Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
3269 : [[maybe_unused]] int const i, // Linkage number
3270 : const Real64 multiplier, // Element multiplier
3271 : const Real64 control, // Element control signal
3272 : [[maybe_unused]] const AirState &propN, // Node 1 properties
3273 : [[maybe_unused]] const AirState &propM, // Node 2 properties
3274 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
3275 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
3276 : )
3277 : {
3278 : // SUBROUTINE INFORMATION:
3279 : // AUTHOR Jason DeGraw and Prateek Shrestha
3280 : // DATE WRITTEN June 2021
3281 : // MODIFIED na
3282 : // MODIFIED na
3283 : // RE-ENGINEERED na
3284 :
3285 : // PURPOSE OF THIS SUBROUTINE:
3286 : // This subroutine computes airflow for a specified mass flow element.
3287 :
3288 105624 : F[0] = mass_flow * control * multiplier;
3289 105624 : DF[0] = 0.0;
3290 105624 : F[1] = 0.0;
3291 105624 : DF[1] = 0.0;
3292 :
3293 105624 : return 1;
3294 : }
3295 :
3296 0 : int SpecifiedVolumeFlow::calculate([[maybe_unused]] EnergyPlusData &state,
3297 : [[maybe_unused]] bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
3298 : [[maybe_unused]] Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
3299 : [[maybe_unused]] int const i, // Linkage number
3300 : const Real64 multiplier, // Element multiplier
3301 : const Real64 control, // Element control signal
3302 : const AirState &propN, // Node 1 properties
3303 : const AirState &propM, // Node 2 properties
3304 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
3305 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
3306 : )
3307 : {
3308 : // SUBROUTINE INFORMATION:
3309 : // AUTHOR Jason DeGraw and Prateek Shrestha
3310 : // DATE WRITTEN June 2021
3311 : // MODIFIED na
3312 : // MODIFIED na
3313 : // RE-ENGINEERED na
3314 :
3315 : // PURPOSE OF THIS SUBROUTINE:
3316 : // This subroutine computes airflow for a specified volume flow element.
3317 :
3318 0 : Real64 flow = volume_flow * control * multiplier;
3319 :
3320 0 : Real64 upwind_density{propN.density};
3321 :
3322 0 : if (flow < 0.0) {
3323 0 : upwind_density = propM.density;
3324 : }
3325 :
3326 0 : F[0] = flow * upwind_density;
3327 0 : DF[0] = 0.0;
3328 0 : F[1] = 0.0;
3329 0 : DF[1] = 0.0;
3330 :
3331 0 : return 1;
3332 : }
3333 :
3334 888893 : int OutdoorAirFan::calculate(EnergyPlusData &state,
3335 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
3336 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
3337 : int const i, // Linkage number
3338 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
3339 : [[maybe_unused]] const Real64 control, // Element control signal
3340 : const AirState &propN, // Node 1 properties
3341 : const AirState &propM, // Node 2 properties
3342 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
3343 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
3344 : )
3345 : {
3346 :
3347 : // PURPOSE OF THIS SUBROUTINE:
3348 : // This subroutine solves airflow for a constant flow rate airflow component -- using standard interface.
3349 :
3350 : // Using/Aliasing
3351 : using HVAC::VerySmallMassFlow;
3352 :
3353 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3354 : Real64 expn;
3355 : Real64 Ctl;
3356 : Real64 coef;
3357 : Real64 Corr;
3358 : Real64 VisAve;
3359 : Real64 Tave;
3360 : Real64 RhoCor;
3361 : // int InletNode;
3362 : Real64 RhozNorm;
3363 : Real64 VisczNorm;
3364 : Real64 CDM;
3365 : Real64 FL;
3366 : Real64 FT;
3367 :
3368 888893 : int AirLoopNum = state.afn->AirflowNetworkLinkageData(i).AirLoopNum;
3369 :
3370 888893 : if (state.dataLoopNodes->Node(InletNode).MassFlowRate > VerySmallMassFlow) {
3371 : // Treat the component as an exhaust fan
3372 888893 : F[0] = state.dataLoopNodes->Node(InletNode).MassFlowRate;
3373 888893 : DF[0] = 0.0;
3374 888893 : if (state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopFanOperationMode == HVAC::FanOp::Cycling &&
3375 0 : state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio > 0.0) {
3376 0 : F[0] = F[0] / state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio;
3377 : }
3378 888893 : return 1;
3379 : } else {
3380 : // Treat the component as a surface crack
3381 : // Crack standard condition from given inputs
3382 0 : Corr = 1.0;
3383 0 : RhozNorm = state.afn->properties.density(StandardP, StandardT, StandardW);
3384 0 : VisczNorm = 1.71432e-5 + 4.828e-8 * StandardT;
3385 :
3386 0 : expn = FlowExpo;
3387 0 : VisAve = (propN.viscosity + propM.viscosity) / 2.0;
3388 0 : Tave = (propN.temperature + propM.temperature) / 2.0;
3389 0 : if (PDROP >= 0.0) {
3390 0 : coef = FlowCoef / propN.sqrt_density * Corr;
3391 : } else {
3392 0 : coef = FlowCoef / propM.sqrt_density * Corr;
3393 : }
3394 :
3395 0 : if (LFLAG) {
3396 : // Initialization by linear relation.
3397 0 : if (PDROP >= 0.0) {
3398 0 : RhoCor = TOKELVIN(propN.temperature) / TOKELVIN(Tave);
3399 0 : Ctl = std::pow(RhozNorm / propN.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
3400 0 : DF[0] = coef * propN.density / propN.viscosity * Ctl;
3401 : } else {
3402 0 : RhoCor = TOKELVIN(propM.temperature) / TOKELVIN(Tave);
3403 0 : Ctl = std::pow(RhozNorm / propM.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
3404 0 : DF[0] = coef * propM.density / propM.viscosity * Ctl;
3405 : }
3406 0 : F[0] = -DF[0] * PDROP;
3407 : } else {
3408 : // Standard calculation.
3409 0 : if (PDROP >= 0.0) {
3410 : // Flow in positive direction.
3411 : // Laminar flow.
3412 0 : RhoCor = TOKELVIN(propN.temperature) / TOKELVIN(Tave);
3413 0 : Ctl = std::pow(RhozNorm / propN.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
3414 0 : CDM = coef * propN.density / propN.viscosity * Ctl;
3415 0 : FL = CDM * PDROP;
3416 : // Turbulent flow.
3417 0 : if (expn == 0.5) {
3418 0 : FT = coef * propN.sqrt_density * std::sqrt(PDROP) * Ctl;
3419 : } else {
3420 0 : FT = coef * propN.sqrt_density * std::pow(PDROP, expn) * Ctl;
3421 : }
3422 : } else {
3423 : // Flow in negative direction.
3424 : // Laminar flow.
3425 0 : RhoCor = TOKELVIN(propM.temperature) / TOKELVIN(Tave);
3426 0 : Ctl = std::pow(RhozNorm / propM.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
3427 0 : CDM = coef * propM.density / propM.viscosity * Ctl;
3428 0 : FL = CDM * PDROP;
3429 : // Turbulent flow.
3430 0 : if (expn == 0.5) {
3431 0 : FT = -coef * propM.sqrt_density * std::sqrt(-PDROP) * Ctl;
3432 : } else {
3433 0 : FT = -coef * propM.sqrt_density * std::pow(-PDROP, expn) * Ctl;
3434 : }
3435 : }
3436 : // Select laminar or turbulent flow.
3437 0 : if (std::abs(FL) <= std::abs(FT)) {
3438 0 : F[0] = FL;
3439 0 : DF[0] = CDM;
3440 : } else {
3441 0 : F[0] = FT;
3442 0 : DF[0] = FT * expn / PDROP;
3443 : }
3444 : }
3445 : }
3446 0 : return 1;
3447 : }
3448 :
3449 888893 : int ReliefFlow::calculate(EnergyPlusData &state,
3450 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
3451 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
3452 : int const i, // Linkage number
3453 : [[maybe_unused]] const Real64 multiplier, // Element multiplier
3454 : [[maybe_unused]] const Real64 control, // Element control signal
3455 : const AirState &propN, // Node 1 properties
3456 : const AirState &propM, // Node 2 properties
3457 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
3458 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
3459 : )
3460 : {
3461 :
3462 : // PURPOSE OF THIS SUBROUTINE:
3463 : // This subroutine solves airflow for a constant flow rate airflow component -- using standard interface.
3464 :
3465 : // Using/Aliasing
3466 : using HVAC::VerySmallMassFlow;
3467 :
3468 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3469 : Real64 expn;
3470 : Real64 Ctl;
3471 : Real64 coef;
3472 : Real64 Corr;
3473 : Real64 VisAve;
3474 : Real64 Tave;
3475 : Real64 RhoCor;
3476 : Real64 RhozNorm;
3477 : Real64 VisczNorm;
3478 : Real64 CDM;
3479 : Real64 FL;
3480 : Real64 FT;
3481 :
3482 888893 : int AirLoopNum = state.afn->AirflowNetworkLinkageData(i).AirLoopNum;
3483 :
3484 888893 : if (state.dataLoopNodes->Node(OutletNode).MassFlowRate > VerySmallMassFlow) {
3485 : // Treat the component as an exhaust fan
3486 888893 : DF[0] = 0.0;
3487 888893 : if (state.afn->PressureSetFlag == PressureCtrlRelief) {
3488 702072 : F[0] = state.afn->ReliefMassFlowRate;
3489 : } else {
3490 186821 : F[0] = state.dataLoopNodes->Node(OutletNode).MassFlowRate;
3491 186821 : if (state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopFanOperationMode == HVAC::FanOp::Cycling &&
3492 0 : state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio > 0.0) {
3493 0 : F[0] = F[0] / state.dataAirLoop->AirLoopAFNInfo(AirLoopNum).LoopOnOffFanPartLoadRatio;
3494 : }
3495 : }
3496 888893 : return 1;
3497 : } else {
3498 : // Treat the component as a surface crack
3499 : // Crack standard condition from given inputs
3500 0 : Corr = 1.0;
3501 0 : RhozNorm = state.afn->properties.density(StandardP, StandardT, StandardW);
3502 0 : VisczNorm = 1.71432e-5 + 4.828e-8 * StandardT;
3503 :
3504 0 : expn = FlowExpo;
3505 0 : VisAve = (propN.viscosity + propM.viscosity) / 2.0;
3506 0 : Tave = (propN.temperature + propM.temperature) / 2.0;
3507 0 : if (PDROP >= 0.0) {
3508 0 : coef = FlowCoef / propN.sqrt_density * Corr;
3509 : } else {
3510 0 : coef = FlowCoef / propM.sqrt_density * Corr;
3511 : }
3512 :
3513 0 : if (LFLAG) {
3514 : // Initialization by linear relation.
3515 0 : if (PDROP >= 0.0) {
3516 0 : RhoCor = TOKELVIN(propN.temperature) / TOKELVIN(Tave);
3517 0 : Ctl = std::pow(RhozNorm / propN.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
3518 0 : DF[0] = coef * propN.density / propN.viscosity * Ctl;
3519 : } else {
3520 0 : RhoCor = TOKELVIN(propM.temperature) / TOKELVIN(Tave);
3521 0 : Ctl = std::pow(RhozNorm / propM.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
3522 0 : DF[0] = coef * propM.density / propM.viscosity * Ctl;
3523 : }
3524 0 : F[0] = -DF[0] * PDROP;
3525 : } else {
3526 : // Standard calculation.
3527 0 : if (PDROP >= 0.0) {
3528 : // Flow in positive direction.
3529 : // Laminar flow.
3530 0 : RhoCor = TOKELVIN(propN.temperature) / TOKELVIN(Tave);
3531 0 : Ctl = std::pow(RhozNorm / propN.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
3532 0 : CDM = coef * propN.density / propN.viscosity * Ctl;
3533 0 : FL = CDM * PDROP;
3534 : // Turbulent flow.
3535 0 : if (expn == 0.5) {
3536 0 : FT = coef * propN.sqrt_density * std::sqrt(PDROP) * Ctl;
3537 : } else {
3538 0 : FT = coef * propN.sqrt_density * std::pow(PDROP, expn) * Ctl;
3539 : }
3540 : } else {
3541 : // Flow in negative direction.
3542 : // Laminar flow.
3543 0 : RhoCor = TOKELVIN(propM.temperature) / TOKELVIN(Tave);
3544 0 : Ctl = std::pow(RhozNorm / propM.density / RhoCor, expn - 1.0) * std::pow(VisczNorm / VisAve, 2.0 * expn - 1.0);
3545 0 : CDM = coef * propM.density / propM.viscosity * Ctl;
3546 0 : FL = CDM * PDROP;
3547 : // Turbulent flow.
3548 0 : if (expn == 0.5) {
3549 0 : FT = -coef * propM.sqrt_density * std::sqrt(-PDROP) * Ctl;
3550 : } else {
3551 0 : FT = -coef * propM.sqrt_density * std::pow(-PDROP, expn) * Ctl;
3552 : }
3553 : }
3554 : // Select laminar or turbulent flow.
3555 0 : if (std::abs(FL) <= std::abs(FT)) {
3556 0 : F[0] = FL;
3557 0 : DF[0] = CDM;
3558 : } else {
3559 0 : F[0] = FT;
3560 0 : DF[0] = FT * expn / PDROP;
3561 : }
3562 : }
3563 : }
3564 0 : return 1;
3565 : }
3566 :
3567 2125611 : void generic_crack(Real64 const coefficient, // Flow coefficient
3568 : Real64 const exponent, // Flow exponent
3569 : bool const linear, // Initialization flag. If true, use linear relationship
3570 : Real64 const pdrop, // Total pressure drop across a component (P1 - P2) [Pa]
3571 : const AirState &propN, // Node 1 properties
3572 : const AirState &propM, // Node 2 properties
3573 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
3574 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
3575 : )
3576 : {
3577 : // SUBROUTINE INFORMATION:
3578 : // AUTHOR George Walton
3579 : // DATE WRITTEN Extracted from AIRNET
3580 : // MODIFIED Lixing Gu, 2/1/04
3581 : // Revised the subroutine to meet E+ needs
3582 : // MODIFIED Lixing Gu, 6/8/05
3583 : // RE-ENGINEERED This subroutine is revised from AFEPLR developed by George Walton, NIST
3584 : // Jason DeGraw
3585 :
3586 : // PURPOSE OF THIS SUBROUTINE:
3587 : // This subroutine solves airflow for a power law component
3588 :
3589 : // METHODOLOGY EMPLOYED:
3590 : // Using Q=C(dP)^n
3591 :
3592 : // FLOW:
3593 : // Calculate normal density and viscocity at reference conditions
3594 2125611 : constexpr Real64 reference_density = AIRDENSITY_CONSTEXPR(101325.0, 20.0, 0.0);
3595 2125611 : constexpr Real64 reference_viscosity = 1.71432e-5 + 4.828e-8 * 20.0;
3596 :
3597 2125611 : Real64 VisAve{0.5 * (propN.viscosity + propM.viscosity)};
3598 2125611 : Real64 Tave{0.5 * (propN.temperature + propM.temperature)};
3599 :
3600 2125611 : Real64 sign{1.0};
3601 2125611 : Real64 upwind_temperature{propN.temperature};
3602 2125611 : Real64 upwind_density{propN.density};
3603 2125611 : Real64 upwind_viscosity{propN.viscosity};
3604 2125611 : Real64 upwind_sqrt_density{propN.sqrt_density};
3605 2125611 : Real64 abs_pdrop = pdrop;
3606 :
3607 2125611 : if (pdrop < 0.0) {
3608 863728 : sign = -1.0;
3609 863728 : upwind_temperature = propM.temperature;
3610 863728 : upwind_density = propM.density;
3611 863728 : upwind_viscosity = propM.viscosity;
3612 863728 : upwind_sqrt_density = propM.sqrt_density;
3613 863728 : abs_pdrop = -pdrop;
3614 : }
3615 :
3616 2125611 : Real64 coef = coefficient / upwind_sqrt_density;
3617 :
3618 : // Laminar calculation
3619 2125611 : Real64 RhoCor{TOKELVIN(upwind_temperature) / TOKELVIN(Tave)};
3620 2125611 : Real64 Ctl{std::pow(reference_density / upwind_density / RhoCor, exponent - 1.0) *
3621 2125611 : std::pow(reference_viscosity / VisAve, 2.0 * exponent - 1.0)};
3622 2125611 : Real64 CDM{coef * upwind_density / upwind_viscosity * Ctl};
3623 2125611 : Real64 FL{CDM * pdrop};
3624 :
3625 2125611 : if (linear) {
3626 0 : DF[0] = CDM;
3627 0 : F[0] = FL;
3628 : } else {
3629 : // Turbulent flow.
3630 : Real64 abs_FT;
3631 2125611 : if (exponent == 0.5) {
3632 0 : abs_FT = coef * upwind_sqrt_density * std::sqrt(abs_pdrop) * Ctl;
3633 : } else {
3634 2125611 : abs_FT = coef * upwind_sqrt_density * std::pow(abs_pdrop, exponent) * Ctl;
3635 : }
3636 : // Select linear or nonlinear flow.
3637 2125611 : if (std::abs(FL) <= abs_FT) {
3638 457 : F[0] = FL;
3639 457 : DF[0] = CDM;
3640 : } else {
3641 2125154 : F[0] = sign * abs_FT;
3642 2125154 : DF[0] = F[0] * exponent / pdrop;
3643 : }
3644 : }
3645 2125611 : }
3646 :
3647 12136 : int GenericDuct(Real64 const Length, // Duct length
3648 : Real64 const Diameter, // Duct diameter
3649 : bool const LFLAG, // Initialization flag.If = 1, use laminar relationship
3650 : Real64 const PDROP, // Total pressure drop across a component (P1 - P2) [Pa]
3651 : const AirState &propN, // Node 1 properties
3652 : const AirState &propM, // Node 2 properties
3653 : std::array<Real64, 2> &F, // Airflow through the component [kg/s]
3654 : std::array<Real64, 2> &DF // Partial derivative: DF/DP
3655 : )
3656 : {
3657 :
3658 : // This subroutine solve air flow as a duct if fan has zero flow rate
3659 :
3660 : // SUBROUTINE PARAMETER DEFINITIONS:
3661 12136 : Real64 constexpr C(0.868589);
3662 12136 : Real64 constexpr EPS(0.001);
3663 12136 : Real64 constexpr Rough(0.0001);
3664 12136 : Real64 constexpr InitLamCoef(128.0);
3665 12136 : Real64 constexpr LamDynCoef(64.0);
3666 12136 : Real64 constexpr LamFriCoef(0.0001);
3667 12136 : Real64 constexpr TurDynCoef(0.0001);
3668 :
3669 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3670 : Real64 A0;
3671 : Real64 A1;
3672 : Real64 A2;
3673 : Real64 B;
3674 : Real64 D;
3675 : Real64 S2;
3676 : Real64 CDM;
3677 : Real64 FL;
3678 : Real64 FT;
3679 : Real64 FTT;
3680 : Real64 RE;
3681 :
3682 : // Get component properties
3683 12136 : Real64 ed = Rough / Diameter;
3684 12136 : Real64 area = Diameter * Diameter * Constant::Pi / 4.0;
3685 12136 : Real64 ld = Length / Diameter;
3686 12136 : Real64 g = 1.14 - 0.868589 * std::log(ed);
3687 12136 : Real64 AA1 = g;
3688 :
3689 12136 : if (LFLAG) {
3690 : // Initialization by linear relation.
3691 0 : if (PDROP >= 0.0) {
3692 0 : DF[0] = (2.0 * propN.density * area * Diameter) / (propN.viscosity * InitLamCoef * ld);
3693 : } else {
3694 0 : DF[0] = (2.0 * propM.density * area * Diameter) / (propM.viscosity * InitLamCoef * ld);
3695 : }
3696 0 : F[0] = -DF[0] * PDROP;
3697 : } else {
3698 : // Standard calculation.
3699 12136 : if (PDROP >= 0.0) {
3700 : // Flow in positive direction.
3701 : // Laminar flow coefficient !=0
3702 : if (LamFriCoef >= 0.001) {
3703 : A2 = LamFriCoef / (2.0 * propN.density * area * area);
3704 : A1 = (propN.viscosity * LamDynCoef * ld) / (2.0 * propN.density * area * Diameter);
3705 : A0 = -PDROP;
3706 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
3707 : FL = (CDM - A1) / (2.0 * A2);
3708 : CDM = 1.0 / CDM;
3709 : } else {
3710 3041 : CDM = (2.0 * propN.density * area * Diameter) / (propN.viscosity * LamDynCoef * ld);
3711 3041 : FL = CDM * PDROP;
3712 : }
3713 3041 : RE = FL * Diameter / (propN.viscosity * area);
3714 : // Turbulent flow; test when Re>10.
3715 3041 : if (RE >= 10.0) {
3716 0 : S2 = std::sqrt(2.0 * propN.density * PDROP) * area;
3717 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
3718 : while (true) {
3719 0 : FT = FTT;
3720 0 : B = (9.3 * propN.viscosity * area) / (FT * Rough);
3721 0 : D = 1.0 + g * B;
3722 0 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
3723 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
3724 0 : if (std::abs(FTT - FT) / FTT < EPS) {
3725 0 : break;
3726 : }
3727 : }
3728 0 : FT = FTT;
3729 : } else {
3730 3041 : FT = FL;
3731 : }
3732 : } else {
3733 : // Flow in negative direction.
3734 : // Laminar flow coefficient !=0
3735 : if (LamFriCoef >= 0.001) {
3736 : A2 = LamFriCoef / (2.0 * propM.density * area * area);
3737 : A1 = (propM.viscosity * LamDynCoef * ld) / (2.0 * propM.density * area * Diameter);
3738 : A0 = PDROP;
3739 : CDM = std::sqrt(A1 * A1 - 4.0 * A2 * A0);
3740 : FL = -(CDM - A1) / (2.0 * A2);
3741 : CDM = 1.0 / CDM;
3742 : } else {
3743 9095 : CDM = (2.0 * propM.density * area * Diameter) / (propM.viscosity * LamDynCoef * ld);
3744 9095 : FL = CDM * PDROP;
3745 : }
3746 9095 : RE = -FL * Diameter / (propM.viscosity * area);
3747 : // Turbulent flow; test when Re>10.
3748 9095 : if (RE >= 10.0) {
3749 0 : S2 = std::sqrt(-2.0 * propM.density * PDROP) * area;
3750 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
3751 : while (true) {
3752 0 : FT = FTT;
3753 0 : B = (9.3 * propM.viscosity * area) / (FT * Rough);
3754 0 : D = 1.0 + g * B;
3755 0 : g -= (g - AA1 + C * std::log(D)) / (1.0 + C * B / D);
3756 0 : FTT = S2 / std::sqrt(ld / pow_2(g) + TurDynCoef);
3757 0 : if (std::abs(FTT - FT) / FTT < EPS) {
3758 0 : break;
3759 : }
3760 : }
3761 0 : FT = -FTT;
3762 : } else {
3763 9095 : FT = FL;
3764 : }
3765 : }
3766 : // Select laminar or turbulent flow.
3767 12136 : if (std::abs(FL) <= std::abs(FT)) {
3768 12136 : F[0] = FL;
3769 12136 : DF[0] = CDM;
3770 : } else {
3771 0 : F[0] = FT;
3772 0 : DF[0] = 0.5 * FT / PDROP;
3773 : }
3774 : }
3775 12136 : return 1;
3776 : }
3777 :
3778 746102 : void DetailedOpeningSolver::presprofile(EnergyPlusData &state,
3779 : int const il, // Linkage number
3780 : int const Pprof, // Opening number
3781 : Real64 const G, // gravitation field strength [N/kg]
3782 : const Array1D<Real64> &DpF, // Stack pressures at start heights of Layers
3783 : const Array1D<Real64> &DpT, // Stack pressures at start heights of Layers
3784 : const Array1D<Real64> &BetaF, // Density gradients in the FROM zone (starting at linkheight) [Kg/m3/m]
3785 : const Array1D<Real64> &BetaT, // Density gradients in the TO zone (starting at linkheight) [Kg/m3/m]
3786 : const Array1D<Real64> &RhoStF, // Density at the start heights of Layers in the FROM zone
3787 : const Array1D<Real64> &RhoStT, // Density at the start heights of Layers in the TO zone
3788 : int const From, // Number of FROM zone
3789 : int const To, // Number of To zone
3790 : Real64 const ActLh, // Actual height of opening [m]
3791 : Real64 const OwnHeightFactor // Cosine of deviation angle of the opening plane from the vertical direction
3792 : )
3793 : {
3794 :
3795 : // SUBROUTINE INFORMATION:
3796 : // AUTHOR Lixing Gu
3797 : // DATE WRITTEN Oct. 2005
3798 : // MODIFIED na
3799 : // RE-ENGINEERED This subroutine is revised based on PresProfile subroutine from COMIS
3800 :
3801 : // PURPOSE OF THIS SUBROUTINE:
3802 : // This subroutine calculates for a large opening profiles of stack pressure difference and
3803 : // densities in the zones linked by the a detailed opening cmponent.
3804 :
3805 : // METHODOLOGY EMPLOYED:
3806 : // The profiles are obtained in the following
3807 : // way: - the opening is divided into NrInt vertical intervals
3808 : // - the stack pressure difference and densities in From-
3809 : // and To-zone are calculated at the centre of each
3810 : // interval aswell as at the top and bottom of the LO
3811 : // - these values are stored in the (NrInt+2)-dimensional
3812 : // arrays DpProf, RhoProfF, RhoProfT.
3813 : // The calculation of stack pressure and density in the two zones
3814 : // is based on the arrays DpF/T, RhoStF/T, BetaF/T. These arrays
3815 : // are calculated in the COMIS routine Lclimb. They contain the
3816 : // values of stack pressure and density at the startheight of the
3817 : // opening and at startheights of all layers lying inside the
3818 : // opening, and the density gradients across the layers.
3819 : // The effective startheight zl(1/2) in the From/To zone and the
3820 : // effective length actLh of the LO take into account the
3821 : // startheightfactor, heightfactor and ownheightfactor. Thus for
3822 : // slanted windows the range of the profiles is the vertical
3823 : // projection of the actual opening.
3824 :
3825 : // REFERENCES:
3826 : // Helmut E. Feustel and Alison Rayner-Hooson, "COMIS Fundamentals," LBL-28560,
3827 : // Lawrence Berkeley National Laboratory, Berkeley, CA, May 1990
3828 :
3829 : // Argument array dimensioning
3830 746102 : EP_SIZE_CHECK(DpF, 2);
3831 746102 : EP_SIZE_CHECK(DpT, 2);
3832 746102 : EP_SIZE_CHECK(BetaF, 2);
3833 746102 : EP_SIZE_CHECK(BetaT, 2);
3834 746102 : EP_SIZE_CHECK(RhoStF, 2);
3835 746102 : EP_SIZE_CHECK(RhoStT, 2);
3836 :
3837 : // Locals
3838 : // SUBROUTINE ARGUMENT DEFINITIONS:
3839 : // in the FROM zone (starting at linkheight) [Pa]
3840 : // (starting at linkheight) [Kg/m3]
3841 : // (starting at linkheight) [Kg/m3]
3842 :
3843 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3844 746102 : Array1D<Real64> zF(2); // Startheights of layers in FROM-, TO-zone
3845 746102 : Array1D<Real64> zT(2);
3846 746102 : Array1D<Real64> zStF(2); // Startheights of layers within the LO, starting with the actual startheight of the LO.
3847 746102 : Array1D<Real64> zStT(2);
3848 : // The values in the arrays DpF, DpT, BetaF, BetaT, RhoStF, RhoStT are calculated at these heights.
3849 : Real64 hghtsFR;
3850 : Real64 hghtsTR;
3851 746102 : Array1D<Real64> hghtsF(NrInt + 2); // Heights of evaluation points for pressure and density profiles
3852 746102 : Array1D<Real64> hghtsT(NrInt + 2);
3853 : Real64 Interval; // Distance between two evaluation points
3854 : Real64 delzF; // Interval between actual evaluation point and startheight of actual layer in FROM-, TO-zone
3855 : Real64 delzT;
3856 : int AnzLayF; // Number of layers in FROM-, TO-zone
3857 : int AnzLayT;
3858 : int lF; // Actual index for DpF/T, BetaF/T, RhoStF/T, zStF/T
3859 : int lT;
3860 : int n;
3861 : int i;
3862 : int k;
3863 :
3864 : // Initialization
3865 746102 : delzF = 0.0;
3866 746102 : delzT = 0.0;
3867 746102 : Interval = ActLh * OwnHeightFactor / NrInt;
3868 :
3869 15668142 : for (n = 1; n <= NrInt; ++n) {
3870 14922040 : hghtsF(n + 1) = state.afn->AirflowNetworkLinkageData(il).NodeHeights[0] + Interval * (n - 0.5);
3871 14922040 : hghtsT(n + 1) = state.afn->AirflowNetworkLinkageData(il).NodeHeights[1] + Interval * (n - 0.5);
3872 : }
3873 746102 : hghtsF(1) = state.afn->AirflowNetworkLinkageData(il).NodeHeights[0];
3874 746102 : hghtsT(1) = state.afn->AirflowNetworkLinkageData(il).NodeHeights[1];
3875 746102 : hghtsF(NrInt + 2) = state.afn->AirflowNetworkLinkageData(il).NodeHeights[0] + ActLh * OwnHeightFactor;
3876 746102 : hghtsT(NrInt + 2) = state.afn->AirflowNetworkLinkageData(il).NodeHeights[1] + ActLh * OwnHeightFactor;
3877 :
3878 746102 : lF = 1;
3879 746102 : lT = 1;
3880 746102 : if (From == 0) {
3881 0 : AnzLayF = 1;
3882 : } else {
3883 746102 : AnzLayF = 0;
3884 : }
3885 746102 : if (To == 0) {
3886 679023 : AnzLayT = 1;
3887 : } else {
3888 67079 : AnzLayT = 0;
3889 : }
3890 :
3891 746102 : if (AnzLayF > 0) {
3892 0 : for (n = 1; n <= AnzLayF; ++n) {
3893 0 : zF(n) = 0.0;
3894 0 : if (hghtsF(1) < 0.0) {
3895 0 : zF(n) = hghtsF(1);
3896 : }
3897 : }
3898 : }
3899 :
3900 746102 : if (AnzLayT > 0) {
3901 1358046 : for (n = 1; n <= AnzLayT; ++n) {
3902 679023 : zT(n) = 0.0;
3903 679023 : if (hghtsT(1) < 0.0) {
3904 0 : zT(n) = hghtsT(1);
3905 : }
3906 : }
3907 : }
3908 :
3909 746102 : zStF(1) = state.afn->AirflowNetworkLinkageData(il).NodeHeights[0];
3910 746102 : i = 2;
3911 746102 : k = 1;
3912 :
3913 746102 : while (k <= AnzLayF) {
3914 0 : if (zF(k) > zStF(1)) {
3915 0 : break;
3916 : }
3917 0 : ++k;
3918 : }
3919 :
3920 746102 : while (k <= AnzLayF) {
3921 0 : if (zF(k) > hghtsF(NrInt)) {
3922 0 : break;
3923 : }
3924 0 : zStF(i) = zF(k); // Autodesk:BoundsViolation zStF(i) @ i>2 and zF(k) @ k>2
3925 0 : ++i;
3926 0 : ++k;
3927 : }
3928 :
3929 746102 : zStF(i) = state.afn->AirflowNetworkLinkageData(il).NodeHeights[0] + ActLh * OwnHeightFactor; // Autodesk:BoundsViolation zStF(i) @ i>2
3930 746102 : zStT(1) = state.afn->AirflowNetworkLinkageData(il).NodeHeights[1];
3931 746102 : i = 2;
3932 746102 : k = 1;
3933 :
3934 1425125 : while (k <= AnzLayT) {
3935 679023 : if (zT(k) > zStT(1)) {
3936 0 : break;
3937 : }
3938 679023 : ++k;
3939 : }
3940 :
3941 746102 : while (k <= AnzLayT) {
3942 0 : if (zT(k) > hghtsT(NrInt)) {
3943 0 : break; // Autodesk:BoundsViolation zT(k) @ k>2
3944 : }
3945 0 : zStT(i) = zT(k); // Autodesk:BoundsViolation zStF(i) @ i>2 and zT(k) @ k>2
3946 0 : ++i;
3947 0 : ++k;
3948 : }
3949 :
3950 746102 : zStT(i) = state.afn->AirflowNetworkLinkageData(il).NodeHeights[1] + ActLh * OwnHeightFactor; // Autodesk:BoundsViolation zStT(i) @ i>2
3951 :
3952 : // Calculation of DpProf, RhoProfF, RhoProfT
3953 17160346 : for (i = 1; i <= NrInt + 2; ++i) {
3954 16414244 : hghtsFR = hghtsF(i);
3955 16414244 : hghtsTR = hghtsT(i);
3956 :
3957 : while (true) {
3958 16414244 : if (hghtsFR > zStF(lF + 1)) {
3959 0 : if (lF > 2) {
3960 0 : break;
3961 : }
3962 0 : ++lF;
3963 : }
3964 16414244 : if (hghtsFR <= zStF(lF + 1)) {
3965 16414244 : break;
3966 : }
3967 : }
3968 :
3969 : while (true) {
3970 16414244 : if (hghtsTR > zStT(lT + 1)) {
3971 0 : ++lT;
3972 : }
3973 16414244 : if (hghtsTR <= zStT(lT + 1)) {
3974 16414244 : break;
3975 : }
3976 : }
3977 :
3978 16414244 : delzF = hghtsF(i) - zStF(lF);
3979 16414244 : delzT = hghtsT(i) - zStT(lT);
3980 :
3981 16414244 : RhoProfF(i + Pprof) = RhoStF(lF) + BetaF(lF) * delzF;
3982 16414244 : RhoProfT(i + Pprof) = RhoStT(lT) + BetaT(lT) * delzT;
3983 :
3984 32828488 : DpProf(i + Pprof) = DpF(lF) - DpT(lT) - G * (RhoStF(lF) * delzF + BetaF(lF) * pow_2(delzF) / 2.0) +
3985 16414244 : G * (RhoStT(lT) * delzT + BetaT(lT) * pow_2(delzT) / 2.0);
3986 : }
3987 746102 : }
3988 :
3989 579185 : void DetailedOpeningSolver::pstack(EnergyPlusData &state, std::vector<AirflowNetwork::AirState> &props, Array1D<Real64> &pz)
3990 : {
3991 :
3992 : // SUBROUTINE INFORMATION:
3993 : // AUTHOR Lixing Gu
3994 : // DATE WRITTEN Oct. 2005
3995 : // MODIFIED na
3996 : // RE-ENGINEERED This subroutine is revised based on PresProfile subroutine from COMIS
3997 :
3998 : // PURPOSE OF THIS SUBROUTINE:
3999 : // This subroutine calculates the stack pressures for a link between two zones
4000 :
4001 : // REFERENCES:
4002 : // Helmut E. Feustel and Alison Rayner-Hooson, "COMIS Fundamentals," LBL-28560,
4003 : // Lawrence Berkeley National Laboratory, Berkeley, CA, May 1990
4004 :
4005 : // USE STATEMENTS:
4006 : // Locals
4007 : // SUBROUTINE ARGUMENT DEFINITIONS:
4008 : // na
4009 :
4010 : // SUBROUTINE PARAMETER DEFINITIONS:
4011 579185 : Real64 constexpr PSea(101325.0);
4012 :
4013 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4014 : // REAL(r64) RhoOut ! air density outside [kg/m3]
4015 : Real64 G; // gravity field strength [N/kg]
4016 : Real64 Pbz; // Pbarom at entrance level [Pa]
4017 579185 : Array2D<Real64> RhoDrL(state.afn->NumOfLinksMultiZone, 2); // dry air density on both sides of the link [kg/m3]
4018 : Real64 TempL1; // Temp in From and To zone at link level [C]
4019 : Real64 TempL2;
4020 : // REAL(r64) Tout ! outside temperature [C]
4021 : Real64 Xhl1; // Humidity in From and To zone at link level [kg/kg]
4022 : Real64 Xhl2;
4023 : // REAL(r64) Xhout ! outside humidity [kg/kg]
4024 579185 : Array1D<Real64> Hfl(state.afn->NumOfLinksMultiZone); // Own height factor for large (slanted) openings
4025 : int Nl; // number of links
4026 :
4027 579185 : Array1D<Real64> DpF(2);
4028 : Real64 DpP;
4029 579185 : Array1D<Real64> DpT(2);
4030 : Real64 H;
4031 579185 : Array1D<Real64> RhoStF(2);
4032 579185 : Array1D<Real64> RhoStT(2);
4033 : Real64 RhoDrDummi;
4034 579185 : Array1D<Real64> BetaStF(2);
4035 579185 : Array1D<Real64> BetaStT(2);
4036 : Real64 T;
4037 : Real64 X;
4038 579185 : Array1D<Real64> HSt(2);
4039 : Real64 TzFrom;
4040 : Real64 XhzFrom;
4041 : Real64 TzTo;
4042 : Real64 XhzTo;
4043 : Real64 ActLh;
4044 : Real64 ActLOwnh;
4045 : Real64 Pref;
4046 : Real64 PzFrom;
4047 : Real64 PzTo;
4048 579185 : Array1D<Real64> RhoLd(2);
4049 : Real64 RhoStd;
4050 : int Fromz;
4051 : int Toz;
4052 : iComponentTypeNum Ltyp;
4053 : int i;
4054 : int ll;
4055 : int Pprof;
4056 : int OpenNum;
4057 :
4058 : Real64 RhoREF;
4059 : Real64 CONV;
4060 :
4061 579185 : RhoREF = state.afn->properties.density(PSea, state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutHumRat);
4062 :
4063 579185 : CONV = state.dataEnvrn->Latitude * 2.0 * Constant::Pi / 360.0;
4064 579185 : G = 9.780373 * (1.0 + 0.0052891 * pow_2(std::sin(CONV)) - 0.0000059 * pow_2(std::sin(2.0 * CONV)));
4065 :
4066 579185 : Hfl = 1.0;
4067 579185 : Pbz = state.dataEnvrn->OutBaroPress;
4068 579185 : Nl = state.afn->NumOfLinksMultiZone;
4069 579185 : OpenNum = 0;
4070 579185 : RhoLd(1) = 1.2;
4071 579185 : RhoLd(2) = 1.2;
4072 579185 : RhoStd = 1.2;
4073 :
4074 8945488 : for (i = 1; i <= Nl; ++i) {
4075 : // Check surface tilt
4076 8366303 : if (i <= Nl - state.afn->NumOfLinksIntraZone) { // Revised by L.Gu, on 9 / 29 / 10
4077 9008868 : if (state.afn->AirflowNetworkLinkageData(i).DetOpenNum > 0 &&
4078 746102 : state.dataSurface->Surface(state.afn->MultizoneSurfaceData(i).SurfNum).Tilt < 90) {
4079 0 : Hfl(i) = state.dataSurface->Surface(state.afn->MultizoneSurfaceData(i).SurfNum).SinTilt;
4080 : }
4081 : }
4082 : // Initialisation
4083 8366303 : int From = state.afn->AirflowNetworkLinkageData(i).NodeNums[0];
4084 8366303 : int To = state.afn->AirflowNetworkLinkageData(i).NodeNums[1];
4085 8366303 : if (state.afn->AirflowNetworkNodeData(From).EPlusZoneNum > 0 && state.afn->AirflowNetworkNodeData(To).EPlusZoneNum > 0) {
4086 2743793 : ll = 0;
4087 5622510 : } else if (state.afn->AirflowNetworkNodeData(From).EPlusZoneNum == 0 && state.afn->AirflowNetworkNodeData(To).EPlusZoneNum > 0) {
4088 0 : ll = 1;
4089 : } else {
4090 5622510 : ll = 3;
4091 : }
4092 :
4093 8366303 : Ltyp = state.afn->AirflowNetworkCompData(state.afn->AirflowNetworkLinkageData(i).CompNum).CompTypeNum;
4094 8366303 : if (Ltyp == iComponentTypeNum::DOP) {
4095 746102 : ActLh = state.afn->MultizoneSurfaceData(i).Height;
4096 746102 : ActLOwnh = ActLh * 1.0;
4097 : } else {
4098 7620201 : ActLh = 0.0;
4099 7620201 : ActLOwnh = 0.0;
4100 : }
4101 :
4102 8366303 : TempL1 = props[From].temperature;
4103 8366303 : Xhl1 = props[From].humidity_ratio;
4104 8366303 : TzFrom = props[From].temperature;
4105 8366303 : XhzFrom = props[From].humidity_ratio;
4106 : // RhoL1 = props[From].density;
4107 8366303 : if (ll == 0 || ll == 3) {
4108 8366303 : PzFrom = pz(From);
4109 : } else {
4110 0 : PzFrom = 0.0;
4111 0 : From = 0;
4112 : }
4113 :
4114 8366303 : int ilayptr = 0;
4115 8366303 : if (From == 0) {
4116 0 : ilayptr = 1;
4117 : }
4118 8366303 : if (ilayptr == 0) {
4119 8366303 : Fromz = 0;
4120 : } else {
4121 0 : Fromz = From;
4122 : }
4123 :
4124 8366303 : TempL2 = props[To].temperature;
4125 8366303 : Xhl2 = props[To].humidity_ratio;
4126 8366303 : TzTo = props[To].temperature;
4127 8366303 : XhzTo = props[To].humidity_ratio;
4128 : // RhoL2 = props[To].density;
4129 :
4130 8366303 : if (ll < 3) {
4131 2743793 : PzTo = pz(To);
4132 : } else {
4133 5622510 : PzTo = 0.0;
4134 5622510 : To = 0;
4135 : }
4136 8366303 : ilayptr = 0;
4137 8366303 : if (To == 0) {
4138 5622510 : ilayptr = 1;
4139 : }
4140 8366303 : if (ilayptr == 0) {
4141 2743793 : Toz = 0;
4142 : } else {
4143 5622510 : Toz = To;
4144 : }
4145 :
4146 : // RhoDrL is Rho at link level without pollutant but with humidity
4147 8366303 : RhoDrL(i, 1) = state.afn->properties.density(state.dataEnvrn->OutBaroPress + PzFrom, TempL1, Xhl1);
4148 8366303 : RhoDrL(i, 2) = state.afn->properties.density(state.dataEnvrn->OutBaroPress + PzTo, TempL2, Xhl2);
4149 :
4150 : // End initialisation
4151 :
4152 : // calculate DpF the difference between Pz and P at Node 1 height
4153 8366303 : ilayptr = 0;
4154 8366303 : if (Fromz == 0) {
4155 8366303 : ilayptr = 1;
4156 : }
4157 8366303 : int j = ilayptr;
4158 8366303 : int k = 1;
4159 8366303 : lclimb(state, G, RhoLd(1), state.afn->AirflowNetworkLinkageData(i).NodeHeights[0], TempL1, Xhl1, DpF(k), Toz, PzTo, Pbz, RhoDrL(i, 1));
4160 8366303 : Real64 RhoL1 = RhoLd(1);
4161 : // For large openings calculate the stack pressure difference profile and the
4162 : // density profile within the the top- and the bottom- height of the large opening
4163 8366303 : if (ActLOwnh > 0.0) {
4164 746102 : HSt(k) = state.afn->AirflowNetworkLinkageData(i).NodeHeights[0];
4165 746102 : RhoStF(k) = RhoL1;
4166 746102 : ++k;
4167 746102 : HSt(k) = 0.0;
4168 746102 : if (HSt(k - 1) < 0.0) {
4169 0 : HSt(k) = HSt(k - 1);
4170 : }
4171 :
4172 : // Search for the first startheight of a layer which is within the top- and the
4173 : // bottom- height of the large opening.
4174 : while (true) {
4175 1492204 : ilayptr = 0;
4176 1492204 : if (Fromz == 0) {
4177 1492204 : ilayptr = 9;
4178 : }
4179 1492204 : if ((j > ilayptr) || (HSt(k) > state.afn->AirflowNetworkLinkageData(i).NodeHeights[0])) {
4180 746102 : break;
4181 : }
4182 746102 : j += 9;
4183 746102 : HSt(k) = 0.0;
4184 746102 : if (HSt(k - 1) < 0.0) {
4185 0 : HSt(k) = HSt(k - 1);
4186 : }
4187 : }
4188 :
4189 : // Calculate Rho and stack pressure for every StartHeight of a layer which is
4190 : // within the top- and the bottom-height of the large opening.
4191 : while (true) {
4192 746102 : ilayptr = 0;
4193 746102 : if (Fromz == 0) {
4194 746102 : ilayptr = 9;
4195 : }
4196 746102 : if ((j > ilayptr) || (HSt(k) >= (state.afn->AirflowNetworkLinkageData(i).NodeHeights[0] + ActLOwnh))) {
4197 746102 : break; // Autodesk:BoundsViolation HSt(k) @ k>2
4198 : }
4199 0 : T = TzFrom;
4200 0 : X = XhzFrom;
4201 0 : lclimb(
4202 0 : state, G, RhoStd, HSt(k), T, X, DpF(k), Fromz, PzFrom, Pbz, RhoDrDummi); // Autodesk:BoundsViolation HSt(k) and DpF(k) @ k>2
4203 0 : RhoStF(k) = RhoStd; // Autodesk:BoundsViolation RhoStF(k) @ k>2
4204 0 : j += 9;
4205 0 : ++k; // Autodesk:Note k>2 now
4206 0 : HSt(k) = 0.0; // Autodesk:BoundsViolation @ k>2
4207 0 : if (HSt(k - 1) < 0.0) {
4208 0 : HSt(k) = HSt(k - 1); // Autodesk:BoundsViolation @ k>2
4209 : }
4210 : }
4211 : // Stack pressure difference and rho for top-height of the large opening
4212 746102 : HSt(k) = state.afn->AirflowNetworkLinkageData(i).NodeHeights[0] + ActLOwnh; // Autodesk:BoundsViolation k>2 poss
4213 746102 : T = TzFrom;
4214 746102 : X = XhzFrom;
4215 746102 : lclimb(state, G, RhoStd, HSt(k), T, X, DpF(k), Fromz, PzFrom, Pbz, RhoDrDummi); // Autodesk:BoundsViolation k>2 poss
4216 746102 : RhoStF(k) = RhoStd; // Autodesk:BoundsViolation k >= 3 poss
4217 :
4218 1492204 : for (j = 1; j <= (k - 1); ++j) {
4219 746102 : BetaStF(j) = (RhoStF(j + 1) - RhoStF(j)) / (HSt(j + 1) - HSt(j));
4220 : }
4221 : }
4222 :
4223 : // repeat procedure for the "To" node, DpT
4224 8366303 : ilayptr = 0;
4225 8366303 : if (Toz == 0) {
4226 8366303 : ilayptr = 1;
4227 : }
4228 8366303 : j = ilayptr;
4229 : // Calculate Rho at link height only if we have large openings or layered zones.
4230 8366303 : k = 1;
4231 8366303 : lclimb(state, G, RhoLd(2), state.afn->AirflowNetworkLinkageData(i).NodeHeights[1], TempL2, Xhl2, DpT(k), Toz, PzTo, Pbz, RhoDrL(i, 2));
4232 8366303 : Real64 RhoL2 = RhoLd(2);
4233 :
4234 : // For large openings calculate the stack pressure difference profile and the
4235 : // density profile within the the top- and the bottom- height of the large opening
4236 8366303 : if (ActLOwnh > 0.0) {
4237 746102 : HSt(k) = state.afn->AirflowNetworkLinkageData(i).NodeHeights[1];
4238 746102 : RhoStT(k) = RhoL2;
4239 746102 : ++k;
4240 746102 : HSt(k) = 0.0;
4241 746102 : if (HSt(k - 1) < 0.0) {
4242 0 : HSt(k) = HSt(k - 1);
4243 : }
4244 : while (true) {
4245 1492204 : ilayptr = 0;
4246 1492204 : if (Toz == 0) {
4247 1492204 : ilayptr = 9;
4248 : }
4249 1492204 : if ((j > ilayptr) || (HSt(k) > state.afn->AirflowNetworkLinkageData(i).NodeHeights[1])) {
4250 746102 : break;
4251 : }
4252 746102 : j += 9;
4253 746102 : HSt(k) = 0.0;
4254 746102 : if (HSt(k - 1) < 0.0) {
4255 0 : HSt(k) = HSt(k - 1);
4256 : }
4257 : }
4258 : // Calculate Rho and stack pressure for every StartHeight of a layer which is
4259 : // within the top- and the bottom-height of the large opening.
4260 : while (true) {
4261 746102 : ilayptr = 0;
4262 746102 : if (Toz == 0) {
4263 746102 : ilayptr = 9;
4264 : }
4265 746102 : if ((j > ilayptr) || (HSt(k) >= (state.afn->AirflowNetworkLinkageData(i).NodeHeights[1] + ActLOwnh))) {
4266 746102 : break; // Autodesk:BoundsViolation Hst(k) @ k>2
4267 : }
4268 0 : T = TzTo;
4269 0 : X = XhzTo;
4270 0 : lclimb(state, G, RhoStd, HSt(k), T, X, DpT(k), Toz, PzTo, Pbz, RhoDrDummi); // Autodesk:BoundsViolation HSt(k) and DpT(k) @ k>2
4271 0 : RhoStT(k) = RhoStd; // Autodesk:BoundsViolation RhoStT(k) @ k>2
4272 0 : j += 9;
4273 0 : ++k; // Autodesk:Note k>2 now
4274 0 : HSt(k) = 0.0; // Autodesk:BoundsViolation @ k>2
4275 0 : if (HSt(k - 1) < 0.0) {
4276 0 : HSt(k) = HSt(k - 1); // Autodesk:BoundsViolation @ k>2
4277 : }
4278 : }
4279 : // Stack pressure difference and rho for top-height of the large opening
4280 746102 : HSt(k) = state.afn->AirflowNetworkLinkageData(i).NodeHeights[1] + ActLOwnh; // Autodesk:BoundsViolation k>2 poss
4281 746102 : T = TzTo;
4282 746102 : X = XhzTo;
4283 746102 : lclimb(state, G, RhoStd, HSt(k), T, X, DpT(k), Toz, PzTo, Pbz, RhoDrDummi); // Autodesk:BoundsViolation k>2 poss
4284 746102 : RhoStT(k) = RhoStd; // Autodesk:BoundsViolation k>2 poss
4285 :
4286 1492204 : for (j = 1; j <= (k - 1); ++j) {
4287 746102 : BetaStT(j) = (RhoStT(j + 1) - RhoStT(j)) / (HSt(j + 1) - HSt(j));
4288 : }
4289 : }
4290 :
4291 : // CALCULATE STACK PRESSURE FOR THE PATH ITSELF for different flow directions
4292 8366303 : H = double(state.afn->AirflowNetworkLinkageData(i).NodeHeights[1]) - double(state.afn->AirflowNetworkLinkageData(i).NodeHeights[0]);
4293 8366303 : if (ll == 0 || ll == 3 || ll == 6) {
4294 8366303 : H -= state.afn->AirflowNetworkNodeData(From).NodeHeight;
4295 : }
4296 8366303 : if (ll < 3) {
4297 2743793 : H += state.afn->AirflowNetworkNodeData(To).NodeHeight;
4298 : }
4299 :
4300 : // IF AIR FLOWS from "From" to "To"
4301 8366303 : Pref = Pbz + PzFrom + DpF(1);
4302 8366303 : DpP = psz(Pref, RhoLd(1), 0.0, 0.0, H, G);
4303 8366303 : DpL(i, 1) = (DpF(1) - DpT(1) + DpP);
4304 :
4305 : // IF AIR FLOWS from "To" to "From"
4306 8366303 : Pref = Pbz + PzTo + DpT(1);
4307 8366303 : DpP = -psz(Pref, RhoLd(2), 0.0, 0.0, -H, G);
4308 8366303 : DpL(i, 2) = (DpF(1) - DpT(1) + DpP);
4309 :
4310 8366303 : if (Ltyp == iComponentTypeNum::DOP) {
4311 746102 : Pprof = OpenNum * (NrInt + 2);
4312 746102 : presprofile(state, i, Pprof, G, DpF, DpT, BetaStF, BetaStT, RhoStF, RhoStT, From, To, ActLh, Hfl(i));
4313 746102 : ++OpenNum;
4314 : }
4315 : }
4316 579185 : }
4317 :
4318 34957416 : Real64 DetailedOpeningSolver::psz(Real64 const Pz0, // Pressure at altitude z0 [Pa]
4319 : Real64 const Rho0, // density at altitude z0 [kg/m3]
4320 : Real64 const beta, // density gradient [kg/m4]
4321 : Real64 const z0, // reference altitude [m]
4322 : Real64 const z, // altitude[m]
4323 : Real64 const g // gravity field strength [N/kg]
4324 : )
4325 : {
4326 :
4327 : // FUNCTION INFORMATION:
4328 : // AUTHOR Lixing Gu
4329 : // DATE WRITTEN Oct. 2005
4330 : // MODIFIED na
4331 : // RE-ENGINEERED This subroutine is revised based on psz function from COMIS
4332 :
4333 : // PURPOSE OF THIS SUBROUTINE:
4334 : // This function determines the pressure due to buoyancy in a stratified density environment
4335 :
4336 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4337 : Real64 dz;
4338 : Real64 rho;
4339 :
4340 34957416 : dz = z - z0;
4341 34957416 : rho = (Rho0 + beta * dz / 2.0);
4342 34957416 : return -Pz0 * (1.0 - std::exp(-dz * rho * g / Pz0)); // Differential pressure from z to z0 [Pa]
4343 : }
4344 :
4345 18224810 : void DetailedOpeningSolver::lclimb(EnergyPlusData &state,
4346 : Real64 const G, // gravity field strength [N/kg]
4347 : Real64 &Rho, // Density link level (initialized with rho zone) [kg/m3]
4348 : Real64 const Z, // Height of the link above the zone reference [m]
4349 : Real64 &T, // temperature at link level [C]
4350 : Real64 &X, // absolute humidity at link level [kg/kg]
4351 : Real64 &Dp, // Stackpressure to the linklevel [Pa]
4352 : int const zone, // Zone number
4353 : Real64 const PZ, // Zone Pressure (reflevel) [Pa]
4354 : Real64 const Pbz, // Barometric pressure at entrance level [Pa]
4355 : Real64 &RhoDr // Air density of dry air on the link level used
4356 : )
4357 : {
4358 :
4359 : // FUNCTION INFORMATION:
4360 : // AUTHOR Lixing Gu
4361 : // DATE WRITTEN Oct. 2005
4362 : // MODIFIED na
4363 : // RE-ENGINEERED This subroutine is revised based on subroutine IClimb from COMIS
4364 :
4365 : // PURPOSE OF THIS SUBROUTINE:
4366 : // This function the differential pressure from the reflevel in a zone To Z, the level of a link
4367 :
4368 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4369 : Real64 H; // Start Height of the layer
4370 : Real64 BetaT; // Temperature gradient of this layer
4371 : Real64 BetaXfct; // Humidity gradient factor of this layer
4372 : Real64 BetaCfct; // Concentration 1 gradient factor of this layer
4373 : Real64 X0;
4374 : Real64 P;
4375 : Real64 Htop;
4376 : Real64 Hbot;
4377 : Real64 Rho0;
4378 : Real64 Rho1;
4379 : Real64 BetaRho;
4380 : static int L(0);
4381 : static int ilayptr(0);
4382 :
4383 18224810 : Dp = 0.0;
4384 18224810 : Rho0 = Rho;
4385 18224810 : X0 = X;
4386 18224810 : if (Z > 0.0) {
4387 : // initialize start values
4388 18224810 : H = 0.0;
4389 18224810 : BetaT = 0.0;
4390 18224810 : BetaXfct = 0.0;
4391 18224810 : BetaCfct = 0.0;
4392 18224810 : BetaRho = 0.0;
4393 18224810 : Hbot = 0.0;
4394 :
4395 18224810 : while (H < 0.0) {
4396 : // loop until H>0 ; The start of the layer is above 0
4397 0 : BetaT = 0.0;
4398 0 : BetaXfct = 0.0;
4399 0 : BetaCfct = 0.0;
4400 0 : L += 9;
4401 0 : ilayptr = 0;
4402 0 : if (zone == 0) {
4403 0 : ilayptr = 9;
4404 : }
4405 0 : if (L >= ilayptr) {
4406 0 : H = Z + 1.0;
4407 : } else {
4408 0 : H = 0.0;
4409 : }
4410 : }
4411 :
4412 : // The link is in this layer also if it is on the top of it.
4413 :
4414 : while (true) {
4415 36449620 : if (H >= Z) {
4416 : // the link ends in this layer , we reached the final Dp and BetaRho
4417 18224810 : Htop = Z;
4418 18224810 : P = PZ + Dp;
4419 18224810 : if (Htop != Hbot) {
4420 18224810 : Rho0 = state.afn->properties.density(Pbz + P, T, X);
4421 18224810 : T += (Htop - Hbot) * BetaT;
4422 18224810 : X += (Htop - Hbot) * BetaXfct * X0;
4423 18224810 : Rho1 = state.afn->properties.density(Pbz + P, T, X);
4424 18224810 : BetaRho = (Rho1 - Rho0) / (Htop - Hbot);
4425 18224810 : Dp += psz(Pbz + P, Rho0, BetaRho, Hbot, Htop, G);
4426 : }
4427 18224810 : RhoDr = state.afn->properties.density(Pbz + PZ + Dp, T, X);
4428 18224810 : Rho = state.afn->properties.density(Pbz + PZ + Dp, T, X);
4429 18224810 : return;
4430 :
4431 : } else {
4432 : // bottom of the layer is below Z (Z above ref)
4433 18224810 : Htop = H;
4434 : // P is the pressure up to the start height of the layer we just reached
4435 18224810 : P = PZ + Dp;
4436 18224810 : if (Htop != Hbot) {
4437 0 : Rho0 = state.afn->properties.density(Pbz + P, T, X);
4438 0 : T += (Htop - Hbot) * BetaT;
4439 0 : X += (Htop - Hbot) * BetaXfct * X0;
4440 0 : Rho1 = state.afn->properties.density(Pbz + P, T, X);
4441 0 : BetaRho = (Rho1 - Rho0) / (Htop - Hbot);
4442 0 : Dp += psz(Pbz + P, Rho0, BetaRho, Hbot, Htop, G);
4443 : }
4444 :
4445 18224810 : RhoDr = state.afn->properties.density(Pbz + PZ + Dp, T, X);
4446 18224810 : Rho = state.afn->properties.density(Pbz + PZ + Dp, T, X);
4447 :
4448 : // place current values Hbot and Beta's
4449 18224810 : Hbot = H;
4450 18224810 : BetaT = 0.0;
4451 18224810 : BetaXfct = 0.0;
4452 18224810 : BetaCfct = 0.0;
4453 18224810 : L += 9;
4454 18224810 : ilayptr = 0;
4455 18224810 : if (zone == 0) {
4456 18224810 : ilayptr = 9;
4457 : }
4458 18224810 : if (L >= ilayptr) {
4459 18224810 : H = Z + 1.0;
4460 : } else {
4461 0 : H = 0.0;
4462 : }
4463 : }
4464 : }
4465 :
4466 : } else {
4467 : // This is the ELSE for negative linkheights Z below the refplane
4468 0 : H = 0.0;
4469 0 : BetaT = 0.0;
4470 0 : BetaXfct = 0.0;
4471 0 : BetaCfct = 0.0;
4472 0 : BetaRho = 0.0;
4473 0 : Htop = 0.0;
4474 0 : while (H > 0.0) {
4475 : // loop until H<0 ; The start of the layer is below the zone refplane
4476 0 : L -= 9;
4477 0 : ilayptr = 0;
4478 0 : if (zone == 0) {
4479 0 : ilayptr = 1;
4480 : }
4481 0 : if (L < ilayptr) {
4482 : // with H=Z (negative) this loop will exit, no data for interval Z-refplane
4483 0 : H = Z;
4484 0 : BetaT = 0.0;
4485 0 : BetaXfct = 0.0;
4486 0 : BetaCfct = 0.0;
4487 0 : BetaRho = 0.0;
4488 : } else {
4489 0 : H = 0.0;
4490 0 : BetaT = 0.0;
4491 0 : BetaXfct = 0.0;
4492 0 : BetaCfct = 0.0;
4493 : }
4494 : }
4495 :
4496 : // The link is in this layer also if it is on the bottom of it.
4497 : while (true) {
4498 0 : if (H <= Z) {
4499 0 : Hbot = Z;
4500 0 : P = PZ + Dp;
4501 0 : if (Htop != Hbot) {
4502 0 : Rho1 = state.afn->properties.density(Pbz + P, T, X);
4503 0 : T += (Hbot - Htop) * BetaT;
4504 0 : X += (Hbot - Htop) * BetaXfct * X0;
4505 0 : Rho0 = state.afn->properties.density(Pbz + P, T, X);
4506 0 : BetaRho = (Rho1 - Rho0) / (Htop - Hbot);
4507 0 : Dp -= psz(Pbz + P, Rho0, BetaRho, Hbot, Htop, G);
4508 : }
4509 0 : RhoDr = state.afn->properties.density(Pbz + PZ + Dp, T, X);
4510 0 : Rho = state.afn->properties.density(Pbz + PZ + Dp, T, X);
4511 0 : return;
4512 : } else {
4513 : // bottom of the layer is below Z (Z below ref)
4514 0 : Hbot = H;
4515 0 : P = PZ + Dp;
4516 0 : if (Htop != Hbot) {
4517 0 : Rho1 = state.afn->properties.density(Pbz + P, T, X);
4518 : // T,X,C calculated for the lower height
4519 0 : T += (Hbot - Htop) * BetaT;
4520 0 : X += (Hbot - Htop) * BetaXfct * X0;
4521 0 : Rho0 = state.afn->properties.density(Pbz + P, T, X);
4522 0 : BetaRho = (Rho1 - Rho0) / (Htop - Hbot);
4523 0 : Dp -= psz(Pbz + P, Rho0, BetaRho, Hbot, Htop, G);
4524 : }
4525 0 : RhoDr = state.afn->properties.density(Pbz + PZ + Dp, T, X);
4526 0 : Rho = state.afn->properties.density(Pbz + PZ + Dp, T, X);
4527 :
4528 : // place current values Hbot and Beta's
4529 0 : Htop = H;
4530 0 : L -= 9;
4531 0 : ilayptr = 0;
4532 0 : if (zone == 0) {
4533 0 : ilayptr = 1;
4534 : }
4535 0 : if (L < ilayptr) {
4536 0 : H = Z - 1.0;
4537 0 : BetaT = 0.0;
4538 0 : BetaXfct = 0.0;
4539 0 : BetaCfct = 0.0;
4540 : } else {
4541 0 : H = 0.0;
4542 0 : BetaT = 0.0;
4543 0 : BetaXfct = 0.0;
4544 0 : BetaCfct = 0.0;
4545 : }
4546 : }
4547 : // ENDIF H<Z
4548 : }
4549 : }
4550 : }
4551 :
4552 : } // namespace AirflowNetwork
4553 :
4554 : } // namespace EnergyPlus
|