Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cassert>
50 :
51 : // EnergyPlus Headers
52 : #include <EnergyPlus/Data/EnergyPlusData.hh>
53 : #include <EnergyPlus/DataGlobals.hh>
54 : #include <EnergyPlus/TARCOGArgs.hh>
55 : #include <EnergyPlus/TARCOGCommon.hh>
56 : #include <EnergyPlus/TARCOGGasses90.hh>
57 : #include <EnergyPlus/TARCOGGassesParams.hh>
58 : #include <EnergyPlus/TARCOGParams.hh>
59 : #include <EnergyPlus/TarcogShading.hh>
60 : #include <EnergyPlus/ThermalISO15099Calc.hh>
61 :
62 : namespace EnergyPlus::ThermalISO15099Calc {
63 : //***********************************************************************
64 : // ThermalISO15099Calc: a TARCOG module
65 : // module For Calculation of Thermal Performance Indices For Center
66 : // of Glass According to ISO 15099
67 : // History of Revisions:
68 : // Revision: 6.0.36 (June/22/2010)
69 : // - Initial setup, extracted and refactored from TARCOG.for
70 : //***********************************************************************
71 :
72 : // MODULE INFORMATION:
73 : // AUTHOR D. Charlie Curcija
74 : // DATE WRITTEN July/2000
75 : // MODIFIED na
76 : // RE-ENGINEERED March/27/2012, Simon Vidanovic
77 :
78 : // Revision: 7.0.13 (March/27/2012), Simon Vidanovic
79 : // - feature: New set of equations is set instead of hhat coefficients and new approach to solution which improves
80 : // speed and stability. Note that this solution does not include laminates
81 :
82 : // PURPOSE OF THIS MODULE:
83 : // Module For Calculation of Thermal Performance Indices For Center
84 : // of Glass According to ISO 15099
85 :
86 : // Using/Aliasing
87 : using namespace TARCOGGassesParams;
88 : using namespace TARCOGParams;
89 : using namespace TARCOGArgs;
90 : using namespace TARCOGCommon;
91 : using namespace TARCOGOutput;
92 : using namespace TARCOGGasses90;
93 : using namespace TarcogShading;
94 :
95 : // Calculation outcome
96 : enum class CalculationOutcome
97 : {
98 : Invalid = -1,
99 : OK,
100 : Num
101 : };
102 :
103 0 : void film(Real64 const tex, Real64 const tw, Real64 const ws, int const iwd, Real64 &hcout, int const ibc)
104 : {
105 : //***********************************************************************
106 : // purpose - to find outdoor film coeff
107 : //***********************************************************************
108 : // Inputs -
109 : // tex - outdoor air temp [k]
110 : // tw - outside surface temp
111 : // ws - wind speed [m/s]
112 : // iwd - wind direction [0 - windward; 1 - leeward]
113 : // Outputs
114 : // hcout - convective film coeff [w m-2 k-1]
115 :
116 : // Locals
117 0 : Real64 constexpr conv(5.6783);
118 :
119 : Real64 vc;
120 : Real64 acoef;
121 : Real64 bexp;
122 :
123 : // calculation of convection component of exterior film coefficient using the :
124 0 : switch (ibc) {
125 0 : case 0: { // ISO 15099
126 0 : hcout = 4.0 + 4.0 * ws;
127 0 : } break;
128 0 : case -1: { // old ASHRAE SPC142 correlation
129 0 : if (iwd == 0) { // windward
130 0 : if (ws > 2.0) {
131 0 : vc = 0.25 * ws;
132 : } else {
133 0 : vc = 0.5;
134 : }
135 : } else { // leeward
136 0 : vc = 0.3 + 0.05 * ws;
137 : }
138 0 : hcout = 3.28 * std::pow(vc, 0.605);
139 0 : hcout *= conv; // convert to metric
140 0 : } break;
141 0 : case -2: { // Yazdanian-Klems correlation:
142 0 : if (iwd == 0) { // windward
143 0 : acoef = 2.38;
144 0 : bexp = 0.89;
145 : } else { // leeward
146 0 : acoef = 2.86;
147 0 : bexp = 0.617;
148 : }
149 0 : hcout = std::sqrt(pow_2(0.84 * std::pow(tw - tex, 0.33)) + pow_2(acoef * std::pow(ws, bexp)));
150 0 : } break;
151 0 : case -3: { // Kimura correlation (Section 8.4.2.3 in ISO 15099-2001):
152 0 : if (iwd == 0) { // windward
153 0 : if (ws > 2.0) {
154 0 : vc = 0.25 * ws;
155 : } else {
156 0 : vc = 0.5 * ws;
157 : }
158 : } else { // leeward
159 0 : vc = 0.3 + 0.05 * ws;
160 : }
161 0 : hcout = 4.7 + 7.6 * vc;
162 0 : } break;
163 0 : default:
164 0 : break;
165 : }
166 0 : }
167 :
168 0 : void Calc_ISO15099(EnergyPlusData &state,
169 : Files &files,
170 : int const nlayer,
171 : int const iwd,
172 : Real64 &tout,
173 : Real64 &tind,
174 : Real64 &trmin,
175 : Real64 const wso,
176 : Real64 const wsi,
177 : Real64 const dir,
178 : Real64 const outir,
179 : int const isky,
180 : Real64 const tsky,
181 : Real64 &esky,
182 : Real64 const fclr,
183 : Real64 const VacuumPressure,
184 : Real64 const VacuumMaxGapThickness,
185 : Array1D<Real64> &gap,
186 : Array1D<Real64> &thick,
187 : Array1D<Real64> &scon,
188 : const Array1D<Real64> &tir,
189 : const Array1D<Real64> &emis,
190 : Real64 const totsol,
191 : Real64 const tilt,
192 : const Array1D<Real64> &asol,
193 : Real64 const height,
194 : Real64 const heightt,
195 : Real64 const width,
196 : const Array1D<Real64> &presure,
197 : Array2A_int const iprop,
198 : Array2A<Real64> const frct,
199 : Array2A<Real64> const xgcon,
200 : Array2A<Real64> const xgvis,
201 : Array2A<Real64> const xgcp,
202 : const Array1D<Real64> &xwght,
203 : const Array1D<Real64> &gama,
204 : const Array1D_int &nmix,
205 : const Array1D_int &SupportPillar,
206 : const Array1D<Real64> &PillarSpacing,
207 : const Array1D<Real64> &PillarRadius,
208 : Array1D<Real64> &theta,
209 : Array1D<Real64> &q,
210 : Array1D<Real64> &qv,
211 : Real64 &ufactor,
212 : Real64 &sc,
213 : Real64 &hflux,
214 : Real64 &hcin,
215 : Real64 &hcout,
216 : Real64 &hrin,
217 : Real64 &hrout,
218 : Real64 &hin,
219 : Real64 &hout,
220 : Array1D<Real64> &hcgas,
221 : Array1D<Real64> &hrgas,
222 : Real64 &shgc,
223 : int &nperr,
224 : std::string &ErrorMessage,
225 : Real64 &shgct,
226 : Real64 &tamb,
227 : Real64 &troom,
228 : const Array1D_int &ibc,
229 : const Array1D<Real64> &Atop,
230 : const Array1D<Real64> &Abot,
231 : const Array1D<Real64> &Al,
232 : const Array1D<Real64> &Ar,
233 : const Array1D<Real64> &Ah,
234 : const Array1D<Real64> &SlatThick,
235 : const Array1D<Real64> &SlatWidth,
236 : const Array1D<Real64> &SlatAngle,
237 : const Array1D<Real64> &SlatCond,
238 : const Array1D<Real64> &SlatSpacing,
239 : const Array1D<Real64> &SlatCurve,
240 : const Array1D<Real64> &vvent,
241 : const Array1D<Real64> &tvent,
242 : const Array1D<TARCOGLayerType> &LayerType,
243 : const Array1D_int &nslice,
244 : const Array1D<Real64> &LaminateA,
245 : const Array1D<Real64> &LaminateB,
246 : const Array1D<Real64> &sumsol,
247 : Array1D<Real64> &Ra,
248 : Array1D<Real64> &Nu,
249 : TARCOGThermalModel const ThermalMod,
250 : int const Debug_mode,
251 : Real64 &ShadeEmisRatioOut,
252 : Real64 &ShadeEmisRatioIn,
253 : Real64 &ShadeHcRatioOut,
254 : Real64 &ShadeHcRatioIn,
255 : Real64 &HcUnshadedOut,
256 : Real64 &HcUnshadedIn,
257 : Array1D<Real64> &Keff,
258 : Array1D<Real64> &ShadeGapKeffConv,
259 : Real64 const SDScalar,
260 : int const SHGCCalc,
261 : int &NumOfIterations,
262 : Real64 const edgeGlCorrFac)
263 : {
264 :
265 : // Argument array dimensioning
266 0 : EP_SIZE_CHECK(gap, MaxGap);
267 0 : EP_SIZE_CHECK(thick, maxlay);
268 0 : EP_SIZE_CHECK(scon, maxlay);
269 0 : EP_SIZE_CHECK(tir, maxlay2);
270 0 : EP_SIZE_CHECK(emis, maxlay2);
271 0 : EP_SIZE_CHECK(asol, maxlay);
272 0 : EP_SIZE_CHECK(presure, maxlay1);
273 0 : iprop.dim(maxgas, maxlay1);
274 0 : frct.dim(maxgas, maxlay1);
275 0 : xgcon.dim(3, maxgas);
276 0 : xgvis.dim(3, maxgas);
277 0 : xgcp.dim(3, maxgas);
278 0 : EP_SIZE_CHECK(xwght, maxgas);
279 0 : EP_SIZE_CHECK(gama, maxgas);
280 0 : EP_SIZE_CHECK(nmix, maxlay1);
281 0 : EP_SIZE_CHECK(SupportPillar, maxlay);
282 0 : EP_SIZE_CHECK(PillarSpacing, maxlay);
283 0 : EP_SIZE_CHECK(PillarRadius, maxlay);
284 0 : EP_SIZE_CHECK(theta, maxlay2);
285 0 : EP_SIZE_CHECK(q, maxlay3);
286 0 : EP_SIZE_CHECK(qv, maxlay1);
287 0 : EP_SIZE_CHECK(hcgas, maxlay1);
288 0 : EP_SIZE_CHECK(hrgas, maxlay1);
289 0 : EP_SIZE_CHECK(ibc, 2);
290 0 : EP_SIZE_CHECK(Atop, maxlay);
291 0 : EP_SIZE_CHECK(Abot, maxlay);
292 0 : EP_SIZE_CHECK(Al, maxlay);
293 0 : EP_SIZE_CHECK(Ar, maxlay);
294 0 : EP_SIZE_CHECK(Ah, maxlay);
295 0 : EP_SIZE_CHECK(SlatThick, maxlay);
296 0 : EP_SIZE_CHECK(SlatWidth, maxlay);
297 0 : EP_SIZE_CHECK(SlatAngle, maxlay);
298 0 : EP_SIZE_CHECK(SlatCond, maxlay);
299 0 : EP_SIZE_CHECK(SlatSpacing, maxlay);
300 0 : EP_SIZE_CHECK(SlatCurve, maxlay);
301 0 : EP_SIZE_CHECK(vvent, maxlay1);
302 0 : EP_SIZE_CHECK(tvent, maxlay1);
303 0 : EP_SIZE_CHECK(LayerType, maxlay);
304 0 : EP_SIZE_CHECK(nslice, maxlay);
305 0 : EP_SIZE_CHECK(LaminateA, maxlay);
306 0 : EP_SIZE_CHECK(LaminateB, maxlay);
307 0 : EP_SIZE_CHECK(sumsol, maxlay);
308 0 : EP_SIZE_CHECK(Ra, maxlay);
309 0 : EP_SIZE_CHECK(Nu, maxlay);
310 0 : EP_SIZE_CHECK(Keff, maxlay);
311 0 : EP_SIZE_CHECK(ShadeGapKeffConv, MaxGap);
312 :
313 : // REAL(r64) :: grho(maxgas,3)
314 : Real64 shgct_NOSD;
315 : Real64 trmout;
316 :
317 : Real64 Gout;
318 : Real64 Gin;
319 : Real64 AchievedErrorTolerance;
320 : Real64 AchievedErrorToleranceSolar;
321 : int NumOfIter;
322 : int NumOfIterSolar;
323 :
324 : Real64 tgg;
325 : Real64 qc1;
326 : Real64 qc2;
327 : Real64 qcgg;
328 :
329 : Real64 ShadeHcModifiedOut;
330 : Real64 ShadeHcModifiedIn;
331 :
332 : // cbi...Variables for "unshaded" run:
333 :
334 : bool NeedUnshadedRun;
335 : int nlayer_NOSD;
336 : Real64 AchievedErrorTolerance_NOSD;
337 : int NumOfIter_NOSD;
338 : Real64 hin_NOSD;
339 : Real64 flux_NOSD;
340 : Real64 hcin_NOSD;
341 : Real64 hrin_NOSD;
342 : Real64 hcout_NOSD;
343 : Real64 hrout_NOSD;
344 : Real64 tamb_NOSD;
345 : Real64 troom_NOSD;
346 : Real64 ufactor_NOSD;
347 : Real64 sc_NOSD;
348 : Real64 hflux_NOSD;
349 : Real64 shgc_NOSD;
350 : Real64 hout_NOSD;
351 : // REAL(r64) :: rs_NOSD(maxlay3)!,sol(maxlay)
352 : Real64 ShadeEmisRatioOut_NOSD;
353 : Real64 ShadeEmisRatioIn_NOSD;
354 : Real64 ShadeHcRatioOut_NOSD;
355 : Real64 ShadeHcRatioIn_NOSD;
356 : Real64 ShadeHcModifiedOut_NOSD;
357 : Real64 ShadeHcModifiedIn_NOSD;
358 :
359 : int FirstSpecularLayer;
360 : int LastSpecularLayer;
361 :
362 : // cbi...Other variables:
363 : Real64 flux;
364 : Real64 hint;
365 : Real64 houtt;
366 : Real64 ebsky;
367 : Real64 ebroom;
368 : int i;
369 : int j;
370 : int OriginalIndex;
371 : int UnshadedDebug;
372 :
373 : // Autodesk:Uninit Initialize variables used uninitialized
374 0 : shgc_NOSD = 0.0; // Autodesk:Uninit Force default initialization
375 0 : sc_NOSD = 0.0; // Autodesk:Uninit Force default initialization
376 0 : hflux_NOSD = 0.0; // Autodesk:Uninit Force default initialization
377 0 : ShadeHcRatioIn_NOSD = 0.0; // Autodesk:Uninit Force default initialization
378 0 : ShadeHcRatioOut_NOSD = 0.0; // Autodesk:Uninit Force default initialization
379 :
380 0 : AchievedErrorTolerance = 0.0;
381 0 : AchievedErrorToleranceSolar = 0.0;
382 0 : AchievedErrorTolerance_NOSD = 0.0;
383 :
384 0 : PrepVariablesISO15099(nlayer,
385 : tout,
386 : tind,
387 : trmin,
388 : isky,
389 : outir,
390 : tsky,
391 : esky,
392 : fclr,
393 : gap,
394 : thick,
395 : scon,
396 : tir,
397 : emis,
398 : tilt,
399 : hin,
400 : hout,
401 : ibc,
402 : SlatThick,
403 : SlatWidth,
404 : SlatAngle,
405 : SlatCond,
406 : LayerType,
407 : ThermalMod,
408 : SDScalar,
409 : ShadeEmisRatioOut,
410 : ShadeEmisRatioIn,
411 : ShadeHcRatioOut,
412 : ShadeHcRatioIn,
413 : Keff,
414 : ShadeGapKeffConv,
415 : sc,
416 : shgc,
417 : ufactor,
418 : flux,
419 0 : state.dataThermalISO15099Calc->LaminateAU,
420 0 : state.dataThermalISO15099Calc->sumsolU,
421 0 : state.dataThermalISO15099Calc->sol0,
422 : hint,
423 : houtt,
424 : trmout,
425 : ebsky,
426 : ebroom,
427 : Gout,
428 : Gin,
429 0 : state.dataThermalISO15099Calc->rir,
430 0 : state.dataThermalISO15099Calc->vfreevent,
431 : nperr,
432 : ErrorMessage);
433 :
434 0 : for (int i = 1; i <= nlayer; ++i) {
435 0 : state.dataThermalISO15099Calc->EffectiveOpenness(i) = Ah(i) / (width * height);
436 : }
437 :
438 0 : updateEffectiveMultipliers(nlayer,
439 : width,
440 : height,
441 : Atop,
442 : Abot,
443 : Al,
444 : Ar,
445 : Ah,
446 0 : state.dataThermalISO15099Calc->Atop_eff,
447 0 : state.dataThermalISO15099Calc->Abot_eff,
448 0 : state.dataThermalISO15099Calc->Al_eff,
449 0 : state.dataThermalISO15099Calc->Ar_eff,
450 0 : state.dataThermalISO15099Calc->Ah_eff,
451 : LayerType,
452 : SlatAngle);
453 :
454 : // No option to take hardcoded variables. All gas coefficients are now passed from outside.
455 : // if (GoAhead(nperr)) call propcon90(ISO15099,mgas,xgcon,xgvis,xgcp,xgrho,xwght,nperr)
456 :
457 : // exit on error
458 0 : if (!(GoAhead(nperr))) return;
459 :
460 : // bi...Write intermediate results to output file:
461 0 : if (files.WriteDebugOutput) {
462 0 : WriteModifiedArguments(files.DebugOutputFile,
463 0 : files.DBGD,
464 : esky,
465 : trmout,
466 : trmin,
467 : ebsky,
468 : ebroom,
469 : Gout,
470 : Gin,
471 : nlayer,
472 : LayerType,
473 : nmix,
474 : frct,
475 : thick,
476 : scon,
477 : gap,
478 : xgcon,
479 : xgvis,
480 : xgcp,
481 : xwght);
482 : }
483 :
484 : // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
485 : // This is "solar radiation" pass
486 : // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
487 :
488 : // This is main calculation in case UFactor calculations will not be performed
489 0 : if ((dir > 0.0) || (SHGCCalc == 0)) {
490 : // call therm1d to calculate heat flux with solar radiation
491 :
492 0 : therm1d(state,
493 : files,
494 : nlayer,
495 : iwd,
496 : tout,
497 : tind,
498 : wso,
499 : wsi,
500 : VacuumPressure,
501 : VacuumMaxGapThickness,
502 : dir,
503 : ebsky,
504 : Gout,
505 : trmout,
506 : trmin,
507 : ebroom,
508 : Gin,
509 : tir,
510 0 : state.dataThermalISO15099Calc->rir,
511 : emis,
512 : gap,
513 : thick,
514 : scon,
515 : tilt,
516 : asol,
517 : height,
518 : heightt,
519 : width,
520 : iprop,
521 : frct,
522 : presure,
523 : nmix,
524 : xwght,
525 : xgcon,
526 : xgvis,
527 : xgcp,
528 : gama,
529 : SupportPillar,
530 : PillarSpacing,
531 : PillarRadius,
532 : theta,
533 : q,
534 : qv,
535 : flux,
536 : hcin,
537 : hrin,
538 : hcout,
539 : hrout,
540 : hin,
541 : hout,
542 : hcgas,
543 : hrgas,
544 : ufactor,
545 : nperr,
546 : ErrorMessage,
547 : tamb,
548 : troom,
549 : ibc,
550 0 : state.dataThermalISO15099Calc->Atop_eff,
551 0 : state.dataThermalISO15099Calc->Abot_eff,
552 0 : state.dataThermalISO15099Calc->Al_eff,
553 0 : state.dataThermalISO15099Calc->Ar_eff,
554 0 : state.dataThermalISO15099Calc->Ah_eff,
555 0 : state.dataThermalISO15099Calc->EffectiveOpenness,
556 : vvent,
557 : tvent,
558 : LayerType,
559 : Ra,
560 : Nu,
561 0 : state.dataThermalISO15099Calc->vfreevent,
562 0 : state.dataThermalISO15099Calc->qcgas,
563 0 : state.dataThermalISO15099Calc->qrgas,
564 0 : state.dataThermalISO15099Calc->Ebf,
565 0 : state.dataThermalISO15099Calc->Ebb,
566 0 : state.dataThermalISO15099Calc->Rf,
567 0 : state.dataThermalISO15099Calc->Rb,
568 : ShadeEmisRatioOut,
569 : ShadeEmisRatioIn,
570 : ShadeHcModifiedOut,
571 : ShadeHcModifiedIn,
572 : ThermalMod,
573 : Debug_mode,
574 : AchievedErrorToleranceSolar,
575 : NumOfIterSolar,
576 : edgeGlCorrFac);
577 :
578 0 : NumOfIterations = NumOfIterSolar;
579 : // exit on error:
580 :
581 0 : if (nlayer > 1) {
582 0 : for (i = 1; i <= nlayer - 1; ++i) {
583 0 : Keff(i) = gap(i) * q(2 * i + 1) / (theta(2 * i + 1) - theta(2 * i));
584 0 : if (IsShadingLayer(LayerType(i))) {
585 0 : Keff(i) = gap(i) * q(2 * i + 1) / (theta(2 * i + 1) - theta(2 * i));
586 : }
587 0 : if (IsShadingLayer(LayerType(i + 1))) {
588 0 : Keff(i) = gap(i) * q(2 * i + 1) / (theta(2 * i + 1) - theta(2 * i));
589 : }
590 : }
591 : }
592 :
593 0 : if (!(GoAhead(nperr))) return;
594 :
595 : // No need to store results in case of non-ufactor run
596 0 : if ((SHGCCalc > 0) && (dir > 0.0)) {
597 0 : solarISO15099(
598 0 : totsol, state.dataThermalISO15099Calc->rtot, state.dataThermalISO15099Calc->rs, nlayer, asol, state.dataThermalISO15099Calc->sft);
599 0 : shgct = state.dataThermalISO15099Calc->sft;
600 0 : shgct_NOSD = 0.0;
601 0 : state.dataThermalISO15099Calc->hcins = hcin;
602 0 : state.dataThermalISO15099Calc->hrins = hrin;
603 0 : state.dataThermalISO15099Calc->hins = hin;
604 0 : state.dataThermalISO15099Calc->hcouts = hcout;
605 0 : state.dataThermalISO15099Calc->hrouts = hrout;
606 0 : state.dataThermalISO15099Calc->houts = hout;
607 0 : state.dataThermalISO15099Calc->ufactors = ufactor;
608 0 : state.dataThermalISO15099Calc->fluxs = flux;
609 0 : for (i = 1; i <= nlayer; ++i) {
610 0 : state.dataThermalISO15099Calc->thetas(2 * i - 1) = theta(2 * i - 1);
611 0 : state.dataThermalISO15099Calc->thetas(2 * i) = theta(2 * i);
612 0 : state.dataThermalISO15099Calc->Ebbs(i) = state.dataThermalISO15099Calc->Ebb(i);
613 0 : state.dataThermalISO15099Calc->Ebfs(i) = state.dataThermalISO15099Calc->Ebf(i);
614 0 : state.dataThermalISO15099Calc->Rbs(i) = state.dataThermalISO15099Calc->Rb(i);
615 0 : state.dataThermalISO15099Calc->Rfs(i) = state.dataThermalISO15099Calc->Rf(i);
616 0 : state.dataThermalISO15099Calc->qs(2 * i - 1) = q(2 * i - 1);
617 0 : state.dataThermalISO15099Calc->qs(2 * i) = q(2 * i);
618 : // qprims(2*i - 1) = qprim(2*i - 1)
619 : // qprims(2*i) = qprim(2*i)
620 0 : state.dataThermalISO15099Calc->qvs(2 * i - 1) = qv(2 * i - 1);
621 0 : state.dataThermalISO15099Calc->qvs(2 * i) = qv(2 * i);
622 0 : state.dataThermalISO15099Calc->hcgass(i) = hcgas(i);
623 0 : state.dataThermalISO15099Calc->hrgass(i) = hrgas(i);
624 0 : state.dataThermalISO15099Calc->qrgaps(i) = state.dataThermalISO15099Calc->qrgas(i);
625 0 : state.dataThermalISO15099Calc->qcgaps(i) = state.dataThermalISO15099Calc->qcgas(i);
626 : }
627 : // CHECK THIS!
628 0 : state.dataThermalISO15099Calc->qs(2 * nlayer + 1) = q(2 * nlayer + 1);
629 : } // if (UFactorCalc.gt.0) then
630 : }
631 :
632 : // No solar radiation pass is not needed to be calculated
633 : // if ((SHGCCalc.gt.0).or.(dir.eq.0)) then
634 0 : if (SHGCCalc > 0) {
635 :
636 : // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
637 : // This is "no solar radiation" pass
638 : // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
639 :
640 0 : hin = hint;
641 0 : hout = houtt;
642 :
643 : // call therm1d to calculate heat flux without solar radiation
644 0 : therm1d(state,
645 : files,
646 : nlayer,
647 : iwd,
648 : tout,
649 : tind,
650 : wso,
651 : wsi,
652 : VacuumPressure,
653 : VacuumMaxGapThickness,
654 : 0.0,
655 : ebsky,
656 : Gout,
657 : trmout,
658 : trmin,
659 : ebroom,
660 : Gin,
661 : tir,
662 0 : state.dataThermalISO15099Calc->rir,
663 : emis,
664 : gap,
665 : thick,
666 : scon,
667 : tilt,
668 0 : state.dataThermalISO15099Calc->sol0,
669 : height,
670 : heightt,
671 : width,
672 : iprop,
673 : frct,
674 : presure,
675 : nmix,
676 : xwght,
677 : xgcon,
678 : xgvis,
679 : xgcp,
680 : gama,
681 : SupportPillar,
682 : PillarSpacing,
683 : PillarRadius,
684 : theta,
685 : q,
686 : qv,
687 : flux,
688 : hcin,
689 : hrin,
690 : hcout,
691 : hrout,
692 : hin,
693 : hout,
694 : hcgas,
695 : hrgas,
696 : ufactor,
697 : nperr,
698 : ErrorMessage,
699 : tamb,
700 : troom,
701 : ibc,
702 0 : state.dataThermalISO15099Calc->Atop_eff,
703 0 : state.dataThermalISO15099Calc->Abot_eff,
704 0 : state.dataThermalISO15099Calc->Al_eff,
705 0 : state.dataThermalISO15099Calc->Ar_eff,
706 0 : state.dataThermalISO15099Calc->Ah_eff,
707 0 : state.dataThermalISO15099Calc->EffectiveOpenness,
708 : vvent,
709 : tvent,
710 : LayerType,
711 : Ra,
712 : Nu,
713 0 : state.dataThermalISO15099Calc->vfreevent,
714 0 : state.dataThermalISO15099Calc->qcgas,
715 0 : state.dataThermalISO15099Calc->qrgas,
716 0 : state.dataThermalISO15099Calc->Ebf,
717 0 : state.dataThermalISO15099Calc->Ebb,
718 0 : state.dataThermalISO15099Calc->Rf,
719 0 : state.dataThermalISO15099Calc->Rb,
720 : ShadeEmisRatioOut,
721 : ShadeEmisRatioIn,
722 : ShadeHcModifiedOut,
723 : ShadeHcModifiedIn,
724 : ThermalMod,
725 : Debug_mode,
726 : AchievedErrorTolerance,
727 : NumOfIter,
728 : edgeGlCorrFac);
729 :
730 0 : NumOfIterations = NumOfIter;
731 :
732 : // exit on error:
733 0 : if (!(GoAhead(nperr))) return;
734 :
735 : // bi...Keep hcout, hcin in case this is an unshaded system:
736 0 : HcUnshadedOut = hcout;
737 0 : HcUnshadedIn = hcin;
738 :
739 : // bi...do an Unshaded run if necessary (Uvalue/Winter conditions):
740 : // bi...Prepare variables for UNSHADED (NO SD) run:
741 :
742 0 : NeedUnshadedRun = false;
743 0 : FirstSpecularLayer = 1;
744 0 : LastSpecularLayer = nlayer;
745 0 : nlayer_NOSD = nlayer;
746 0 : if (IsShadingLayer(LayerType(1))) {
747 0 : --nlayer_NOSD;
748 0 : FirstSpecularLayer = 2;
749 0 : NeedUnshadedRun = true;
750 : }
751 :
752 : // if (LayerType(nlayer).eq.VENETBLIND) then
753 0 : if (IsShadingLayer(LayerType(nlayer))) {
754 0 : --nlayer_NOSD;
755 0 : LastSpecularLayer = nlayer - 1;
756 0 : NeedUnshadedRun = true;
757 : }
758 :
759 : // no unshaded run for now
760 0 : NeedUnshadedRun = false;
761 : // bi...Set outdoor & indoor gas properties:
762 0 : if (NeedUnshadedRun) {
763 0 : state.dataThermalISO15099Calc->nmix_NOSD(1) = nmix(1);
764 0 : state.dataThermalISO15099Calc->presure_NOSD(1) = presure(1);
765 0 : state.dataThermalISO15099Calc->nmix_NOSD(nlayer_NOSD + 1) = nmix(nlayer + 1);
766 0 : state.dataThermalISO15099Calc->presure_NOSD(nlayer_NOSD + 1) = presure(nlayer + 1);
767 0 : for (j = 1; j <= nmix(1); ++j) {
768 0 : state.dataThermalISO15099Calc->iprop_NOSD(j, 1) = iprop(j, 1);
769 0 : state.dataThermalISO15099Calc->frct_NOSD(j, 1) = frct(j, 1);
770 : }
771 0 : for (j = 1; j <= nmix(nlayer_NOSD + 1); ++j) {
772 0 : state.dataThermalISO15099Calc->iprop_NOSD(j, nlayer_NOSD + 1) = iprop(j, nlayer + 1);
773 0 : state.dataThermalISO15099Calc->frct_NOSD(j, nlayer_NOSD + 1) = frct(j, nlayer + 1);
774 : }
775 0 : for (i = 1; i <= nlayer_NOSD; ++i) {
776 0 : OriginalIndex = FirstSpecularLayer + i - 1;
777 0 : state.dataThermalISO15099Calc->Atop_NOSD(i) = state.dataThermalISO15099Calc->Atop_eff(OriginalIndex);
778 0 : state.dataThermalISO15099Calc->Abot_NOSD(i) = state.dataThermalISO15099Calc->Abot_eff(OriginalIndex);
779 0 : state.dataThermalISO15099Calc->Al_NOSD(i) = state.dataThermalISO15099Calc->Al_eff(OriginalIndex);
780 0 : state.dataThermalISO15099Calc->Ar_NOSD(i) = state.dataThermalISO15099Calc->Ar_eff(OriginalIndex);
781 0 : state.dataThermalISO15099Calc->Ah_NOSD(i) = state.dataThermalISO15099Calc->Ah_eff(OriginalIndex);
782 :
783 0 : state.dataThermalISO15099Calc->SlatThick_NOSD(i) = SlatThick(OriginalIndex);
784 0 : state.dataThermalISO15099Calc->SlatWidth_NOSD(i) = SlatWidth(OriginalIndex);
785 0 : state.dataThermalISO15099Calc->SlatAngle_NOSD(i) = SlatAngle(OriginalIndex);
786 0 : state.dataThermalISO15099Calc->SlatCond_NOSD(i) = SlatCond(OriginalIndex);
787 0 : state.dataThermalISO15099Calc->SlatSpacing_NOSD(i) = SlatSpacing(OriginalIndex);
788 0 : state.dataThermalISO15099Calc->SlatCurve_NOSD(i) = SlatCurve(OriginalIndex);
789 :
790 : // cbi... TO do when Forced Ventilation is implemented: take care of appropriate arguments!!!
791 : // vvent_NOSD
792 : // tvent_NOSD
793 :
794 0 : state.dataThermalISO15099Calc->LayerType_NOSD(i) = LayerType(OriginalIndex);
795 :
796 0 : state.dataThermalISO15099Calc->thick_NOSD(i) = thick(OriginalIndex);
797 0 : state.dataThermalISO15099Calc->scon_NOSD(i) = scon(OriginalIndex);
798 0 : state.dataThermalISO15099Calc->tir_NOSD(2 * i - 1) = tir(2 * OriginalIndex - 1);
799 0 : state.dataThermalISO15099Calc->emis_NOSD(2 * i - 1) = emis(2 * OriginalIndex - 1);
800 0 : state.dataThermalISO15099Calc->emis_NOSD(2 * i) = emis(2 * OriginalIndex);
801 0 : state.dataThermalISO15099Calc->rir_NOSD(2 * i - 1) = state.dataThermalISO15099Calc->rir(2 * OriginalIndex - 1);
802 0 : state.dataThermalISO15099Calc->rir_NOSD(2 * i) = state.dataThermalISO15099Calc->rir(2 * OriginalIndex);
803 :
804 0 : state.dataThermalISO15099Calc->gap_NOSD(i) = gap(OriginalIndex);
805 :
806 0 : if (i < nlayer_NOSD) {
807 0 : state.dataThermalISO15099Calc->nmix_NOSD(i + 1) = nmix(OriginalIndex + 1);
808 0 : state.dataThermalISO15099Calc->presure_NOSD(i + 1) = presure(OriginalIndex + 1);
809 0 : for (j = 1; j <= state.dataThermalISO15099Calc->nmix_NOSD(i + 1); ++j) {
810 0 : state.dataThermalISO15099Calc->iprop_NOSD(j, i + 1) = iprop(j, OriginalIndex + 1);
811 0 : state.dataThermalISO15099Calc->frct_NOSD(j, i + 1) = frct(j, OriginalIndex + 1);
812 : }
813 : }
814 :
815 0 : state.dataThermalISO15099Calc->LaminateA_NOSD(i) = LaminateA(OriginalIndex);
816 0 : state.dataThermalISO15099Calc->LaminateB_NOSD(i) = LaminateB(OriginalIndex);
817 0 : state.dataThermalISO15099Calc->sumsol_NOSD(i) = sumsol(OriginalIndex);
818 :
819 0 : state.dataThermalISO15099Calc->nslice_NOSD(i) = nslice(OriginalIndex);
820 : }
821 :
822 : // This is UNSHADED pass - no solar radiation:
823 0 : hin_NOSD = hint;
824 0 : hout_NOSD = houtt;
825 :
826 : // Simon: Removed unshaded debug output for now
827 0 : UnshadedDebug = 0;
828 0 : if (files.WriteDebugOutput && (UnshadedDebug == 1)) {
829 0 : print(files.DebugOutputFile, "\n");
830 0 : print(files.DebugOutputFile, "UNSHADED RUN:\n");
831 0 : print(files.DebugOutputFile, "\n");
832 :
833 0 : WriteInputArguments(state,
834 0 : files.DebugOutputFile,
835 0 : files.DBGD,
836 : tout,
837 : tind,
838 : trmin,
839 : wso,
840 : iwd,
841 : wsi,
842 : dir,
843 : outir,
844 : isky,
845 : tsky,
846 : esky,
847 : fclr,
848 : VacuumPressure,
849 : VacuumMaxGapThickness,
850 : ibc,
851 : hout_NOSD,
852 : hin_NOSD,
853 : TARCOGGassesParams::Stdrd::ISO15099,
854 : ThermalMod,
855 : SDScalar,
856 : height,
857 : heightt,
858 : width,
859 : tilt,
860 : totsol,
861 : nlayer_NOSD,
862 0 : state.dataThermalISO15099Calc->LayerType_NOSD,
863 0 : state.dataThermalISO15099Calc->thick_NOSD,
864 0 : state.dataThermalISO15099Calc->scon_NOSD,
865 : asol,
866 0 : state.dataThermalISO15099Calc->tir_NOSD,
867 0 : state.dataThermalISO15099Calc->emis_NOSD,
868 0 : state.dataThermalISO15099Calc->Atop_NOSD,
869 0 : state.dataThermalISO15099Calc->Abot_NOSD,
870 0 : state.dataThermalISO15099Calc->Al_NOSD,
871 0 : state.dataThermalISO15099Calc->Ar_NOSD,
872 0 : state.dataThermalISO15099Calc->Ah_NOSD,
873 0 : state.dataThermalISO15099Calc->SlatThick_NOSD,
874 0 : state.dataThermalISO15099Calc->SlatWidth_NOSD,
875 0 : state.dataThermalISO15099Calc->SlatAngle_NOSD,
876 0 : state.dataThermalISO15099Calc->SlatCond_NOSD,
877 0 : state.dataThermalISO15099Calc->SlatSpacing_NOSD,
878 0 : state.dataThermalISO15099Calc->SlatCurve_NOSD,
879 0 : state.dataThermalISO15099Calc->nslice_NOSD,
880 0 : state.dataThermalISO15099Calc->LaminateA_NOSD,
881 0 : state.dataThermalISO15099Calc->LaminateB_NOSD,
882 0 : state.dataThermalISO15099Calc->sumsol_NOSD,
883 0 : state.dataThermalISO15099Calc->gap_NOSD,
884 0 : state.dataThermalISO15099Calc->vvent_NOSD,
885 0 : state.dataThermalISO15099Calc->tvent_NOSD,
886 0 : state.dataThermalISO15099Calc->presure_NOSD,
887 0 : state.dataThermalISO15099Calc->nmix_NOSD,
888 0 : state.dataThermalISO15099Calc->iprop_NOSD,
889 0 : state.dataThermalISO15099Calc->frct_NOSD,
890 : xgcon,
891 : xgvis,
892 : xgcp,
893 : xwght);
894 :
895 : } // end if UnshadedDebug = 1
896 :
897 : // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
898 : // This is "Unshaded, No solar radiation" pass
899 : // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
900 : // call therm1d to calculate heat flux with solar radiation
901 0 : therm1d(state,
902 : files,
903 : nlayer_NOSD,
904 : iwd,
905 : tout,
906 : tind,
907 : wso,
908 : wsi,
909 : VacuumPressure,
910 : VacuumMaxGapThickness,
911 : 0.0,
912 : ebsky,
913 : Gout,
914 : trmout,
915 : trmin,
916 : ebroom,
917 : Gin,
918 0 : state.dataThermalISO15099Calc->tir_NOSD,
919 0 : state.dataThermalISO15099Calc->rir_NOSD,
920 0 : state.dataThermalISO15099Calc->emis_NOSD,
921 0 : state.dataThermalISO15099Calc->gap_NOSD,
922 0 : state.dataThermalISO15099Calc->thick_NOSD,
923 0 : state.dataThermalISO15099Calc->scon_NOSD,
924 : tilt,
925 0 : state.dataThermalISO15099Calc->sol0,
926 : height,
927 : heightt,
928 : width,
929 0 : state.dataThermalISO15099Calc->iprop_NOSD,
930 0 : state.dataThermalISO15099Calc->frct_NOSD,
931 0 : state.dataThermalISO15099Calc->presure_NOSD,
932 0 : state.dataThermalISO15099Calc->nmix_NOSD,
933 : xwght,
934 : xgcon,
935 : xgvis,
936 : xgcp,
937 : gama,
938 : SupportPillar,
939 : PillarSpacing,
940 : PillarRadius,
941 0 : state.dataThermalISO15099Calc->theta_NOSD,
942 0 : state.dataThermalISO15099Calc->q_NOSD,
943 0 : state.dataThermalISO15099Calc->qv_NOSD,
944 : flux_NOSD,
945 : hcin_NOSD,
946 : hrin_NOSD,
947 : hcout_NOSD,
948 : hrout_NOSD,
949 : hin_NOSD,
950 : hout_NOSD,
951 0 : state.dataThermalISO15099Calc->hcgas_NOSD,
952 0 : state.dataThermalISO15099Calc->hrgas_NOSD,
953 : ufactor_NOSD,
954 : nperr,
955 : ErrorMessage,
956 : tamb_NOSD,
957 : troom_NOSD,
958 : ibc,
959 0 : state.dataThermalISO15099Calc->Atop_NOSD,
960 0 : state.dataThermalISO15099Calc->Abot_NOSD,
961 0 : state.dataThermalISO15099Calc->Al_NOSD,
962 0 : state.dataThermalISO15099Calc->Ar_NOSD,
963 0 : state.dataThermalISO15099Calc->Ah_NOSD,
964 0 : state.dataThermalISO15099Calc->EffectiveOpenness_NOSD,
965 0 : state.dataThermalISO15099Calc->vvent_NOSD,
966 0 : state.dataThermalISO15099Calc->tvent_NOSD,
967 0 : state.dataThermalISO15099Calc->LayerType_NOSD,
968 0 : state.dataThermalISO15099Calc->Ra_NOSD,
969 0 : state.dataThermalISO15099Calc->Nu_NOSD,
970 0 : state.dataThermalISO15099Calc->vfreevent_NOSD,
971 0 : state.dataThermalISO15099Calc->qcgas_NOSD,
972 0 : state.dataThermalISO15099Calc->qrgas_NOSD,
973 0 : state.dataThermalISO15099Calc->Ebf_NOSD,
974 0 : state.dataThermalISO15099Calc->Ebb_NOSD,
975 0 : state.dataThermalISO15099Calc->Rf_NOSD,
976 0 : state.dataThermalISO15099Calc->Rb_NOSD,
977 : ShadeEmisRatioOut_NOSD,
978 : ShadeEmisRatioIn_NOSD,
979 : ShadeHcModifiedOut_NOSD,
980 : ShadeHcModifiedIn_NOSD,
981 : ThermalMod,
982 : Debug_mode,
983 : AchievedErrorTolerance_NOSD,
984 : NumOfIter_NOSD,
985 : edgeGlCorrFac);
986 :
987 0 : NumOfIterations = NumOfIter_NOSD;
988 : // exit on error
989 0 : if (!(GoAhead(nperr))) return;
990 :
991 : // bi... Keep these values:
992 0 : HcUnshadedOut = hcout_NOSD;
993 0 : HcUnshadedIn = hcin_NOSD;
994 :
995 0 : ShadeHcRatioOut = ShadeHcModifiedOut / HcUnshadedOut;
996 0 : ShadeHcRatioIn = ShadeHcModifiedIn / HcUnshadedIn;
997 :
998 : // bi...unshaded results:
999 0 : if (files.WriteDebugOutput && (UnshadedDebug == 1)) {
1000 0 : WriteOutputArguments(files.DebugOutputFile,
1001 0 : files.DBGD,
1002 : nlayer_NOSD,
1003 : tamb,
1004 0 : state.dataThermalISO15099Calc->q_NOSD,
1005 0 : state.dataThermalISO15099Calc->qv_NOSD,
1006 0 : state.dataThermalISO15099Calc->qcgas_NOSD,
1007 0 : state.dataThermalISO15099Calc->qrgas_NOSD,
1008 0 : state.dataThermalISO15099Calc->theta_NOSD,
1009 0 : state.dataThermalISO15099Calc->vfreevent_NOSD,
1010 0 : state.dataThermalISO15099Calc->vvent_NOSD,
1011 0 : state.dataThermalISO15099Calc->Keff_NOSD,
1012 0 : state.dataThermalISO15099Calc->ShadeGapKeffConv_NOSD,
1013 : troom_NOSD,
1014 : ufactor_NOSD,
1015 : shgc_NOSD,
1016 : sc_NOSD,
1017 : hflux_NOSD,
1018 : shgct_NOSD,
1019 : hcin_NOSD,
1020 : hrin_NOSD,
1021 : hcout_NOSD,
1022 : hrout_NOSD,
1023 0 : state.dataThermalISO15099Calc->Ra_NOSD,
1024 0 : state.dataThermalISO15099Calc->Nu_NOSD,
1025 0 : state.dataThermalISO15099Calc->LayerType_NOSD,
1026 0 : state.dataThermalISO15099Calc->Ebf_NOSD,
1027 0 : state.dataThermalISO15099Calc->Ebb_NOSD,
1028 0 : state.dataThermalISO15099Calc->Rf_NOSD,
1029 0 : state.dataThermalISO15099Calc->Rb_NOSD,
1030 : ebsky,
1031 : Gout,
1032 : ebroom,
1033 : Gin,
1034 : ShadeEmisRatioIn_NOSD,
1035 : ShadeEmisRatioOut_NOSD,
1036 : ShadeHcRatioIn_NOSD,
1037 : ShadeHcRatioOut_NOSD,
1038 : hcin_NOSD,
1039 : hcout_NOSD,
1040 0 : state.dataThermalISO15099Calc->hcgas_NOSD,
1041 0 : state.dataThermalISO15099Calc->hrgas_NOSD,
1042 : AchievedErrorTolerance_NOSD,
1043 : NumOfIter_NOSD); // Autodesk:Uninit shgc_NOSD, sc_NOSD, hflux_NOSD,
1044 : // ShadeHcRatioIn_NOSD, ShadeHcRatioOut_NOSD were
1045 : // uninitialized
1046 : } // end if UnshadedDebug = 1
1047 : } // end if NeedUnshadedRun...
1048 :
1049 : // bi Set T6-related quantities keff, keffc: (using non-solar pass results)
1050 0 : if (nlayer > 1) {
1051 0 : for (i = 1; i <= nlayer - 1; ++i) {
1052 0 : Keff(i) = gap(i) * q(2 * i + 1) / (theta(2 * i + 1) - theta(2 * i));
1053 0 : if (IsShadingLayer(LayerType(i))) {
1054 0 : Keff(i) = gap(i) * q(2 * i + 1) / (theta(2 * i + 1) - theta(2 * i));
1055 : }
1056 0 : if (IsShadingLayer(LayerType(i + 1))) {
1057 0 : Keff(i) = gap(i) * q(2 * i + 1) / (theta(2 * i + 1) - theta(2 * i));
1058 : }
1059 0 : if (IsShadingLayer(LayerType(i))) {
1060 : // Keff(i) = gap(i) * qprim(2*i+1) / (theta(2*i+1) - theta(2*i))
1061 0 : if ((i > 1) && (i < nlayer)) {
1062 0 : tgg = gap(i - 1) + gap(i) + thick(i);
1063 0 : qc1 = state.dataThermalISO15099Calc->qcgas(i - 1);
1064 0 : qc2 = state.dataThermalISO15099Calc->qcgas(i);
1065 0 : qcgg = (qc1 + qc2) / 2.0;
1066 0 : ShadeGapKeffConv(i) = tgg * qcgg / (theta(2 * i + 1) - theta(2 * i - 2));
1067 : }
1068 : }
1069 : }
1070 : }
1071 :
1072 : } // if (UFactorCalc.ne.0) then
1073 :
1074 : // bi... For debugging purposes:
1075 0 : state.dataThermalISO15099Calc->qeff = ufactor * std::abs(tout - tind);
1076 0 : state.dataThermalISO15099Calc->flux_nonsolar = flux;
1077 :
1078 0 : if ((SHGCCalc > 0) && (dir > 0.0)) {
1079 0 : shgc = totsol - (state.dataThermalISO15099Calc->fluxs - flux) / dir;
1080 0 : sc = shgc / 0.87;
1081 0 : hcin = state.dataThermalISO15099Calc->hcins;
1082 0 : hrin = state.dataThermalISO15099Calc->hrins;
1083 0 : hin = state.dataThermalISO15099Calc->hins;
1084 0 : hcout = state.dataThermalISO15099Calc->hcouts;
1085 0 : hrout = state.dataThermalISO15099Calc->hrouts;
1086 0 : hout = state.dataThermalISO15099Calc->houts;
1087 0 : flux = state.dataThermalISO15099Calc->fluxs; // <--- ???
1088 0 : for (i = 1; i <= nlayer; ++i) {
1089 0 : theta(2 * i - 1) = state.dataThermalISO15099Calc->thetas(2 * i - 1);
1090 0 : theta(2 * i) = state.dataThermalISO15099Calc->thetas(2 * i);
1091 0 : state.dataThermalISO15099Calc->Ebb(i) = state.dataThermalISO15099Calc->Ebbs(i);
1092 0 : state.dataThermalISO15099Calc->Ebf(i) = state.dataThermalISO15099Calc->Ebfs(i);
1093 0 : state.dataThermalISO15099Calc->Rb(i) = state.dataThermalISO15099Calc->Rbs(i);
1094 0 : state.dataThermalISO15099Calc->Rf(i) = state.dataThermalISO15099Calc->Rfs(i);
1095 0 : q(2 * i - 1) = state.dataThermalISO15099Calc->qs(2 * i - 1);
1096 0 : q(2 * i) = state.dataThermalISO15099Calc->qs(2 * i);
1097 : // qprim(2*i - 1) = qprims(2*i - 1)
1098 : // qprim(2*i) = qprims(2*i)
1099 0 : qv(2 * i - 1) = state.dataThermalISO15099Calc->qvs(2 * i - 1);
1100 0 : qv(2 * i) = state.dataThermalISO15099Calc->qvs(2 * i);
1101 0 : hcgas(i) = state.dataThermalISO15099Calc->hcgass(i);
1102 0 : hrgas(i) = state.dataThermalISO15099Calc->hrgass(i);
1103 0 : state.dataThermalISO15099Calc->qcgas(i) = state.dataThermalISO15099Calc->qcgaps(i);
1104 0 : state.dataThermalISO15099Calc->qrgas(i) = state.dataThermalISO15099Calc->qrgaps(i);
1105 0 : AchievedErrorTolerance = AchievedErrorToleranceSolar;
1106 0 : NumOfIter = NumOfIterSolar;
1107 : }
1108 :
1109 : // bi CHECK THIS!
1110 0 : q(2 * nlayer + 1) = state.dataThermalISO15099Calc->qs(2 * nlayer + 1);
1111 : }
1112 :
1113 0 : hflux = flux; // save flux value for output table
1114 :
1115 : // bi... Write results to debug output file:
1116 0 : if (files.WriteDebugOutput) {
1117 0 : WriteOutputArguments(files.DebugOutputFile,
1118 0 : files.DBGD,
1119 : nlayer,
1120 : tamb,
1121 : q,
1122 : qv,
1123 0 : state.dataThermalISO15099Calc->qcgas,
1124 0 : state.dataThermalISO15099Calc->qrgas,
1125 : theta,
1126 0 : state.dataThermalISO15099Calc->vfreevent,
1127 : vvent,
1128 : Keff,
1129 : ShadeGapKeffConv,
1130 : troom,
1131 : ufactor,
1132 : shgc,
1133 : sc,
1134 : hflux,
1135 : shgct,
1136 : hcin,
1137 : hrin,
1138 : hcout,
1139 : hrout,
1140 : Ra,
1141 : Nu,
1142 : LayerType,
1143 0 : state.dataThermalISO15099Calc->Ebf,
1144 0 : state.dataThermalISO15099Calc->Ebb,
1145 0 : state.dataThermalISO15099Calc->Rf,
1146 0 : state.dataThermalISO15099Calc->Rb,
1147 : ebsky,
1148 : Gout,
1149 : ebroom,
1150 : Gin,
1151 : ShadeEmisRatioIn,
1152 : ShadeEmisRatioOut,
1153 : ShadeHcRatioIn,
1154 : ShadeHcRatioOut,
1155 : HcUnshadedIn,
1156 : HcUnshadedOut,
1157 : hcgas,
1158 : hrgas,
1159 : AchievedErrorTolerance,
1160 : NumOfIter);
1161 : } // if WriteDebugOutput.eq.true - writing output file
1162 : }
1163 :
1164 0 : void therm1d(EnergyPlusData &state,
1165 : Files &files,
1166 : int const nlayer,
1167 : int const iwd,
1168 : Real64 &tout,
1169 : Real64 &tind,
1170 : Real64 const wso,
1171 : Real64 const wsi,
1172 : Real64 const VacuumPressure,
1173 : Real64 const VacuumMaxGapThickness,
1174 : Real64 const dir,
1175 : Real64 &ebsky,
1176 : Real64 const Gout,
1177 : Real64 const trmout,
1178 : Real64 const trmin,
1179 : Real64 &ebroom,
1180 : Real64 const Gin,
1181 : const Array1D<Real64> &tir,
1182 : const Array1D<Real64> &rir,
1183 : const Array1D<Real64> &emis,
1184 : const Array1D<Real64> &gap,
1185 : const Array1D<Real64> &thick,
1186 : const Array1D<Real64> &scon,
1187 : Real64 const tilt,
1188 : const Array1D<Real64> &asol,
1189 : Real64 const height,
1190 : Real64 const heightt,
1191 : Real64 const width,
1192 : Array2_int const &iprop,
1193 : Array2<Real64> const &frct,
1194 : const Array1D<Real64> &presure,
1195 : const Array1D_int &nmix,
1196 : const Array1D<Real64> &wght,
1197 : Array2<Real64> const &gcon,
1198 : Array2<Real64> const &gvis,
1199 : Array2<Real64> const &gcp,
1200 : const Array1D<Real64> &gama,
1201 : const Array1D_int &SupportPillar,
1202 : const Array1D<Real64> &PillarSpacing,
1203 : const Array1D<Real64> &PillarRadius,
1204 : Array1D<Real64> &theta,
1205 : Array1D<Real64> &q,
1206 : Array1D<Real64> &qv,
1207 : Real64 &flux,
1208 : Real64 &hcin,
1209 : Real64 &hrin,
1210 : Real64 &hcout,
1211 : Real64 &hrout,
1212 : Real64 const hin,
1213 : Real64 const hout,
1214 : Array1D<Real64> &hcgas,
1215 : Array1D<Real64> &hrgas,
1216 : Real64 &ufactor,
1217 : int &nperr,
1218 : std::string &ErrorMessage,
1219 : Real64 &tamb,
1220 : Real64 &troom,
1221 : const Array1D_int &ibc,
1222 : const Array1D<Real64> &Atop,
1223 : const Array1D<Real64> &Abot,
1224 : const Array1D<Real64> &Al,
1225 : const Array1D<Real64> &Ar,
1226 : const Array1D<Real64> &Ah,
1227 : const Array1D<Real64> &EffectiveOpenness,
1228 : const Array1D<Real64> &vvent,
1229 : const Array1D<Real64> &tvent,
1230 : const Array1D<TARCOGLayerType> &LayerType,
1231 : Array1D<Real64> &Ra,
1232 : Array1D<Real64> &Nu,
1233 : Array1D<Real64> &vfreevent,
1234 : Array1D<Real64> &qcgas,
1235 : Array1D<Real64> &qrgas,
1236 : Array1D<Real64> &Ebf,
1237 : Array1D<Real64> &Ebb,
1238 : Array1D<Real64> &Rf,
1239 : Array1D<Real64> &Rb,
1240 : Real64 &ShadeEmisRatioOut,
1241 : Real64 &ShadeEmisRatioIn,
1242 : Real64 &ShadeHcModifiedOut,
1243 : Real64 &ShadeHcModifiedIn,
1244 : TARCOGThermalModel ThermalMod,
1245 : [[maybe_unused]] int const Debug_mode,
1246 : Real64 &AchievedErrorTolerance,
1247 : int &TotalIndex,
1248 : Real64 const edgeGlCorrFac)
1249 : {
1250 : //********************************************************************************
1251 : // Main subroutine for calculation of 1-D heat transfer in the center of glazing.
1252 : //********************************************************************************
1253 : // Inputs
1254 : // nlayer number of solid layers
1255 : // iwd wind direction
1256 : // tout outside temp in k
1257 : // tind inside temp in k
1258 : // wso wind speed in m/s
1259 : // wsi inside forced air speed m/s
1260 : // Ebsky ir flux from outside
1261 : // Gout back facing radiosity from outside
1262 : // Trmout Mean outdoor radiant temperature
1263 : // Trmin Mean indoor radiant temperature
1264 : // Ebroom ir flux from room
1265 : // Gin front facing radiosity from room
1266 : // tir ir transmittance of each layer
1267 : // rir ir reflectance of each surface
1268 : // emis ir emittances of each surface
1269 : // gap array of gap widths in meters
1270 : // thick thickness of glazing layers (m)
1271 : // scon Vector of conductivities of 'glazing' layers
1272 : // tilt Window tilt (deg). vert: tilt=90, hor out up: tilt=0, hor out down: tilt=180
1273 : // sol absorbed solar energy for each layer in w/m2
1274 : // height glazing cavity height
1275 : // heightt
1276 : // iprop
1277 : // frct
1278 : // presure
1279 : // nmix vector of number of gasses in a mixture for each gap
1280 : // hin convective indoor film coefficient (if non-zero hin input)
1281 : // hout convective outdoor film coeff. (if non-zero hout input)
1282 : // outputs
1283 : // theta temp distribution in k
1284 : // flux net heat flux between room and window
1285 : // rtot overall thermal resistance
1286 : // rs ?
1287 : // hcin convective indoor film coeff.
1288 : // hrin radiative part of indoor film coeff.
1289 : // hcout convective outdoor film coeff.
1290 : // hrout radiative part of outdoor film coeff.
1291 : // hin convective indoor film coefficient
1292 : // hout convective outdoor film coeff.
1293 : // ufactor overall u-factor
1294 : // qcgap vector of convective/conductive parts of flux in gaps
1295 : // qrgap vector of radiative parts of flux in gaps
1296 : // nperr
1297 : // *Inactives**
1298 : // wa - window azimuth (degrees, clockwise from south)
1299 : // hgas matrix of gap film coefficients
1300 : // Locals
1301 : // Ebb Vector
1302 : // Ebf Vector
1303 : // Rb Vector
1304 : // Rf Vector
1305 : // a Array
1306 : // b Array
1307 : // hhat Vector
1308 : // err iteration tolerance
1309 : // dtmax max temp difference after iteration
1310 : // index iteration step
1311 :
1312 : // Using
1313 : // Locals
1314 : // 0 - don't create debug output files
1315 : // 1 - append results to existing debug output file
1316 : // 2 - store results in new debug output file
1317 : // 3 - save in-between results (in all iterations) to existing debug file
1318 :
1319 0 : Array2D<Real64> a(4 * nlayer, 4 * nlayer);
1320 0 : Array1D<Real64> b(4 * nlayer);
1321 : // REAL(r64) :: hhatv(maxlay3),hcv(maxlay3), Ebgap(maxlay3), Tgap(maxlay1)
1322 :
1323 : // REAL(r64) :: alpha
1324 : int maxiter;
1325 :
1326 : Real64 qr_gap_out;
1327 : Real64 qr_gap_in;
1328 :
1329 0 : Array1D<Real64> told(2 * nlayer);
1330 :
1331 : // Simon: parameters used in case of JCFN iteration method
1332 0 : Array1D<Real64> FRes({1, 4 * nlayer}); // store function results from current iteration
1333 0 : Array1D<Real64> FResOld({1, 4 * nlayer}); // store function results from previous iteration
1334 0 : Array1D<Real64> FResDiff({1, 4 * nlayer}); // save difference in results between iterations
1335 0 : Array1D<Real64> Radiation({1, 2 * nlayer}); // radiation on layer surfaces. used as temporary storage during iterations
1336 :
1337 0 : Array1D<Real64> x({1, 4 * nlayer}); // temporary vector for storing results (theta and Radiation). used for easier handling
1338 0 : Array1D<Real64> dX({1, 4 * nlayer}, 0.0); // difference in results
1339 0 : Array2D<Real64> Jacobian({1, 4 * nlayer}, {1, 4 * nlayer}); // diagonal vector for jacobian computation-free newton method
1340 0 : Array1D<Real64> DRes({1, 4 * nlayer}); // used in jacobian forward-difference approximation
1341 :
1342 : // This is used to store matrix before equation solver. It is important because solver destroys
1343 : // content of matrices
1344 0 : Array2D<Real64> LeftHandSide({1, 4 * nlayer}, {1, 4 * nlayer});
1345 0 : Array1D<Real64> RightHandSide({1, 4 * nlayer});
1346 :
1347 : // Simon: Keep best achieved convergence
1348 : Real64 prevDifference;
1349 : Real64 Relaxation;
1350 0 : Array1D<Real64> RadiationSave({1, 2 * nlayer});
1351 0 : Array1D<Real64> thetaSave({1, 2 * nlayer});
1352 : int currentTry;
1353 :
1354 : int CSMFlag;
1355 : int i;
1356 : int j;
1357 : int k;
1358 : Real64 curDifference;
1359 : int index;
1360 : int curTempCorrection;
1361 :
1362 : Real64 qc_gap_in;
1363 : Real64 hc_modified_in;
1364 :
1365 : CalculationOutcome CalcOutcome;
1366 :
1367 : bool iterationsFinished; // To mark whether or not iterations are finished
1368 : bool saveIterationResults;
1369 : bool updateGapTemperature;
1370 : // logical :: TurnOnNewton
1371 :
1372 0 : int SDLayerIndex = -1;
1373 :
1374 0 : Array1D<Real64> sconScaled(maxlay);
1375 :
1376 : // Simon: This is set to zero until it is resolved what to do with modifier
1377 0 : ShadeHcModifiedOut = 0.0;
1378 0 : CSMFlag = 0;
1379 0 : CalcOutcome = CalculationOutcome::Invalid;
1380 0 : curTempCorrection = 0;
1381 0 : AchievedErrorTolerance = 0.0;
1382 0 : curDifference = 0.0;
1383 0 : currentTry = 0;
1384 0 : index = 0;
1385 0 : TotalIndex = 0;
1386 0 : iterationsFinished = false;
1387 0 : qv = 0.0;
1388 0 : Ebb = 0.0;
1389 0 : Ebf = 0.0;
1390 0 : Rb = 0.0;
1391 0 : Rf = 0.0;
1392 0 : a = 0.0;
1393 0 : b = 0.0;
1394 :
1395 0 : FRes = 0.0;
1396 0 : FResOld = 0.0;
1397 0 : FResDiff = 0.0;
1398 0 : Radiation = 0.0;
1399 0 : Relaxation = RelaxationStart;
1400 :
1401 0 : maxiter = NumOfIterations;
1402 :
1403 0 : saveIterationResults = false;
1404 :
1405 0 : for (i = 1; i <= nlayer; ++i) {
1406 0 : k = 2 * i;
1407 0 : Radiation(k) = Ebb(i);
1408 0 : Radiation(k - 1) = Ebf(i);
1409 0 : told(k - 1) = 0.0;
1410 0 : told(k) = 0.0;
1411 : }
1412 :
1413 : // bi...Set LayerTypeSpec array - need to treat venetians AND woven shades as glass:
1414 0 : if (ThermalMod == TARCOGThermalModel::CSM) {
1415 0 : for (i = 1; i <= nlayer; ++i) {
1416 0 : if (IsShadingLayer(LayerType(i))) {
1417 : // LayerTypeSpec( i ) = 0; //Unused
1418 0 : SDLayerIndex = i;
1419 : } else {
1420 : // LayerTypeSpec( i ) = LayerType( i ); //Unused
1421 : }
1422 : }
1423 : }
1424 :
1425 : // first store results before iterations begin
1426 0 : if (saveIterationResults) {
1427 0 : storeIterationResults(state,
1428 : files,
1429 : nlayer,
1430 : index,
1431 : theta,
1432 : trmout,
1433 : tamb,
1434 : trmin,
1435 : troom,
1436 : ebsky,
1437 : ebroom,
1438 : hcin,
1439 : hcout,
1440 : hrin,
1441 : hrout,
1442 : hin,
1443 : hout,
1444 : Ebb,
1445 : Ebf,
1446 : Rb,
1447 : Rf,
1448 : nperr);
1449 : }
1450 :
1451 0 : state.dataThermalISO15099Calc->Tgap(1) = tout;
1452 0 : state.dataThermalISO15099Calc->Tgap(nlayer + 1) = tind;
1453 0 : for (i = 2; i <= nlayer; ++i) {
1454 0 : state.dataThermalISO15099Calc->Tgap(i) = (theta(2 * i - 1) + theta(2 * i - 2)) / 2;
1455 : }
1456 : //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1457 : //!!! MAIN ITERATION LOOP
1458 : //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1459 0 : while (!(iterationsFinished)) {
1460 :
1461 0 : for (i = 1; i <= 2 * nlayer; ++i) {
1462 0 : if (theta(i) < 0) {
1463 0 : theta(i) = 1.0 * i;
1464 : }
1465 : }
1466 :
1467 : // do i=1,nlayer+1
1468 : // if (i == 1) then
1469 : // Tgap(i) = tout
1470 : // else if (i == nlayer+1) then
1471 : // Tgap(i) = tind
1472 : // else
1473 : // Tgap(i) = (theta(2*i-2) + theta(2*i-1)) / 2.0d0
1474 : // end if
1475 : // end do
1476 :
1477 : // skip updating gap temperatures for shading devices. Gap temperature in that case is not simply average
1478 : // between two layer temperatures
1479 0 : for (i = 2; i <= nlayer; ++i) {
1480 0 : updateGapTemperature = false;
1481 0 : if ((!(IsShadingLayer(LayerType(i - 1)))) && (!(IsShadingLayer(LayerType(i))))) {
1482 0 : updateGapTemperature = true;
1483 : }
1484 0 : if (updateGapTemperature) {
1485 0 : state.dataThermalISO15099Calc->Tgap(i) = (theta(2 * i - 1) + theta(2 * i - 2)) / 2;
1486 : }
1487 : }
1488 :
1489 : // evaluate convective/conductive components of gap
1490 0 : hatter(state,
1491 : nlayer,
1492 : iwd,
1493 : tout,
1494 : tind,
1495 : wso,
1496 : wsi,
1497 : VacuumPressure,
1498 : VacuumMaxGapThickness,
1499 : ebsky,
1500 : tamb,
1501 : ebroom,
1502 : troom,
1503 : gap,
1504 : height,
1505 : heightt,
1506 : scon,
1507 : tilt,
1508 : theta,
1509 0 : state.dataThermalISO15099Calc->Tgap,
1510 : Radiation,
1511 : trmout,
1512 : trmin,
1513 : iprop,
1514 : frct,
1515 : presure,
1516 : nmix,
1517 : wght,
1518 : gcon,
1519 : gvis,
1520 : gcp,
1521 : gama,
1522 : SupportPillar,
1523 : PillarSpacing,
1524 : PillarRadius,
1525 0 : state.dataThermalISO15099Calc->hgas,
1526 : hcgas,
1527 : hrgas,
1528 : hcin,
1529 : hcout,
1530 : hin,
1531 : hout,
1532 : index,
1533 : ibc,
1534 : nperr,
1535 : ErrorMessage,
1536 : hrin,
1537 : hrout,
1538 : Ra,
1539 : Nu);
1540 :
1541 0 : effectiveLayerCond(state,
1542 : nlayer,
1543 : LayerType,
1544 : scon,
1545 : thick,
1546 : iprop,
1547 : frct,
1548 : nmix,
1549 : presure,
1550 : wght,
1551 : gcon,
1552 : gvis,
1553 : gcp,
1554 : EffectiveOpenness,
1555 : theta,
1556 : sconScaled,
1557 : nperr,
1558 : ErrorMessage);
1559 :
1560 : // exit on error
1561 0 : if (!(GoAhead(nperr))) return;
1562 :
1563 : // bi...Override hhat values near SHADING DEVICE layer(s), but only for CSM thermal model:
1564 0 : if ((ThermalMod == TARCOGThermalModel::CSM) && (SDLayerIndex > 0)) {
1565 : // adjust hhat values
1566 : // call adjusthhat(SDLayerIndex, ibc, tout, tind, nlayer, theta, wso, wsi, iwd, height, heightt, tilt, &
1567 : // & thick, gap, hout, hrout, hin, hrin, iprop, frct, presure, nmix, wght, gcon, gvis, gcp, &
1568 : // index, SDScalar, Ebf, Ebb, hgas, hhat, nperr, ErrorMessage)
1569 : // do i = 1, maxlay3
1570 : // hhatv(i) = 0.0d0
1571 : // Ebgap(i) = 0.0d0
1572 : // qv(i) = 0.0d0
1573 : // hcv(i) = 0.0d0
1574 : // end do
1575 0 : matrixQBalance(nlayer,
1576 : a,
1577 : b,
1578 : sconScaled,
1579 : hcgas,
1580 0 : state.dataThermalISO15099Calc->hcgapMod,
1581 : asol,
1582 : qv,
1583 0 : state.dataThermalISO15099Calc->hcv,
1584 : tind,
1585 : tout,
1586 : Gin,
1587 : Gout,
1588 : theta,
1589 : tir,
1590 : rir,
1591 : emis,
1592 : edgeGlCorrFac);
1593 : } else {
1594 : // bi...There are no Venetian layers, or ThermalMod is not CSM, so carry on as usual:
1595 0 : shading(state,
1596 : theta,
1597 : gap,
1598 0 : state.dataThermalISO15099Calc->hgas,
1599 : hcgas,
1600 : hrgas,
1601 : frct,
1602 : iprop,
1603 : presure,
1604 : nmix,
1605 : wght,
1606 : gcon,
1607 : gvis,
1608 : gcp,
1609 : nlayer,
1610 : width,
1611 : height,
1612 : tilt,
1613 : tout,
1614 : tind,
1615 : Atop,
1616 : Abot,
1617 : Al,
1618 : Ar,
1619 : Ah,
1620 : vvent,
1621 : tvent,
1622 : LayerType,
1623 0 : state.dataThermalISO15099Calc->Tgap,
1624 : qv,
1625 0 : state.dataThermalISO15099Calc->hcv,
1626 : nperr,
1627 : ErrorMessage,
1628 : vfreevent);
1629 :
1630 : // exit on error
1631 0 : if (!(GoAhead(nperr))) return;
1632 :
1633 0 : matrixQBalance(nlayer,
1634 : a,
1635 : b,
1636 : sconScaled,
1637 : hcgas,
1638 0 : state.dataThermalISO15099Calc->hcgapMod,
1639 : asol,
1640 : qv,
1641 0 : state.dataThermalISO15099Calc->hcv,
1642 : tind,
1643 : tout,
1644 : Gin,
1645 : Gout,
1646 : theta,
1647 : tir,
1648 : rir,
1649 : emis,
1650 : edgeGlCorrFac);
1651 :
1652 : } // end if
1653 :
1654 0 : FResOld = FRes;
1655 :
1656 : // Pack results in one array
1657 0 : for (i = 1; i <= nlayer; ++i) {
1658 0 : k = 4 * i - 3;
1659 0 : j = 2 * i - 1;
1660 :
1661 0 : x(k) = theta(j);
1662 0 : x(k + 1) = Radiation(j);
1663 0 : x(k + 2) = Radiation(j + 1);
1664 0 : x(k + 3) = theta(j + 1);
1665 : }
1666 :
1667 0 : CalculateFuncResults(nlayer, a, b, x, FRes);
1668 :
1669 0 : FResDiff = FRes - FResOld;
1670 :
1671 0 : LeftHandSide = a;
1672 0 : RightHandSide = b;
1673 0 : EquationsSolver(state, LeftHandSide, RightHandSide, 4 * nlayer, nperr, ErrorMessage);
1674 :
1675 : // Simon: This is much better, but also much slower convergence criteria. Think of how to make this flexible and allow
1676 : // user to change this from outside (through argument passing)
1677 : // curDifference = ABS(FRes(1))
1678 : // do i = 2, 4*nlayer
1679 : // curDifference = MAX(curDifference, ABS(FRes(i)))
1680 : // curDifference = curDifference + ABS(FRes(i))
1681 : // end do
1682 :
1683 0 : curDifference = std::abs(theta(1) - told(1));
1684 : // curDifference = ABS(FRes(1))
1685 0 : for (i = 2; i <= 2 * nlayer; ++i) {
1686 : // do i = 2, 4*nlayer
1687 0 : curDifference = max(curDifference, std::abs(theta(i) - told(i)));
1688 : // curDifference = MAX(ABS(FRes(i)), curDifference)
1689 : }
1690 :
1691 0 : for (i = 1; i <= nlayer; ++i) {
1692 0 : k = 4 * i - 3;
1693 0 : j = 2 * i - 1;
1694 : // if (TurnOnNewton) then
1695 : // theta(j) = theta(j) + Relaxation*dx(k)
1696 : // theta(j+1) = theta(j+1) + Relaxation*dx(k+1)
1697 : // Radiation(j) = Radiation(j) + Relaxation*dx(k+2)
1698 : // Radiation(j+1) = Radiation(j+1) + Relaxation*dx(k+3)
1699 : // else
1700 : // dX(k) = RightHandSide(k) - theta(j)
1701 : // dX(k+1) = RightHandSide(k + 1) - theta(j+1)
1702 : // dX(k+2) = RightHandSide(k + 2) - Radiation(j)
1703 : // dX(k+3) = RightHandSide(k + 3) - Radiation(j+1)
1704 0 : told(j) = theta(j);
1705 0 : told(j + 1) = theta(j + 1);
1706 0 : theta(j) = (1 - Relaxation) * theta(j) + Relaxation * RightHandSide(k);
1707 0 : Radiation(j) = (1 - Relaxation) * Radiation(j) + Relaxation * RightHandSide(k + 1);
1708 0 : Radiation(j + 1) = (1 - Relaxation) * Radiation(j + 1) + Relaxation * RightHandSide(k + 2);
1709 0 : theta(j + 1) = (1 - Relaxation) * theta(j + 1) + Relaxation * RightHandSide(k + 3);
1710 : // end if
1711 : }
1712 :
1713 : // it is important not to update gaps around shading layers since that is already calculated by
1714 : // shading routines
1715 0 : for (i = 1; i <= nlayer + 1; ++i) {
1716 0 : updateGapTemperature = true;
1717 0 : if ((i == 1) || (i == nlayer + 1)) {
1718 : // update gap array with interior and exterior temperature
1719 0 : updateGapTemperature = true;
1720 : } else {
1721 : // update gap temperature only if gap on both sides
1722 0 : updateGapTemperature = false;
1723 0 : if ((!(IsShadingLayer(LayerType(i - 1)))) && (!(IsShadingLayer(LayerType(i))))) {
1724 0 : updateGapTemperature = true;
1725 : }
1726 : }
1727 0 : j = 2 * (i - 1);
1728 0 : if (updateGapTemperature) {
1729 0 : if (i == 1) {
1730 0 : state.dataThermalISO15099Calc->Tgap(1) = tout;
1731 0 : } else if (i == (nlayer + 1)) {
1732 0 : state.dataThermalISO15099Calc->Tgap(i) = tind;
1733 : } else {
1734 0 : state.dataThermalISO15099Calc->Tgap(i) = (theta(j) + theta(j + 1)) / 2;
1735 : }
1736 : }
1737 : }
1738 :
1739 : // and store results during iterations
1740 0 : if (saveIterationResults) {
1741 0 : storeIterationResults(state,
1742 : files,
1743 : nlayer,
1744 : index + 1,
1745 : theta,
1746 : trmout,
1747 : tamb,
1748 : trmin,
1749 : troom,
1750 : ebsky,
1751 : ebroom,
1752 : hcin,
1753 : hcout,
1754 : hrin,
1755 : hrout,
1756 : hin,
1757 : hout,
1758 : Ebb,
1759 : Ebf,
1760 : Rb,
1761 : Rf,
1762 : nperr);
1763 : }
1764 :
1765 0 : if (!(GoAhead(nperr))) return;
1766 :
1767 0 : prevDifference = curDifference;
1768 :
1769 0 : if ((index == 0) || (curDifference < AchievedErrorTolerance)) {
1770 0 : AchievedErrorTolerance = curDifference;
1771 0 : currentTry = 0;
1772 0 : for (i = 1; i <= 2 * nlayer; ++i) {
1773 0 : RadiationSave(i) = Radiation(i);
1774 0 : thetaSave(i) = theta(i);
1775 : }
1776 : } else {
1777 : // This is case when program solution diverged
1778 0 : ++currentTry;
1779 0 : if (currentTry >= NumOfTries) {
1780 0 : currentTry = 0;
1781 0 : for (i = 1; i <= 2 * nlayer; ++i) {
1782 0 : Radiation(i) = RadiationSave(i);
1783 0 : theta(i) = thetaSave(i);
1784 : }
1785 : // if (.not.TurnOnNewton) then
1786 : // TurnOnNewton = .TRUE.
1787 : // else
1788 0 : Relaxation -= RelaxationDecrease;
1789 0 : TotalIndex += index;
1790 0 : index = 0;
1791 : // Start from best achieved convergence
1792 0 : if (Relaxation <= 0.0) { // cannot continue with relaxation equal to zero
1793 0 : iterationsFinished = true;
1794 : }
1795 : // TurnOnNewton = .TRUE.
1796 : // end if ! if (.not.TurnOnNewton) then
1797 : } // f (currentTry == NumOfTries) then
1798 : }
1799 :
1800 : // Check if results were found:
1801 0 : if (curDifference < ConvergenceTolerance) {
1802 0 : CalcOutcome = CalculationOutcome::OK;
1803 0 : TotalIndex += index;
1804 0 : iterationsFinished = true;
1805 : }
1806 :
1807 0 : if (index >= maxiter) {
1808 0 : Relaxation -= RelaxationDecrease;
1809 0 : TotalIndex += index;
1810 0 : index = 0;
1811 : // TurnOnNewton = .TRUE.
1812 :
1813 : // Start from best achieved convergence
1814 0 : for (i = 1; i <= 2 * nlayer; ++i) {
1815 0 : Radiation(i) = RadiationSave(i);
1816 0 : theta(i) = thetaSave(i);
1817 : }
1818 0 : if (Relaxation <= 0.0) { // cannot continue with relaxation equal to zero
1819 0 : iterationsFinished = true;
1820 : }
1821 : }
1822 :
1823 0 : ++index;
1824 : }
1825 :
1826 : // Get results from closest iteration and store it
1827 0 : if (CalcOutcome == CalculationOutcome::OK) {
1828 0 : for (i = 1; i <= 2 * nlayer; ++i) {
1829 0 : Radiation(i) = RadiationSave(i);
1830 0 : theta(i) = thetaSave(i);
1831 : }
1832 :
1833 0 : for (i = 2; i <= nlayer; ++i) {
1834 0 : updateGapTemperature = false;
1835 0 : if ((!(IsShadingLayer(LayerType(i - 1)))) && (!(IsShadingLayer(LayerType(i))))) {
1836 0 : updateGapTemperature = true;
1837 : }
1838 :
1839 0 : if (updateGapTemperature) {
1840 0 : state.dataThermalISO15099Calc->Tgap(i) = (theta(2 * i - 1) + theta(2 * i - 2)) / 2;
1841 : }
1842 : }
1843 :
1844 : // Simon: It is important to recalculate coefficients from most accurate run
1845 0 : hatter(state,
1846 : nlayer,
1847 : iwd,
1848 : tout,
1849 : tind,
1850 : wso,
1851 : wsi,
1852 : VacuumPressure,
1853 : VacuumMaxGapThickness,
1854 : ebsky,
1855 : tamb,
1856 : ebroom,
1857 : troom,
1858 : gap,
1859 : height,
1860 : heightt,
1861 : scon,
1862 : tilt,
1863 : theta,
1864 0 : state.dataThermalISO15099Calc->Tgap,
1865 : Radiation,
1866 : trmout,
1867 : trmin,
1868 : iprop,
1869 : frct,
1870 : presure,
1871 : nmix,
1872 : wght,
1873 : gcon,
1874 : gvis,
1875 : gcp,
1876 : gama,
1877 : SupportPillar,
1878 : PillarSpacing,
1879 : PillarRadius,
1880 0 : state.dataThermalISO15099Calc->hgas,
1881 : hcgas,
1882 : hrgas,
1883 : hcin,
1884 : hcout,
1885 : hin,
1886 : hout,
1887 : index,
1888 : ibc,
1889 : nperr,
1890 : ErrorMessage,
1891 : hrin,
1892 : hrout,
1893 : Ra,
1894 : Nu);
1895 :
1896 0 : shading(state,
1897 : theta,
1898 : gap,
1899 0 : state.dataThermalISO15099Calc->hgas,
1900 : hcgas,
1901 : hrgas,
1902 : frct,
1903 : iprop,
1904 : presure,
1905 : nmix,
1906 : wght,
1907 : gcon,
1908 : gvis,
1909 : gcp,
1910 : nlayer,
1911 : width,
1912 : height,
1913 : tilt,
1914 : tout,
1915 : tind,
1916 : Atop,
1917 : Abot,
1918 : Al,
1919 : Ar,
1920 : Ah,
1921 : vvent,
1922 : tvent,
1923 : LayerType,
1924 0 : state.dataThermalISO15099Calc->Tgap,
1925 : qv,
1926 0 : state.dataThermalISO15099Calc->hcv,
1927 : nperr,
1928 : ErrorMessage,
1929 : vfreevent);
1930 : }
1931 :
1932 0 : if (CalcOutcome == CalculationOutcome::Invalid) {
1933 0 : ErrorMessage = "Tarcog failed to converge";
1934 0 : nperr = 2; // error 2: failed to converge...
1935 : }
1936 :
1937 : // Get radiation results first
1938 : // if (curEquationsApproach.eq.eaQBalance) then
1939 0 : for (i = 1; i <= nlayer; ++i) {
1940 0 : k = 2 * i - 1;
1941 0 : Rf(i) = Radiation(k);
1942 0 : Rb(i) = Radiation(k + 1);
1943 0 : Ebf(i) = Constant::StefanBoltzmann * pow_4(theta(k));
1944 0 : Ebb(i) = Constant::StefanBoltzmann * pow_4(theta(k + 1));
1945 : }
1946 : // end if
1947 :
1948 : // Finishing calcs:
1949 0 : resist(nlayer, trmout, tout, trmin, tind, hcgas, hrgas, theta, q, qv, LayerType, thick, scon, ufactor, flux, qcgas, qrgas);
1950 :
1951 : // bi... Set T6-related quantities - ratios for modified epsilon, hc for modelling external SDs:
1952 : // (using non-solar pass results)
1953 0 : if ((dir == 0.0) && (nlayer > 1)) {
1954 :
1955 0 : qr_gap_out = Rf(2) - Rb(1);
1956 0 : qr_gap_in = Rf(nlayer) - Rb(nlayer - 1);
1957 :
1958 0 : if (IsShadingLayer(LayerType(1))) {
1959 0 : ShadeEmisRatioOut = qr_gap_out / (emis(3) * Constant::StefanBoltzmann * (pow_4(theta(3)) - pow_4(trmout)));
1960 : // qc_gap_out = qprim(3) - qr_gap_out
1961 : // qcgapout2 = qcgas(1)
1962 : // Hc_modified_out = (qc_gap_out / (theta(3) - tout))
1963 : // ShadeHcModifiedOut = Hc_modified_out
1964 : }
1965 :
1966 0 : if (IsShadingLayer(LayerType(nlayer))) {
1967 0 : ShadeEmisRatioIn = qr_gap_in / (emis(2 * nlayer - 2) * Constant::StefanBoltzmann * (pow_4(trmin) - pow_4(theta(2 * nlayer - 2))));
1968 0 : qc_gap_in = q(2 * nlayer - 1) - qr_gap_in;
1969 0 : hc_modified_in = (qc_gap_in / (tind - theta(2 * nlayer - 2)));
1970 0 : ShadeHcModifiedIn = hc_modified_in;
1971 : }
1972 : } // IF dir = 0
1973 0 : }
1974 :
1975 0 : void guess(Real64 const tout,
1976 : Real64 const tind,
1977 : int const nlayer,
1978 : const Array1D<Real64> &gap,
1979 : const Array1D<Real64> &thick,
1980 : Real64 &width,
1981 : Array1D<Real64> &theta,
1982 : Array1D<Real64> &Ebb,
1983 : Array1D<Real64> &Ebf,
1984 : Array1D<Real64> &Tgap)
1985 : {
1986 : //***********************************************************************
1987 : // purpose - initializes temperature distribution assuming
1988 : // a constant temperature gradient across the window
1989 : //***********************************************************************
1990 : // Input
1991 : // tout outdoor air temperature (k)
1992 : // tind indoor air temperature (k)
1993 : // nlayer number of solid layers in window output
1994 : // gap thickness of gas gaps (m)
1995 : // thick thickness of glazing layers (m)
1996 : // Output
1997 : // width total width of the glazing system
1998 : // theta array of surface temps starting from outdoor layer (k)
1999 : // Ebb vector of emissive power (?) of the back surface (# of layers)
2000 : // Ebf vector of emissive power (?) of the front surface (# of layers)
2001 : // Locals
2002 : // x Vector of running width
2003 : // delta delta T per unit length
2004 :
2005 : // Using
2006 : // Argument array dimensioning
2007 0 : EP_SIZE_CHECK(gap, MaxGap);
2008 0 : EP_SIZE_CHECK(thick, maxlay);
2009 0 : EP_SIZE_CHECK(theta, maxlay2);
2010 0 : EP_SIZE_CHECK(Ebb, maxlay);
2011 0 : EP_SIZE_CHECK(Ebf, maxlay);
2012 0 : EP_SIZE_CHECK(Tgap, maxlay1);
2013 :
2014 : // Locals
2015 0 : Array1D<Real64> x(maxlay2);
2016 : Real64 delta;
2017 : int i;
2018 : int j;
2019 : int k;
2020 :
2021 0 : x(1) = 0.001;
2022 0 : x(2) = x(1) + thick(1);
2023 :
2024 0 : for (i = 2; i <= nlayer; ++i) {
2025 0 : j = 2 * i - 1;
2026 0 : k = 2 * i;
2027 0 : x(j) = x(j - 1) + gap(i - 1);
2028 0 : x(k) = x(k - 1) + thick(i);
2029 : }
2030 :
2031 0 : width = x(nlayer * 2) + 0.01;
2032 0 : delta = (tind - tout) / width;
2033 :
2034 0 : if (delta == 0.0) {
2035 0 : delta = TemperatureQuessDiff / width;
2036 : }
2037 :
2038 0 : for (i = 1; i <= nlayer; ++i) {
2039 0 : j = 2 * i;
2040 0 : theta(j - 1) = tout + x(j - 1) * delta;
2041 0 : theta(j) = tout + x(j) * delta;
2042 0 : Ebf(i) = Constant::StefanBoltzmann * pow_4(theta(j - 1));
2043 0 : Ebb(i) = Constant::StefanBoltzmann * pow_4(theta(j));
2044 : }
2045 :
2046 0 : for (i = 1; i <= nlayer + 1; ++i) {
2047 0 : if (i == 1) {
2048 0 : Tgap(1) = tout;
2049 0 : } else if (i == (nlayer + 1)) {
2050 0 : Tgap(nlayer + 1) = tind;
2051 : } else {
2052 0 : Tgap(i) = (theta(2 * i - 1) + theta(2 * i - 2)) / 2;
2053 : }
2054 : }
2055 0 : }
2056 :
2057 0 : void solarISO15099(Real64 const totsol, Real64 const rtot, const Array1D<Real64> &rs, int const nlayer, const Array1D<Real64> &absol, Real64 &sf)
2058 : {
2059 : //***********************************************************************
2060 : // This subroutine calculates the shading coefficient for a window.
2061 : //***********************************************************************
2062 : // Inputs:
2063 : // absol array of absorbed fraction of solar radiation in lites
2064 : // totsol total solar transmittance
2065 : // rtot total thermal resistance of window
2066 : // rs array of thermal resistances of each gap and layer
2067 : // layer number of layers
2068 : // dir direct solar radiation
2069 : // Outputs:
2070 : // sf solar gain of space
2071 :
2072 : // Argument array dimensioning
2073 0 : EP_SIZE_CHECK(rs, maxlay3);
2074 0 : EP_SIZE_CHECK(absol, maxlay);
2075 :
2076 : // Locals
2077 : Real64 flowin;
2078 : Real64 fract;
2079 : int i;
2080 : int j;
2081 :
2082 0 : fract = 0.0;
2083 0 : flowin = 0.0;
2084 0 : sf = 0.0;
2085 :
2086 0 : if (rtot == 0.0) {
2087 0 : return;
2088 : }
2089 :
2090 : // evaluate inward flowing fraction of absorbed radiation:
2091 0 : flowin = (rs(1) + 0.5 * rs(2)) / rtot;
2092 0 : fract = absol(1) * flowin;
2093 :
2094 0 : for (i = 2; i <= nlayer; ++i) {
2095 0 : j = 2 * i;
2096 0 : flowin += (0.5 * (rs(j - 2) + rs(j)) + rs(j - 1)) / rtot;
2097 0 : fract += absol(i) * flowin;
2098 : }
2099 0 : sf = totsol + fract; // add inward fraction to directly transmitted fraction
2100 : }
2101 :
2102 0 : void resist(int const nlayer,
2103 : Real64 const trmout,
2104 : Real64 const Tout,
2105 : Real64 const trmin,
2106 : Real64 const tind,
2107 : const Array1D<Real64> &hcgas,
2108 : const Array1D<Real64> &hrgas,
2109 : Array1D<Real64> const &Theta,
2110 : Array1D<Real64> &qlayer,
2111 : const Array1D<Real64> &qv,
2112 : const Array1D<TARCOGLayerType> &LayerType,
2113 : const Array1D<Real64> &thick,
2114 : const Array1D<Real64> &scon,
2115 : Real64 &ufactor,
2116 : Real64 &flux,
2117 : Array1D<Real64> &qcgas,
2118 : Array1D<Real64> &qrgas)
2119 : {
2120 : //***********************************************************************
2121 : // subroutine to calculate total thermal resistance of the glazing system
2122 : //***********************************************************************
2123 :
2124 : // Locals
2125 : int i;
2126 :
2127 : // Simon: calculation of heat flow through gaps and layers as well as ventilation speed and heat flow
2128 : // are kept just for reporting purposes. U-factor calculation is performed by calculating heat flow transfer
2129 : // at indoor layer
2130 :
2131 : // calculate heat flow for external and internal environments and gaps
2132 0 : for (i = 1; i <= nlayer + 1; ++i) {
2133 0 : if (i == 1) {
2134 0 : qcgas(i) = hcgas(i) * (Theta(2 * i - 1) - Tout);
2135 0 : qrgas(i) = hrgas(i) * (Theta(2 * i - 1) - trmout);
2136 0 : qlayer(2 * i - 1) = qcgas(i) + qrgas(i);
2137 : // rs(2*i-1) = 1/hgas(i)
2138 0 : } else if (i == (nlayer + 1)) {
2139 0 : qcgas(i) = hcgas(i) * (tind - Theta(2 * i - 2));
2140 0 : qrgas(i) = hrgas(i) * (trmin - Theta(2 * i - 2));
2141 0 : qlayer(2 * i - 1) = qcgas(i) + qrgas(i);
2142 : // rs(2*i-1) = 1/hgas(i)
2143 : } else {
2144 0 : qcgas(i) = hcgas(i) * (Theta(2 * i - 1) - Theta(2 * i - 2));
2145 0 : qrgas(i) = hrgas(i) * (Theta(2 * i - 1) - Theta(2 * i - 2));
2146 0 : qlayer(2 * i - 1) = qcgas(i) + qrgas(i);
2147 : // rs(2*i-1) = 1/hgas(i)
2148 : }
2149 : }
2150 :
2151 : //.....Calculate thermal resistances for glazing layers:
2152 0 : for (i = 1; i <= nlayer; ++i) {
2153 : // rs(2*i) = thick(i)/scon(i)
2154 0 : qlayer(2 * i) = scon(i) / thick(i) * (Theta(2 * i) - Theta(2 * i - 1));
2155 : }
2156 :
2157 0 : flux = qlayer(2 * nlayer + 1);
2158 0 : if (IsShadingLayer(LayerType(nlayer))) {
2159 0 : flux += qv(nlayer);
2160 : }
2161 :
2162 0 : ufactor = 0.0;
2163 0 : if (tind != Tout) {
2164 0 : ufactor = flux / (tind - Tout);
2165 : }
2166 0 : }
2167 :
2168 0 : void hatter(EnergyPlusData &state,
2169 : int const nlayer,
2170 : int const iwd,
2171 : Real64 const tout,
2172 : Real64 const tind,
2173 : Real64 const wso,
2174 : Real64 const wsi,
2175 : Real64 const VacuumPressure,
2176 : Real64 const VacuumMaxGapThickness,
2177 : Real64 const ebsky,
2178 : Real64 &tamb,
2179 : Real64 const ebroom,
2180 : Real64 &troom,
2181 : const Array1D<Real64> &gap,
2182 : Real64 const height,
2183 : Real64 const heightt,
2184 : const Array1D<Real64> &scon,
2185 : Real64 const tilt,
2186 : Array1D<Real64> const &theta,
2187 : const Array1D<Real64> &Tgap,
2188 : Array1D<Real64> const &Radiation,
2189 : Real64 const trmout,
2190 : Real64 const trmin,
2191 : Array2_int const &iprop,
2192 : Array2<Real64> const &frct,
2193 : const Array1D<Real64> &presure,
2194 : const Array1D_int &nmix,
2195 : const Array1D<Real64> &wght,
2196 : Array2<Real64> const &gcon,
2197 : Array2<Real64> const &gvis,
2198 : Array2<Real64> const &gcp,
2199 : const Array1D<Real64> &gama,
2200 : const Array1D_int &SupportPillar,
2201 : const Array1D<Real64> &PillarSpacing,
2202 : const Array1D<Real64> &PillarRadius,
2203 : Array1D<Real64> &hgas,
2204 : Array1D<Real64> &hcgas,
2205 : Array1D<Real64> &hrgas,
2206 : Real64 &hcin,
2207 : Real64 &hcout,
2208 : Real64 const hin,
2209 : Real64 const hout,
2210 : int const index,
2211 : const Array1D_int &ibc,
2212 : int &nperr,
2213 : std::string &ErrorMessage,
2214 : Real64 &hrin,
2215 : Real64 &hrout,
2216 : Array1D<Real64> &Ra,
2217 : Array1D<Real64> &Nu)
2218 : {
2219 : //***********************************************************************
2220 : // This subroutine calculates the array of conductances/film coefficients used to model convection. The conductances/film
2221 : // coefficients are calculated as functions of temperature defined with the usual variable h and THEN are converted into an
2222 : // equivalent value interms of the black body emittance based on the surface
2223 : //***********************************************************************
2224 : // Inputs
2225 : // nlayer number of solid layers
2226 : // iwd wind direction
2227 : // tout outside temp in k
2228 : // tind inside temp in k
2229 : // wso wind speed in m/s
2230 : // wsi inside forced air speed m/s
2231 : // Ebsky ir flux from outside
2232 : // Ebroom ir flux from room
2233 : // Gout radiosity (ir flux) of the combined environment (sky+ground)
2234 : // Gin
2235 : // gap vector of gap widths in meters
2236 : // height IGU cavity height
2237 : // heightt
2238 : // thick glazing layer thickness
2239 : // scon Vector of conductivities of each glazing layer
2240 : // tilt Window tilt (in degrees)
2241 : // theta Vector of average temperatures
2242 : // Ebb
2243 : // Ebf
2244 : // iprop array of gap mixtures
2245 : // frct vector of mixture fractions
2246 : // presure
2247 : // hin Indoor Indoor combined film coefficient (if non-zero)
2248 : // hout Outdoor combined film coefficient (if non-zero)
2249 : // nmix vector of number of gasses in a mixture for each gap
2250 : // Ouputs
2251 : // hhat vector of all film coefficients (maxlay3)
2252 : // hgas vector of gap 'film' coeff.
2253 : // hcin Indoor convective surface heat transfer coefficient
2254 : // hcout Outdoor convective heat transfer coeff
2255 : // hrin Indoor radiative surface heat transfer coefficient
2256 : // hrout Outdoor radiative surface heat transfer coefficient
2257 : // hin Indoor combined film coefficient
2258 : // hout Outdoor combined film coefficient
2259 : // index iteration step
2260 : // ibc
2261 : // Inactives**
2262 : // wa - window azimuth (degrees, clockwise from south)
2263 :
2264 : // Locals
2265 : int i;
2266 : int k;
2267 : int nface;
2268 :
2269 : // evaluate convective/conductive components of gap grashof number, thermal conductivity and their derivatives:
2270 0 : nface = 2 * nlayer;
2271 :
2272 0 : filmg(state,
2273 : tilt,
2274 : theta,
2275 : Tgap,
2276 : nlayer,
2277 : height,
2278 : gap,
2279 : iprop,
2280 : frct,
2281 : VacuumPressure,
2282 : presure,
2283 : nmix,
2284 : wght,
2285 : gcon,
2286 : gvis,
2287 : gcp,
2288 : gama,
2289 : hcgas,
2290 : Ra,
2291 : Nu,
2292 : nperr,
2293 : ErrorMessage);
2294 :
2295 0 : if (!(GoAhead(nperr))) {
2296 0 : return;
2297 : }
2298 :
2299 : // this is adding influence of pillar to hgas
2300 0 : filmPillar(state, SupportPillar, scon, PillarSpacing, PillarRadius, nlayer, gap, hcgas, VacuumMaxGapThickness, nperr, ErrorMessage);
2301 :
2302 0 : if (!(GoAhead(nperr))) {
2303 0 : return;
2304 : }
2305 :
2306 : // adjust radiation coefficients
2307 : // hrgas = 0.0d0
2308 0 : for (i = 2; i <= nlayer; ++i) {
2309 0 : k = 2 * i - 1;
2310 : // if ((theta(k)-theta(k-1)) == 0) then
2311 : // theta(k-1) = theta(k-1) + tempCorrection
2312 : // end if
2313 0 : if ((theta(k) - theta(k - 1)) != 0) {
2314 0 : hrgas(i) = (Radiation(k) - Radiation(k - 1)) / (theta(k) - theta(k - 1));
2315 : }
2316 :
2317 0 : hgas(i) = hcgas(i) + hrgas(i);
2318 : }
2319 :
2320 : // convective indoor film coeff:
2321 0 : if (ibc(2) <= 0) {
2322 0 : filmi(state,
2323 : tind,
2324 0 : theta(nface),
2325 : nlayer,
2326 : tilt,
2327 : wsi,
2328 : heightt,
2329 : iprop,
2330 : frct,
2331 : presure,
2332 : nmix,
2333 : wght,
2334 : gcon,
2335 : gvis,
2336 : gcp,
2337 : hcin,
2338 0 : ibc(2),
2339 : nperr,
2340 : ErrorMessage);
2341 0 : } else if (ibc(2) == 1) {
2342 0 : hcin = hin - hrin;
2343 : // Simon: First iteration is with index = 0 and that means it should reenter iteration with whatever is provided as input
2344 : // else if (ibc(2).eq.2.and.index.eq.1) then
2345 0 : } else if ((ibc(2) == 2) && (index == 0)) {
2346 0 : hcin = hin;
2347 : }
2348 0 : if (hcin < 0) {
2349 0 : nperr = 8;
2350 0 : ErrorMessage = "Hcin is less then zero.";
2351 0 : return;
2352 : }
2353 :
2354 0 : hcgas(nlayer + 1) = hcin;
2355 : // hrin = 0.95d0*(Ebroom - Radiation(2*nlayer))/(Trmin-theta(2*nlayer))+0.05d0*hrin
2356 0 : hrin = (ebroom - Radiation(2 * nlayer)) / (trmin - theta(2 * nlayer));
2357 : // if ((Theta(2*nlayer) - Trmin).ne.0) then
2358 : // hrin = sigma * emis(2*nlayer) * (Theta(2*nlayer)**4 - Trmin**4)/(Theta(2*nlayer) - Trmin)
2359 : // else
2360 : // Theta(2*nlayer) = Theta(2*nlayer) + tempCorrection
2361 : // hrin = sigma * emis(2*nlayer) * (Theta(2*nlayer)**4 - Trmin**4)/(Theta(2*nlayer) - Trmin)
2362 : // end if
2363 0 : hrgas(nlayer + 1) = hrin;
2364 : // hgas(nlayer+1) = hcgas(nlayer+1) + hrgas(nlayer+1)
2365 0 : troom = (hcin * tind + hrin * trmin) / (hcin + hrin);
2366 :
2367 : // convective outdoor film coeff:
2368 0 : if (ibc(1) <= 0) {
2369 0 : film(tout, theta(1), wso, iwd, hcout, ibc(1));
2370 0 : } else if (ibc(1) == 1) {
2371 0 : hcout = hout - hrout;
2372 : // Simon: First iteration is with index = 0 and that means it should reenter iteration with whatever is provided as input
2373 : // else if (ibc(1).eq.2.and.index.eq.1) then
2374 0 : } else if ((ibc(1) == 2) && (index == 0)) {
2375 0 : hcout = hout;
2376 : }
2377 0 : if (hcout < 0) {
2378 0 : nperr = 9;
2379 0 : ErrorMessage = "Hcout is less than zero.";
2380 0 : return;
2381 : }
2382 :
2383 0 : hcgas(1) = hcout;
2384 0 : hrout = (Radiation(1) - ebsky) / (theta(1) - trmout);
2385 : // if ((Theta(1) - Trmout).ne.0) then
2386 : // hrout = sigma * emis(1) * (Theta(1)**4 - Trmout**4)/(Theta(1) - Trmout)
2387 : // else
2388 : // Theta(1) = Theta(1) + tempCorrection
2389 : // hrout = sigma * emis(1) * (Theta(1)**4 - Trmout**4)/(Theta(1) - Trmout)
2390 : // end if
2391 0 : hrgas(1) = hrout;
2392 : // hgas(1) = hrout + hcout
2393 0 : tamb = (hcout * tout + hrout * trmout) / (hcout + hrout);
2394 : }
2395 :
2396 0 : void effectiveLayerCond(EnergyPlusData &state,
2397 : int const nlayer,
2398 : const Array1D<TARCOGLayerType> &LayerType, // Layer type
2399 : const Array1D<Real64> &scon, // Layer thermal conductivity
2400 : const Array1D<Real64> &thick, // Layer thickness
2401 : Array2A_int const iprop, // Gas type in gaps
2402 : Array2A<Real64> const frct, // Fraction of gas
2403 : const Array1D_int &nmix, // Gas mixture
2404 : const Array1D<Real64> &pressure, // Gas pressure [Pa]
2405 : const Array1D<Real64> &wght, // Molecular weight
2406 : Array2A<Real64> const gcon, // Gas specific conductivity
2407 : Array2A<Real64> const gvis, // Gas specific viscosity
2408 : Array2A<Real64> const gcp, // Gas specific heat
2409 : const Array1D<Real64> &EffectiveOpenness, // Layer effective openness [m2]
2410 : Array1D<Real64> const &theta, // Layer surface temperatures [K]
2411 : Array1D<Real64> &sconScaled, // Layer conductivity divided by thickness
2412 : int &nperr, // Error message flag
2413 : std::string &ErrorMessage // Error message
2414 : )
2415 : {
2416 0 : for (int i = 1; i <= nlayer; ++i) {
2417 0 : if (LayerType(i) != TARCOGLayerType::SPECULAR) {
2418 0 : Real64 tLayer = (theta(2 * i - 1) + theta(2 * i)) / 2;
2419 0 : Real64 nmix1 = nmix(i);
2420 0 : Real64 press1 = (pressure(i) + pressure(i + 1)) / 2.0;
2421 0 : for (int j = 1; j <= maxgas; ++j) {
2422 0 : state.dataThermalISO15099Calc->iprop1(j) = iprop(j, i);
2423 0 : state.dataThermalISO15099Calc->frct1(j) = frct(j, i);
2424 : }
2425 :
2426 : Real64 con;
2427 : Real64 visc;
2428 : Real64 dens;
2429 : Real64 cp;
2430 : Real64 pr;
2431 0 : GASSES90(state,
2432 : tLayer,
2433 0 : state.dataThermalISO15099Calc->iprop1,
2434 0 : state.dataThermalISO15099Calc->frct1,
2435 : press1,
2436 : nmix1,
2437 : wght,
2438 : gcon,
2439 : gvis,
2440 : gcp,
2441 : con,
2442 : visc,
2443 : dens,
2444 : cp,
2445 : pr,
2446 : TARCOGGassesParams::Stdrd::ISO15099,
2447 : nperr,
2448 : ErrorMessage);
2449 0 : sconScaled(i) = (EffectiveOpenness(i) * con + (1 - EffectiveOpenness(i)) * scon(i)) / thick(i);
2450 : } else {
2451 0 : sconScaled(i) = scon(i) / thick(i);
2452 : }
2453 : }
2454 0 : }
2455 :
2456 0 : void filmi(EnergyPlusData &state,
2457 : Real64 const tair,
2458 : Real64 const t,
2459 : int const nlayer,
2460 : Real64 const tilt,
2461 : Real64 const wsi,
2462 : Real64 const height,
2463 : Array2A_int const iprop,
2464 : Array2A<Real64> const frct,
2465 : const Array1D<Real64> &presure,
2466 : const Array1D_int &nmix,
2467 : const Array1D<Real64> &wght,
2468 : Array2A<Real64> const gcon,
2469 : Array2A<Real64> const gvis,
2470 : Array2A<Real64> const gcp,
2471 : Real64 &hcin,
2472 : int const ibc,
2473 : int &nperr,
2474 : std::string &ErrorMessage)
2475 : {
2476 : //***********************************************************************
2477 : // purpose to evaluate heat flux at indoor surface of window using still air correlations (Curcija and Goss 1993)
2478 : // found in SPC142 equations 5.43 - 5.48.
2479 : //***********************************************************************
2480 : // Input
2481 : // tair - room air temperature
2482 : // t - inside surface temperature
2483 : // nlayer number of glazing layers
2484 : // tilt - the tilt of the glazing in degrees
2485 : // wsi - room wind speed (m/s)
2486 : // height - window height
2487 : // iprop
2488 : // frct
2489 : // presure
2490 : // nmix vector of number of gasses in a mixture for each gap
2491 : // Output
2492 : // hcin - indoor convective heat transfer coeff
2493 :
2494 : // If there is forced air in the room than use SPC142 correlation 5.49 to calculate the room side film coefficient.
2495 :
2496 : // Using
2497 : // Argument array dimensioning
2498 0 : iprop.dim(maxgas, maxlay1);
2499 0 : frct.dim(maxgas, maxlay1);
2500 0 : EP_SIZE_CHECK(presure, maxlay1);
2501 0 : EP_SIZE_CHECK(nmix, maxlay1);
2502 0 : EP_SIZE_CHECK(wght, maxgas);
2503 0 : gcon.dim(3, maxgas);
2504 0 : gvis.dim(3, maxgas);
2505 0 : gcp.dim(3, maxgas);
2506 :
2507 : // Locals
2508 : int j;
2509 : Real64 tiltr;
2510 : Real64 tmean;
2511 : Real64 delt;
2512 : Real64 con;
2513 : Real64 visc;
2514 : Real64 dens;
2515 : Real64 cp;
2516 : Real64 pr;
2517 : Real64 gr;
2518 : Real64 RaCrit;
2519 : Real64 RaL;
2520 0 : Real64 Gnui(0.0);
2521 :
2522 0 : if (wsi > 0.0) { // main IF
2523 0 : switch (ibc) {
2524 0 : case 0: {
2525 0 : hcin = 4.0 + 4.0 * wsi;
2526 0 : } break;
2527 0 : case -1: {
2528 0 : hcin = 5.6 + 3.8 * wsi; // SPC142 correlation
2529 0 : return;
2530 : } break;
2531 0 : default:
2532 0 : break;
2533 : }
2534 : } else { // main IF - else
2535 0 : tiltr = tilt * 2.0 * Constant::Pi / 360.0; // convert tilt in degrees to radians
2536 0 : tmean = tair + 0.25 * (t - tair);
2537 0 : delt = std::abs(tair - t);
2538 :
2539 0 : for (j = 1; j <= nmix(nlayer + 1); ++j) {
2540 0 : state.dataThermalISO15099Calc->ipropi(j) = iprop(j, nlayer + 1);
2541 0 : state.dataThermalISO15099Calc->frcti(j) = frct(j, nlayer + 1);
2542 : }
2543 :
2544 0 : GASSES90(state,
2545 : tmean,
2546 0 : state.dataThermalISO15099Calc->ipropi,
2547 0 : state.dataThermalISO15099Calc->frcti,
2548 0 : presure(nlayer + 1),
2549 0 : nmix(nlayer + 1),
2550 : wght,
2551 : gcon,
2552 : gvis,
2553 : gcp,
2554 : con,
2555 : visc,
2556 : dens,
2557 : cp,
2558 : pr,
2559 : TARCOGGassesParams::Stdrd::ISO15099,
2560 : nperr,
2561 : ErrorMessage);
2562 :
2563 : // Calculate grashoff number:
2564 : // The grashoff number is the Rayleigh Number (equation 5.29) in SPC142 divided by the Prandtl Number (prand):
2565 0 : gr = Constant::Gravity * pow_3(height) * delt * pow_2(dens) / (tmean * pow_2(visc));
2566 :
2567 0 : RaL = gr * pr;
2568 : // write(*,*)' RaCrit,RaL,gr,pr '
2569 : // write(*,*) RaCrit,RaL,gr,pr
2570 :
2571 0 : if ((0.0 <= tilt) && (tilt < 15.0)) { // IF no. 1
2572 0 : Gnui = 0.13 * std::pow(RaL, 1.0 / 3.0);
2573 0 : } else if ((15.0 <= tilt) && (tilt <= 90.0)) {
2574 : // if the room air is still THEN use equations 5.43 - 5.48:
2575 0 : RaCrit = 2.5e5 * std::pow(std::exp(0.72 * tilt) / std::sin(tiltr), 0.2);
2576 0 : if (RaL <= RaCrit) { // IF no. 2
2577 0 : Gnui = 0.56 * root_4(RaL * std::sin(tiltr));
2578 : // write(*,*) ' Nu ', Gnui
2579 : } else {
2580 : // Gnui = 0.13d0*(RaL**0.3333d0 - RaCrit**0.3333d0) + 0.56d0*(RaCrit*sin(tiltr))**0.25d0
2581 0 : Gnui = 0.13 * (std::pow(RaL, 1.0 / 3.0) - std::pow(RaCrit, 1.0 / 3.0)) + 0.56 * root_4(RaCrit * std::sin(tiltr));
2582 : } // end if no. 2
2583 0 : } else if ((90.0 < tilt) && (tilt <= 179.0)) {
2584 0 : Gnui = 0.56 * root_4(RaL * std::sin(tiltr));
2585 0 : } else if ((179.0 < tilt) && (tilt <= 180.0)) {
2586 0 : Gnui = 0.58 * std::pow(RaL, 1 / 3.0);
2587 : } else {
2588 0 : assert(false);
2589 : } // end if no. 1
2590 : // write(*,*) ' RaL ', RaL, ' RaCrit', RaCrit
2591 : // write(*,*)' Nusselt Number ',Gnui
2592 :
2593 0 : hcin = Gnui * (con / height);
2594 : // hin = 1.77d0*(ABS(t-tair))**0.25d0
2595 :
2596 : } // end main IF
2597 : }
2598 :
2599 0 : void filmg(EnergyPlusData &state,
2600 : Real64 const tilt,
2601 : const Array1D<Real64> &theta,
2602 : const Array1D<Real64> &Tgap,
2603 : int const nlayer,
2604 : Real64 const height,
2605 : const Array1D<Real64> &gap,
2606 : Array2A_int const iprop,
2607 : Array2A<Real64> const frct,
2608 : Real64 const VacuumPressure,
2609 : const Array1D<Real64> &presure,
2610 : const Array1D_int &nmix,
2611 : const Array1D<Real64> &wght,
2612 : Array2A<Real64> const gcon,
2613 : Array2A<Real64> const gvis,
2614 : Array2A<Real64> const gcp,
2615 : const Array1D<Real64> &gama,
2616 : Array1D<Real64> &hcgas,
2617 : Array1D<Real64> &Rayleigh,
2618 : Array1D<Real64> &Nu,
2619 : int &nperr,
2620 : std::string &ErrorMessage)
2621 : {
2622 : //***********************************************************************
2623 : // subroutine to calculate effective conductance of gaps
2624 : //***********************************************************************
2625 : // Inputs:
2626 : // tilt window angle (deg)
2627 : // theta vector of surface temperatures [K]
2628 : // nlayer total number of glazing layers
2629 : // height glazing cavity height
2630 : // gap vector of gap widths [m]
2631 : // iprop
2632 : // frct
2633 : // presure
2634 : // nmix vector of number of gasses in a mixture for each gap
2635 : // Output:
2636 : // hgas vector of gap coefficients
2637 : // nperr error code
2638 : // Locals:
2639 : // gr gap grashof number
2640 : // con gap gas conductivity
2641 : // visc dynamic viscosity @ mean temperature [g/m*s]
2642 : // dens density @ mean temperature [kg/m^3]
2643 : // cp specific heat @ mean temperature [J/g*K]
2644 : // pr gap gas Prandtl number
2645 : // tmean average film temperature
2646 : // delt temperature difference
2647 :
2648 : // Using
2649 : // Argument array dimensioning
2650 0 : EP_SIZE_CHECK(theta, maxlay2);
2651 0 : EP_SIZE_CHECK(Tgap, maxlay1);
2652 0 : EP_SIZE_CHECK(gap, MaxGap);
2653 0 : iprop.dim(maxgas, maxlay1);
2654 0 : frct.dim(maxgas, maxlay1);
2655 0 : EP_SIZE_CHECK(presure, maxlay1);
2656 0 : EP_SIZE_CHECK(nmix, maxlay1);
2657 0 : EP_SIZE_CHECK(wght, maxgas);
2658 0 : gcon.dim(3, maxgas);
2659 0 : gvis.dim(3, maxgas);
2660 0 : gcp.dim(3, maxgas);
2661 0 : EP_SIZE_CHECK(gama, maxgas);
2662 0 : EP_SIZE_CHECK(hcgas, maxlay1);
2663 0 : EP_SIZE_CHECK(Rayleigh, maxlay);
2664 0 : EP_SIZE_CHECK(Nu, maxlay);
2665 :
2666 : // Locals
2667 : Real64 con;
2668 : Real64 visc;
2669 : Real64 dens;
2670 : Real64 cp;
2671 : Real64 pr;
2672 : Real64 delt;
2673 : Real64 tmean;
2674 : Real64 ra;
2675 : Real64 asp;
2676 : Real64 gnu;
2677 : int i;
2678 : int j;
2679 : int k;
2680 : int l;
2681 :
2682 0 : hcgas = 0.0;
2683 :
2684 0 : for (i = 1; i <= nlayer - 1; ++i) {
2685 0 : j = 2 * i;
2686 0 : k = j + 1;
2687 : // determine the gas properties of each gap:
2688 : // tmean = (theta(j)+theta(k))/2.0d0
2689 0 : tmean = Tgap(i + 1); // Tgap(1) is exterior environment
2690 0 : delt = std::abs(theta(j) - theta(k));
2691 : // Temperatures should not be equal. This can happen in initial temperature guess before iterations started
2692 0 : if (delt == 0.0) delt = 1.0e-6;
2693 0 : for (l = 1; l <= nmix(i + 1); ++l) {
2694 0 : state.dataThermalISO15099Calc->ipropg(l) = iprop(l, i + 1);
2695 0 : state.dataThermalISO15099Calc->frctg(l) = frct(l, i + 1);
2696 : }
2697 :
2698 0 : if (presure(i + 1) > VacuumPressure) {
2699 0 : GASSES90(state,
2700 : tmean,
2701 0 : state.dataThermalISO15099Calc->ipropg,
2702 0 : state.dataThermalISO15099Calc->frctg,
2703 0 : presure(i + 1),
2704 0 : nmix(i + 1),
2705 : wght,
2706 : gcon,
2707 : gvis,
2708 : gcp,
2709 : con,
2710 : visc,
2711 : dens,
2712 : cp,
2713 : pr,
2714 : TARCOGGassesParams::Stdrd::ISO15099,
2715 : nperr,
2716 : ErrorMessage);
2717 :
2718 : // Calculate grashoff number:
2719 : // The grashoff number is the Rayleigh Number (equation 5.29) in SPC142 divided by the Prandtl Number (prand):
2720 0 : ra = Constant::Gravity * pow_3(gap(i)) * delt * cp * pow_2(dens) / (tmean * visc * con);
2721 0 : Rayleigh(i) = ra;
2722 : // write(*,*) 'height,gap(i),asp',height,gap(i),asp
2723 : // asp = 1
2724 : // if (gap(i).ne.0) then
2725 0 : asp = height / gap(i);
2726 : // end if
2727 : // determine the Nusselt number:
2728 0 : nusselt(tilt, ra, asp, gnu, nperr, ErrorMessage);
2729 :
2730 0 : Nu(i) = gnu;
2731 : // calculate effective conductance of the gap
2732 0 : hcgas(i + 1) = con / gap(i) * gnu;
2733 :
2734 : // write(*,*)'theta(j),theta(k),j,k',j,theta(j),k,theta(k)
2735 : // write(*,*)'Nusselt,Rayleigh,Prandtl,hgas(k),k'
2736 : // write(*,*) gnu,gr*pr,pr,hgas(k),k
2737 : } else { // low pressure calculations
2738 0 : GassesLow(tmean, wght(iprop(1, i + 1)), presure(i + 1), gama(iprop(1, i + 1)), con, nperr, ErrorMessage);
2739 0 : hcgas(i + 1) = con;
2740 : } // if (pressure(i+1).gt.VacuumPressure) then
2741 : }
2742 0 : }
2743 :
2744 0 : void filmPillar(EnergyPlusData &state,
2745 : const Array1D_int &SupportPillar, // Shows whether or not gap have support pillar
2746 : const Array1D<Real64> &scon, // Conductivity of glass layers
2747 : const Array1D<Real64> &PillarSpacing, // Pillar spacing for each gap (used in case there is support pillar)
2748 : const Array1D<Real64> &PillarRadius, // Pillar radius for each gap (used in case there is support pillar)
2749 : int const nlayer,
2750 : const Array1D<Real64> &gap,
2751 : Array1D<Real64> &hcgas,
2752 : [[maybe_unused]] Real64 const VacuumMaxGapThickness,
2753 : [[maybe_unused]] int &nperr,
2754 : [[maybe_unused]] std::string &ErrorMessage)
2755 : {
2756 : //***********************************************************************
2757 : // subroutine to calculate effective conductance of support pillars
2758 : //***********************************************************************
2759 :
2760 : // Using
2761 : // Argument array dimensioning
2762 0 : EP_SIZE_CHECK(SupportPillar, maxlay);
2763 0 : EP_SIZE_CHECK(scon, maxlay);
2764 0 : EP_SIZE_CHECK(PillarSpacing, maxlay);
2765 0 : EP_SIZE_CHECK(PillarRadius, maxlay);
2766 0 : EP_SIZE_CHECK(gap, MaxGap);
2767 0 : EP_SIZE_CHECK(hcgas, maxlay1);
2768 :
2769 : // Locals
2770 : // 0 - does not have support pillar
2771 : // 1 - have support pillar
2772 :
2773 0 : for (state.dataThermalISO15099Calc->iFP = 1; state.dataThermalISO15099Calc->iFP <= nlayer - 1; ++state.dataThermalISO15099Calc->iFP) {
2774 0 : state.dataThermalISO15099Calc->kFP = 2 * state.dataThermalISO15099Calc->iFP + 1;
2775 0 : if (SupportPillar(state.dataThermalISO15099Calc->iFP) == YES_SupportPillar) {
2776 :
2777 : // Average glass conductivity is taken as average from both glass surrounding gap
2778 0 : state.dataThermalISO15099Calc->aveGlassConductivity =
2779 0 : (scon(state.dataThermalISO15099Calc->iFP) + scon(state.dataThermalISO15099Calc->iFP + 1)) / 2;
2780 :
2781 0 : state.dataThermalISO15099Calc->cpa =
2782 0 : 2.0 * state.dataThermalISO15099Calc->aveGlassConductivity * PillarRadius(state.dataThermalISO15099Calc->iFP) /
2783 0 : (pow_2(PillarSpacing(state.dataThermalISO15099Calc->iFP)) *
2784 0 : (1.0 + 2.0 * gap(state.dataThermalISO15099Calc->iFP) / (Constant::Pi * PillarRadius(state.dataThermalISO15099Calc->iFP))));
2785 :
2786 : // It is important to add on previous values calculated for gas
2787 0 : hcgas(state.dataThermalISO15099Calc->iFP + 1) += state.dataThermalISO15099Calc->cpa;
2788 : } // if (SupportPillar(i).eq.YES_SupportPillar) then
2789 : }
2790 0 : }
2791 :
2792 0 : void nusselt(Real64 const tilt, Real64 const ra, Real64 const asp, Real64 &gnu, int &nperr, std::string &ErrorMessage)
2793 : {
2794 : //***********************************************************************
2795 : // purpose to calculate nusselt modulus for air gaps (ISO15099)
2796 : //***********************************************************************
2797 : // Input
2798 : // tilt tilt in degrees
2799 : // ra rayleigh number
2800 : // asp Aspect ratio
2801 : // Output
2802 : // gnu nusselt number
2803 : // nperr
2804 :
2805 : // Using
2806 : // Locals
2807 : Real64 subNu1;
2808 : Real64 subNu2;
2809 : Real64 subNu3;
2810 : Real64 Nu1;
2811 : Real64 Nu2;
2812 : Real64 G;
2813 : Real64 Nu60;
2814 : Real64 Nu90;
2815 : Real64 tiltr;
2816 :
2817 0 : subNu1 = 0.0;
2818 0 : subNu2 = 0.0;
2819 0 : subNu3 = 0.0;
2820 0 : Nu1 = 0.0;
2821 0 : Nu2 = 0.0;
2822 0 : Nu90 = 0.0;
2823 0 : Nu60 = 0.0;
2824 0 : G = 0.0;
2825 0 : tiltr = tilt * 2.0 * Constant::Pi / 360.0; // convert tilt in degrees to radians
2826 0 : if ((tilt >= 0.0) && (tilt < 60.0)) { // ISO/DIS 15099 - chapter 5.3.3.1
2827 0 : subNu1 = 1.0 - 1708.0 / (ra * std::cos(tiltr));
2828 0 : subNu1 = pos(subNu1);
2829 0 : subNu2 = 1.0 - (1708.0 * std::pow(std::sin(1.8 * tiltr), 1.6)) / (ra * std::cos(tiltr));
2830 0 : subNu3 = std::pow(ra * std::cos(tiltr) / 5830.0, 1.0 / 3.0) - 1.0;
2831 0 : subNu3 = pos(subNu3);
2832 0 : gnu = 1.0 + 1.44 * subNu1 * subNu2 + subNu3; // equation 42
2833 0 : if (ra >= 1.0e5) {
2834 0 : nperr = 1001; // Rayleigh number is out of range
2835 0 : ErrorMessage = "Rayleigh number out of range in Nusselt num. calc. for gaps (angle between 0 and 60 deg).";
2836 : }
2837 0 : if (asp <= 20.0) {
2838 0 : nperr = 1002; // Aspect Ratio is out of range
2839 0 : ErrorMessage = "Aspect Ratio out of range in Nusselt num. calc. for gaps (angle between 0 and 60 deg).";
2840 : }
2841 0 : } else if (tilt == 60.0) { // ISO/DIS 15099 - chapter 5.3.3.2
2842 0 : G = 0.5 / std::pow(1.0 + std::pow(ra / 3160.0, 20.6), 0.1); // equation 47
2843 0 : Nu1 = std::pow(1.0 + pow_7((0.0936 * std::pow(ra, 0.314)) / (1.0 + G)), 0.1428571); // equation 45
2844 0 : Nu2 = (0.104 + 0.175 / asp) * std::pow(ra, 0.283); // equation 46
2845 0 : gnu = max(Nu1, Nu2); // equation 44
2846 0 : } else if ((tilt > 60.0) && (tilt < 90.0)) { // ISO/DIS 15099 - chapter 5.3.3.3
2847 0 : if ((ra > 100.0) && (ra < 2.0e7) && (asp > 5.0) && (asp < 100.0)) {
2848 0 : G = 0.5 / std::pow(1.0 + std::pow(ra / 3160.0, 20.6), 0.1); // equation 47
2849 0 : Nu1 = std::pow(1.0 + pow_7((0.0936 * std::pow(ra, 0.314)) / (1.0 + G)), 0.1428571); // equation 45
2850 0 : Nu2 = (0.104 + 0.175 / asp) * std::pow(ra, 0.283); // equation 46
2851 0 : Nu60 = max(Nu1, Nu2); // equation 44
2852 0 : Nu2 = 0.242 * std::pow(ra / asp, 0.272); // equation 52
2853 0 : if (ra > 5.0e4) {
2854 0 : Nu1 = 0.0673838 * std::pow(ra, 1.0 / 3.0); // equation 49
2855 0 : } else if ((ra > 1.0e4) && (ra <= 5.0e4)) {
2856 0 : Nu1 = 0.028154 * std::pow(ra, 0.4134); // equation 50
2857 0 : } else if (ra <= 1.0e4) {
2858 0 : Nu1 = 1.0 + 1.7596678e-10 * std::pow(ra, 2.2984755); // equation 51
2859 : }
2860 0 : } else if (ra <= 100.0) {
2861 0 : G = 0.5 / std::pow(1.0 + std::pow(ra / 3160.0, 20.6), 0.1); // equation 47
2862 0 : Nu1 = std::pow(1.0 + pow_7((0.0936 * std::pow(ra, 0.314)) / (1.0 + G)), 0.1428571); // equation 45
2863 0 : Nu2 = (0.104 + 0.175 / asp) * std::pow(ra, 0.283); // equation 46
2864 0 : Nu60 = max(Nu1, Nu2); // equation 44
2865 0 : Nu2 = 0.242 * std::pow(ra / asp, 0.272); // equation 52
2866 0 : Nu1 = 1.0 + 1.7596678e-10 * std::pow(ra, 2.2984755); // equation 51
2867 0 : nperr = 1003; // Rayleigh number is less than 100
2868 0 : ErrorMessage = "Rayleigh number is less than 100 in Nusselt number calculations for gaps (angle between 60 and 90 degrees).";
2869 0 : } else if (ra > 2.0e7) {
2870 0 : G = 0.5 / std::pow(1.0 + std::pow(ra / 3160.0, 20.6), 0.1); // equation 47
2871 0 : Nu1 = std::pow(1.0 + pow_7((0.0936 * std::pow(ra, 0.314)) / (1.0 + G)), 0.1428571); // equation 45
2872 0 : Nu2 = (0.104 + 0.175 / asp) * std::pow(ra, 0.283); // equation 46
2873 0 : Nu60 = max(Nu1, Nu2); // equation 44
2874 0 : Nu2 = 0.242 * std::pow(ra / asp, 0.272); // equation 52
2875 0 : Nu1 = 0.0673838 * std::pow(ra, 1.0 / 3.0); // equation 49
2876 0 : nperr = 1004; // Rayleigh number is great from 2e7
2877 0 : ErrorMessage = "Rayleigh number is greater than 2e7 in Nusselt number calculations for gaps (angle between 60 and 90 degrees).";
2878 0 : } else if ((asp <= 5.0) || (asp >= 100.0)) {
2879 0 : G = 0.5 / std::pow(1.0 + std::pow(ra / 3160.0, 20.6), 0.1); // equation 47
2880 0 : Nu1 = std::pow(1.0 + pow_7((0.0936 * std::pow(ra, 0.314)) / (1.0 + G)), 0.1428571); // equation 45
2881 0 : Nu2 = (0.104 + 0.175 / asp) * std::pow(ra, 0.283); // equation 46
2882 0 : Nu60 = max(Nu1, Nu2); // equation 44
2883 0 : Nu2 = 0.242 * std::pow(ra / asp, 0.272); // equation 52
2884 0 : if (ra > 5.0e4) {
2885 0 : Nu1 = 0.0673838 * std::pow(ra, 1.0 / 3.0); // equation 49
2886 0 : } else if ((ra > 1.0e4) && (ra <= 5.0e4)) {
2887 0 : Nu1 = 0.028154 * std::pow(ra, 0.4134); // equation 50
2888 0 : } else if (ra <= 1.0e4) {
2889 0 : Nu1 = 1.0 + 1.7596678e-10 * std::pow(ra, 2.2984755); // equation 51
2890 : }
2891 0 : nperr = 1005; // Aspect Ratio is out of range
2892 0 : ErrorMessage = "Aspect Ratio is out of range in Nusselt number calculations for gaps (angle between 60 and 90 degrees).";
2893 : }
2894 0 : Nu90 = max(Nu1, Nu2); // equation 48
2895 0 : gnu = ((Nu90 - Nu60) / (90.0 - 60.0)) * (tilt - 60.0) + Nu60; // linear interpolation between 60 and 90 degrees
2896 0 : } else if (tilt == 90.0) { // ISO/DIS 15099 - chapter 5.3.3.4
2897 0 : Nu2 = 0.242 * std::pow(ra / asp, 0.272); // equation 52
2898 0 : if (ra > 5.0e4) {
2899 0 : Nu1 = 0.0673838 * std::pow(ra, 1.0 / 3.0); // equation 49
2900 0 : } else if ((ra > 1.0e4) && (ra <= 5.0e4)) {
2901 0 : Nu1 = 0.028154 * std::pow(ra, 0.4134); // equation 50
2902 : // Nu1 = 0.028154d0 * ra ** 0.414d0 !equation 50 - DISCONTINUITY CORRECTED
2903 0 : } else if (ra <= 1.0e4) {
2904 0 : Nu1 = 1.0 + 1.7596678e-10 * std::pow(ra, 2.2984755); // equation 51
2905 : }
2906 0 : gnu = max(Nu1, Nu2); // equation 48
2907 0 : } else if ((tilt > 90.0) && (tilt <= 180.0)) {
2908 0 : Nu2 = 0.242 * std::pow(ra / asp, 0.272); // equation 52
2909 0 : if (ra > 5.0e4) {
2910 0 : Nu1 = 0.0673838 * std::pow(ra, 1.0 / 3.0); // equation 49
2911 0 : } else if ((ra > 1.0e4) && (ra <= 5.0e4)) {
2912 0 : Nu1 = 0.028154 * std::pow(ra, 0.4134); // equation 50
2913 0 : } else if (ra <= 1.0e4) {
2914 0 : Nu1 = 1.0 + 1.7596678e-10 * std::pow(ra, 2.2984755); // equation 51
2915 : }
2916 0 : gnu = max(Nu1, Nu2); // equation 48
2917 0 : gnu = 1.0 + (gnu - 1.0) * std::sin(tiltr); // equation 53
2918 : } else {
2919 0 : nperr = 10; // error flag: angle is out of range
2920 0 : ErrorMessage = "Window tilt angle is out of range.";
2921 0 : return;
2922 : }
2923 : }
2924 :
2925 0 : void storeIterationResults(EnergyPlusData &state,
2926 : Files &files,
2927 : int const nlayer,
2928 : int const index,
2929 : const Array1D<Real64> &theta,
2930 : Real64 const trmout,
2931 : Real64 const tamb,
2932 : Real64 const trmin,
2933 : Real64 const troom,
2934 : Real64 const ebsky,
2935 : Real64 const ebroom,
2936 : Real64 const hcin,
2937 : Real64 const hcout,
2938 : Real64 const hrin,
2939 : Real64 const hrout,
2940 : Real64 const hin,
2941 : Real64 const hout,
2942 : const Array1D<Real64> &Ebb,
2943 : const Array1D<Real64> &Ebf,
2944 : const Array1D<Real64> &Rb,
2945 : const Array1D<Real64> &Rf,
2946 : int &)
2947 : {
2948 0 : auto &dynFormat = state.dataThermalISO15099Calc->dynFormat;
2949 : int i;
2950 :
2951 : // write(a,1000) index
2952 0 : print(files.TarcogIterationsFile, "*************************************************************************************************\n");
2953 0 : print(files.TarcogIterationsFile, "Iteration number: {:5}\n", index);
2954 :
2955 0 : print(files.TarcogIterationsFile, "Trmin = {:8.4F}\n", trmin - Constant::Kelvin);
2956 0 : print(files.TarcogIterationsFile, "Troom = {:12.6F}\n", troom - Constant::Kelvin);
2957 0 : print(files.TarcogIterationsFile, "Trmout = {:8.4F}\n", trmout - Constant::Kelvin);
2958 0 : print(files.TarcogIterationsFile, "Tamb = {:12.6F}\n", tamb - Constant::Kelvin);
2959 :
2960 0 : print(files.TarcogIterationsFile, "Ebsky = {:8.4F}\n", ebsky);
2961 0 : print(files.TarcogIterationsFile, "Ebroom = {:8.4F}\n", ebroom);
2962 :
2963 0 : print(files.TarcogIterationsFile, "hcin = {:8.4F}\n", hcin);
2964 0 : print(files.TarcogIterationsFile, "hcout = {:8.4F}\n", hcout);
2965 0 : print(files.TarcogIterationsFile, "hrin = {:8.4F}\n", hrin);
2966 0 : print(files.TarcogIterationsFile, "hrout = {:8.4F}\n", hrout);
2967 0 : print(files.TarcogIterationsFile, "hin = {:8.4F}\n", hin);
2968 0 : print(files.TarcogIterationsFile, "hout = {:8.4F}\n", hout);
2969 :
2970 : // Write headers for Ebb and Ebf
2971 0 : for (i = 1; i <= 2 * nlayer; ++i) {
2972 0 : if (i == 1) {
2973 0 : dynFormat = "";
2974 : }
2975 0 : if (mod(i, 2) == 1) {
2976 0 : dynFormat += fmt::format("Ebf({:3})", (i + 1) / 2);
2977 : } else {
2978 0 : dynFormat += fmt::format("Ebb({:3})", (i + 1) / 2);
2979 : }
2980 0 : if (i != 2 * nlayer) {
2981 0 : dynFormat += "===";
2982 : }
2983 : }
2984 0 : print(files.TarcogIterationsFile, dynFormat);
2985 0 : print(files.TarcogIterationsFile, "\n");
2986 :
2987 : // write Ebb and Ebf
2988 0 : print(files.TarcogIterationsFile, "{:16.8F} {:16.8F}", Ebf(1), Ebb(1));
2989 0 : for (i = 2; i <= nlayer; ++i) {
2990 0 : print(files.TarcogIterationsFile, " {:16.8F} {:16.8F}", Ebf(i), Ebb(i));
2991 : }
2992 0 : print(files.TarcogIterationsFile, "\n");
2993 :
2994 : // Write headers for Rb and Rf
2995 0 : for (i = 1; i <= 2 * nlayer; ++i) {
2996 0 : const std::string a = fmt::format("{:3}", (i + 1) / 2); // this is just to simulate correct integer in brackets
2997 0 : if (i == 1) {
2998 0 : dynFormat = "";
2999 : }
3000 0 : if (mod(i, 2) == 1) {
3001 0 : dynFormat += "Rf(" + a + ')';
3002 : } else {
3003 0 : dynFormat += "Rb(" + a + ')';
3004 : }
3005 0 : if (i != 2 * nlayer) {
3006 0 : dynFormat += "===";
3007 : }
3008 0 : }
3009 0 : print(files.TarcogIterationsFile, dynFormat);
3010 0 : print(files.TarcogIterationsFile, "\n");
3011 : // write Rb and Rf
3012 0 : print(files.TarcogIterationsFile, "{:16.8F} {:16.8F}", Rf(1), Rb(1));
3013 0 : for (i = 1; i <= nlayer; ++i) {
3014 0 : print(files.TarcogIterationsFile, " {:16.8F} {:16.8F}", Rf(i), Rb(i));
3015 : }
3016 0 : print(files.TarcogIterationsFile, "\n");
3017 :
3018 : // Write header for temperatures
3019 0 : for (i = 1; i <= 2 * nlayer; ++i) {
3020 0 : const std::string a = fmt::format("{:3}", i);
3021 0 : if (i == 1) {
3022 0 : dynFormat = "";
3023 : }
3024 0 : dynFormat += "theta(" + a + ')';
3025 0 : if (i != (2 * nlayer)) {
3026 0 : dynFormat += "==";
3027 : }
3028 0 : }
3029 0 : print(files.TarcogIterationsFile, dynFormat);
3030 0 : print(files.TarcogIterationsFile, "\n");
3031 :
3032 : // write temperatures
3033 0 : print(files.TarcogIterationsFile, "{:16.8F} \n", theta(1) - Constant::Kelvin);
3034 0 : for (i = 2; i <= 2 * nlayer; ++i) {
3035 0 : print(files.TarcogIterationsFile, " {:16.8F} \n", theta(i) - Constant::Kelvin);
3036 : }
3037 0 : print(files.TarcogIterationsFile, "\n");
3038 :
3039 : // close(TarcogIterationsFileNumber)
3040 :
3041 : // write results in csv file
3042 0 : if (index == 0) {
3043 0 : dynFormat = " ";
3044 0 : for (i = 1; i <= 2 * nlayer; ++i) {
3045 0 : const std::string a = fmt::format("{:3}", i);
3046 0 : if (i != 2 * nlayer) {
3047 0 : dynFormat += "theta(" + a + "),";
3048 : } else {
3049 0 : dynFormat += "theta(" + a + ')';
3050 : }
3051 0 : }
3052 0 : print(files.IterationCSVFile, dynFormat);
3053 0 : print(files.IterationCSVFile, "\n");
3054 : }
3055 0 : print(files.IterationCSVFile, "{:16.8F} \n", theta(1) - Constant::Kelvin);
3056 0 : for (i = 2; i <= 2 * nlayer; ++i) {
3057 0 : print(files.IterationCSVFile, " {:16.8F} \n", theta(i) - Constant::Kelvin);
3058 : }
3059 0 : print(files.IterationCSVFile, "\n");
3060 :
3061 : // close(IterationCSVFileNumber)
3062 0 : }
3063 :
3064 0 : void CalculateFuncResults(int const nlayer, Array2<Real64> const &a, const Array1D<Real64> &b, const Array1D<Real64> &x, Array1D<Real64> &FRes)
3065 : {
3066 : // Tuned Rewritten to traverse a in unit stride order
3067 0 : int const nlayer4(4 * nlayer);
3068 0 : for (int i = 1; i <= nlayer4; ++i) {
3069 0 : FRes(i) = -b(i);
3070 : }
3071 0 : for (int j = 1; j <= nlayer4; ++j) {
3072 0 : Real64 const x_j(x(j));
3073 0 : for (int i = 1; i <= nlayer4; ++i) {
3074 0 : FRes(i) += a(j, i) * x_j;
3075 : }
3076 : }
3077 0 : }
3078 :
3079 : } // namespace EnergyPlus::ThermalISO15099Calc
|