Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 :
54 : // EnergyPlus Headers
55 : #include <EnergyPlus/Construction.hh>
56 : #include <EnergyPlus/Data/EnergyPlusData.hh>
57 : #include <EnergyPlus/DataBSDFWindow.hh>
58 : #include <EnergyPlus/DataEnvironment.hh>
59 : #include <EnergyPlus/DataHeatBalSurface.hh>
60 : #include <EnergyPlus/DataHeatBalance.hh>
61 : #include <EnergyPlus/DataLoopNode.hh>
62 : #include <EnergyPlus/DataSurfaces.hh>
63 : #include <EnergyPlus/DataViewFactorInformation.hh>
64 : #include <EnergyPlus/DataWindowEquivalentLayer.hh>
65 : #include <EnergyPlus/DataZoneEquipment.hh>
66 : #include <EnergyPlus/DaylightingManager.hh>
67 : #include <EnergyPlus/General.hh>
68 : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
69 : #include <EnergyPlus/Material.hh>
70 : #include <EnergyPlus/Psychrometrics.hh>
71 : #include <EnergyPlus/ScheduleManager.hh>
72 : #include <EnergyPlus/UtilityRoutines.hh>
73 : #include <EnergyPlus/WindowEquivalentLayer.hh>
74 :
75 : namespace EnergyPlus::WindowEquivalentLayer {
76 :
77 : // MODULE INFORMATION
78 : // AUTHOR Bereket A. Nigusse, FSEC/UCF
79 : // DATE WRITTEN May 2013
80 :
81 : // PURPOSE OF THIS MODULE:
82 : // Manages the equivalent layer (ASHWAT) window model optical and thermal
83 : // calculations
84 : // METHODOLOGY EMPLOYED:
85 : // Uses net radiation method to calculate the optical properties of a multi-layer
86 : // window construction. Most of the routines in this module were adopted directly
87 : // from ASHRAE 1311-RP.
88 : // REFERENCES:
89 : // John L. Wright, Charles S. Barnaby, Michael R. Collins, and Nathan A. Kotey.
90 : // Improving Cooling Load Calculations for Fenestration with Shading Devices
91 : // ASHRAE 1311-RP, Final Report, February 11, 2009.
92 : // Edwards, D.K. 1977. Solar absorption by each element in an absorber-coverglass
93 : // array,Technical Note, Solar Energy, Vol. 19, pp. 401-402.
94 : // Kotey, N. A., J. L. Wright, and M. R. Collins. 2008. "Determining Longwave
95 : // RadiativeProperties of Flat Shading Materials," 33rd Annual SESCI / 3rd CSBC
96 : // Conference Proceedings, Fredericton, NB.
97 : // Kotey, N.A., Wright, J.L., M. R. Collins. 2009a. "Determination of Angle-Dependent
98 : // SolarOptical Properties of Roller Blind Materials," drafted for submission to
99 : // ASHRAE Transactions, Vol. 115, Pt. 1.
100 :
101 : // Kotey, N.A., Wright, J.L., M. R. Collins. 2009b. "Determination of Angle-Dependent
102 : // Solar Optical Properties of Drapery Fabrics," in review, ASHRAE Transactions,
103 : // Vol. 115, Pt. 2.
104 : // Wright, J. L. 2008. "Calculating Centre-Glass Performance Indices of Glazing
105 : // Systems with Shading Devices," ASHRAE Transactions, Vol. 114, Pt. 2.
106 : // Wright, J. L., N. Y. T. Huang, and M. R. Collins. 2008. "Thermal Resistance
107 : // of a Window with an Enclosed Venetian Blind: A Simplified Model,"
108 : // ASHRAE Transactions, Vol. 114, Pt. 1.
109 :
110 : // Yahoda, D. S. and J. L. Wright. 2004. "Methods for Calculating the Effective
111 : // Longwave Radiative Properties of a Venetian Blind Layer," ASHRAE Transactions,
112 : // Vol. 110, Pt. 1., pp. 463-473.
113 : // Yahoda, D. S. and J. L. Wright. 2005. "Methods for Calculating the Effective
114 : // Solar-Optical Properties of a Venetian Blind Layer," ASHRAE Transactions,
115 : // Vol. 111, Pt. 1, pp. 572-586.
116 : // Yahoda, D. S. and J. L. Wright. 2004. "Heat Transfer Analysis of a Between-Panes
117 : // Venetian Blind Using Effective Longwave Radiative Properties," ASHRAE Transactions,
118 : // Vol. 110, Pt. 1., pp. 455-462.
119 : // Using/Aliasing
120 : using namespace DataHeatBalance;
121 : using namespace DataSurfaces;
122 :
123 : // constexpr std::array<std::string_view, (int)Orientation::Num> orientationNamesUC = {"HORIZONTAL", "VERTICAL"};
124 :
125 109 : void InitEquivalentLayerWindowCalculations(EnergyPlusData &state)
126 : {
127 :
128 : // SUBROUTINE INFORMATION:
129 : // AUTHOR Bereket Nigusse
130 : // DATE WRITTEN May 2013
131 :
132 : // PURPOSE OF THIS SUBROUTINE:
133 : // Initializes the optical properties for the Equivalent Layer (ASHWAT) Window model
134 : // METHODOLOGY EMPLOYED:
135 : // Gets the EquivalentLayer Window Layers Inputs. Fills in the derived data type
136 : // based on the inputs specified.
137 :
138 109 : if (state.dataWindowEquivLayer->TotWinEquivLayerConstructs < 1) {
139 102 : return;
140 : }
141 7 : if (!allocated(state.dataWindowEquivLayer->CFS)) {
142 7 : state.dataWindowEquivLayer->CFS.allocate(state.dataWindowEquivLayer->TotWinEquivLayerConstructs);
143 : }
144 7 : if (!allocated(state.dataWindowEquivalentLayer->EQLDiffPropFlag)) {
145 7 : state.dataWindowEquivalentLayer->EQLDiffPropFlag.allocate(state.dataWindowEquivLayer->TotWinEquivLayerConstructs);
146 : }
147 7 : if (!allocated(state.dataWindowEquivalentLayer->CFSDiffAbsTrans)) {
148 7 : state.dataWindowEquivalentLayer->CFSDiffAbsTrans.allocate(2, CFSMAXNL + 1, state.dataWindowEquivLayer->TotWinEquivLayerConstructs);
149 : }
150 :
151 7 : state.dataWindowEquivalentLayer->EQLDiffPropFlag = true;
152 7 : state.dataWindowEquivalentLayer->CFSDiffAbsTrans = 0.0;
153 :
154 31 : for (int ConstrNum = 1; ConstrNum <= state.dataHeatBal->TotConstructs; ++ConstrNum) {
155 24 : if (!state.dataConstruction->Construct(ConstrNum).TypeIsWindow) {
156 17 : continue;
157 : }
158 7 : if (!state.dataConstruction->Construct(ConstrNum).WindowTypeEQL) {
159 0 : continue; // skip if not equivalent layer window
160 : }
161 :
162 7 : SetEquivalentLayerWindowProperties(state, ConstrNum);
163 :
164 : } // end do for TotConstructs
165 :
166 14 : for (int SurfNum : state.dataSurface->AllHTWindowSurfaceList) {
167 7 : if (!state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).WindowTypeEQL) {
168 0 : continue;
169 : }
170 :
171 7 : state.dataSurface->SurfWinWindowModelType(SurfNum) = WindowModel::EQL;
172 :
173 7 : } // end do for SurfNum
174 : }
175 :
176 7 : void SetEquivalentLayerWindowProperties(EnergyPlusData &state, int const ConstrNum)
177 : {
178 :
179 : // SUBROUTINE INFORMATION:
180 : // AUTHOR Bereket Nigusse
181 : // DATE WRITTEN May 2013
182 :
183 : // PURPOSE OF THIS SUBROUTINE:
184 : // Populates the the equivalent layer window model optical and thermal
185 : // properties, fills default values and shades geometrical calculations
186 :
187 : // METHODOLOGY EMPLOYED:
188 : // uses some routine developed for ASHRAE RP-1311 (ASHWAT Model)
189 :
190 7 : Array2D<Real64> SysAbs1(2, CFSMAXNL + 1); // layers absorptance and system transmittance
191 :
192 7 : auto &s_mat = state.dataMaterial;
193 :
194 7 : if (!allocated(state.dataWindowEquivLayer->CFSLayers)) {
195 7 : state.dataWindowEquivLayer->CFSLayers.allocate(state.dataConstruction->Construct(ConstrNum).TotLayers);
196 : }
197 :
198 7 : int sLayer = 0; // glazing and shade layers (non-gas layers) index
199 7 : int gLayer = 0; // gap layer index
200 7 : int EQLNum = state.dataConstruction->Construct(ConstrNum).EQLConsPtr;
201 :
202 7 : auto &CFS = state.dataWindowEquivLayer->CFS;
203 :
204 7 : CFS(EQLNum).Name = state.dataConstruction->Construct(ConstrNum).Name;
205 :
206 36 : for (int Layer = 1; Layer <= state.dataConstruction->Construct(ConstrNum).TotLayers; ++Layer) {
207 :
208 29 : Material::Group group1 = s_mat->materials(state.dataConstruction->Construct(ConstrNum).LayerPoint(1))->group;
209 29 : if (group1 != Material::Group::GlassEQL && group1 != Material::Group::ShadeEQL && group1 != Material::Group::DrapeEQL &&
210 0 : group1 != Material::Group::ScreenEQL && group1 != Material::Group::BlindEQL && group1 != Material::Group::WindowGapEQL) {
211 0 : continue;
212 : }
213 :
214 29 : int MaterNum = state.dataConstruction->Construct(ConstrNum).LayerPoint(Layer);
215 29 : auto const *mat = s_mat->materials(MaterNum);
216 :
217 29 : if (mat->group == Material::Group::BlindEQL) {
218 4 : auto const *thisMaterial = dynamic_cast<Material::MaterialBlindEQL const *>(mat);
219 4 : assert(thisMaterial != nullptr);
220 :
221 4 : ++sLayer;
222 4 : CFS(EQLNum).L(sLayer).Name = thisMaterial->Name;
223 : // longwave property input
224 4 : CFS(EQLNum).L(sLayer).LWP_MAT.EPSLF = thisMaterial->TAR.IR.Ft.Emi;
225 4 : CFS(EQLNum).L(sLayer).LWP_MAT.EPSLB = thisMaterial->TAR.IR.Bk.Emi;
226 4 : CFS(EQLNum).L(sLayer).LWP_MAT.TAUL = thisMaterial->TAR.IR.Ft.Tra;
227 :
228 4 : CFS(EQLNum).VBLayerPtr = sLayer;
229 4 : if (thisMaterial->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
230 3 : CFS(EQLNum).L(sLayer).LTYPE = LayerType::VBHOR;
231 1 : } else if (thisMaterial->SlatOrientation == DataWindowEquivalentLayer::Orientation::Vertical) {
232 1 : CFS(EQLNum).L(sLayer).LTYPE = LayerType::VBVER;
233 : }
234 4 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSFBD = thisMaterial->TAR.Sol.Ft.Bm[0].DfRef;
235 4 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSBBD = thisMaterial->TAR.Sol.Bk.Bm[0].DfRef;
236 4 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSFBD = thisMaterial->TAR.Sol.Ft.Bm[0].DfTra;
237 4 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSBBD = thisMaterial->TAR.Sol.Bk.Bm[0].DfTra;
238 :
239 4 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSFDD = thisMaterial->TAR.Sol.Ft.Df.Ref;
240 4 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSBDD = thisMaterial->TAR.Sol.Bk.Df.Ref;
241 4 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUS_DD = thisMaterial->TAR.Sol.Ft.Df.Tra;
242 4 : CFS(EQLNum).L(sLayer).PHI_DEG = thisMaterial->SlatAngle;
243 4 : CFS(EQLNum).L(sLayer).CNTRL = static_cast<int>(thisMaterial->slatAngleType);
244 4 : CFS(EQLNum).L(sLayer).S = thisMaterial->SlatSeparation;
245 4 : CFS(EQLNum).L(sLayer).W = thisMaterial->SlatWidth;
246 4 : CFS(EQLNum).L(sLayer).C = thisMaterial->SlatCrown;
247 :
248 25 : } else if (mat->group == Material::Group::GlassEQL) {
249 14 : auto const *thisMaterial = dynamic_cast<Material::MaterialGlassEQL const *>(mat);
250 14 : assert(thisMaterial != nullptr);
251 : // glazing
252 14 : ++sLayer;
253 14 : CFS(EQLNum).L(sLayer).Name = thisMaterial->Name;
254 : // longwave property input
255 14 : CFS(EQLNum).L(sLayer).LWP_MAT.EPSLF = thisMaterial->TAR.IR.Ft.Emi;
256 14 : CFS(EQLNum).L(sLayer).LWP_MAT.EPSLB = thisMaterial->TAR.IR.Bk.Emi;
257 14 : CFS(EQLNum).L(sLayer).LWP_MAT.TAUL = thisMaterial->TAR.IR.Ft.Tra;
258 :
259 14 : CFS(EQLNum).L(sLayer).LTYPE = LayerType::GLAZE;
260 14 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSFBB = thisMaterial->TAR.Sol.Ft.Bm[0].BmRef;
261 14 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSBBB = thisMaterial->TAR.Sol.Bk.Bm[0].BmRef;
262 14 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSFBB = thisMaterial->TAR.Sol.Ft.Bm[0].BmTra;
263 :
264 14 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSFBD = thisMaterial->TAR.Sol.Ft.Bm[0].DfRef;
265 14 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSBBD = thisMaterial->TAR.Sol.Bk.Bm[0].DfRef;
266 14 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSFBD = thisMaterial->TAR.Sol.Ft.Bm[0].DfTra;
267 14 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSBBD = thisMaterial->TAR.Sol.Bk.Bm[0].DfTra;
268 :
269 14 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSFDD = thisMaterial->TAR.Sol.Ft.Df.Ref;
270 14 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSBDD = thisMaterial->TAR.Sol.Bk.Df.Ref;
271 14 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUS_DD = thisMaterial->TAR.Sol.Ft.Df.Tra;
272 :
273 11 : } else if (mat->group == Material::Group::ShadeEQL) {
274 0 : auto const *thisMaterial = dynamic_cast<Material::MaterialShadeEQL const *>(mat);
275 0 : assert(thisMaterial != nullptr);
276 : // roller blind
277 0 : ++sLayer;
278 0 : CFS(EQLNum).L(sLayer).Name = thisMaterial->Name;
279 : // longwave property input
280 0 : CFS(EQLNum).L(sLayer).LWP_MAT.EPSLF = thisMaterial->TAR.IR.Ft.Emi;
281 0 : CFS(EQLNum).L(sLayer).LWP_MAT.EPSLB = thisMaterial->TAR.IR.Bk.Emi;
282 0 : CFS(EQLNum).L(sLayer).LWP_MAT.TAUL = thisMaterial->TAR.IR.Ft.Tra;
283 :
284 0 : CFS(EQLNum).L(sLayer).LTYPE = LayerType::ROLLB;
285 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSFBB = thisMaterial->TAR.Sol.Ft.Bm[0].BmTra;
286 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSBBB = thisMaterial->TAR.Sol.Bk.Bm[0].BmTra;
287 0 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSFBD = thisMaterial->TAR.Sol.Ft.Bm[0].DfRef;
288 0 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSBBD = thisMaterial->TAR.Sol.Bk.Bm[0].DfRef;
289 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSFBD = thisMaterial->TAR.Sol.Ft.Bm[0].DfTra;
290 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSBBD = thisMaterial->TAR.Sol.Bk.Bm[0].DfTra;
291 :
292 11 : } else if (mat->group == Material::Group::DrapeEQL) {
293 0 : auto const *thisMaterial = dynamic_cast<Material::MaterialDrapeEQL const *>(mat);
294 0 : assert(thisMaterial != nullptr);
295 : // drapery fabric
296 0 : ++sLayer;
297 0 : CFS(EQLNum).L(sLayer).Name = thisMaterial->Name;
298 : // longwave property input
299 0 : CFS(EQLNum).L(sLayer).LWP_MAT.EPSLF = thisMaterial->TAR.IR.Ft.Emi;
300 0 : CFS(EQLNum).L(sLayer).LWP_MAT.EPSLB = thisMaterial->TAR.IR.Bk.Emi;
301 0 : CFS(EQLNum).L(sLayer).LWP_MAT.TAUL = thisMaterial->TAR.IR.Ft.Tra;
302 :
303 0 : CFS(EQLNum).L(sLayer).LTYPE = LayerType::DRAPE;
304 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSFBB = thisMaterial->TAR.Sol.Ft.Bm[0].BmTra;
305 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSBBB = thisMaterial->TAR.Sol.Bk.Bm[0].BmTra;
306 0 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSFBD = thisMaterial->TAR.Sol.Ft.Bm[0].DfRef;
307 0 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSBBD = thisMaterial->TAR.Sol.Bk.Bm[0].DfRef;
308 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSFBD = thisMaterial->TAR.Sol.Ft.Bm[0].DfTra;
309 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSBBD = thisMaterial->TAR.Sol.Bk.Bm[0].DfTra;
310 :
311 0 : CFS(EQLNum).L(sLayer).S = thisMaterial->pleatedLength;
312 0 : CFS(EQLNum).L(sLayer).W = thisMaterial->pleatedWidth;
313 : // init diffuse SWP to force default derivation
314 0 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSFDD = -1.0;
315 0 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSBDD = -1.0;
316 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUS_DD = -1.0;
317 :
318 11 : } else if (mat->group == Material::Group::ScreenEQL) {
319 0 : auto const *thisMaterial = dynamic_cast<Material::MaterialScreenEQL const *>(mat);
320 0 : assert(thisMaterial != nullptr);
321 : // insect screen
322 0 : ++sLayer;
323 0 : CFS(EQLNum).L(sLayer).Name = thisMaterial->Name;
324 : // longwave property input
325 0 : CFS(EQLNum).L(sLayer).LWP_MAT.EPSLF = thisMaterial->TAR.IR.Ft.Emi;
326 0 : CFS(EQLNum).L(sLayer).LWP_MAT.EPSLB = thisMaterial->TAR.IR.Bk.Emi;
327 0 : CFS(EQLNum).L(sLayer).LWP_MAT.TAUL = thisMaterial->TAR.IR.Ft.Tra;
328 :
329 0 : CFS(EQLNum).L(sLayer).LTYPE = LayerType::INSCRN;
330 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSFBB = thisMaterial->TAR.Sol.Ft.Bm[0].BmTra;
331 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSBBB = thisMaterial->TAR.Sol.Bk.Bm[0].BmTra;
332 0 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSFBD = thisMaterial->TAR.Sol.Ft.Bm[0].DfRef;
333 0 : CFS(EQLNum).L(sLayer).SWP_MAT.RHOSBBD = thisMaterial->TAR.Sol.Bk.Bm[0].DfRef;
334 :
335 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSFBD = thisMaterial->TAR.Sol.Ft.Bm[0].DfTra;
336 0 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSBBD = thisMaterial->TAR.Sol.Bk.Bm[0].DfTra;
337 : // wire geometry
338 0 : CFS(EQLNum).L(sLayer).S = thisMaterial->wireSpacing;
339 0 : CFS(EQLNum).L(sLayer).W = thisMaterial->wireDiameter;
340 :
341 11 : } else if (mat->group == Material::Group::WindowGapEQL) {
342 11 : auto const *matGas = dynamic_cast<Material::MaterialGasMix const *>(mat);
343 11 : assert(matGas != nullptr);
344 :
345 : // Gap or Gas Layer
346 11 : ++gLayer;
347 :
348 11 : CFS(EQLNum).G(gLayer).Name = matGas->Name;
349 : // previously the values of the levels are 1-3, now it's 0-2
350 11 : CFS(EQLNum).G(gLayer).GTYPE = (int)matGas->gapVentType + 1;
351 11 : CFS(EQLNum).G(gLayer).TAS = matGas->Thickness;
352 :
353 11 : auto const &gas = matGas->gases[0];
354 11 : CFS(EQLNum).G(gLayer).FG.Name = Material::gasTypeNames[(int)gas.type];
355 11 : CFS(EQLNum).G(gLayer).FG.AK = gas.con.c0;
356 11 : CFS(EQLNum).G(gLayer).FG.BK = gas.con.c1;
357 11 : CFS(EQLNum).G(gLayer).FG.CK = gas.con.c2;
358 11 : CFS(EQLNum).G(gLayer).FG.ACP = gas.cp.c0;
359 11 : CFS(EQLNum).G(gLayer).FG.BCP = gas.cp.c1;
360 11 : CFS(EQLNum).G(gLayer).FG.CCP = gas.cp.c2;
361 11 : CFS(EQLNum).G(gLayer).FG.AVISC = gas.cp.c0;
362 11 : CFS(EQLNum).G(gLayer).FG.BVISC = gas.cp.c1;
363 11 : CFS(EQLNum).G(gLayer).FG.CVISC = gas.cp.c2;
364 11 : CFS(EQLNum).G(gLayer).FG.MHAT = gas.wght;
365 : // fills gas density and effective gap thickness
366 11 : BuildGap(state, CFS(EQLNum).G(gLayer), CFS(EQLNum).G(gLayer).GTYPE, CFS(EQLNum).G(gLayer).TAS);
367 : } else {
368 0 : ++sLayer;
369 0 : CFS(EQLNum).L(sLayer).Name = mat->Name;
370 0 : CFS(EQLNum).L(sLayer).LTYPE = LayerType::NONE;
371 : }
372 : // beam beam transmittance is the same for front and back side
373 29 : CFS(EQLNum).L(sLayer).SWP_MAT.TAUSBBB = CFS(EQLNum).L(sLayer).SWP_MAT.TAUSFBB;
374 29 : CFS(EQLNum).NL = sLayer;
375 :
376 : // checks optical properties and fill in default values for diffuse optical
377 : // properties by calculating from other optical inputs, also fills in geometrical inputs
378 29 : CheckAndFixCFSLayer(state, CFS(EQLNum).L(sLayer));
379 :
380 : } // end do for Construct(ConstrNum)%TotLayers
381 :
382 : // Finalize CFS after get input. Correct effective gap thickness for VB
383 7 : FinalizeCFS(state, CFS(EQLNum));
384 :
385 : // get total solid layers (glazing layers + shade layers)
386 7 : state.dataConstruction->Construct(ConstrNum).TotSolidLayers = CFS(EQLNum).NL;
387 :
388 : // Calculate layers diffuse absorptance and system diffuse transmittance
389 7 : CalcEQLWindowOpticalProperty(state, CFS(EQLNum), SolarArrays::DIFF, SysAbs1, 0.0, 0.0, 0.0);
390 7 : state.dataConstruction->Construct(ConstrNum).TransDiffFrontEQL = SysAbs1(1, CFS(EQLNum).NL + 1);
391 7 : state.dataWindowEquivalentLayer->CFSDiffAbsTrans(_, _, EQLNum) = SysAbs1;
392 7 : state.dataConstruction->Construct(ConstrNum).AbsDiffFrontEQL({1, CFSMAXNL}) = SysAbs1(1, {1, CFSMAXNL});
393 7 : state.dataConstruction->Construct(ConstrNum).AbsDiffBackEQL({1, CFSMAXNL}) = SysAbs1(2, {1, CFSMAXNL});
394 : // get construction front and back diffuse effective reflectance
395 7 : state.dataConstruction->Construct(ConstrNum).ReflectSolDiffFront = CFS(EQLNum).L(1).SWP_EL.RHOSFDD;
396 7 : state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack = CFS(EQLNum).L(CFS(EQLNum).NL).SWP_EL.RHOSBDD;
397 : // calculate U-Value, SHGC and Normal Transmittance of EQL Window
398 7 : CalcEQLWindowStandardRatings(state, ConstrNum);
399 :
400 7 : if (CFSHasControlledShade(state, CFS(EQLNum)) > 0) {
401 3 : CFS(EQLNum).ISControlled = true; // is controlled
402 : }
403 :
404 : // set internal face emissivity
405 7 : state.dataConstruction->Construct(ConstrNum).InsideAbsorpThermal = EffectiveEPSLB(CFS(EQLNum));
406 7 : }
407 :
408 7 : void CalcEQLWindowUvalue(EnergyPlusData &state,
409 : CFSTY const &FS, // CFS to be calculated
410 : Real64 &UNFRC // NFRC U-factor, W/m2-K
411 : )
412 : {
413 : // SUBROUTINE INFORMATION:
414 : // AUTHOR JOHN L. WRIGHT/Chip Barnaby
415 : // DATE WRITTEN Last Modified February 2008
416 : // MODIFIED Bereket Nigusse, May 2013
417 : // Replaced inside convection calculation with ISO Std 15099
418 :
419 : // PURPOSE OF THIS SUBROUTINE:
420 : // Calculates U-value of equivalent layer window at standard
421 : // fenestration winter rating conditions
422 :
423 : // METHODOLOGY EMPLOYED:
424 : // uses routine developed for ASHRAE RP-1311 (ASHWAT Model)
425 : // NFRC rated *HEATING* U-factor or Winter Rating Condition
426 : // tin = 294.15d0 ! Inside air temperature (69.8F, 21.0C)
427 : // tout = 255.15d0 ! Outside air temperature (-0.4F, -18C)
428 : // hcout = 26.d0 ! Outside convective film conductance at 5.5 m/s (12.3 mph)
429 : // ! wind speed (the value used in Window 5)
430 : // BeamSolarInc = 0.0
431 :
432 7 : Real64 constexpr Height(1.0); // window height, m
433 7 : Real64 constexpr TOUT(-18.0); // outdoor air temperature, C
434 7 : Real64 constexpr TIN(21.0); // indoor air temperature, C
435 : static constexpr std::string_view RoutineName("CalcEQLWindowUvalue: ");
436 :
437 : Real64 U; // U-factor, W/m2-K
438 : Real64 UOld; // U-factor during previous iteration step, W/m2-K
439 : Real64 HXO; // outdoor combined conv+rad surf coeff, W/m2-K
440 : Real64 HXI; // indoor combined conf+rad surf coeff, W/m2-K
441 : Real64 HRO; // outdoor side radiation surf coeff, W/m2-K
442 : Real64 HCO; // outdoor side convection surf coeff, W/m2-K
443 : Real64 HRI; // indoor side radiation surf coeff, W/m2-K
444 : Real64 HCI; // indoor side convection surf coeff, W/m2-K
445 : Real64 TGO;
446 : Real64 TGI;
447 : Real64 TGIK;
448 : Real64 TIK;
449 : Real64 DT; // temperature difference, K
450 : Real64 EO; // outside face effective emissivity, (-)
451 : Real64 EI; // inside face effective emissivity, (-)
452 : int I; // index
453 :
454 7 : bool CFSURated = false; // false if U-Value calculation failed
455 :
456 : // Initial guess value for combined conductance
457 7 : HXO = 29.0; // 1/FenROut
458 7 : HXI = 7.0; // 1/FenRIn
459 7 : HCO = 26.0;
460 7 : HCI = 3.0; // Initial guess
461 :
462 7 : DT = TIN - TOUT; // note DT == 0 detected in CFSUFactor()
463 7 : EO = FS.L(1).LWP_EL.EPSLF; // emissivities outside
464 7 : EI = FS.L(FS.NL).LWP_EL.EPSLB; // emissivities inside
465 7 : U = 5.0 / FS.NL; // initial guess
466 :
467 : // Iterate: find surface temperature, update coeffs, converge to U
468 17 : for (I = 1; I <= 10; ++I) {
469 17 : TGO = TOUT + U * DT / HXO; // update glazing surface temps
470 17 : TGI = TIN - U * DT / HXI;
471 17 : HRO = Constant::StefanBoltzmann * EO * (pow_2(TGO + Constant::Kelvin) + pow_2(TOUT + Constant::Kelvin)) *
472 17 : ((TGO + Constant::Kelvin) + (TOUT + Constant::Kelvin));
473 17 : HRI = Constant::StefanBoltzmann * EI * (pow_2(TGI + Constant::Kelvin) + pow_2(TIN + Constant::Kelvin)) *
474 17 : ((TGI + Constant::Kelvin) + (TIN + Constant::Kelvin));
475 : // HCI = HIC_ASHRAE( Height, TGI, TI) ! BAN June 2103 Replaced with ISO Std 15099
476 17 : TGIK = TGI + Constant::Kelvin;
477 17 : TIK = TIN + Constant::Kelvin;
478 17 : HCI = HCInWindowStandardRatings(state, Height, TGIK, TIK);
479 17 : if (HCI < 0.001) {
480 0 : break;
481 : }
482 17 : HXI = HCI + HRI;
483 17 : HXO = HCO + HRO;
484 17 : UOld = U;
485 17 : if (!CFSUFactor(state, FS, TOUT, HCO, TIN, HCI, U)) {
486 0 : break;
487 : }
488 17 : if (I > 1 && FEQX(U, UOld, 0.001)) {
489 7 : CFSURated = true;
490 7 : break;
491 : }
492 : }
493 7 : if (!CFSURated) {
494 0 : ShowWarningMessage(state, format("{}Fenestration U-Value calculation failed for {}", RoutineName, FS.Name));
495 0 : ShowContinueError(state, format("...Calculated U-value = {:.4T}", U));
496 0 : ShowContinueError(state, "...Check consistency of inputs");
497 : }
498 7 : UNFRC = U;
499 7 : }
500 :
501 7 : void CalcEQLWindowSHGCAndTransNormal(EnergyPlusData &state,
502 : CFSTY const &FS, // fenestration system
503 : Real64 &SHGCSummer, // solar heat gain coefficient
504 : Real64 &TransNormal // transmittance at normal incidence
505 : )
506 : {
507 :
508 : // SUBROUTINE INFORMATION:
509 : // AUTHOR Bereket Nigusse
510 : // DATE WRITTEN May 2013
511 :
512 : // PURPOSE OF THIS SUBROUTINE:
513 : // Calculates SHGC and Normal Transmittance of equivalent layer fenestration.
514 :
515 : // METHODOLOGY EMPLOYED:
516 : // Uses routine developed for ASHRAE RP-1311 (ASHWAT Model)
517 : // Summer Window Rating Conditions
518 : // tin = 297.15d0 ! indoor air condition (75.2F, 24.0C)
519 : // tout = 305.15d0 ! Outside air temperature (89.6F, 32C)
520 : // hcout = 15.d0 ! Outside convective film conductance at 2.8 m/s (6.2 mph) wind speed
521 : // BeamSolarInc = 783.0d0 ! Direct normal incident solar radiation, W/m2
522 :
523 7 : constexpr Real64 TOL(0.01);
524 7 : constexpr Real64 TIN(297.15);
525 7 : constexpr Real64 TOUT(305.15);
526 7 : constexpr Real64 BeamSolarInc(783.0);
527 : static constexpr std::string_view RoutineName("CalcEQLWindowSHGCAndTransNormal: ");
528 :
529 : Real64 HCOUT;
530 : Real64 TRMOUT;
531 : Real64 TRMIN;
532 : Real64 HCIN;
533 7 : Array1D<Real64> QOCF(CFSMAXNL);
534 7 : Array1D<Real64> JB({0, CFSMAXNL});
535 7 : Array1D<Real64> JF({1, CFSMAXNL + 1});
536 7 : Array1D<Real64> T(CFSMAXNL);
537 7 : Array1D<Real64> Q({0, CFSMAXNL});
538 7 : Array1D<Real64> H({0, CFSMAXNL + 1});
539 7 : Array2D<Real64> Abs1(2, CFSMAXNL + 1);
540 : Real64 QOCFRoom;
541 : Real64 UCG;
542 : Real64 SHGC;
543 : Real64 IncA;
544 : Real64 VProfA;
545 : Real64 HProfA;
546 : int NL;
547 : int I;
548 :
549 : // Object Data
550 7 : Array1D<CFSSWP> SWP_ON(CFSMAXNL);
551 :
552 7 : NL = FS.NL;
553 7 : IncA = 0.0;
554 7 : VProfA = 0.0;
555 7 : HProfA = 0.0;
556 7 : Abs1 = 0.0;
557 7 : HCIN = 3.0; // Initial guess
558 7 : HCOUT = 15.0;
559 14 : if (FS.L(1).LTYPE == LayerType::ROLLB || FS.L(1).LTYPE == LayerType::DRAPE || FS.L(1).LTYPE == LayerType::INSCRN ||
560 14 : FS.L(1).LTYPE == LayerType::VBHOR || FS.L(1).LTYPE == LayerType::VBVER) { // Exterior Roller Blind Present | Exterior Drape Fabric | Exterior
561 : // Insect Screen Present | Exterior Venetian Blind Present
562 : // Reduced convection coefficient due to external attachment
563 0 : HCOUT = 12.25;
564 : }
565 :
566 : // Temperatures
567 7 : TRMOUT = TOUT;
568 7 : TRMIN = TIN;
569 :
570 : // Convert direct-normal solar properties for beam incidence to current incident angle
571 25 : for (I = 1; I <= NL; ++I) {
572 18 : ASHWAT_OffNormalProperties(state, FS.L(I), IncA, VProfA, HProfA, SWP_ON(I));
573 : }
574 7 : ASHWAT_Solar(FS.NL, SWP_ON, state.dataWindowEquivLayer->SWP_ROOMBLK, 1.0, 0.0, 0.0, Abs1(1, {1, FS.NL + 1}), Abs1(2, {1, FS.NL + 1}));
575 7 : TransNormal = Abs1(1, NL + 1);
576 :
577 : // Calculate SHGC using net radiation method (ASHWAT Model)
578 7 : bool CFSSHGC = ASHWAT_ThermalRatings(state,
579 : FS,
580 : TIN,
581 : TOUT,
582 : HCIN,
583 : HCOUT,
584 : TRMOUT,
585 : TRMIN,
586 : BeamSolarInc,
587 14 : BeamSolarInc * Abs1(1, {1, NL + 1}),
588 : TOL,
589 : QOCF,
590 : QOCFRoom,
591 : T,
592 : Q,
593 : JF,
594 : JB,
595 : H,
596 : UCG,
597 : SHGC,
598 : true);
599 :
600 7 : if (!CFSSHGC) {
601 0 : ShowWarningMessage(state, format("{}Solar heat gain coefficient calculation failed for {}", RoutineName, FS.Name));
602 0 : ShowContinueError(state, format("...Calculated SHGC = {:.4T}", SHGC));
603 0 : ShowContinueError(state, format("...Calculated U-Value = {:.4T}", UCG));
604 0 : ShowContinueError(state, "...Check consistency of inputs.");
605 0 : return;
606 : }
607 7 : SHGCSummer = SHGC;
608 7 : }
609 :
610 1115 : void CalcEQLWindowOpticalProperty(EnergyPlusData &state,
611 : CFSTY &FS, // fenestration system
612 : SolarArrays const DiffBeamFlag, // isDIFF: calc diffuse properties
613 : Array2A<Real64> Abs1,
614 : Real64 const IncA, // angle of incidence, radians
615 : Real64 const VProfA, // inc solar vertical profile angle, radians
616 : Real64 const HProfA // inc solar horizontal profile angle, radians
617 : )
618 : {
619 : // SUBROUTINE INFORMATION:
620 : // AUTHOR University of WaterLoo
621 : // MODIFIED Bereket Nigusse, May 2013
622 :
623 : // PURPOSE OF THIS SUBROUTINE:
624 : // Calculates absorptance for each layer, and transmittance of the
625 : // fenestration for beam and diffuse solar radiation
626 :
627 : // METHODOLOGY EMPLOYED:
628 : // uses routine developed for ASHRAE RP-1311 (ASHWAT Model). Uses net radiation method.
629 :
630 : // Argument array dimensioning
631 1115 : Abs1.dim(2, CFSMAXNL + 1);
632 :
633 : // Locals
634 : // SUBROUTINE ARGUMENT DEFINITIONS:
635 : // else: isBEAM
636 : // returned: layer abs for unit (1 W/m2) incident
637 : // if beam, Abs1( :, 1) = abs for IncA
638 : // Abs1( :, 2) = trans Beam-Diffuse only
639 : // if diff, Abs1( :, 1) = abs for outside diff
640 : // Abs1( :, 2) = abs for inside diff
641 : // + = up-from-horizontal
642 : // + = west-of-normal
643 : // convect coefficients, W/m2-K
644 :
645 : // Object Data
646 1115 : Array1D<CFSSWP> SWP_ON(CFSMAXNL);
647 :
648 1115 : int NL = FS.NL;
649 1115 : Abs1 = 0.0;
650 :
651 1115 : if (FS.ISControlled) { // at least 1 controlled layer found
652 2568 : for (int iL = 1; iL <= NL; ++iL) {
653 : // If there is shade control (Venetian Blind Only).
654 1926 : if (IsControlledShade(state, FS.L(iL))) {
655 642 : DoShadeControl(state, FS.L(iL), IncA, VProfA, HProfA);
656 : }
657 : }
658 : }
659 :
660 1115 : if (DiffBeamFlag != SolarArrays::DIFF) {
661 : // Beam: Convert direct-normal solar properties to off-normal properties
662 2851 : for (int I = 1; I <= NL; ++I) {
663 2064 : ASHWAT_OffNormalProperties(state, FS.L(I), IncA, VProfA, HProfA, SWP_ON(I));
664 : }
665 787 : ASHWAT_Solar(FS.NL, SWP_ON, state.dataWindowEquivLayer->SWP_ROOMBLK, 1.0, 0.0, 0.0, Abs1(1, {1, FS.NL + 1}), Abs1(2, {1, FS.NL + 1}));
666 : } else {
667 : // diffuse
668 328 : Array1D<CFSSWP> const SWP_EL(FS.L.ma(&CFSLAYER::SWP_EL)); // Autodesk:F2C++ Can't slice a member array so we create a temporary: Inefficient
669 328 : ASHWAT_Solar(FS.NL, SWP_EL, state.dataWindowEquivLayer->SWP_ROOMBLK, 0.0, 1.0, 0.0, Abs1(1, {1, FS.NL + 1}));
670 328 : ASHWAT_Solar(FS.NL, SWP_EL, state.dataWindowEquivLayer->SWP_ROOMBLK, 0.0, 0.0, 1.0, Abs1(2, {1, FS.NL + 1}));
671 : // CFSFenProp = LOK1 .AND. LOK2
672 328 : }
673 1115 : }
674 :
675 2352 : void EQLWindowSurfaceHeatBalance(EnergyPlusData &state,
676 : int const SurfNum, // Surface number
677 : Real64 const HcOut, // outside convection coefficient at this timestep, W/m2K
678 : Real64 &SurfInsideTemp, // Inside window surface temperature (innermost face) [C]
679 : Real64 &SurfOutsideTemp, // Outside surface temperature (C)
680 : Real64 &SurfOutsideEmiss,
681 : DataBSDFWindow::Condition const CalcCondition // Calculation condition (summer, winter or no condition)
682 : )
683 : {
684 : // SUBROUTINE INFORMATION:
685 : // AUTHOR Bereket Nigusse
686 : // DATE WRITTEN May 2013
687 :
688 : // PURPOSE OF THIS SUBROUTINE:
689 : // performs surface heat balance and returns in the inside and outside surface temperatures
690 :
691 : // METHODOLOGY EMPLOYED:
692 : // uses the solar-thermal routine developed for ASHRAE RP-1311 (ASHWAT Model).
693 :
694 : using Psychrometrics::PsyCpAirFnW;
695 : using Psychrometrics::PsyTdpFnWPb;
696 :
697 2352 : Real64 constexpr TOL(0.0001); // convergence tolerance
698 :
699 : int NL; // Number of layers
700 2352 : Real64 TIN(0);
701 : Real64 TRMIN;
702 2352 : Real64 Tout(0);
703 : Real64 TRMOUT;
704 : Real64 QCONV;
705 2352 : Array1D<Real64> QOCF(CFSMAXNL);
706 : Real64 QOCFRoom;
707 2352 : Array1D<Real64> JB({0, CFSMAXNL});
708 2352 : Array1D<Real64> JF({1, CFSMAXNL + 1});
709 2352 : Array1D<Real64> T(CFSMAXNL);
710 2352 : Array1D<Real64> Q({0, CFSMAXNL});
711 2352 : Array1D<Real64> H({0, CFSMAXNL + 1});
712 2352 : Array1D<Real64> QAllSWwinAbs({1, CFSMAXNL + 1});
713 :
714 : int EQLNum; // equivalent layer window index
715 : int ConstrNum; // Construction number
716 :
717 : Real64 LWAbsIn; // effective long wave absorptance/emissivity back side
718 : Real64 LWAbsOut; // effective long wave absorptance/emissivity front side
719 2352 : Real64 outir(0);
720 : Real64 rmir;
721 : Real64 Ebout;
722 : Real64 QXConv; // extra convective gain from this surface
723 2352 : Real64 TaIn(0); // zone air temperature
724 : Real64 tsky; // sky temperature
725 : Real64 HcIn; // inside convection coefficient at this timestep, W/m2K
726 : Real64 ConvHeatFlowNatural; // Convective heat flow from gap between glass and interior shade or blind (W)
727 : Real64 NetIRHeatGainWindow; // net radiation gain from the window surface to the zone (W)
728 : Real64 ConvHeatGainWindow; // net convection heat gain from inside surface of window to zone air (W)
729 : LayerType InSideLayerType; // interior shade type
730 :
731 : Real64 SrdSurfTempAbs; // Absolute temperature of a surrounding surface
732 : Real64 OutSrdIR;
733 :
734 2352 : if (CalcCondition != DataBSDFWindow::Condition::Invalid) {
735 0 : return;
736 : }
737 :
738 2352 : ConstrNum = state.dataSurface->Surface(SurfNum).Construction;
739 2352 : QXConv = 0.0;
740 2352 : ConvHeatFlowNatural = 0.0;
741 :
742 2352 : EQLNum = state.dataConstruction->Construct(ConstrNum).EQLConsPtr;
743 2352 : HcIn = state.dataHeatBalSurf->SurfHConvInt(SurfNum); // windows inside surface convective film conductance
744 :
745 2352 : if (CalcCondition == DataBSDFWindow::Condition::Invalid) {
746 2352 : int SurfNumAdj = state.dataSurface->Surface(SurfNum).ExtBoundCond;
747 2352 : Real64 RefAirTemp = state.dataSurface->Surface(SurfNum).getInsideAirTemperature(state, SurfNum);
748 2352 : TaIn = RefAirTemp;
749 2352 : TIN = TaIn + Constant::Kelvin; // Inside air temperature, K
750 :
751 : // now get "outside" air temperature
752 2352 : if (SurfNumAdj > 0) {
753 : // this is interzone window. the outside condition is determined from the adjacent zone
754 : // condition
755 0 : int enclNumAdj = state.dataSurface->Surface(SurfNumAdj).RadEnclIndex;
756 0 : RefAirTemp = state.dataSurface->Surface(SurfNumAdj).getInsideAirTemperature(state, SurfNumAdj);
757 0 : Tout = RefAirTemp + Constant::Kelvin; // outside air temperature
758 0 : tsky = state.dataViewFactor->EnclRadInfo(enclNumAdj).MRT +
759 : Constant::Kelvin; // TODO this misses IR from sources such as high temp radiant and baseboards
760 :
761 : // The IR radiance of this window's "exterior" surround is the IR radiance
762 : // from surfaces and high-temp radiant sources in the adjacent zone
763 0 : outir = state.dataSurface->SurfWinIRfromParentZone(SurfNumAdj) + state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(SurfNumAdj) +
764 0 : state.dataHeatBal->SurfQdotRadIntGainsInPerArea(SurfNumAdj);
765 :
766 : } else { // Exterior window (ExtBoundCond = 0)
767 : // Calculate LWR from surrounding surfaces if defined for an exterior window
768 2352 : OutSrdIR = 0;
769 2352 : if (state.dataGlobal->AnyLocalEnvironmentsInModel) {
770 0 : if (state.dataSurface->Surface(SurfNum).SurfHasSurroundingSurfProperty) {
771 0 : SrdSurfTempAbs = state.dataSurface->Surface(SurfNum).SrdSurfTemp + Constant::Kelvin;
772 0 : OutSrdIR = Constant::StefanBoltzmann * state.dataSurface->Surface(SurfNum).ViewFactorSrdSurfs * pow_4(SrdSurfTempAbs);
773 : }
774 : }
775 2352 : if (state.dataSurface->Surface(SurfNum).ExtWind) { // Window is exposed to wind (and possibly rain)
776 2352 : if (state.dataEnvrn->IsRain) { // Raining: since wind exposed, outside window surface gets wet
777 0 : Tout = state.dataSurface->SurfOutWetBulbTemp(SurfNum) + Constant::Kelvin;
778 : } else { // Dry
779 2352 : Tout = state.dataSurface->SurfOutDryBulbTemp(SurfNum) + Constant::Kelvin;
780 : }
781 : } else { // Window not exposed to wind
782 0 : Tout = state.dataSurface->SurfOutDryBulbTemp(SurfNum) + Constant::Kelvin;
783 : }
784 2352 : tsky = state.dataEnvrn->SkyTempKelvin;
785 2352 : Ebout = Constant::StefanBoltzmann * pow_4(Tout);
786 : // ASHWAT model may be slightly different
787 2352 : outir = state.dataSurface->Surface(SurfNum).ViewFactorSkyIR *
788 2352 : (state.dataSurface->SurfAirSkyRadSplit(SurfNum) * Constant::StefanBoltzmann * pow_4(tsky) +
789 2352 : (1.0 - state.dataSurface->SurfAirSkyRadSplit(SurfNum)) * Ebout) +
790 2352 : state.dataSurface->Surface(SurfNum).ViewFactorGroundIR * Ebout + OutSrdIR;
791 : }
792 : }
793 : // Outdoor conditions
794 2352 : TRMOUT = root_4(outir / Constant::StefanBoltzmann); // it is in Kelvin scale
795 : // indoor conditions
796 2352 : LWAbsIn = EffectiveEPSLB(state.dataWindowEquivLayer->CFS(EQLNum)); // windows inside face effective thermal emissivity
797 2352 : LWAbsOut = EffectiveEPSLF(state.dataWindowEquivLayer->CFS(EQLNum)); // windows outside face effective thermal emissivity
798 2352 : SurfOutsideEmiss = LWAbsOut;
799 : // Indoor mean radiant temperature.
800 : // IR incident on window from zone surfaces and high-temp radiant sources
801 2352 : rmir = state.dataSurface->SurfWinIRfromParentZone(SurfNum) + state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(SurfNum) +
802 2352 : state.dataHeatBal->SurfQdotRadIntGainsInPerArea(SurfNum);
803 2352 : TRMIN = root_4(rmir / Constant::StefanBoltzmann); // TODO check model equation.
804 :
805 2352 : NL = state.dataWindowEquivLayer->CFS(EQLNum).NL;
806 2352 : QAllSWwinAbs({1, NL + 1}) = state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, {1, NL + 1});
807 : // Solve energy balance(s) for temperature at each node/layer and
808 : // heat flux, including components, between each pair of nodes/layers
809 2352 : ASHWAT_ThermalCalc(state,
810 2352 : state.dataWindowEquivLayer->CFS(EQLNum),
811 : TIN,
812 : Tout,
813 : HcIn,
814 : HcOut,
815 : TRMOUT,
816 : TRMIN,
817 4704 : QAllSWwinAbs({1, NL + 1}),
818 : TOL,
819 : QOCF,
820 : QOCFRoom,
821 : T,
822 : Q,
823 : JF,
824 : JB,
825 : H);
826 :
827 : // effective surface temperature is set to surface temperature calculated
828 : // by the fenestration layers temperature solver
829 2352 : SurfInsideTemp = T(NL) - Constant::Kelvin;
830 : // Convective to room
831 2352 : QCONV = H(NL) * (T(NL) - TIN);
832 : // Other convective = total conv - standard model prediction
833 2352 : QXConv = QCONV - HcIn * (SurfInsideTemp - TaIn);
834 : // Save the extra convection term. This term is added to the zone air heat
835 : // balance equation
836 2352 : state.dataSurface->SurfWinOtherConvHeatGain(SurfNum) = state.dataSurface->Surface(SurfNum).Area * QXConv;
837 2352 : SurfOutsideTemp = T(1) - Constant::Kelvin;
838 : // Various reporting calculations
839 2352 : InSideLayerType = state.dataWindowEquivLayer->CFS(EQLNum).L(NL).LTYPE;
840 2352 : if (InSideLayerType == LayerType::GLAZE) {
841 888 : ConvHeatFlowNatural = 0.0;
842 : } else {
843 1464 : ConvHeatFlowNatural = state.dataSurface->Surface(SurfNum).Area * QOCFRoom;
844 : }
845 2352 : state.dataSurface->SurfWinEffInsSurfTemp(SurfNum) = SurfInsideTemp;
846 2352 : NetIRHeatGainWindow =
847 2352 : state.dataSurface->Surface(SurfNum).Area * LWAbsIn * (Constant::StefanBoltzmann * pow_4(SurfInsideTemp + Constant::Kelvin) - rmir);
848 2352 : ConvHeatGainWindow = state.dataSurface->Surface(SurfNum).Area * HcIn * (SurfInsideTemp - TaIn);
849 : // Window heat gain (or loss) is calculated here
850 2352 : state.dataSurface->SurfWinHeatGain(SurfNum) =
851 2352 : state.dataSurface->SurfWinTransSolar(SurfNum) + ConvHeatGainWindow + NetIRHeatGainWindow + ConvHeatFlowNatural -
852 2352 : (state.dataSurface->SurfWinLossSWZoneToOutWinRep(SurfNum) +
853 2352 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(SurfNum) * state.dataSurface->Surface(SurfNum).Area);
854 2352 : state.dataSurface->SurfWinConvHeatFlowNatural(SurfNum) = ConvHeatFlowNatural;
855 2352 : state.dataSurface->SurfWinGainConvShadeToZoneRep(SurfNum) = ConvHeatGainWindow;
856 2352 : state.dataSurface->SurfWinGainIRGlazToZoneRep(SurfNum) = NetIRHeatGainWindow;
857 2352 : state.dataSurface->SurfWinGainIRShadeToZoneRep(SurfNum) = NetIRHeatGainWindow;
858 2352 : if (InSideLayerType == LayerType::GLAZE) {
859 : // no interior shade
860 888 : state.dataSurface->SurfWinGainIRShadeToZoneRep(SurfNum) = 0.0;
861 : } else {
862 : // Interior shade exists
863 1464 : state.dataSurface->SurfWinGainIRGlazToZoneRep(SurfNum) = 0.0;
864 : }
865 2352 : }
866 :
867 0 : void OPENNESS_LW(Real64 const OPENNESS, // shade openness (=tausbb at normal incidence)
868 : Real64 const EPSLW0, // apparent LW emittance of shade at 0 openness
869 : Real64 const TAULW0, // apparent LW transmittance of shade at 0 openness
870 : Real64 &EPSLW, // returned: effective LW emittance of shade
871 : Real64 &TAULW // returned: effective LW transmittance of shade
872 : )
873 : {
874 : // SUBROUTINE INFORMATION:
875 : // AUTHOR John L. Wright and Nathan Kotey, University of Waterloo,
876 : // Mechanical Engineering, Advanced Glazing System Laboratory
877 :
878 : // PURPOSE OF THIS SUBROUTINE:
879 : // Modifies long wave properties for shade types characterized by openness.
880 : // Applies to shade type: insect screen, roller blind, drape fabric
881 :
882 : // (= wire or thread emittance)
883 : // typical (default) values
884 : // dark insect screen = .93
885 : // metallic insect screen = .32
886 : // roller blinds = .91
887 : // drape fabric = .87
888 : // typical (default) values
889 : // dark insect screen = .02
890 : // metallic insect screen = .19
891 : // roller blinds = .05
892 : // drape fabric = .05
893 :
894 0 : EPSLW = EPSLW0 * (1.0 - OPENNESS);
895 0 : TAULW = TAULW0 * (1.0 - OPENNESS) + OPENNESS;
896 0 : }
897 :
898 2608 : Real64 P01(EnergyPlusData &state,
899 : Real64 const P, // property
900 : std::string_view const WHAT // identifier for err msg
901 : )
902 : {
903 : // AUTHOR ASHRAE 1311-RP
904 : // MODIFIED Bereket Nigusse, May 2013
905 : // Added error messages
906 :
907 : // PURPOSE OF THIS FUNCTION:
908 : // Constrains property to range 0 - 1
909 :
910 : static constexpr std::string_view RoutineName("P01: ");
911 :
912 2608 : if (P < -0.05 || P > 1.05) {
913 0 : ShowWarningMessage(state, format("{}property value should have been between 0 and 1", RoutineName));
914 0 : ShowContinueError(state, format("{}=: property value is ={:.4T}", WHAT, P));
915 0 : if (P < 0.0) {
916 0 : ShowContinueError(state, "property value is reset to 0.0");
917 0 : } else if (P > 1.0) {
918 0 : ShowContinueError(state, "property value is reset to 1.0");
919 : }
920 : }
921 2608 : return max(0.0, min(1.0, P));
922 : }
923 :
924 : Real64
925 0 : HEMINT(EnergyPlusData &state,
926 : std::function<Real64(EnergyPlusData &state, Real64 const THETA, int const OPT, const Array1D<Real64> &)> F, // property integrand function
927 : int const F_Opt, // options passed to F() (hipRHO, hipTAU)
928 : const Array1D<Real64> &F_P // parameters passed to F()
929 : )
930 : {
931 : // AUTHOR ASHRAE 1311-RP
932 :
933 : // PURPOSE OF THIS FUNCTION:
934 : // Romberg Integration of Property function over hemispherical dome
935 : // METHODOLOGY EMPLOYED:
936 : // Romberg Integration.
937 :
938 : // Argument array dimensioning
939 0 : EP_SIZE_CHECK(F_P, state.dataWindowEquivalentLayer->hipDIM);
940 :
941 0 : constexpr Real64 KMAX(8); // max steps
942 0 : int const NPANMAX(std::pow(2, KMAX));
943 0 : Real64 constexpr TOL(0.0005); // convergence tolerance
944 : static constexpr std::string_view RoutineName("HEMINT");
945 :
946 0 : Array2D<Real64> T(KMAX, KMAX);
947 : Real64 FX;
948 : Real64 X;
949 : Real64 DX;
950 : Real64 DIFF;
951 : int K;
952 :
953 0 : Real64 X1 = 0.0; // integration limits
954 0 : Real64 X2 = Constant::PiOvr2;
955 0 : int nPan = 1;
956 0 : Real64 SUM = 0.0;
957 0 : for (K = 1; K <= KMAX; ++K) {
958 0 : DX = (X2 - X1) / nPan;
959 0 : int iPX = NPANMAX / nPan;
960 0 : for (int I = 0; I <= nPan; ++I) {
961 0 : if (K == 1 || mod(I * iPX, iPX * 2) != 0) {
962 : // evaluate integrand function for new X values
963 : // 2 * sin( x) * cos( x) covers hemisphere with single integral
964 0 : X = X1 + I * DX;
965 0 : FX = 2.0 * std::sin(X) * std::cos(X) * F(state, X, F_Opt, F_P);
966 0 : if (K == 1) {
967 0 : FX /= 2.0;
968 : }
969 0 : SUM += FX;
970 : }
971 : }
972 :
973 0 : T(K, 1) = DX * SUM;
974 : // trapezoid result - i.e., first column Romberg entry
975 : // Now complete the row
976 0 : if (K > 1) {
977 0 : for (int L = 2; L <= K; ++L) {
978 0 : Real64 const pow_4_L_1(std::pow(4.0, L - 1));
979 0 : T(K, L) = (pow_4_L_1 * T(K, L - 1) - T(K - 1, L - 1)) / (pow_4_L_1 - 1.0);
980 : }
981 : // check for convergence
982 : // do 8 panels minimum, else can miss F() features
983 0 : if (nPan >= 8) {
984 0 : DIFF = std::abs(T(K, K) - T(K - 1, K - 1));
985 0 : if (DIFF < TOL) {
986 0 : break;
987 : }
988 : }
989 : }
990 0 : nPan *= 2;
991 : }
992 0 : if (K > KMAX) {
993 0 : K = KMAX;
994 : }
995 0 : return P01(state, T(K, K), RoutineName);
996 0 : }
997 :
998 0 : void RB_DIFF(EnergyPlusData &state,
999 : Real64 const RHO_BT0, // normal incidence beam-total reflectance
1000 : Real64 const TAU_BT0, // normal incidence beam-total transmittance
1001 : Real64 const TAU_BB0, // normal incidence beam-beam transmittance
1002 : Real64 &RHO_DD, // returned: diffuse-diffuse reflectance
1003 : Real64 &TAU_DD // returned: diffuse-diffuse transmittance
1004 : )
1005 : {
1006 : // SUBROUTINE INFORMATION:
1007 : // AUTHOR John L. Wright and Nathan Kotey, University of Waterloo,
1008 : // Mechanical Engineering, Advanced Glazing System Laboratory
1009 :
1010 : // PURPOSE OF THIS SUBROUTINE:
1011 : // Calculates roller blind diffuse-diffuse solar optical properties by integrating
1012 : // the corresponding properties over the hemisphere
1013 :
1014 : static constexpr std::string_view RoutineName("RB_DIFF: ");
1015 :
1016 0 : Array1D<Real64> P(state.dataWindowEquivalentLayer->hipDIM);
1017 : Real64 SumRefAndTran; // sum of the reflectance and transmittance
1018 :
1019 0 : RHO_DD = RHO_BT0;
1020 0 : P(state.dataWindowEquivalentLayer->hipRHO_BT0) = RHO_BT0;
1021 0 : P(state.dataWindowEquivalentLayer->hipTAU_BT0) = TAU_BT0;
1022 0 : P(state.dataWindowEquivalentLayer->hipTAU_BB0) = TAU_BB0;
1023 :
1024 0 : TAU_DD = HEMINT(state, RB_F, 0, P);
1025 :
1026 0 : if (RHO_DD + TAU_DD > 1.0) {
1027 0 : SumRefAndTran = RHO_DD + TAU_DD;
1028 0 : ShowWarningMessage(state, format("{}Roller blind diffuse-diffuse properties are inconsistent", RoutineName));
1029 0 : ShowContinueError(state, format("...The diffuse-diffuse reflectance = {:.4T}", RHO_DD));
1030 0 : ShowContinueError(state, format("...The diffuse-diffuse transmittance = {:.4T}", TAU_DD));
1031 0 : ShowContinueError(state, format("...Sum of diffuse reflectance and transmittance = {:.4T}", SumRefAndTran));
1032 0 : ShowContinueError(state, "...This sum cannot be > 1.0. Transmittance will be reset to 1 minus reflectance");
1033 0 : TAU_DD = 1.0 - RHO_DD;
1034 : }
1035 0 : }
1036 :
1037 0 : Real64 RB_F(EnergyPlusData &state,
1038 : Real64 const THETA, // incidence angle, radians
1039 : [[maybe_unused]] int const OPT, // options (unused)
1040 : const Array1D<Real64> &P // parameters
1041 : )
1042 : {
1043 : // AUTHOR ASHRAE 1311-RP
1044 :
1045 : // PURPOSE OF THIS FUNCTION:
1046 : // Roller blind integrand
1047 :
1048 : // Argument array dimensioning
1049 0 : EP_SIZE_CHECK(P, state.dataWindowEquivalentLayer->hipDIM);
1050 :
1051 : Real64 RHO_BD;
1052 : Real64 TAU_BB;
1053 : Real64 TAU_BD;
1054 :
1055 0 : RB_BEAM(state,
1056 : THETA,
1057 0 : P(state.dataWindowEquivalentLayer->hipRHO_BT0),
1058 0 : P(state.dataWindowEquivalentLayer->hipTAU_BT0),
1059 0 : P(state.dataWindowEquivalentLayer->hipTAU_BB0),
1060 : RHO_BD,
1061 : TAU_BB,
1062 : TAU_BD);
1063 :
1064 0 : return TAU_BB + TAU_BD;
1065 : }
1066 :
1067 0 : void RB_BEAM(EnergyPlusData &state,
1068 : Real64 const xTHETA, // angle of incidence, radians (0 - PI/2)
1069 : Real64 const RHO_BT0, // normal incidence beam-total front reflectance
1070 : Real64 const TAU_BT0, // normal incidence beam-total transmittance
1071 : Real64 const TAU_BB0, // normal incidence beam-beam transmittance
1072 : Real64 &RHO_BD, // returned: beam-diffuse front reflectance
1073 : Real64 &TAU_BB, // returned: beam-beam transmittance
1074 : Real64 &TAU_BD // returned: beam-diffuse transmittance
1075 : )
1076 : {
1077 : // SUBROUTINE INFORMATION:
1078 : // AUTHOR John L. Wright, University of Waterloo,
1079 : // Mechanical Engineering, Advanced Glazing System Laboratory
1080 :
1081 : // PURPOSE OF THIS SUBROUTINE:
1082 : // Calculates the roller blind off-normal properties using semi-empirical relations
1083 :
1084 : // SUBROUTINE ARGUMENT DEFINITIONS:
1085 : // TAU_BT0 = TAU_BB0 + TAU_BD0
1086 : // (openness)
1087 :
1088 : static constexpr std::string_view ContextName("RB_BEAM TauBD");
1089 :
1090 : Real64 THETA; // working angle of incidence (limited < 90 deg)
1091 : Real64 TAUM0; // apparent blind material transmittance at normal incidence
1092 : Real64 THETA_CUTOFF; // cutoff angle, radians (angle beyond which total transmittance goes to zero)
1093 : Real64 TAUBT_EXPO; // exponent in the beam-total transmittance model
1094 : Real64 TAUBB_EXPO; // exponent in the beam-beam transmittance model
1095 : Real64 TAU_BT; // beam-total transmittance
1096 :
1097 0 : THETA = min(89.99 * Constant::DegToRad, xTHETA);
1098 :
1099 0 : if (TAU_BB0 > 0.9999) {
1100 0 : TAU_BB = 1.0;
1101 0 : TAU_BT = 1.0;
1102 : } else {
1103 : // beam total
1104 0 : TAUM0 = min(1.0, (TAU_BT0 - TAU_BB0) / (1.0 - TAU_BB0));
1105 0 : if (TAUM0 <= 0.33) {
1106 0 : TAUBT_EXPO = 0.133 * std::pow(TAUM0 + 0.003, -0.467);
1107 : } else {
1108 0 : TAUBT_EXPO = 0.33 * (1.0 - TAUM0);
1109 : }
1110 0 : TAU_BT = TAU_BT0 * std::pow(std::cos(THETA), TAUBT_EXPO); // always 0 - 1
1111 :
1112 0 : Real64 const cos_TAU_BB0(std::cos(TAU_BB0 * Constant::PiOvr2));
1113 0 : THETA_CUTOFF = Constant::DegToRad * (90.0 - 25.0 * cos_TAU_BB0);
1114 0 : if (THETA >= THETA_CUTOFF) {
1115 0 : TAU_BB = 0.0;
1116 : } else {
1117 0 : TAUBB_EXPO = 0.6 * std::pow(cos_TAU_BB0, 0.3);
1118 0 : TAU_BB = TAU_BB0 * std::pow(std::cos(Constant::PiOvr2 * THETA / THETA_CUTOFF), TAUBB_EXPO);
1119 : // BB correlation can produce results slightly larger than BT
1120 : // Enforce consistency
1121 0 : TAU_BB = min(TAU_BT, TAU_BB);
1122 : }
1123 : }
1124 :
1125 0 : RHO_BD = RHO_BT0;
1126 0 : TAU_BD = P01(state, TAU_BT - TAU_BB, ContextName);
1127 0 : }
1128 :
1129 0 : void IS_DIFF(EnergyPlusData &state,
1130 : Real64 const RHO_BT0, // normal incidence beam-total reflectance
1131 : Real64 const TAU_BT0, // normal incidence beam-total transmittance
1132 : Real64 const TAU_BB0, // normal incidence beam-beam transmittance
1133 : Real64 &RHO_DD, // returned: diffuse-diffuse reflectance
1134 : Real64 &TAU_DD // returned: diffuse-diffuse transmittance
1135 : )
1136 : {
1137 : // SUBROUTINE INFORMATION:
1138 : // AUTHOR John L. Wright, University of Waterloo,
1139 : // Mechanical Engineering, Advanced Glazing System Laboratory
1140 :
1141 : // PURPOSE OF THIS SUBROUTINE:
1142 : // Calculates insect screen diffuse-diffuse solar optical properties by integrating
1143 : // the corresponding properties over the hemisphere
1144 :
1145 : // SUBROUTINE ARGUMENT DEFINITIONS:
1146 : // TAU_BT0 = TAU_BB0 + TAU_BD0
1147 0 : Array1D<Real64> P(state.dataWindowEquivalentLayer->hipDIM);
1148 :
1149 : static constexpr std::string_view RoutineName("IS_DIFF: ");
1150 :
1151 : Real64 SumRefAndTran;
1152 :
1153 0 : P(state.dataWindowEquivalentLayer->hipRHO_BT0) = RHO_BT0;
1154 0 : P(state.dataWindowEquivalentLayer->hipTAU_BT0) = TAU_BT0;
1155 0 : P(state.dataWindowEquivalentLayer->hipTAU_BB0) = TAU_BB0;
1156 :
1157 0 : RHO_DD = HEMINT(state, IS_F, state.dataWindowEquivalentLayer->hipRHO, P);
1158 0 : TAU_DD = HEMINT(state, IS_F, state.dataWindowEquivalentLayer->hipTAU, P);
1159 :
1160 0 : if (RHO_DD + TAU_DD > 1.0) {
1161 0 : SumRefAndTran = RHO_DD + TAU_DD;
1162 0 : ShowWarningMessage(state, format("{}Calculated insect screen diffuse-diffuse properties are inconsistent", RoutineName));
1163 0 : ShowContinueError(state, format("...The diffuse-diffuse reflectance = {:.4T}", RHO_DD));
1164 0 : ShowContinueError(state, format("...The diffuse-diffuse transmittance = {:.4T}", TAU_DD));
1165 0 : ShowContinueError(state, format("...Sum of diffuse reflectance and transmittance = {:.4T}", SumRefAndTran));
1166 0 : ShowContinueError(state, "...This sum cannot be > 1.0. Transmittance will be reset to 1 minus reflectance");
1167 0 : TAU_DD = 1.0 - RHO_DD;
1168 : }
1169 0 : }
1170 :
1171 0 : Real64 IS_F(EnergyPlusData &state,
1172 : Real64 const THETA, // incidence angle, radians
1173 : int const OPT, // options (1=reflectance, 2=transmittance)
1174 : const Array1D<Real64> &P // parameters
1175 : )
1176 : {
1177 : // AUTHOR ASHRAE 1311-RP
1178 :
1179 : // PURPOSE OF THIS FUNCTION:
1180 : // Insect screen integrand
1181 :
1182 : // Argument array dimensioning
1183 0 : EP_SIZE_CHECK(P, state.dataWindowEquivalentLayer->hipDIM);
1184 :
1185 : Real64 RHO_BD;
1186 : Real64 TAU_BB;
1187 : Real64 TAU_BD;
1188 :
1189 0 : IS_BEAM(state,
1190 : THETA,
1191 0 : P(state.dataWindowEquivalentLayer->hipRHO_BT0),
1192 0 : P(state.dataWindowEquivalentLayer->hipTAU_BT0),
1193 0 : P(state.dataWindowEquivalentLayer->hipTAU_BB0),
1194 : RHO_BD,
1195 : TAU_BB,
1196 : TAU_BD);
1197 :
1198 0 : if (OPT == state.dataWindowEquivalentLayer->hipRHO) {
1199 0 : return RHO_BD;
1200 0 : } else if (OPT == state.dataWindowEquivalentLayer->hipTAU) {
1201 0 : return TAU_BB + TAU_BD;
1202 : } else {
1203 0 : return -1.0;
1204 : }
1205 : }
1206 :
1207 0 : void IS_BEAM(EnergyPlusData &state,
1208 : Real64 const xTHETA, // incidence angle, radians (0 - PI/2)
1209 : Real64 const RHO_BT0, // beam-total reflectance
1210 : Real64 const TAU_BT0, // beam-total transmittance at normal incidence
1211 : Real64 const TAU_BB0, // beam-beam transmittance at normal incidence
1212 : Real64 &RHO_BD, // returned: beam-diffuse reflectance
1213 : Real64 &TAU_BB, // returned: beam-beam transmittance
1214 : Real64 &TAU_BD // returned: beam-diffuse transmittance
1215 : )
1216 : {
1217 : // SUBROUTINE INFORMATION:
1218 : // AUTHOR John L. Wright, University of Waterloo,
1219 : // Mechanical Engineering, Advanced Glazing System Laboratory
1220 :
1221 : // PURPOSE OF THIS SUBROUTINE:
1222 : // Calculates insect screen off-normal solar optical properties
1223 : // using semi-empirical relations.
1224 :
1225 : // SUBROUTINE ARGUMENT DEFINITIONS:
1226 : // TAU_BTO = TAU_BB0 + TAU_BD0
1227 :
1228 : static constexpr std::string_view RhoBD_Name("IS_BEAM RhoBD");
1229 : static constexpr std::string_view TauBB_Name("IS_BEAM TauBB");
1230 : static constexpr std::string_view TauBT_Name("IS_BEAM TauBT");
1231 : static constexpr std::string_view TauBD_Name("IS_BEAM TauBD");
1232 :
1233 : Real64 THETA_CUTOFF; // cutoff angle, radians (beyond which TAU_BB = 0)
1234 : Real64 B; // working temp
1235 : Real64 RHO_W; // apparent wire reflectance
1236 : Real64 RHO_BT90; // beam-total reflectance at 90 deg incidence
1237 : Real64 TAU_BT; // beam-total transmittance
1238 :
1239 0 : Real64 const THETA(min(89.99 * Constant::DegToRad, xTHETA)); // working incident angle, radians
1240 0 : Real64 const COSTHETA(std::cos(THETA));
1241 :
1242 0 : RHO_W = RHO_BT0 / max(0.00001, 1.0 - TAU_BB0);
1243 0 : B = -0.45 * std::log(max(RHO_W, 0.01));
1244 :
1245 0 : RHO_BT90 = RHO_BT0 + (1.0 - RHO_BT0) * (0.35 * RHO_W);
1246 :
1247 0 : RHO_BD = P01(state, RHO_BT0 + (RHO_BT90 - RHO_BT0) * (1.0 - std::pow(COSTHETA, B)), RhoBD_Name);
1248 :
1249 0 : if (TAU_BT0 < 0.00001) {
1250 0 : TAU_BB = 0.0;
1251 0 : TAU_BT = 0.0;
1252 : } else {
1253 0 : THETA_CUTOFF = std::acos(IS_DSRATIO(TAU_BB0));
1254 :
1255 0 : if (THETA >= THETA_CUTOFF) {
1256 0 : TAU_BB = 0.0;
1257 : } else {
1258 0 : B = -0.45 * std::log(max(TAU_BB0, 0.01)) + 0.1;
1259 0 : TAU_BB = P01(state, TAU_BB0 * std::pow(std::cos(Constant::PiOvr2 * THETA / THETA_CUTOFF), B), TauBB_Name);
1260 : }
1261 :
1262 0 : B = -0.65 * std::log(max(TAU_BT0, 0.01)) + 0.1;
1263 0 : TAU_BT = P01(state, TAU_BT0 * std::pow(COSTHETA, B), TauBT_Name);
1264 : }
1265 :
1266 0 : TAU_BD = P01(state, TAU_BT - TAU_BB, TauBD_Name);
1267 0 : }
1268 :
1269 0 : Real64 IS_OPENNESS(Real64 const D, // wire diameter
1270 : Real64 const S // wire spacing
1271 : )
1272 : {
1273 : // AUTHOR ASHRAE 1311-RP
1274 :
1275 : // PURPOSE OF THIS FUNCTION:
1276 : // Returns openness from wire geometry.
1277 :
1278 0 : if (S > 0.0) {
1279 0 : return pow_2(max(S - D, 0.0) / S);
1280 : } else {
1281 0 : return 0.0;
1282 : }
1283 : }
1284 :
1285 0 : Real64 IS_DSRATIO(Real64 const OPENNESS) // openness
1286 : {
1287 : // AUTHOR ASHRAE 1311-RP
1288 :
1289 : // PURPOSE OF THIS FUNCTION:
1290 : // Returns ratio of diameter to spacing
1291 :
1292 0 : if (OPENNESS > 0.0) {
1293 0 : return 1.0 - min(std::sqrt(OPENNESS), 1.0);
1294 : } else {
1295 0 : return 0.0;
1296 : }
1297 : }
1298 :
1299 0 : void FM_DIFF(EnergyPlusData &state,
1300 : Real64 const RHO_BT0, // fabric beam-total reflectance at normal incidence
1301 : Real64 const TAU_BT0, // fabric beam-total transmittance at normal incidence
1302 : Real64 const TAU_BB0, // forward facing fabric beam-beam transmittance at normal incidence
1303 : Real64 &RHO_DD, // returned: fabric diffuse-diffuse reflectance
1304 : Real64 &TAU_DD // returned: fabric diffuse-diffuse transmittance
1305 : )
1306 : {
1307 : // SUBROUTINE INFORMATION:
1308 : // AUTHOR John L. Wright, University of Waterloo,
1309 : // Mechanical Engineering, Advanced Glazing System Laboratory
1310 :
1311 : // PURPOSE OF THIS SUBROUTINE:
1312 : // Calculates drape fabric diffuse-diffuse solar optical properties by integrating
1313 : // the corresponding beam properties over the hemisphere.
1314 :
1315 : // SUBROUTINE ARGUMENT DEFINITIONS:
1316 : // (TAU_BT0 = TAU_BB0 + TAU_BD0)
1317 : // SUBROUTINE PARAMETER DEFINITIONS:
1318 : static constexpr std::string_view RoutineName("FM_DIFF: ");
1319 :
1320 : Real64 TAU_BD0;
1321 0 : Array1D<Real64> P(state.dataWindowEquivalentLayer->hipDIM);
1322 : Real64 SumRefAndTran;
1323 :
1324 0 : TAU_BD0 = TAU_BT0 - TAU_BB0;
1325 :
1326 0 : P(state.dataWindowEquivalentLayer->hipRHO_BT0) = RHO_BT0;
1327 0 : P(state.dataWindowEquivalentLayer->hipTAU_BT0) = TAU_BT0;
1328 0 : P(state.dataWindowEquivalentLayer->hipTAU_BB0) = TAU_BB0;
1329 :
1330 0 : RHO_DD = HEMINT(state, FM_F, state.dataWindowEquivalentLayer->hipRHO, P);
1331 0 : TAU_DD = HEMINT(state, FM_F, state.dataWindowEquivalentLayer->hipTAU, P);
1332 :
1333 0 : if (RHO_DD + TAU_DD > 1.0) {
1334 0 : SumRefAndTran = RHO_DD + TAU_DD;
1335 0 : ShowWarningMessage(state, format("{}Calculated drape fabric diffuse-diffuse properties are inconsistent", RoutineName));
1336 0 : ShowContinueError(state, format("...The diffuse-diffuse reflectance = {:.4T}", RHO_DD));
1337 0 : ShowContinueError(state, format("...The diffuse-diffuse transmittance = {:.4T}", TAU_DD));
1338 0 : ShowContinueError(state, format("...Sum of diffuse reflectance and transmittance = {:.4T}", SumRefAndTran));
1339 0 : ShowContinueError(state, "...This sum cannot be > 1.0. Transmittance will be reset to 1 minus reflectance");
1340 0 : TAU_DD = 1.0 - RHO_DD;
1341 : }
1342 0 : }
1343 :
1344 0 : Real64 FM_F(EnergyPlusData &state,
1345 : Real64 const THETA, // incidence angle, radians
1346 : int const Opt, // options (hipRHO, hipTAU)
1347 : const Array1D<Real64> &P // parameters
1348 : )
1349 : {
1350 : // AUTHOR ASHRAE 1311-RP
1351 :
1352 : // PURPOSE OF THIS FUNCTION:
1353 : // Drape fabric property integrand.
1354 :
1355 : // Argument array dimensioning
1356 0 : EP_SIZE_CHECK(P, state.dataWindowEquivalentLayer->hipDIM);
1357 :
1358 : Real64 RHO_BD;
1359 : Real64 TAU_BB;
1360 : Real64 TAU_BD;
1361 :
1362 0 : FM_BEAM(state,
1363 : THETA,
1364 0 : P(state.dataWindowEquivalentLayer->hipRHO_BT0),
1365 0 : P(state.dataWindowEquivalentLayer->hipTAU_BT0),
1366 0 : P(state.dataWindowEquivalentLayer->hipTAU_BB0),
1367 : RHO_BD,
1368 : TAU_BB,
1369 : TAU_BD);
1370 :
1371 0 : if (Opt == state.dataWindowEquivalentLayer->hipRHO) {
1372 0 : return RHO_BD;
1373 0 : } else if (Opt == state.dataWindowEquivalentLayer->hipTAU) {
1374 0 : return TAU_BB + TAU_BD;
1375 : } else {
1376 0 : return -1.0;
1377 : }
1378 : }
1379 :
1380 0 : void FM_BEAM(EnergyPlusData &state,
1381 : Real64 const xTHETA, // incidence angle, radians (0 - PI/2)
1382 : Real64 const RHO_BT0, // fabric beam-total reflectance
1383 : Real64 const TAU_BT0, // fabric beam-total transmittance at normal incidence
1384 : Real64 const TAU_BB0, // fabric beam-beam transmittance at normal incidence
1385 : Real64 &RHO_BD, // returned: fabric beam-diffuse reflectance
1386 : Real64 &TAU_BB, // returned: fabric beam-beam transmittance
1387 : Real64 &TAU_BD // returned: fabric beam-diffuse transmittance
1388 : )
1389 : {
1390 :
1391 : // SUBROUTINE INFORMATION:
1392 : // AUTHOR John L. Wright, University of Waterloo,
1393 : // Mechanical Engineering, Advanced Glazing System Laboratory
1394 :
1395 : // PURPOSE OF THIS SUBROUTINE:
1396 : // Calculates the solar optical properties of a fabric for beam radiation incident
1397 : // on the forward facing surface using optical properties at normal incidence and
1398 : // semi-empirical relations.
1399 :
1400 : // SUBROUTINE ARGUMENT DEFINITIONS:
1401 : // TAU_BTO = TAU_BB0 + TAU_BD0
1402 : // = openness
1403 :
1404 : Real64 THETA; // working incident angle, radians
1405 : Real64 R; // working temps
1406 : Real64 B;
1407 : Real64 RHO_Y; // apparent yarn reflectance
1408 : Real64 RHO_BT90; // beam-total reflectance at 90 deg incidence
1409 : Real64 TAU_BT; // beam-total transmittance
1410 :
1411 0 : THETA = std::abs(max(-89.99 * Constant::DegToRad, min(89.99 * Constant::DegToRad, xTHETA)));
1412 : // limit -89.99 - +89.99
1413 : // by symmetry, optical properties same at +/- theta
1414 0 : Real64 const COSTHETA(std::cos(THETA));
1415 :
1416 0 : RHO_Y = RHO_BT0 / max(0.00001, 1.0 - TAU_BB0);
1417 0 : R = 0.7 * std::pow(RHO_Y, 0.7);
1418 0 : RHO_BT90 = RHO_BT0 + (1.0 - RHO_BT0) * R;
1419 0 : B = 0.6;
1420 0 : RHO_BD = P01(state, RHO_BT0 + (RHO_BT90 - RHO_BT0) * (1.0 - std::pow(COSTHETA, B)), "FM_BEAM RhoBD");
1421 :
1422 0 : if (TAU_BT0 < 0.00001) {
1423 0 : TAU_BB = 0.0;
1424 0 : TAU_BD = 0.0;
1425 : } else {
1426 0 : B = max(-0.5 * std::log(max(TAU_BB0, 0.01)), 0.35);
1427 0 : TAU_BB = TAU_BB0 * std::pow(COSTHETA, B);
1428 :
1429 0 : B = max(-0.5 * std::log(max(TAU_BT0, 0.01)), 0.35);
1430 0 : TAU_BT = TAU_BT0 * std::pow(COSTHETA, B);
1431 :
1432 0 : TAU_BD = P01(state, TAU_BT - TAU_BB, "FM_BEAM TauBD");
1433 : }
1434 0 : }
1435 :
1436 0 : void PD_LW(EnergyPlusData &state,
1437 : Real64 const S, // pleat spacing (> 0)
1438 : Real64 const W, // pleat depth (>=0, same units as S)
1439 : Real64 const OPENNESS_FABRIC, // fabric openness, 0-1 (=tausbb at normal incidence)
1440 : Real64 const EPSLWF0_FABRIC, // fabric LW front emittance at 0 openness
1441 : Real64 const EPSLWB0_FABRIC, // fabric LW back emittance at 0 openness
1442 : Real64 const TAULW0_FABRIC, // fabric LW transmittance at 0 openness
1443 : Real64 &EPSLWF_PD, // returned: drape front effective LW emittance
1444 : Real64 &TAULW_PD // returned: drape effective LW transmittance
1445 : )
1446 : {
1447 :
1448 : // SUBROUTINE INFORMATION:
1449 : // AUTHOR John L. Wright, University of Waterloo,
1450 : // Mechanical Engineering, Advanced Glazing System Laboratory
1451 :
1452 : // PURPOSE OF THIS SUBROUTINE:
1453 : // Calculates the effective longwave emittance and transmittance of a drapery layer
1454 :
1455 : // SUBROUTINE ARGUMENT DEFINITIONS:
1456 : // typical (default) = 0.92
1457 : // typical (default) = 0.92
1458 : // nearly always 0
1459 : static constexpr std::string_view RhoLWF_Name("PD_LW RhoLWF");
1460 : static constexpr std::string_view RhoLWB_Name("PD_LW RhoLWB");
1461 : static constexpr std::string_view EpsLWF_Name("PD_LW EpsLWF");
1462 :
1463 : Real64 RHOLWF_FABRIC;
1464 : Real64 RHOLWB_FABRIC;
1465 : Real64 TAULW_FABRIC;
1466 : Real64 EPSLWF_FABRIC;
1467 : Real64 EPSLWB_FABRIC;
1468 : Real64 TAULX;
1469 : Real64 RHOLWF_PD;
1470 :
1471 0 : OPENNESS_LW(OPENNESS_FABRIC, EPSLWF0_FABRIC, TAULW0_FABRIC, EPSLWF_FABRIC, TAULW_FABRIC);
1472 0 : OPENNESS_LW(OPENNESS_FABRIC, EPSLWB0_FABRIC, TAULW0_FABRIC, EPSLWB_FABRIC, TAULX);
1473 :
1474 0 : RHOLWF_FABRIC = P01(state, 1.0 - EPSLWF_FABRIC - TAULW_FABRIC, RhoLWF_Name);
1475 0 : RHOLWB_FABRIC = P01(state, 1.0 - EPSLWB_FABRIC - TAULW_FABRIC, RhoLWB_Name);
1476 :
1477 0 : PD_DIFF(state, S, W, RHOLWF_FABRIC, RHOLWB_FABRIC, TAULW_FABRIC, RHOLWF_PD, TAULW_PD);
1478 :
1479 0 : EPSLWF_PD = P01(state, 1.0 - TAULW_PD - RHOLWF_PD, EpsLWF_Name);
1480 0 : }
1481 :
1482 0 : void PD_DIFF(EnergyPlusData &state,
1483 : Real64 const S, // pleat spacing (> 0)
1484 : Real64 const W, // pleat depth (>=0, same units as S)
1485 : Real64 const RHOFF_DD, // fabric front diffuse-diffuse reflectance
1486 : Real64 const RHOBF_DD, // fabric back diffuse-diffuse reflectance
1487 : Real64 const TAUF_DD, // fabric diffuse-diffuse transmittance
1488 : Real64 &RHOFDD, // returned: drape diffuse-diffuse reflectance
1489 : Real64 &TAUFDD // returned: drape diffuse-diffuse transmittance
1490 : )
1491 : {
1492 : // SUBROUTINE INFORMATION:
1493 : // AUTHOR John L. Wright, University of Waterloo,
1494 : // Mechanical Engineering, Advanced Glazing System Laboratory
1495 :
1496 : // PURPOSE OF THIS SUBROUTINE:
1497 : // Calculates the effective diffuse transmittance and reflectance of a drapery layer.
1498 : // Used for both LW and solar diffuse.
1499 : // METHODOLOGY EMPLOYED:
1500 : // Eight surface flat-fabric model with rectangular enclosure. If you want the back-side
1501 : // reflectance call this routine a second time with reversed front and back properties
1502 :
1503 0 : constexpr int N(6);
1504 : static constexpr std::string_view TauDD_Name("PD_DIFF TauDD");
1505 : static constexpr std::string_view RhoDD_Name("PD_DIFF RhoDD");
1506 :
1507 : Real64 AK; // length of diagonal strings of the rectangular enclosure
1508 : Real64 CG;
1509 : Real64 F12; // shape factors
1510 : Real64 F14;
1511 : Real64 F32;
1512 : Real64 F21;
1513 : Real64 F31;
1514 : Real64 F34;
1515 : Real64 F24;
1516 : Real64 F41;
1517 : Real64 F42;
1518 : Real64 F57;
1519 : Real64 F56;
1520 : Real64 F58;
1521 : Real64 F67;
1522 : Real64 F65;
1523 : Real64 F68;
1524 : Real64 F75;
1525 : Real64 F76;
1526 : Real64 F78;
1527 : Real64 F85;
1528 : Real64 F87;
1529 : Real64 F86;
1530 : Real64 J1; // radiosity, surface i
1531 : Real64 J2;
1532 : Real64 J4;
1533 : Real64 J7;
1534 : Real64 J6;
1535 : Real64 J8;
1536 : Real64 G1; // irradiance, surface i
1537 : Real64 G3;
1538 : Real64 G5;
1539 : Real64 G7;
1540 0 : Array2D<Real64> A(N + 2, N);
1541 0 : Array1D<Real64> XSOL(N);
1542 :
1543 0 : if (W / S < state.dataWindowEquivalentLayer->SMALL_ERROR) {
1544 : // flat drape (no pleats)
1545 0 : RHOFDD = RHOFF_DD;
1546 0 : TAUFDD = TAUF_DD;
1547 0 : return;
1548 : }
1549 :
1550 : // SOLVE FOR DIAGONAL STRINGS AND SHAPE FACTORS
1551 :
1552 0 : AK = std::sqrt(S * S + W * W);
1553 0 : CG = AK;
1554 0 : F12 = (S + W - AK) / (2.0 * S);
1555 0 : F14 = (S + W - CG) / (2.0 * S);
1556 0 : F32 = F14;
1557 0 : F31 = (AK + CG - 2.0 * W) / (2.0 * S);
1558 0 : F34 = F12;
1559 0 : F21 = (S + W - AK) / (2.0 * W);
1560 0 : F24 = (AK + CG - 2.0 * S) / (2.0 * W);
1561 0 : F41 = (S + W - CG) / (2.0 * W);
1562 0 : F42 = F24;
1563 0 : F57 = F31;
1564 0 : F56 = F12;
1565 0 : F58 = F14;
1566 0 : F75 = F31;
1567 0 : F76 = F32;
1568 0 : F78 = F34;
1569 0 : F67 = F41;
1570 0 : F65 = F21;
1571 0 : F68 = F24;
1572 0 : F85 = F41;
1573 0 : F87 = F21;
1574 0 : F86 = F42;
1575 :
1576 0 : A = 0.0; // INITIALIZE RADIOSITY MATRIX COEFFICIENTS
1577 0 : XSOL = 0.0; // INITIALIZE SOLUTION VECTOR COEFFICIENTS
1578 :
1579 : // POPULATE THE COEFFICIENTS OF THE RADIOSITY MATRIX
1580 :
1581 0 : A(1, 1) = 1.0;
1582 0 : A(2, 1) = -RHOBF_DD * F12;
1583 0 : A(3, 1) = -RHOBF_DD * F14;
1584 0 : A(4, 1) = 0.0;
1585 0 : A(5, 1) = 0.0;
1586 0 : A(6, 1) = 0.0;
1587 0 : A(7, 1) = TAUF_DD;
1588 0 : A(1, 2) = -RHOBF_DD * F21;
1589 0 : A(2, 2) = 1.0;
1590 0 : A(3, 2) = -RHOBF_DD * F24;
1591 0 : A(4, 2) = -TAUF_DD * F87;
1592 0 : A(5, 2) = -TAUF_DD * F86;
1593 0 : A(6, 2) = 0.0;
1594 0 : A(7, 2) = TAUF_DD * F85;
1595 0 : A(1, 3) = -RHOBF_DD * F41;
1596 0 : A(2, 3) = -RHOBF_DD * F42;
1597 0 : A(3, 3) = 1.0;
1598 0 : A(4, 3) = -TAUF_DD * F67;
1599 0 : A(5, 3) = 0.0;
1600 0 : A(6, 3) = -TAUF_DD * F68;
1601 0 : A(7, 3) = TAUF_DD * F65;
1602 0 : A(1, 4) = 0.0;
1603 0 : A(2, 4) = 0.0;
1604 0 : A(3, 4) = 0.0;
1605 0 : A(4, 4) = 1.0;
1606 0 : A(5, 4) = -RHOFF_DD * F76;
1607 0 : A(6, 4) = -RHOFF_DD * F78;
1608 0 : A(7, 4) = RHOFF_DD * F75;
1609 0 : A(1, 5) = -TAUF_DD * F41;
1610 0 : A(2, 5) = -TAUF_DD * F42;
1611 0 : A(3, 5) = 0.0;
1612 0 : A(4, 5) = -RHOFF_DD * F67;
1613 0 : A(5, 5) = 1.0;
1614 0 : A(6, 5) = -RHOFF_DD * F68;
1615 0 : A(7, 5) = RHOFF_DD * F65;
1616 0 : A(1, 6) = -TAUF_DD * F21;
1617 0 : A(2, 6) = 0.0;
1618 0 : A(3, 6) = -TAUF_DD * F24;
1619 0 : A(4, 6) = -RHOFF_DD * F87;
1620 0 : A(5, 6) = -RHOFF_DD * F86;
1621 0 : A(6, 6) = 1.0;
1622 0 : A(7, 6) = RHOFF_DD * F85;
1623 :
1624 0 : SOLMATS(N, A, XSOL);
1625 :
1626 0 : J1 = XSOL(1);
1627 0 : J2 = XSOL(2);
1628 0 : J4 = XSOL(3);
1629 0 : J7 = XSOL(4);
1630 0 : J6 = XSOL(5);
1631 0 : J8 = XSOL(6);
1632 :
1633 0 : G1 = F12 * J2 + F14 * J4;
1634 0 : G3 = F32 * J2 + F31 * J1 + F34 * J4;
1635 0 : G5 = F57 * J7 + F56 * J6 + F58 * J8;
1636 0 : G7 = F75 + F76 * J6 + F78 * J8;
1637 :
1638 0 : TAUFDD = P01(state, (G3 + TAUF_DD * G7) / 2.0, TauDD_Name);
1639 0 : RHOFDD = P01(state, (RHOFF_DD + TAUF_DD * G1 + G5) / 2.0, RhoDD_Name);
1640 0 : }
1641 :
1642 0 : void PD_BEAM(EnergyPlusData &state,
1643 : Real64 const S, // pleat spacing (> 0)
1644 : Real64 const W, // pleat depth (>=0, same units as S)
1645 : Real64 const OHM_V_RAD, // vertical profile angle, radians +=above horiz
1646 : Real64 const OHM_H_RAD, // horizontal profile angle, radians=clockwise when viewed from above
1647 : Real64 const RHOFF_BT0, // beam total reflectance front (outside)
1648 : Real64 const TAUFF_BB0, // beam beam transmittance front (outside)
1649 : Real64 const TAUFF_BD0, // beam diffuse transmittance front (outside)
1650 : Real64 const RHOFF_DD, // diffuse-diffuse reflectance front (outside)
1651 : Real64 const TAUFF_DD, // diffuse-diffuse transmittance front (outside)
1652 : Real64 const RHOBF_BT0, // beam total reflectance back (inside)
1653 : Real64 const TAUBF_BB0, // beam beam total transmittance back (inside)
1654 : Real64 const TAUBF_BD0, // beam diffuse transmittance back (inside)
1655 : Real64 const RHOBF_DD, // diffuse-diffuse reflectance front (outside)
1656 : Real64 const TAUBF_DD, // diffuse-diffuse transmittance front (outside)
1657 : Real64 &RHO_BD, // returned: drape front beam-diffuse reflectance
1658 : Real64 &TAU_BB, // returned: drape beam-beam transmittance
1659 : Real64 &TAU_BD // returned: drape beam-diffuse transmittance
1660 : )
1661 : {
1662 : // SUBROUTINE INFORMATION:
1663 : // AUTHOR John L. Wright, University of Waterloo,
1664 : // Mechanical Engineering, Advanced Glazing System Laboratory
1665 :
1666 : // PURPOSE OF THIS SUBROUTINE:
1667 : // calculates the effective front-side solar optical properties of a drapery layer.
1668 : // METHODOLOGY EMPLOYED:
1669 : // Pleated drape flat-fabric model with rectangular enclosure
1670 :
1671 : Real64 DE; // length of directly illuminated surface on side of pleat that
1672 : // is open on front (same units as S and W)
1673 : Real64 EF; // length of pleat side shaded surface (W-DE) (same units as S and W)
1674 : Real64 OMEGA_V; // profile angles limited to +/- PI/2
1675 : Real64 OMEGA_H;
1676 : Real64 TAUFF_BT0;
1677 : Real64 TAUBF_BT0;
1678 : Real64 THETA_PARL; // beam incidence angles on pleat surface parallel / perpendicular
1679 : Real64 THETA_PERP;
1680 : // to window plane
1681 : Real64 RHOFF_BT_PARL;
1682 : Real64 TAUFF_BB_PARL;
1683 : Real64 TAUFF_BD_PARL;
1684 : Real64 RHOBF_BT_PARL;
1685 : Real64 TAUBF_BB_PARL;
1686 : Real64 TAUBF_BD_PARL;
1687 : Real64 RHOFF_BT_PERP;
1688 : Real64 TAUFF_BB_PERP;
1689 : Real64 TAUFF_BD_PERP;
1690 : Real64 RHOBF_BT_PERP;
1691 : Real64 TAUBF_BB_PERP;
1692 : Real64 TAUBF_BD_PERP;
1693 :
1694 0 : OMEGA_V = std::abs(max(-89.5 * Constant::DegToRad, min(89.5 * Constant::DegToRad, OHM_V_RAD)));
1695 0 : OMEGA_H = std::abs(max(-89.5 * Constant::DegToRad, min(89.5 * Constant::DegToRad, OHM_H_RAD)));
1696 : // limit profile angles -89.5 - +89.5
1697 : // by symmetry, properties same for +/- profile angle
1698 :
1699 : // incidence angles on pleat front/back (_PARL) and sides (_PERP)
1700 0 : Real64 const tan_OMEGA_V(std::tan(OMEGA_V));
1701 0 : Real64 const cos_OMEGA_H(std::cos(OMEGA_H));
1702 0 : Real64 const sin_OMEGA_H(std::sin(OMEGA_H));
1703 0 : THETA_PARL = std::acos(std::abs(std::cos(std::atan(tan_OMEGA_V * cos_OMEGA_H)) * cos_OMEGA_H));
1704 0 : THETA_PERP = std::acos(std::abs(std::cos(std::atan(tan_OMEGA_V * sin_OMEGA_H)) * sin_OMEGA_H));
1705 :
1706 : // off-normal fabric properties, front surface
1707 0 : TAUFF_BT0 = TAUFF_BB0 + TAUFF_BD0;
1708 0 : FM_BEAM(state, THETA_PARL, RHOFF_BT0, TAUFF_BT0, TAUFF_BB0, RHOFF_BT_PARL, TAUFF_BB_PARL, TAUFF_BD_PARL);
1709 0 : if (W / S < state.dataWindowEquivalentLayer->SMALL_ERROR) {
1710 : // flat drape (no pleats) -- return fabric properties
1711 0 : RHO_BD = RHOFF_BT_PARL;
1712 0 : TAU_BD = TAUFF_BD_PARL;
1713 0 : TAU_BB = TAUFF_BB_PARL;
1714 0 : return;
1715 : }
1716 :
1717 0 : FM_BEAM(state, THETA_PERP, RHOFF_BT0, TAUFF_BT0, TAUFF_BB0, RHOFF_BT_PERP, TAUFF_BB_PERP, TAUFF_BD_PERP);
1718 :
1719 : // Off-normal fabric properties, back surface
1720 0 : TAUBF_BT0 = TAUBF_BB0 + TAUBF_BD0;
1721 0 : FM_BEAM(state, THETA_PARL, RHOBF_BT0, TAUBF_BT0, TAUBF_BB0, RHOBF_BT_PARL, TAUBF_BB_PARL, TAUBF_BD_PARL);
1722 0 : FM_BEAM(state, THETA_PERP, RHOBF_BT0, TAUBF_BT0, TAUBF_BB0, RHOBF_BT_PERP, TAUBF_BB_PERP, TAUBF_BD_PERP);
1723 :
1724 0 : DE = S * std::abs(cos_OMEGA_H / max(0.000001, sin_OMEGA_H));
1725 0 : EF = W - DE;
1726 :
1727 : // select geometric case
1728 0 : if (DE < W - state.dataWindowEquivalentLayer->SMALL_ERROR) {
1729 : // illuminated length less than pleat depth
1730 0 : if (DE < EF - state.dataWindowEquivalentLayer->SMALL_ERROR) {
1731 : // illum < shade
1732 0 : PD_BEAM_CASE_I(S,
1733 : W,
1734 : OMEGA_H,
1735 : DE,
1736 : RHOFF_BT_PARL,
1737 : TAUFF_BB_PARL,
1738 : TAUFF_BD_PARL,
1739 : RHOBF_BT_PARL,
1740 : TAUBF_BB_PARL,
1741 : TAUBF_BD_PARL,
1742 : RHOFF_BT_PERP,
1743 : TAUFF_BB_PERP,
1744 : TAUFF_BD_PERP,
1745 : RHOBF_BT_PERP,
1746 : TAUBF_BB_PERP,
1747 : TAUBF_BD_PERP,
1748 : RHOBF_DD,
1749 : RHOFF_DD,
1750 : TAUFF_DD,
1751 : TAUBF_DD,
1752 : RHO_BD,
1753 : TAU_BD,
1754 : TAU_BB);
1755 0 : } else if (DE <= EF + state.dataWindowEquivalentLayer->SMALL_ERROR) {
1756 : // illum and shade equal
1757 0 : PD_BEAM_CASE_II(S,
1758 : W,
1759 : OMEGA_H,
1760 : DE,
1761 : RHOFF_BT_PARL,
1762 : TAUFF_BB_PARL,
1763 : TAUFF_BD_PARL,
1764 : RHOBF_BT_PARL,
1765 : TAUBF_BB_PARL,
1766 : TAUBF_BD_PARL,
1767 : RHOFF_BT_PERP,
1768 : TAUFF_BB_PERP,
1769 : TAUFF_BD_PERP,
1770 : RHOBF_BT_PERP,
1771 : TAUBF_BB_PERP,
1772 : TAUBF_BD_PERP,
1773 : RHOBF_DD,
1774 : RHOFF_DD,
1775 : TAUFF_DD,
1776 : TAUBF_DD,
1777 : RHO_BD,
1778 : TAU_BD,
1779 : TAU_BB);
1780 : } else {
1781 : // illum > shade
1782 0 : PD_BEAM_CASE_III(S,
1783 : W,
1784 : OMEGA_H,
1785 : DE,
1786 : RHOFF_BT_PARL,
1787 : TAUFF_BB_PARL,
1788 : TAUFF_BD_PARL,
1789 : RHOBF_BT_PARL,
1790 : TAUBF_BB_PARL,
1791 : TAUBF_BD_PARL,
1792 : RHOFF_BT_PERP,
1793 : TAUFF_BB_PERP,
1794 : TAUFF_BD_PERP,
1795 : RHOBF_BT_PERP,
1796 : TAUBF_BB_PERP,
1797 : TAUBF_BD_PERP,
1798 : RHOBF_DD,
1799 : RHOFF_DD,
1800 : TAUFF_DD,
1801 : TAUBF_DD,
1802 : RHO_BD,
1803 : TAU_BD,
1804 : TAU_BB);
1805 : }
1806 0 : } else if (DE <= W + state.dataWindowEquivalentLayer->SMALL_ERROR) {
1807 : // illum length same as pleat depth
1808 0 : PD_BEAM_CASE_IV(S,
1809 : W,
1810 : OMEGA_H,
1811 : DE,
1812 : RHOFF_BT_PARL,
1813 : TAUFF_BB_PARL,
1814 : TAUFF_BD_PARL,
1815 : RHOBF_BT_PARL,
1816 : TAUBF_BB_PARL,
1817 : TAUBF_BD_PARL,
1818 : RHOFF_BT_PERP,
1819 : TAUFF_BB_PERP,
1820 : TAUFF_BD_PERP,
1821 : RHOBF_BT_PERP,
1822 : TAUBF_BB_PERP,
1823 : TAUBF_BD_PERP,
1824 : RHOBF_DD,
1825 : RHOFF_DD,
1826 : TAUFF_DD,
1827 : TAUBF_DD,
1828 : RHO_BD,
1829 : TAU_BD,
1830 : TAU_BB);
1831 0 : } else if (DE < 9000.0 * S) {
1832 : // some direct illum on pleat back
1833 0 : PD_BEAM_CASE_V(S,
1834 : W,
1835 : OMEGA_H,
1836 : DE,
1837 : RHOFF_BT_PARL,
1838 : TAUFF_BB_PARL,
1839 : TAUFF_BD_PARL,
1840 : RHOBF_BT_PARL,
1841 : TAUBF_BB_PARL,
1842 : TAUBF_BD_PARL,
1843 : RHOFF_BT_PERP,
1844 : TAUFF_BB_PERP,
1845 : TAUFF_BD_PERP,
1846 : RHOBF_BT_PERP,
1847 : TAUBF_BB_PERP,
1848 : TAUBF_BD_PERP,
1849 : RHOBF_DD,
1850 : RHOFF_DD,
1851 : TAUFF_DD,
1852 : TAUBF_DD,
1853 : RHO_BD,
1854 : TAU_BD,
1855 : TAU_BB);
1856 : } else {
1857 : // beam parallel to pleat sides (no direct illum on pleat back)
1858 0 : PD_BEAM_CASE_VI(S,
1859 : W,
1860 : OMEGA_H,
1861 : DE,
1862 : RHOFF_BT_PARL,
1863 : TAUFF_BB_PARL,
1864 : TAUFF_BD_PARL,
1865 : RHOBF_BT_PARL,
1866 : TAUBF_BB_PARL,
1867 : TAUBF_BD_PARL,
1868 : RHOFF_BT_PERP,
1869 : TAUFF_BB_PERP,
1870 : TAUFF_BD_PERP,
1871 : RHOBF_BT_PERP,
1872 : TAUBF_BB_PERP,
1873 : TAUBF_BD_PERP,
1874 : RHOBF_DD,
1875 : RHOFF_DD,
1876 : TAUFF_DD,
1877 : TAUBF_DD,
1878 : RHO_BD,
1879 : TAU_BD,
1880 : TAU_BB);
1881 : }
1882 : }
1883 :
1884 0 : void PD_BEAM_CASE_I(Real64 const S, // pleat spacing (> 0)
1885 : Real64 const W, // pleat depth (>=0, same units as S)
1886 : [[maybe_unused]] Real64 const OMEGA_H, // horizontal profile angle, radians
1887 : Real64 const DE, // width of illumination on pleat bottom (same units as S)
1888 : Real64 const RHOFF_BT_PARL,
1889 : Real64 const TAUFF_BB_PARL,
1890 : Real64 const TAUFF_BD_PARL,
1891 : [[maybe_unused]] Real64 const RHOBF_BT_PARL,
1892 : [[maybe_unused]] Real64 const TAUBF_BB_PARL,
1893 : [[maybe_unused]] Real64 const TAUBF_BD_PARL,
1894 : Real64 const RHOFF_BT_PERP,
1895 : Real64 const TAUFF_BB_PERP,
1896 : Real64 const TAUFF_BD_PERP,
1897 : Real64 const RHOBF_BT_PERP,
1898 : Real64 const TAUBF_BB_PERP,
1899 : Real64 const TAUBF_BD_PERP,
1900 : Real64 const RHOBF_DD, // fabric back diffuse-diffuse reflectance
1901 : Real64 const RHOFF_DD, // fabric front diffuse-diffuse reflectance
1902 : Real64 const TAUFF_DD, // fabric front diffuse-diffuse transmittance
1903 : Real64 const TAUBF_DD, // fabric back diffuse-diffuse transmittance
1904 : Real64 &RHO_BD, // returned: drape front beam-diffuse reflectance
1905 : Real64 &TAU_BD, // returned: drape front beam-diffuse transmittance
1906 : Real64 &TAU_BB // returned: drape front beam-beam transmittance
1907 : )
1908 : {
1909 :
1910 : // SUBROUTINE INFORMATION:
1911 : // AUTHOR John L. Wright, University of Waterloo,
1912 : // Mechanical Engineering, Advanced Glazing System Laboratory
1913 :
1914 : // PURPOSE OF THIS SUBROUTINE:
1915 : // calculates the effective front-side solar optical properties of a drapery layer.
1916 : // METHODOLOGY EMPLOYED:
1917 : // FOURTEEN SURFACE FLAT-FABRIC MODEL WITH RECTANGULAR ENCLOSURE
1918 :
1919 : // SUBROUTINE ARGUMENT DEFINITIONS:
1920 : // fabric properties at current (off-normal) incidence
1921 : // _PARL = surface parallel to window (pleat top/bot)
1922 : // _PERP = surface perpendicular to window (pleat side)
1923 :
1924 0 : int constexpr N(12);
1925 :
1926 : Real64 TAUBF_BT_PERP;
1927 : Real64 AB; // lengths of surfaces and diagonal strings
1928 : Real64 GN;
1929 : Real64 NP;
1930 : Real64 GP;
1931 : Real64 NK;
1932 : Real64 PK;
1933 : Real64 BC;
1934 : Real64 AN;
1935 : Real64 AP;
1936 : Real64 AK;
1937 : Real64 BG;
1938 : Real64 BP;
1939 : Real64 CG;
1940 : Real64 BK;
1941 : Real64 CP;
1942 : Real64 CN;
1943 : Real64 Z1_BB; // beam source terms
1944 : Real64 Z7_BB;
1945 : Real64 Z1_BD; // diffuse source terms due to incident beam radiation
1946 : Real64 Z2_BD;
1947 : Real64 Z7_BD;
1948 : Real64 Z3_BD;
1949 : Real64 Z9_BD;
1950 : Real64 Z13_BD;
1951 : Real64 Z14_BD;
1952 : // shape factors
1953 : Real64 F12;
1954 : Real64 F13;
1955 : Real64 F14;
1956 : Real64 F16;
1957 : Real64 F17;
1958 : Real64 F21;
1959 : Real64 F25;
1960 : Real64 F26;
1961 : Real64 F27;
1962 : Real64 F31;
1963 : Real64 F35;
1964 : Real64 F36;
1965 : Real64 F37;
1966 : Real64 F41;
1967 : Real64 F45;
1968 : Real64 F46;
1969 : Real64 F47;
1970 : Real64 F51;
1971 : Real64 F52;
1972 : Real64 F53;
1973 : Real64 F54;
1974 : Real64 F56;
1975 : Real64 F57;
1976 : Real64 F61;
1977 : Real64 F62;
1978 : Real64 F63;
1979 : Real64 F64;
1980 : Real64 F71;
1981 : Real64 F72;
1982 : Real64 F73;
1983 : Real64 F74;
1984 : Real64 F89;
1985 : Real64 F810;
1986 : Real64 F811;
1987 : Real64 F812;
1988 : Real64 F813;
1989 : Real64 F814;
1990 : Real64 F911;
1991 : Real64 F912;
1992 : Real64 F913;
1993 : Real64 F914;
1994 : Real64 F1011;
1995 : Real64 F1012;
1996 : Real64 F1013;
1997 : Real64 F1014;
1998 : Real64 F119;
1999 : Real64 F1110;
2000 : Real64 F1112;
2001 : Real64 F1113;
2002 : Real64 F1114;
2003 : Real64 F129;
2004 : Real64 F1210;
2005 : Real64 F1211;
2006 : Real64 F139;
2007 : Real64 F1310;
2008 : Real64 F1311;
2009 : Real64 F149;
2010 : Real64 F1410;
2011 : Real64 F1411;
2012 : Real64 J1; // radiosity, surface i
2013 : Real64 J2;
2014 : Real64 J3;
2015 : Real64 J4;
2016 : Real64 J6;
2017 : Real64 J7;
2018 : Real64 J9;
2019 : Real64 J10;
2020 : Real64 J11;
2021 : Real64 J12;
2022 : Real64 J13;
2023 : Real64 J14;
2024 : Real64 G1; // irradiance, surface i
2025 : Real64 G5;
2026 : Real64 G8;
2027 : Real64 G11;
2028 0 : Array2D<Real64> A(N + 2, N); // coefficients of the radiosity equations matrix
2029 0 : Array1D<Real64> XSOL(N); // solution vector (obtained after solving the radiosity equations matrix)
2030 :
2031 0 : TAUBF_BT_PERP = TAUBF_BD_PERP + TAUBF_BB_PERP;
2032 :
2033 0 : AB = DE;
2034 0 : GN = DE;
2035 0 : NP = DE;
2036 0 : GP = 2.0 * DE;
2037 0 : NK = W - DE;
2038 0 : PK = W - 2.0 * DE;
2039 0 : BC = NK;
2040 0 : AN = std::sqrt(S * S + DE * DE);
2041 0 : AP = std::sqrt(S * S + GP * GP);
2042 0 : AK = std::sqrt(W * W + S * S);
2043 0 : BG = AN;
2044 0 : BP = AN;
2045 0 : CG = AK;
2046 0 : BK = std::sqrt(S * S + BC * BC);
2047 0 : CP = std::sqrt(S * S + PK * PK);
2048 0 : CN = std::sqrt(S * S + NK * NK);
2049 :
2050 0 : Z1_BB = TAUFF_BB_PARL;
2051 0 : Z1_BD = TAUFF_BD_PARL;
2052 0 : Z2_BD = Z1_BB * RHOBF_BT_PERP * S / GN;
2053 0 : Z7_BB = TAUFF_BB_PERP * S / DE;
2054 0 : Z7_BD = TAUFF_BD_PERP * S / DE;
2055 0 : Z3_BD = Z7_BB * RHOBF_BT_PERP;
2056 0 : Z9_BD = RHOFF_BT_PERP * S / DE;
2057 0 : Z13_BD = Z7_BB * TAUBF_BT_PERP;
2058 0 : Z14_BD = Z1_BB * TAUBF_BT_PERP * S / GN;
2059 :
2060 0 : F12 = (S + GN - AN) / (2.0 * S);
2061 0 : F13 = (AN + GP - (GN + AP)) / (2.0 * S);
2062 0 : F14 = (AP + W - (GP + AK)) / (2.0 * S);
2063 0 : F16 = (W + BG - (AB + CG)) / (2.0 * S);
2064 0 : F17 = (S + AB - BG) / (2.0 * S);
2065 0 : F21 = (S + GN - AN) / (2.0 * GN);
2066 0 : F25 = (W + CN - (CG + NK)) / (2.0 * GN);
2067 0 : F26 = (CG + S - (BG + CN)) / (2.0 * GN);
2068 0 : F27 = (AN + BG - 2.0 * S) / (2.0 * GN);
2069 0 : F31 = (AN + GP - (GN + AP)) / (2.0 * NP);
2070 0 : F35 = (NK + CP - (CN + PK)) / (2.0 * NP);
2071 0 : F36 = (CN + BP - (S + CP)) / (2.0 * NP);
2072 0 : F37 = (S + AP - (AN + BP)) / (2.0 * NP);
2073 0 : F41 = (W + AP - (GP + AK)) / (2.0 * PK);
2074 0 : F45 = (S + PK - CP) / (2.0 * PK);
2075 0 : F46 = (CP + BK - (S + BP)) / (2.0 * PK);
2076 0 : F47 = (BP + AK - (AP + BK)) / (2.0 * PK);
2077 0 : F51 = (AK + CG - 2.0 * W) / (2.0 * S);
2078 0 : F52 = (W + CN - (CG + NK)) / (2.0 * S);
2079 0 : F53 = (NK + CP - (CN + PK)) / (2.0 * S);
2080 0 : F54 = (S + PK - CP) / (2.0 * S);
2081 0 : F56 = (S + BC - BK) / (2.0 * S);
2082 0 : F57 = (W + BK - (BC + AK)) / (2.0 * S);
2083 0 : F61 = (W + BG - (AB + CG)) / (2.0 * BC);
2084 0 : F62 = (S + CG - (BG + CN)) / (2.0 * BC);
2085 0 : F63 = (CN + BP - (S + CP)) / (2.0 * BC);
2086 0 : F64 = (BK + CP - (S + BP)) / (2.0 * BC);
2087 0 : F71 = F21;
2088 0 : F72 = F27;
2089 0 : F73 = F37;
2090 0 : F74 = (BP + AK - (BK + AP)) / (2.0 * AB);
2091 0 : F89 = F12;
2092 0 : F810 = F16;
2093 0 : F811 = F51;
2094 0 : F812 = F14;
2095 0 : F813 = F13;
2096 0 : F814 = F12;
2097 0 : F911 = F25;
2098 0 : F912 = F74;
2099 0 : F913 = F73;
2100 0 : F914 = F27;
2101 0 : F1011 = (BC + S - BK) / (2.0 * BC);
2102 0 : F1012 = F64;
2103 0 : F1013 = F63;
2104 0 : F1014 = F62;
2105 0 : F119 = F57;
2106 0 : F1110 = F56;
2107 0 : F1112 = F54;
2108 0 : F1113 = F53;
2109 0 : F1114 = F52;
2110 0 : F129 = F47;
2111 0 : F1210 = F46;
2112 0 : F1211 = F45;
2113 0 : F139 = F37;
2114 0 : F1310 = F36;
2115 0 : F1311 = F35;
2116 0 : F149 = F27;
2117 0 : F1410 = F26;
2118 0 : F1411 = F25;
2119 :
2120 0 : A = 0.0; // INITIALIZE RADIOSITY MATRIX COEFFICIENTS
2121 0 : XSOL = 0.0; // INITIALIZE SOLUTION VECTOR COEFFICIENTS
2122 :
2123 : // POPULATE THE COEFFICIENTS OF THE RADIOSITY MATRIX
2124 :
2125 0 : A(1, 1) = 1.0;
2126 0 : A(2, 1) = -RHOBF_DD * F12;
2127 0 : A(3, 1) = -RHOBF_DD * F13;
2128 0 : A(4, 1) = -RHOBF_DD * F14;
2129 0 : A(5, 1) = -RHOBF_DD * F16;
2130 0 : A(6, 1) = -RHOBF_DD * F17;
2131 0 : A(7, 1) = 0.0;
2132 0 : A(8, 1) = 0.0;
2133 0 : A(9, 1) = 0.0;
2134 0 : A(10, 1) = 0.0;
2135 0 : A(11, 1) = 0.0;
2136 0 : A(12, 1) = 0.0;
2137 0 : A(13, 1) = Z1_BD;
2138 0 : A(1, 2) = -RHOBF_DD * F21;
2139 0 : A(2, 2) = 1.0;
2140 0 : A(3, 2) = 0.0;
2141 0 : A(4, 2) = 0.0;
2142 0 : A(5, 2) = -RHOBF_DD * F26;
2143 0 : A(6, 2) = -RHOBF_DD * F27;
2144 0 : A(7, 2) = -TAUFF_DD * F149;
2145 0 : A(8, 2) = -TAUFF_DD * F1410;
2146 0 : A(9, 2) = -TAUFF_DD * F1411;
2147 0 : A(10, 2) = 0.0;
2148 0 : A(11, 2) = 0.0;
2149 0 : A(12, 2) = 0.0;
2150 0 : A(13, 2) = Z2_BD;
2151 0 : A(1, 3) = -RHOBF_DD * F31;
2152 0 : A(2, 3) = 0.0;
2153 0 : A(3, 3) = 1.0;
2154 0 : A(4, 3) = 0.0;
2155 0 : A(5, 3) = -RHOBF_DD * F36;
2156 0 : A(6, 3) = -RHOBF_DD * F37;
2157 0 : A(7, 3) = -TAUFF_DD * F139;
2158 0 : A(8, 3) = -TAUFF_DD * F1310;
2159 0 : A(9, 3) = -TAUFF_DD * F1311;
2160 0 : A(10, 3) = 0.0;
2161 0 : A(11, 3) = 0.0;
2162 0 : A(12, 3) = 0.0;
2163 0 : A(13, 3) = Z3_BD;
2164 0 : A(1, 4) = -RHOBF_DD * F41;
2165 0 : A(2, 4) = 0.0;
2166 0 : A(3, 4) = 0.0;
2167 0 : A(4, 4) = 1.0;
2168 0 : A(5, 4) = -RHOBF_DD * F46;
2169 0 : A(6, 4) = -RHOBF_DD * F47;
2170 0 : A(7, 4) = -TAUFF_DD * F129;
2171 0 : A(8, 4) = -TAUFF_DD * F1210;
2172 0 : A(9, 4) = -TAUFF_DD * F1211;
2173 0 : A(10, 4) = 0.0;
2174 0 : A(11, 4) = 0.0;
2175 0 : A(12, 4) = 0.0;
2176 0 : A(13, 4) = 0.0;
2177 0 : A(1, 5) = -RHOBF_DD * F61;
2178 0 : A(2, 5) = -RHOBF_DD * F62;
2179 0 : A(3, 5) = -RHOBF_DD * F63;
2180 0 : A(4, 5) = -RHOBF_DD * F64;
2181 0 : A(5, 5) = 1.0;
2182 0 : A(6, 5) = 0.0;
2183 0 : A(7, 5) = 0.0;
2184 0 : A(8, 5) = 0.0;
2185 0 : A(9, 5) = -TAUFF_DD * F1011;
2186 0 : A(10, 5) = -TAUFF_DD * F1012;
2187 0 : A(11, 5) = -TAUFF_DD * F1013;
2188 0 : A(12, 5) = -TAUFF_DD * F1014;
2189 0 : A(13, 5) = 0.0;
2190 0 : A(1, 6) = -RHOBF_DD * F71;
2191 0 : A(2, 6) = -RHOBF_DD * F72;
2192 0 : A(3, 6) = -RHOBF_DD * F73;
2193 0 : A(4, 6) = -RHOBF_DD * F74;
2194 0 : A(5, 6) = 0.0;
2195 0 : A(6, 6) = 1.0;
2196 0 : A(7, 6) = 0.0;
2197 0 : A(8, 6) = 0.0;
2198 0 : A(9, 6) = -TAUFF_DD * F911;
2199 0 : A(10, 6) = -TAUFF_DD * F912;
2200 0 : A(11, 6) = -TAUFF_DD * F913;
2201 0 : A(12, 6) = -TAUFF_DD * F914;
2202 0 : A(13, 6) = Z7_BD;
2203 0 : A(1, 7) = -TAUBF_DD * F71;
2204 0 : A(2, 7) = -TAUBF_DD * F72;
2205 0 : A(3, 7) = -TAUBF_DD * F73;
2206 0 : A(4, 7) = -TAUBF_DD * F74;
2207 0 : A(5, 7) = 0.0;
2208 0 : A(6, 7) = 0.0;
2209 0 : A(7, 7) = 1.0;
2210 0 : A(8, 7) = 0.0;
2211 0 : A(9, 7) = -RHOFF_DD * F911;
2212 0 : A(10, 7) = -RHOFF_DD * F912;
2213 0 : A(11, 7) = -RHOFF_DD * F913;
2214 0 : A(12, 7) = -RHOFF_DD * F914;
2215 0 : A(13, 7) = Z9_BD;
2216 0 : A(1, 8) = -TAUBF_DD * F61;
2217 0 : A(2, 8) = -TAUBF_DD * F62;
2218 0 : A(3, 8) = -TAUBF_DD * F63;
2219 0 : A(4, 8) = -TAUBF_DD * F64;
2220 0 : A(5, 8) = 0.0;
2221 0 : A(6, 8) = 0.0;
2222 0 : A(7, 8) = 0.0;
2223 0 : A(8, 8) = 1.0;
2224 0 : A(9, 8) = -RHOFF_DD * F1011;
2225 0 : A(10, 8) = -RHOFF_DD * F1012;
2226 0 : A(11, 8) = -RHOFF_DD * F1013;
2227 0 : A(12, 8) = -RHOFF_DD * F1014;
2228 0 : A(13, 8) = 0.0;
2229 0 : A(1, 9) = 0.0;
2230 0 : A(2, 9) = 0.0;
2231 0 : A(3, 9) = 0.0;
2232 0 : A(4, 9) = 0.0;
2233 0 : A(5, 9) = 0.0;
2234 0 : A(6, 9) = 0.0;
2235 0 : A(7, 9) = -RHOFF_DD * F119;
2236 0 : A(8, 9) = -RHOFF_DD * F1110;
2237 0 : A(9, 9) = 1.0;
2238 0 : A(10, 9) = -RHOFF_DD * F1112;
2239 0 : A(11, 9) = -RHOFF_DD * F1113;
2240 0 : A(12, 9) = -RHOFF_DD * F1114;
2241 0 : A(13, 9) = 0.0;
2242 0 : A(1, 10) = -TAUBF_DD * F41;
2243 0 : A(2, 10) = 0.0;
2244 0 : A(3, 10) = 0.0;
2245 0 : A(4, 10) = 0.0;
2246 0 : A(5, 10) = -TAUBF_DD * F46;
2247 0 : A(6, 10) = -TAUBF_DD * F47;
2248 0 : A(7, 10) = -RHOFF_DD * F129;
2249 0 : A(8, 10) = -RHOFF_DD * F1210;
2250 0 : A(9, 10) = -RHOFF_DD * F1211;
2251 0 : A(10, 10) = 1.0;
2252 0 : A(11, 10) = 0.0;
2253 0 : A(12, 10) = 0.0;
2254 0 : A(13, 10) = 0.0;
2255 0 : A(1, 11) = -TAUBF_DD * F31;
2256 0 : A(2, 11) = 0.0;
2257 0 : A(3, 11) = 0.0;
2258 0 : A(4, 11) = 0.0;
2259 0 : A(5, 11) = -TAUBF_DD * F36;
2260 0 : A(6, 11) = -TAUBF_DD * F37;
2261 0 : A(7, 11) = -RHOFF_DD * F139;
2262 0 : A(8, 11) = -RHOFF_DD * F1310;
2263 0 : A(9, 11) = -RHOFF_DD * F1311;
2264 0 : A(10, 11) = 0.0;
2265 0 : A(11, 11) = 1.0;
2266 0 : A(12, 11) = 0.0;
2267 0 : A(13, 11) = Z13_BD;
2268 0 : A(1, 12) = -TAUBF_DD * F21;
2269 0 : A(2, 12) = 0.0;
2270 0 : A(3, 12) = 0.0;
2271 0 : A(4, 12) = 0.0;
2272 0 : A(5, 12) = -TAUBF_DD * F26;
2273 0 : A(6, 12) = -TAUBF_DD * F27;
2274 0 : A(7, 12) = -RHOFF_DD * F149;
2275 0 : A(8, 12) = -RHOFF_DD * F1410;
2276 0 : A(9, 12) = -RHOFF_DD * F1411;
2277 0 : A(10, 12) = 0.0;
2278 0 : A(11, 12) = 0.0;
2279 0 : A(12, 12) = 1.0;
2280 0 : A(13, 12) = Z14_BD;
2281 :
2282 0 : SOLMATS(N, A, XSOL);
2283 :
2284 0 : J1 = XSOL(1);
2285 0 : J2 = XSOL(2);
2286 0 : J3 = XSOL(3);
2287 0 : J4 = XSOL(4);
2288 0 : J6 = XSOL(5);
2289 0 : J7 = XSOL(6);
2290 0 : J9 = XSOL(7);
2291 0 : J10 = XSOL(8);
2292 0 : J11 = XSOL(9);
2293 0 : J12 = XSOL(10);
2294 0 : J13 = XSOL(11);
2295 0 : J14 = XSOL(12);
2296 :
2297 0 : G1 = F12 * J2 + F13 * J3 + F14 * J4 + F16 * J6 + F17 * J7;
2298 0 : G5 = F56 * J6 + F57 * J7 + F51 * J1 + F52 * J2 + F53 * J3 + F54 * J4;
2299 0 : G8 = F89 * J9 + F810 * J10 + F811 * J11 + F812 * J12 + F813 * J13 + F814 * J14;
2300 0 : G11 = F1112 * J12 + F1113 * J13 + F1114 * J14 + F119 * J9 + F1110 * J10;
2301 :
2302 0 : TAU_BB = 0.0;
2303 0 : TAU_BD = (G5 + TAUFF_DD * G11) / 2.0;
2304 0 : RHO_BD = (RHOFF_BT_PARL + TAUBF_DD * G1 + G8) / 2.0;
2305 0 : }
2306 :
2307 0 : void PD_BEAM_CASE_II(Real64 const S, // pleat spacing (> 0)
2308 : Real64 const W, // pleat depth (>=0, same units as S)
2309 : [[maybe_unused]] Real64 const OMEGA_H, // horizontal profile angle, radians
2310 : Real64 const DE, // width of illumination on pleat bottom (same units as S)
2311 : Real64 const RHOFF_BT_PARL,
2312 : Real64 const TAUFF_BB_PARL,
2313 : Real64 const TAUFF_BD_PARL,
2314 : [[maybe_unused]] Real64 const RHOBF_BT_PARL,
2315 : [[maybe_unused]] Real64 const TAUBF_BB_PARL,
2316 : [[maybe_unused]] Real64 const TAUBF_BD_PARL,
2317 : Real64 const RHOFF_BT_PERP,
2318 : Real64 const TAUFF_BB_PERP,
2319 : Real64 const TAUFF_BD_PERP,
2320 : Real64 const RHOBF_BT_PERP,
2321 : Real64 const TAUBF_BB_PERP,
2322 : Real64 const TAUBF_BD_PERP,
2323 : Real64 const RHOBF_DD, // fabric back diffuse-diffuse reflectance
2324 : Real64 const RHOFF_DD, // fabric front diffuse-diffuse reflectance
2325 : Real64 const TAUFF_DD, // fabric front diffuse-diffuse transmittance
2326 : Real64 const TAUBF_DD, // fabric back diffuse-diffuse transmittance
2327 : Real64 &RHO_BD, // returned: drape front beam-diffuse reflectance
2328 : Real64 &TAU_BD, // returned: drape front beam-diffuse transmittance
2329 : Real64 &TAU_BB // returned: drape front beam-beam transmittance
2330 : )
2331 : {
2332 :
2333 : // SUBROUTINE INFORMATION:
2334 : // AUTHOR John L. Wright, University of Waterloo,
2335 : // Mechanical Engineering, Advanced Glazing System Laboratory
2336 :
2337 : // PURPOSE OF THIS SUBROUTINE:
2338 : // calculates the effective front-side solar optical properties of a drapery layer.
2339 : // METHODOLOGY EMPLOYED:
2340 : // TWELVE SURFACE FLAT-FABRIC MODEL WITH RECTANGULAR ENCLOSURE
2341 :
2342 : // fabric properties at current (off-normal) incidence
2343 : // _PARL = surface parallel to window (pleat top/bot)
2344 : // _PERP = surface perpendicular to window (pleat side)
2345 :
2346 0 : int constexpr N(10);
2347 :
2348 : Real64 TAUBF_BT_PERP;
2349 : Real64 AB; // lengths of surfaces and diagonal strings
2350 : Real64 GN;
2351 : Real64 NK;
2352 : Real64 BC;
2353 : Real64 AN;
2354 : Real64 AK;
2355 : Real64 BG;
2356 : Real64 CG;
2357 : Real64 BK;
2358 : Real64 CN;
2359 : Real64 Z1_BD; // diffuse source terms due to incident beam radiation
2360 : Real64 Z2_BD;
2361 : Real64 Z3_BD;
2362 : Real64 Z6_BD;
2363 : Real64 Z8_BD;
2364 : Real64 Z11_BD;
2365 : Real64 Z12_BD;
2366 : Real64 Z1_BB; // beam source terms due to incident beam radiation
2367 : Real64 Z6_BB;
2368 : // shape factors
2369 : Real64 F12;
2370 : Real64 F13;
2371 : Real64 F15;
2372 : Real64 F16;
2373 : Real64 F21;
2374 : Real64 F25;
2375 : Real64 F26;
2376 : Real64 F31;
2377 : Real64 F35;
2378 : Real64 F36;
2379 : Real64 F41;
2380 : Real64 F42;
2381 : Real64 F43;
2382 : Real64 F45;
2383 : Real64 F46;
2384 : Real64 F51;
2385 : Real64 F52;
2386 : Real64 F53;
2387 : Real64 F54;
2388 : Real64 F61;
2389 : Real64 F62;
2390 : Real64 F63;
2391 : Real64 F78;
2392 : Real64 F79;
2393 : Real64 F710;
2394 : Real64 F711;
2395 : Real64 F712;
2396 : Real64 F810;
2397 : Real64 F811;
2398 : Real64 F812;
2399 : Real64 F910;
2400 : Real64 F911;
2401 : Real64 F912;
2402 : Real64 F108;
2403 : Real64 F109;
2404 : Real64 F1011;
2405 : Real64 F1012;
2406 : Real64 F118;
2407 : Real64 F119;
2408 : Real64 F1110;
2409 : Real64 F128;
2410 : Real64 F129;
2411 : Real64 F1210;
2412 :
2413 : Real64 J1; // radiosity, surface i
2414 : Real64 J2;
2415 : Real64 J3;
2416 : Real64 J5;
2417 : Real64 J6;
2418 : Real64 J8;
2419 : Real64 J9;
2420 : Real64 J10;
2421 : Real64 J11;
2422 : Real64 J12;
2423 : Real64 G1; // irradiance, surface i
2424 : Real64 G4;
2425 : Real64 G7;
2426 : Real64 G10;
2427 0 : Array2D<Real64> A(N + 2, N); // coefficients of the radiosity equations matrix
2428 0 : Array1D<Real64> XSOL(N); // solution vector (obtained after solving the radiosity equations matrix)
2429 :
2430 0 : TAUBF_BT_PERP = TAUBF_BD_PERP + TAUBF_BB_PERP;
2431 :
2432 0 : AB = DE;
2433 0 : GN = DE;
2434 0 : NK = W - DE;
2435 0 : BC = NK;
2436 0 : AN = std::sqrt(S * S + DE * DE);
2437 0 : AK = std::sqrt(W * W + S * S);
2438 0 : BG = AN;
2439 0 : CG = AK;
2440 0 : BK = std::sqrt(S * S + BC * BC);
2441 0 : CN = std::sqrt(S * S + NK * NK);
2442 :
2443 0 : Z1_BB = TAUFF_BB_PARL;
2444 0 : Z1_BD = TAUFF_BD_PARL;
2445 0 : Z2_BD = Z1_BB * RHOBF_BT_PERP * S / GN;
2446 0 : Z6_BB = TAUFF_BB_PERP * S / DE;
2447 0 : Z6_BD = TAUFF_BD_PERP * S / DE;
2448 0 : Z3_BD = Z6_BB * RHOBF_BT_PERP;
2449 0 : Z8_BD = RHOFF_BT_PERP * S / DE;
2450 0 : Z11_BD = Z6_BB * TAUBF_BT_PERP;
2451 0 : Z12_BD = Z1_BB * TAUBF_BT_PERP * S / GN;
2452 :
2453 0 : F12 = (S + GN - AN) / (2.0 * S);
2454 0 : F13 = (W + AN - (GN + AK)) / (2.0 * S);
2455 0 : F15 = (W + BG - (AB + CG)) / (2.0 * S);
2456 0 : F16 = (S + AB - BG) / (2.0 * S);
2457 0 : F21 = (S + GN - AN) / (2.0 * GN);
2458 0 : F25 = (S + CG - (BG + CN)) / (2.0 * GN);
2459 0 : F26 = (AN + BG - 2.0 * S) / (2.0 * GN);
2460 0 : F31 = (W + AN - (GN + AK)) / (2.0 * NK);
2461 0 : F35 = (BK + CN - 2.0 * S) / (2.0 * NK);
2462 0 : F36 = (S + AK - (AN + BK)) / (2.0 * NK);
2463 0 : F41 = (AK + CG - 2.0 * W) / (2.0 * S);
2464 0 : F42 = (W + CN - (CG + NK)) / (2.0 * S);
2465 0 : F43 = (S + NK - CN) / (2.0 * S);
2466 0 : F45 = (S + BC - BK) / (2.0 * S);
2467 0 : F46 = (W + BK - (AK + BC)) / (2.0 * S);
2468 0 : F51 = (W + BG - (AB + CG)) / (2.0 * BC);
2469 0 : F52 = (S + CG - (BG + CN)) / (2.0 * BC);
2470 0 : F53 = (BK + CN - 2.0 * S) / (2.0 * BC);
2471 0 : F54 = (S + BC - BK) / (2.0 * BC);
2472 0 : F61 = (S + AB - BG) / (2.0 * AB);
2473 0 : F62 = (AN + BG - 2.0 * S) / (2.0 * AB);
2474 0 : F63 = (S + AK - (AN + BK)) / (2.0 * AB);
2475 0 : F78 = F12;
2476 0 : F79 = F13;
2477 0 : F710 = (AK + CG - 2.0 * W) / (2.0 * S);
2478 0 : F711 = F15;
2479 0 : F712 = F16;
2480 0 : F810 = (W + CN - (CG + NK)) / (2.0 * S);
2481 0 : F811 = F25;
2482 0 : F812 = F26;
2483 0 : F910 = (S + NK - CN) / (2.0 * NK);
2484 0 : F911 = F35;
2485 0 : F912 = F36;
2486 0 : F108 = F42;
2487 0 : F109 = F43;
2488 0 : F1011 = F45;
2489 0 : F1012 = F46;
2490 0 : F118 = F52;
2491 0 : F119 = F53;
2492 0 : F1110 = (S + BC - BK) / (2.0 * NK);
2493 0 : F128 = F62;
2494 0 : F129 = F63;
2495 0 : F1210 = (W + BK - (AK + BC)) / (2.0 * GN);
2496 :
2497 0 : A = 0.0; // INITIALIZE RADIOSITY MATRIX COEFFICIENTS
2498 0 : XSOL = 0.0; // INITIALIZE SOLUTION VECTOR COEFFICIENTS
2499 :
2500 : // POPULATE THE COEFFICIENTS OF THE RADIOSITY MATRIX
2501 :
2502 0 : A(1, 1) = 1.0;
2503 0 : A(2, 1) = -RHOBF_DD * F12;
2504 0 : A(3, 1) = -RHOBF_DD * F13;
2505 0 : A(4, 1) = -RHOBF_DD * F15;
2506 0 : A(5, 1) = -RHOBF_DD * F16;
2507 0 : A(6, 1) = 0.0;
2508 0 : A(7, 1) = 0.0;
2509 0 : A(8, 1) = 0.0;
2510 0 : A(9, 1) = 0.0;
2511 0 : A(10, 1) = 0.0;
2512 0 : A(11, 1) = Z1_BD;
2513 0 : A(1, 2) = -RHOBF_DD * F21;
2514 0 : A(2, 2) = 1.0;
2515 0 : A(3, 2) = 0.0;
2516 0 : A(4, 2) = -RHOBF_DD * F25;
2517 0 : A(5, 2) = -RHOBF_DD * F26;
2518 0 : A(6, 2) = -TAUFF_DD * F128;
2519 0 : A(7, 2) = -TAUFF_DD * F129;
2520 0 : A(8, 2) = -TAUFF_DD * F1210;
2521 0 : A(9, 2) = 0.0;
2522 0 : A(10, 2) = 0.0;
2523 0 : A(11, 2) = Z2_BD;
2524 0 : A(1, 3) = -RHOBF_DD * F31;
2525 0 : A(2, 3) = 0.0;
2526 0 : A(3, 3) = 1.0;
2527 0 : A(4, 3) = -RHOBF_DD * F35;
2528 0 : A(5, 3) = -RHOBF_DD * F36;
2529 0 : A(6, 3) = -TAUFF_DD * F118;
2530 0 : A(7, 3) = -TAUFF_DD * F119;
2531 0 : A(8, 3) = -TAUFF_DD * F1110;
2532 0 : A(9, 3) = 0.0;
2533 0 : A(10, 3) = 0.0;
2534 0 : A(11, 3) = Z3_BD;
2535 0 : A(1, 4) = -RHOBF_DD * F51;
2536 0 : A(2, 4) = -RHOBF_DD * F52;
2537 0 : A(3, 4) = -RHOBF_DD * F53;
2538 0 : A(4, 4) = 1.0;
2539 0 : A(5, 4) = 0.0;
2540 0 : A(6, 4) = 0.0;
2541 0 : A(7, 4) = 0.0;
2542 0 : A(8, 4) = -TAUFF_DD * F910;
2543 0 : A(9, 4) = -TAUFF_DD * F911;
2544 0 : A(10, 4) = -TAUFF_DD * F912;
2545 0 : A(11, 4) = 0.0;
2546 0 : A(1, 5) = -RHOBF_DD * F61;
2547 0 : A(2, 5) = -RHOBF_DD * F62;
2548 0 : A(3, 5) = -RHOBF_DD * F63;
2549 0 : A(4, 5) = 0.0;
2550 0 : A(5, 5) = 1.0;
2551 0 : A(6, 5) = 0.0;
2552 0 : A(7, 5) = 0.0;
2553 0 : A(8, 5) = -TAUFF_DD * F810;
2554 0 : A(9, 5) = -TAUFF_DD * F811;
2555 0 : A(10, 5) = -TAUFF_DD * F812;
2556 0 : A(11, 5) = Z6_BD;
2557 0 : A(1, 6) = -TAUBF_DD * F61;
2558 0 : A(2, 6) = -TAUBF_DD * F62;
2559 0 : A(3, 6) = -TAUBF_DD * F63;
2560 0 : A(4, 6) = 0.0;
2561 0 : A(5, 6) = 0.0;
2562 0 : A(6, 6) = 1.0;
2563 0 : A(7, 6) = 0.0;
2564 0 : A(8, 6) = -RHOFF_DD * F810;
2565 0 : A(9, 6) = -RHOFF_DD * F811;
2566 0 : A(10, 6) = -RHOFF_DD * F812;
2567 0 : A(11, 6) = Z8_BD;
2568 0 : A(1, 7) = -TAUBF_DD * F51;
2569 0 : A(2, 7) = -TAUBF_DD * F52;
2570 0 : A(3, 7) = -TAUBF_DD * F53;
2571 0 : A(4, 7) = 0.0;
2572 0 : A(5, 7) = 0.0;
2573 0 : A(6, 7) = 0.0;
2574 0 : A(7, 7) = 1.0;
2575 0 : A(8, 7) = -RHOFF_DD * F910;
2576 0 : A(9, 7) = -RHOFF_DD * F911;
2577 0 : A(10, 7) = -RHOFF_DD * F912;
2578 0 : A(11, 7) = 0.0;
2579 0 : A(1, 8) = 0.0;
2580 0 : A(2, 8) = 0.0;
2581 0 : A(3, 8) = 0.0;
2582 0 : A(4, 8) = 0.0;
2583 0 : A(5, 8) = 0.0;
2584 0 : A(6, 8) = -RHOFF_DD * F108;
2585 0 : A(7, 8) = -RHOFF_DD * F109;
2586 0 : A(8, 8) = 1.0;
2587 0 : A(9, 8) = -RHOFF_DD * F1011;
2588 0 : A(10, 8) = -RHOFF_DD * F1012;
2589 0 : A(11, 8) = 0.0;
2590 0 : A(1, 9) = -TAUBF_DD * F31;
2591 0 : A(2, 9) = 0.0;
2592 0 : A(3, 9) = 0.0;
2593 0 : A(4, 9) = -TAUBF_DD * F35;
2594 0 : A(5, 9) = -TAUBF_DD * F36;
2595 0 : A(6, 9) = -RHOFF_DD * F118;
2596 0 : A(7, 9) = -RHOFF_DD * F119;
2597 0 : A(8, 9) = -RHOFF_DD * F1110;
2598 0 : A(9, 9) = 1.0;
2599 0 : A(10, 9) = 0.0;
2600 0 : A(11, 9) = Z11_BD;
2601 0 : A(1, 10) = -TAUBF_DD * F21;
2602 0 : A(2, 10) = 0.0;
2603 0 : A(3, 10) = 0.0;
2604 0 : A(4, 10) = -TAUBF_DD * F25;
2605 0 : A(5, 10) = -TAUBF_DD * F26;
2606 0 : A(6, 10) = -RHOFF_DD * F128;
2607 0 : A(7, 10) = -RHOFF_DD * F129;
2608 0 : A(8, 10) = -RHOFF_DD * F1210;
2609 0 : A(9, 10) = 0.0;
2610 0 : A(10, 10) = 1.0;
2611 0 : A(11, 10) = Z12_BD;
2612 :
2613 0 : SOLMATS(N, A, XSOL);
2614 :
2615 0 : J1 = XSOL(1);
2616 0 : J2 = XSOL(2);
2617 0 : J3 = XSOL(3);
2618 0 : J5 = XSOL(4);
2619 0 : J6 = XSOL(5);
2620 0 : J8 = XSOL(6);
2621 0 : J9 = XSOL(7);
2622 0 : J10 = XSOL(8);
2623 0 : J11 = XSOL(9);
2624 0 : J12 = XSOL(10);
2625 :
2626 0 : G1 = F12 * J2 + F13 * J3 + F15 * J5 + F16 * J6;
2627 0 : G4 = F41 * J1 + F42 * J2 + F43 * J3 + F45 * J5 + F46 * J6;
2628 0 : G7 = F78 * J8 + F79 * J9 + F710 * J10 + F711 * J11 + F712 * J12;
2629 0 : G10 = F108 * J8 + F109 * J9 + F1011 * J11 + F1012 * J12;
2630 :
2631 0 : TAU_BB = 0.0;
2632 0 : TAU_BD = (G4 + TAUFF_DD * G10) / 2.0;
2633 0 : RHO_BD = (RHOFF_BT_PARL + TAUBF_DD * G1 + G7) / 2.0;
2634 0 : }
2635 :
2636 0 : void PD_BEAM_CASE_III(Real64 const S, // pleat spacing (> 0)
2637 : Real64 const W, // pleat depth (>=0, same units as S)
2638 : Real64 const OMEGA_H, // horizontal profile angle, radians
2639 : Real64 const DE, // width of illumination on pleat bottom (same units as S)
2640 : Real64 const RHOFF_BT_PARL,
2641 : Real64 const TAUFF_BB_PARL,
2642 : Real64 const TAUFF_BD_PARL,
2643 : [[maybe_unused]] Real64 const RHOBF_BT_PARL,
2644 : [[maybe_unused]] Real64 const TAUBF_BB_PARL,
2645 : [[maybe_unused]] Real64 const TAUBF_BD_PARL,
2646 : Real64 const RHOFF_BT_PERP,
2647 : Real64 const TAUFF_BB_PERP,
2648 : Real64 const TAUFF_BD_PERP,
2649 : Real64 const RHOBF_BT_PERP,
2650 : Real64 const TAUBF_BB_PERP,
2651 : Real64 const TAUBF_BD_PERP,
2652 : Real64 const RHOBF_DD, // fabric back diffuse-diffuse reflectance
2653 : Real64 const RHOFF_DD, // fabric front diffuse-diffuse reflectance
2654 : Real64 const TAUFF_DD, // fabric front diffuse-diffuse transmittance
2655 : Real64 const TAUBF_DD, // fabric back diffuse-diffuse transmittance
2656 : Real64 &RHO_BD, // returned: drape front beam-diffuse reflectance
2657 : Real64 &TAU_BD, // returned: drape front beam-diffuse transmittance
2658 : Real64 &TAU_BB // returned: drape front beam-beam transmittance
2659 : )
2660 : {
2661 :
2662 : // SUBROUTINE INFORMATION:
2663 : // AUTHOR John L. Wright, University of Waterloo,
2664 : // Mechanical Engineering, Advanced Glazing System Laboratory
2665 :
2666 : // PURPOSE OF THIS SUBROUTINE:
2667 : // calculates the effective front-side solar optical properties of a drapery layer.
2668 : // METHODOLOGY EMPLOYED:
2669 : // TWELVE SURFACE FLAT-FABRIC MODEL WITH RECTANGULAR ENCLOSURE
2670 :
2671 : // fabric properties at current (off-normal) incidence
2672 : // _PARL = surface parallel to window (pleat top/bot)
2673 : // _PERP = surface perpendicular to window (pleat side)
2674 :
2675 : // SUBROUTINE PARAMETER DEFINITIONS:
2676 0 : int constexpr N(10);
2677 :
2678 : Real64 TAUBF_BT_PERP;
2679 : Real64 AB; // lengths for surfaces and diagonal strings
2680 : Real64 GN;
2681 : Real64 NK;
2682 : Real64 BC;
2683 : Real64 AN;
2684 : Real64 AK;
2685 : Real64 BG;
2686 : Real64 CG;
2687 : Real64 BK;
2688 : Real64 CN;
2689 : Real64 Z1_BB; // beam source terms
2690 : Real64 Z6_BB;
2691 : Real64 Z1_BD; // diffuse source terms
2692 : Real64 Z2_BD;
2693 : Real64 Z6_BD;
2694 : Real64 Z3_BD;
2695 : Real64 Z8_BD;
2696 : Real64 Z11_BD;
2697 : Real64 Z12_BD;
2698 : // shape factors
2699 : Real64 F12;
2700 : Real64 F13;
2701 : Real64 F15;
2702 : Real64 F16;
2703 : Real64 F21;
2704 : Real64 F25;
2705 : Real64 F26;
2706 : Real64 F31;
2707 : Real64 F35;
2708 : Real64 F36;
2709 : Real64 F41;
2710 : Real64 F42;
2711 : Real64 F43;
2712 : Real64 F45;
2713 : Real64 F46;
2714 : Real64 F51;
2715 : Real64 F52;
2716 : Real64 F53;
2717 : Real64 F54;
2718 : Real64 F61;
2719 : Real64 F62;
2720 : Real64 F63;
2721 : Real64 F78;
2722 : Real64 F79;
2723 : Real64 F710;
2724 : Real64 F711;
2725 : Real64 F712;
2726 : Real64 F810;
2727 : Real64 F811;
2728 : Real64 F812;
2729 : Real64 F910;
2730 : Real64 F911;
2731 : Real64 F912;
2732 : Real64 F108;
2733 : Real64 F109;
2734 : Real64 F1011;
2735 : Real64 F1012;
2736 : Real64 F118;
2737 : Real64 F119;
2738 : Real64 F1110;
2739 : Real64 F128;
2740 : Real64 F129;
2741 : Real64 F1210;
2742 : Real64 J1; // radiosity, surface i
2743 : Real64 J2;
2744 : Real64 J3;
2745 : Real64 J5;
2746 : Real64 J6;
2747 : Real64 J8;
2748 : Real64 J9;
2749 : Real64 J10;
2750 : Real64 J11;
2751 : Real64 J12;
2752 : Real64 G1; // irradiance, surface i
2753 : Real64 G4;
2754 : Real64 G7;
2755 : Real64 G10;
2756 :
2757 0 : Array2D<Real64> A(N + 2, N); // coefficients of the radiosity equations matrix
2758 0 : Array1D<Real64> XSOL(N); // solution vector (obtained after solving the radiosity equations matrix)
2759 :
2760 0 : TAUBF_BT_PERP = TAUBF_BD_PERP + TAUBF_BB_PERP;
2761 :
2762 0 : AB = DE;
2763 0 : GN = DE;
2764 0 : NK = W - DE;
2765 0 : BC = NK;
2766 0 : AN = std::sqrt(S * S + DE * DE);
2767 0 : AK = std::sqrt(W * W + S * S);
2768 0 : BG = AN;
2769 0 : CG = AK;
2770 0 : BK = std::sqrt(S * S + BC * BC);
2771 0 : CN = std::sqrt(S * S + NK * NK);
2772 :
2773 0 : Z1_BB = TAUFF_BB_PARL;
2774 0 : Z1_BD = TAUFF_BD_PARL;
2775 0 : Z2_BD = Z1_BB * RHOBF_BT_PERP * S / GN;
2776 0 : Z6_BB = TAUFF_BB_PERP * S / DE;
2777 0 : Z6_BD = TAUFF_BD_PERP * S / DE;
2778 0 : Z3_BD = Z6_BB * RHOBF_BT_PERP;
2779 0 : Z8_BD = RHOFF_BT_PERP * S / DE;
2780 0 : Z11_BD = Z6_BB * TAUBF_BT_PERP;
2781 0 : Z12_BD = Z1_BB * TAUBF_BT_PERP * S / GN;
2782 :
2783 0 : F12 = (S + GN - AN) / (2.0 * S);
2784 0 : F13 = (W + AN - (GN + AK)) / (2.0 * S);
2785 0 : F15 = (W + BG - (AB + CG)) / (2.0 * S);
2786 0 : F16 = (S + AB - BG) / (2.0 * S);
2787 0 : F21 = (S + GN - AN) / (2.0 * GN);
2788 0 : F25 = (S + CG - (BG + CN)) / (2.0 * GN);
2789 0 : F26 = (AN + BG - 2.0 * S) / (2.0 * GN);
2790 0 : F31 = (W + AN - (GN + AK)) / (2.0 * NK);
2791 0 : F35 = (BK + CN - 2.0 * S) / (2.0 * NK);
2792 0 : F36 = (S + AK - (AN + BK)) / (2.0 * NK);
2793 0 : F41 = (AK + CG - 2.0 * W) / (2.0 * S);
2794 0 : F42 = (W + CN - (CG + NK)) / (2.0 * S);
2795 0 : F43 = (S + NK - CN) / (2.0 * S);
2796 0 : F45 = (S + BC - BK) / (2.0 * S);
2797 0 : F46 = (W + BK - (AK + BC)) / (2.0 * S);
2798 0 : F51 = (W + BG - (AB + CG)) / (2.0 * BC);
2799 0 : F52 = (S + CG - (BG + CN)) / (2.0 * BC);
2800 0 : F53 = (BK + CN - 2.0 * S) / (2.0 * BC);
2801 0 : F54 = (S + BC - BK) / (2.0 * BC);
2802 0 : F61 = (S + AB - BG) / (2.0 * AB);
2803 0 : F62 = (AN + BG - 2.0 * S) / (2.0 * AB);
2804 0 : F63 = (S + AK - (AN + BK)) / (2.0 * AB);
2805 0 : F78 = F12;
2806 0 : F79 = F13;
2807 0 : F710 = (AK + CG - 2.0 * W) / (2.0 * S);
2808 0 : F711 = F15;
2809 0 : F712 = F16;
2810 0 : F810 = (W + CN - (CG + NK)) / (2.0 * S);
2811 0 : F811 = F25;
2812 0 : F812 = F26;
2813 0 : F910 = (S + NK - CN) / (2.0 * NK);
2814 0 : F911 = F35;
2815 0 : F912 = F36;
2816 0 : F108 = F42;
2817 0 : F109 = F43;
2818 0 : F1011 = F45;
2819 0 : F1012 = F46;
2820 0 : F118 = F52;
2821 0 : F119 = F53;
2822 0 : F1110 = (S + BC - BK) / (2.0 * NK);
2823 0 : F128 = F62;
2824 0 : F129 = F63;
2825 0 : F1210 = (W + BK - (AK + BC)) / (2.0 * GN);
2826 :
2827 0 : A = 0.0; // INITIALIZE RADIOSITY MATRIX COEFFICIENTS
2828 0 : XSOL = 0.0; // INITIALIZE SOLUTION VECTOR COEFFICIENTS
2829 :
2830 : // POPULATE THE COEFFICIENTS OF THE RADIOSITY MATRIX
2831 :
2832 0 : A(1, 1) = 1.0;
2833 0 : A(2, 1) = -RHOBF_DD * F12;
2834 0 : A(3, 1) = -RHOBF_DD * F13;
2835 0 : A(4, 1) = -RHOBF_DD * F15;
2836 0 : A(5, 1) = -RHOBF_DD * F16;
2837 0 : A(6, 1) = 0.0;
2838 0 : A(7, 1) = 0.0;
2839 0 : A(8, 1) = 0.0;
2840 0 : A(9, 1) = 0.0;
2841 0 : A(10, 1) = 0.0;
2842 0 : A(11, 1) = Z1_BD;
2843 0 : A(1, 2) = -RHOBF_DD * F21;
2844 0 : A(2, 2) = 1.0;
2845 0 : A(3, 2) = 0.0;
2846 0 : A(4, 2) = -RHOBF_DD * F25;
2847 0 : A(5, 2) = -RHOBF_DD * F26;
2848 0 : A(6, 2) = -TAUFF_DD * F128;
2849 0 : A(7, 2) = -TAUFF_DD * F129;
2850 0 : A(8, 2) = -TAUFF_DD * F1210;
2851 0 : A(9, 2) = 0.0;
2852 0 : A(10, 2) = 0.0;
2853 0 : A(11, 2) = Z2_BD;
2854 0 : A(1, 3) = -RHOBF_DD * F31;
2855 0 : A(2, 3) = 0.0;
2856 0 : A(3, 3) = 1.0;
2857 0 : A(4, 3) = -RHOBF_DD * F35;
2858 0 : A(5, 3) = -RHOBF_DD * F36;
2859 0 : A(6, 3) = -TAUFF_DD * F118;
2860 0 : A(7, 3) = -TAUFF_DD * F119;
2861 0 : A(8, 3) = -TAUFF_DD * F1110;
2862 0 : A(9, 3) = 0.0;
2863 0 : A(10, 3) = 0.0;
2864 0 : A(11, 3) = Z3_BD;
2865 0 : A(1, 4) = -RHOBF_DD * F51;
2866 0 : A(2, 4) = -RHOBF_DD * F52;
2867 0 : A(3, 4) = -RHOBF_DD * F53;
2868 0 : A(4, 4) = 1.0;
2869 0 : A(5, 4) = 0.0;
2870 0 : A(6, 4) = 0.0;
2871 0 : A(7, 4) = 0.0;
2872 0 : A(8, 4) = -TAUFF_DD * F910;
2873 0 : A(9, 4) = -TAUFF_DD * F911;
2874 0 : A(10, 4) = -TAUFF_DD * F912;
2875 0 : A(11, 4) = 0.0;
2876 0 : A(1, 5) = -RHOBF_DD * F61;
2877 0 : A(2, 5) = -RHOBF_DD * F62;
2878 0 : A(3, 5) = -RHOBF_DD * F63;
2879 0 : A(4, 5) = 0.0;
2880 0 : A(5, 5) = 1.0;
2881 0 : A(6, 5) = 0.0;
2882 0 : A(7, 5) = 0.0;
2883 0 : A(8, 5) = -TAUFF_DD * F810;
2884 0 : A(9, 5) = -TAUFF_DD * F811;
2885 0 : A(10, 5) = -TAUFF_DD * F812;
2886 0 : A(11, 5) = Z6_BD;
2887 0 : A(1, 6) = -TAUBF_DD * F61;
2888 0 : A(2, 6) = -TAUBF_DD * F62;
2889 0 : A(3, 6) = -TAUBF_DD * F63;
2890 0 : A(4, 6) = 0.0;
2891 0 : A(5, 6) = 0.0;
2892 0 : A(6, 6) = 1.0;
2893 0 : A(7, 6) = 0.0;
2894 0 : A(8, 6) = -RHOFF_DD * F810;
2895 0 : A(9, 6) = -RHOFF_DD * F811;
2896 0 : A(10, 6) = -RHOFF_DD * F812;
2897 0 : A(11, 6) = Z8_BD;
2898 0 : A(1, 7) = -TAUBF_DD * F51;
2899 0 : A(2, 7) = -TAUBF_DD * F52;
2900 0 : A(3, 7) = -TAUBF_DD * F53;
2901 0 : A(4, 7) = 0.0;
2902 0 : A(5, 7) = 0.0;
2903 0 : A(6, 7) = 0.0;
2904 0 : A(7, 7) = 1.0;
2905 0 : A(8, 7) = -RHOFF_DD * F910;
2906 0 : A(9, 7) = -RHOFF_DD * F911;
2907 0 : A(10, 7) = -RHOFF_DD * F912;
2908 0 : A(11, 7) = 0.0;
2909 0 : A(1, 8) = 0.0;
2910 0 : A(2, 8) = 0.0;
2911 0 : A(3, 8) = 0.0;
2912 0 : A(4, 8) = 0.0;
2913 0 : A(5, 8) = 0.0;
2914 0 : A(6, 8) = -RHOFF_DD * F108;
2915 0 : A(7, 8) = -RHOFF_DD * F109;
2916 0 : A(8, 8) = 1.0;
2917 0 : A(9, 8) = -RHOFF_DD * F1011;
2918 0 : A(10, 8) = -RHOFF_DD * F1012;
2919 0 : A(11, 8) = 0.0;
2920 0 : A(1, 9) = -TAUBF_DD * F31;
2921 0 : A(2, 9) = 0.0;
2922 0 : A(3, 9) = 0.0;
2923 0 : A(4, 9) = -TAUBF_DD * F35;
2924 0 : A(5, 9) = -TAUBF_DD * F36;
2925 0 : A(6, 9) = -RHOFF_DD * F118;
2926 0 : A(7, 9) = -RHOFF_DD * F119;
2927 0 : A(8, 9) = -RHOFF_DD * F1110;
2928 0 : A(9, 9) = 1.0;
2929 0 : A(10, 9) = 0.0;
2930 0 : A(11, 9) = Z11_BD;
2931 0 : A(1, 10) = -TAUBF_DD * F21;
2932 0 : A(2, 10) = 0.0;
2933 0 : A(3, 10) = 0.0;
2934 0 : A(4, 10) = -TAUBF_DD * F25;
2935 0 : A(5, 10) = -TAUBF_DD * F26;
2936 0 : A(6, 10) = -RHOFF_DD * F128;
2937 0 : A(7, 10) = -RHOFF_DD * F129;
2938 0 : A(8, 10) = -RHOFF_DD * F1210;
2939 0 : A(9, 10) = 0.0;
2940 0 : A(10, 10) = 1.0;
2941 0 : A(11, 10) = Z12_BD;
2942 :
2943 0 : SOLMATS(N, A, XSOL);
2944 :
2945 0 : J1 = XSOL(1);
2946 0 : J2 = XSOL(2);
2947 0 : J3 = XSOL(3);
2948 0 : J5 = XSOL(4);
2949 0 : J6 = XSOL(5);
2950 0 : J8 = XSOL(6);
2951 0 : J9 = XSOL(7);
2952 0 : J10 = XSOL(8);
2953 0 : J11 = XSOL(9);
2954 0 : J12 = XSOL(10);
2955 :
2956 0 : G1 = F12 * J2 + F13 * J3 + F15 * J5 + F16 * J6;
2957 0 : G4 = F41 * J1 + F42 * J2 + F43 * J3 + F45 * J5 + F46 * J6;
2958 0 : G7 = F78 * J8 + F79 * J9 + F710 * J10 + F711 * J11 + F712 * J12;
2959 0 : G10 = F108 * J8 + F109 * J9 + F1011 * J11 + F1012 * J12;
2960 :
2961 0 : TAU_BB = (TAUFF_BB_PERP * (AB - NK) * std::abs(std::sin(OMEGA_H))) / (2.0 * S * std::abs(std::cos(OMEGA_H)));
2962 0 : TAU_BD = (G4 + TAUFF_DD * G10) / 2.0;
2963 0 : RHO_BD = (RHOFF_BT_PARL + TAUBF_DD * G1 + G7) / 2.0;
2964 0 : }
2965 :
2966 0 : void PD_BEAM_CASE_IV(Real64 const S, // pleat spacing (> 0)
2967 : Real64 const W, // pleat depth (>=0, same units as S)
2968 : [[maybe_unused]] Real64 const OMEGA_H, // horizontal profile angle, radians
2969 : [[maybe_unused]] Real64 const DE, // width of illumination on pleat bottom (same units as S)
2970 : Real64 const RHOFF_BT_PARL,
2971 : Real64 const TAUFF_BB_PARL,
2972 : Real64 const TAUFF_BD_PARL,
2973 : [[maybe_unused]] Real64 const RHOBF_BT_PARL,
2974 : [[maybe_unused]] Real64 const TAUBF_BB_PARL,
2975 : [[maybe_unused]] Real64 const TAUBF_BD_PARL,
2976 : Real64 const RHOFF_BT_PERP,
2977 : Real64 const TAUFF_BB_PERP,
2978 : Real64 const TAUFF_BD_PERP,
2979 : Real64 const RHOBF_BT_PERP,
2980 : Real64 const TAUBF_BB_PERP,
2981 : Real64 const TAUBF_BD_PERP,
2982 : Real64 const RHOBF_DD, // fabric back diffuse-diffuse reflectance
2983 : Real64 const RHOFF_DD, // fabric front diffuse-diffuse reflectance
2984 : Real64 const TAUFF_DD, // fabric front diffuse-diffuse transmittance
2985 : Real64 const TAUBF_DD, // fabric back diffuse-diffuse transmittance
2986 : Real64 &RHO_BD, // returned: drape front beam-diffuse reflectance
2987 : Real64 &TAU_BD, // returned: drape front beam-diffuse transmittance
2988 : Real64 &TAU_BB // returned: drape front beam-beam transmittance
2989 : )
2990 : {
2991 : // SUBROUTINE INFORMATION:
2992 : // AUTHOR John L. Wright, University of Waterloo,
2993 : // Mechanical Engineering, Advanced Glazing System Laboratory
2994 :
2995 : // PURPOSE OF THIS SUBROUTINE:
2996 : // calculates the effective front-side solar optical properties of a drapery layer.
2997 : // METHODOLOGY EMPLOYED:
2998 : // Eight surface flat-fabric model with rectangular enclosure
2999 :
3000 : // fabric properties at current (off-normal) incidence
3001 : // _PARL = surface parallel to window (pleat top/bot)
3002 : // _PERP = surface perpendicular to window (pleat side)
3003 : // SUBROUTINE PARAMETER DEFINITIONS:
3004 0 : int constexpr N(6);
3005 :
3006 : Real64 TAUBF_BT_PERP;
3007 : Real64 AK; // length of diagonal strings
3008 : Real64 CG;
3009 : Real64 Z1_BB; // beam source term
3010 : Real64 Z1_BD; // diffuse source terms
3011 : Real64 Z2_BD;
3012 : Real64 Z4_BD;
3013 : Real64 Z6_BD;
3014 : Real64 Z8_BD;
3015 : // shape factors
3016 : Real64 F12;
3017 : Real64 F14;
3018 : Real64 F21;
3019 : Real64 F24;
3020 : Real64 F31;
3021 : Real64 F32;
3022 : Real64 F34;
3023 : Real64 F41;
3024 : Real64 F42;
3025 : Real64 F56;
3026 : Real64 F57;
3027 : Real64 F58;
3028 : Real64 F67;
3029 : Real64 F68;
3030 : Real64 F76;
3031 : Real64 F78;
3032 : Real64 F86;
3033 : Real64 F87;
3034 : Real64 J1; // radiosity, surface i
3035 : Real64 J2;
3036 : Real64 J4;
3037 : Real64 J6;
3038 : Real64 J7;
3039 : Real64 J8;
3040 : Real64 G1; // irradiance, surface i
3041 : Real64 G3;
3042 : Real64 G5;
3043 : Real64 G7;
3044 0 : Array2D<Real64> A(N + 2, N); // coefficients of the radiosity equations matrix
3045 0 : Array1D<Real64> XSOL(N); // solution vector (obtained after solving the radiosity equations matrix)
3046 :
3047 0 : TAUBF_BT_PERP = TAUBF_BD_PERP + TAUBF_BB_PERP;
3048 :
3049 0 : AK = std::sqrt(W * W + S * S);
3050 0 : CG = AK;
3051 :
3052 0 : Z1_BB = TAUFF_BB_PARL;
3053 0 : Z1_BD = TAUFF_BD_PARL;
3054 0 : Z2_BD = Z1_BB * RHOBF_BT_PERP * S / W;
3055 0 : Z4_BD = TAUFF_BD_PERP * S / W;
3056 0 : Z6_BD = RHOFF_BT_PERP * S / W;
3057 0 : Z8_BD = Z1_BB * TAUBF_BT_PERP * S / W;
3058 :
3059 0 : F12 = (S + W - AK) / (2.0 * S);
3060 0 : F14 = (S + W - CG) / (2.0 * S);
3061 0 : F21 = (S + W - AK) / (2.0 * W);
3062 0 : F24 = (AK + CG - 2.0 * S) / (2.0 * W);
3063 0 : F31 = (AK + CG - 2.0 * W) / (2.0 * S);
3064 0 : F32 = F12;
3065 0 : F34 = F12;
3066 0 : F41 = F21;
3067 0 : F42 = F24;
3068 0 : F56 = F12;
3069 0 : F57 = F31;
3070 0 : F58 = F14;
3071 0 : F67 = F41;
3072 0 : F68 = F24;
3073 0 : F76 = F32;
3074 0 : F78 = F34;
3075 0 : F86 = F42;
3076 0 : F87 = F21;
3077 :
3078 0 : A = 0.0; // INITIALIZE RADIOSITY MATRIX COEFFICIENTS
3079 0 : XSOL = 0.0; // INITIALIZE SOLUTION VECTOR COEFFICIENTS
3080 :
3081 : // POPULATE THE COEFFICIENTS OF THE RADIOSITY MATRIX
3082 :
3083 0 : A(1, 1) = 1.0;
3084 0 : A(2, 1) = -RHOBF_DD * F12;
3085 0 : A(3, 1) = -RHOBF_DD * F14;
3086 0 : A(4, 1) = 0.0;
3087 0 : A(5, 1) = 0.0;
3088 0 : A(6, 1) = 0.0;
3089 0 : A(7, 1) = Z1_BD;
3090 0 : A(1, 2) = -RHOBF_DD * F21;
3091 0 : A(2, 2) = 1.0;
3092 0 : A(3, 2) = -RHOBF_DD * F24;
3093 0 : A(4, 2) = -TAUFF_DD * F86;
3094 0 : A(5, 2) = -TAUFF_DD * F87;
3095 0 : A(6, 2) = 0.0;
3096 0 : A(7, 2) = Z2_BD;
3097 0 : A(1, 3) = -RHOBF_DD * F41;
3098 0 : A(2, 3) = -RHOBF_DD * F42;
3099 0 : A(3, 3) = 1.0;
3100 0 : A(4, 3) = 0.0;
3101 0 : A(5, 3) = -TAUFF_DD * F67;
3102 0 : A(6, 3) = -TAUFF_DD * F68;
3103 0 : A(7, 3) = Z4_BD;
3104 0 : A(1, 4) = -TAUBF_DD * F41;
3105 0 : A(2, 4) = -TAUBF_DD * F42;
3106 0 : A(3, 4) = 0.0;
3107 0 : A(4, 4) = 1.0;
3108 0 : A(5, 4) = -RHOFF_DD * F67;
3109 0 : A(6, 4) = -RHOFF_DD * F68;
3110 0 : A(7, 4) = Z6_BD;
3111 0 : A(1, 5) = 0.0;
3112 0 : A(2, 5) = 0.0;
3113 0 : A(3, 5) = 0.0;
3114 0 : A(4, 5) = -RHOFF_DD * F76;
3115 0 : A(5, 5) = 1.0;
3116 0 : A(6, 5) = -RHOFF_DD * F78;
3117 0 : A(7, 5) = 0.0;
3118 0 : A(1, 6) = -TAUBF_DD * F21;
3119 0 : A(2, 6) = 0.0;
3120 0 : A(3, 6) = -TAUBF_DD * F24;
3121 0 : A(4, 6) = -RHOFF_DD * F86;
3122 0 : A(5, 6) = -RHOFF_DD * F87;
3123 0 : A(6, 6) = 1.0;
3124 0 : A(7, 6) = Z8_BD;
3125 :
3126 0 : SOLMATS(N, A, XSOL);
3127 :
3128 0 : J1 = XSOL(1);
3129 0 : J2 = XSOL(2);
3130 0 : J4 = XSOL(3);
3131 0 : J6 = XSOL(4);
3132 0 : J7 = XSOL(5);
3133 0 : J8 = XSOL(6);
3134 :
3135 0 : G1 = F12 * J2 + F14 * J4;
3136 0 : G3 = F31 * J1 + F32 * J2 + F34 * J4;
3137 0 : G5 = F56 * J6 + F57 * J7 + F58 * J8;
3138 0 : G7 = F76 * J6 + F78 * J8;
3139 :
3140 0 : TAU_BB = TAUFF_BB_PERP / 2.0;
3141 0 : TAU_BD = (G3 + TAUFF_DD * G7) / 2.0;
3142 0 : RHO_BD = (RHOFF_BT_PARL + TAUBF_DD * G1 + G5) / 2.0;
3143 0 : }
3144 :
3145 0 : void PD_BEAM_CASE_V(Real64 const S, // pleat spacing (> 0)
3146 : Real64 const W, // pleat depth (>=0, same units as S)
3147 : Real64 const OMEGA_H, // horizontal profile angle, radians
3148 : Real64 const DE, // width of illumination on pleat bottom (same units as S)
3149 : Real64 const RHOFF_BT_PARL,
3150 : Real64 const TAUFF_BB_PARL,
3151 : Real64 const TAUFF_BD_PARL,
3152 : [[maybe_unused]] Real64 const RHOBF_BT_PARL,
3153 : [[maybe_unused]] Real64 const TAUBF_BB_PARL,
3154 : [[maybe_unused]] Real64 const TAUBF_BD_PARL,
3155 : Real64 const RHOFF_BT_PERP,
3156 : Real64 const TAUFF_BB_PERP,
3157 : Real64 const TAUFF_BD_PERP,
3158 : Real64 const RHOBF_BT_PERP,
3159 : Real64 const TAUBF_BB_PERP,
3160 : Real64 const TAUBF_BD_PERP,
3161 : Real64 const RHOBF_DD, // fabric back diffuse-diffuse reflectance
3162 : Real64 const RHOFF_DD, // fabric front diffuse-diffuse reflectance
3163 : Real64 const TAUFF_DD, // fabric front diffuse-diffuse transmittance
3164 : Real64 const TAUBF_DD, // fabric back diffuse-diffuse transmittance
3165 : Real64 &RHO_BD, // returned: drape front beam-diffuse reflectance
3166 : Real64 &TAU_BD, // returned: drape front beam-diffuse transmittance
3167 : Real64 &TAU_BB // returned: drape front beam-beam transmittance
3168 : )
3169 : {
3170 :
3171 : // SUBROUTINE INFORMATION:
3172 : // AUTHOR John L. Wright, University of Waterloo,
3173 : // Mechanical Engineering, Advanced Glazing System Laboratory
3174 :
3175 : // PURPOSE OF THIS SUBROUTINE:
3176 : // calculates the effective front-side solar optical properties of a drapery layer.
3177 : // METHODOLOGY EMPLOYED:
3178 : // NINE SURFACE FLAT-FABRIC MODEL WITH RECTANGULAR ENCLOSURE
3179 :
3180 : // fabric properties at current (off-normal) incidence
3181 : // _PARL = surface parallel to window (pleat top/bot)
3182 : // _PERP = surface perpendicular to window (pleat side)
3183 : // SUBROUTINE PARAMETER DEFINITIONS:
3184 0 : int constexpr N(7);
3185 :
3186 : Real64 TAUBF_BT_PERP;
3187 : Real64 AK; // lengths of surfaces and diagonal strings
3188 : Real64 CG;
3189 : Real64 MK;
3190 : Real64 DK;
3191 : Real64 MF;
3192 : Real64 DM;
3193 : Real64 GM;
3194 : Real64 GF;
3195 : Real64 Z1_BB; // beam source term
3196 : Real64 Z1_BD; // diffuse source terms
3197 : Real64 Z2_BD;
3198 : Real64 Z4_BD;
3199 : Real64 Z6_BD;
3200 : Real64 Z7_BD;
3201 : Real64 Z9_BD;
3202 : // shape factors
3203 : Real64 F12;
3204 : Real64 F14;
3205 : Real64 F21;
3206 : Real64 F24;
3207 : Real64 F31;
3208 : Real64 F32;
3209 : Real64 F34;
3210 : Real64 F41;
3211 : Real64 F42;
3212 : Real64 F56;
3213 : Real64 F57;
3214 : Real64 F58;
3215 : Real64 F59;
3216 : Real64 F67;
3217 : Real64 F68;
3218 : Real64 F69;
3219 : Real64 F76;
3220 : Real64 F79;
3221 : Real64 F86;
3222 : Real64 F89;
3223 : Real64 F96;
3224 : Real64 F97;
3225 : Real64 F98;
3226 : Real64 J1; // radiosities
3227 : Real64 J2;
3228 : Real64 J4;
3229 : Real64 J6;
3230 : Real64 J7;
3231 : Real64 J8;
3232 : Real64 J9;
3233 : Real64 G1; // irradiances
3234 : Real64 G3;
3235 : Real64 G5;
3236 : Real64 G7;
3237 : Real64 G8;
3238 :
3239 0 : Array2D<Real64> A(N + 2, N); // coefficients of the radiosity equations matrix
3240 0 : Array1D<Real64> XSOL(N); // solution vector (obtained after solving the radiosity equations matrix)
3241 :
3242 0 : TAUBF_BT_PERP = TAUBF_BD_PERP + TAUBF_BB_PERP;
3243 :
3244 0 : AK = std::sqrt(W * W + S * S);
3245 0 : CG = AK;
3246 0 : Real64 const cos_OMEGA_H(std::abs(std::cos(OMEGA_H)));
3247 0 : Real64 const sin_OMEGA_H(std::abs(std::sin(OMEGA_H)));
3248 0 : MK = (W * sin_OMEGA_H) / cos_OMEGA_H;
3249 0 : DK = AK;
3250 0 : MF = S - MK;
3251 0 : DM = std::sqrt(W * W + MF * MF);
3252 0 : GM = std::sqrt(W * W + MK * MK);
3253 0 : GF = AK;
3254 :
3255 0 : Z1_BB = TAUFF_BB_PARL;
3256 0 : Z1_BD = TAUFF_BD_PARL;
3257 0 : Z2_BD = Z1_BB * RHOBF_BT_PERP * S / DE;
3258 0 : Z4_BD = TAUFF_BD_PERP * S / DE;
3259 0 : Z6_BD = RHOFF_BT_PERP * S / DE;
3260 0 : Z7_BD = RHOFF_BT_PARL;
3261 0 : Z9_BD = Z1_BB * TAUBF_BT_PERP * S / DE;
3262 :
3263 0 : F12 = (S + W - AK) / (2.0 * S);
3264 0 : F14 = (S + W - CG) / (2.0 * S);
3265 0 : F21 = (S + W - AK) / (2.0 * W);
3266 0 : F24 = (AK + CG - 2.0 * S) / (2.0 * W);
3267 0 : F31 = (AK + CG - 2.0 * W) / (2.0 * S);
3268 0 : F32 = F14;
3269 0 : F34 = F12;
3270 0 : F41 = F21;
3271 0 : F42 = F24;
3272 0 : F56 = F12;
3273 0 : F57 = (DM + GF - (GM + W)) / (2.0 * S);
3274 0 : F58 = (DK + GM - (DM + W)) / (2.0 * S);
3275 0 : F59 = F14;
3276 0 : F67 = (W + MF - DM) / (2.0 * W);
3277 0 : F68 = (DM + S - (DK + MF)) / (2.0 * W);
3278 0 : F69 = F24;
3279 0 : F76 = (W + MF - DM) / (2.0 * MF);
3280 0 : F79 = (GM + S - (GF + MK)) / (2.0 * MF);
3281 0 : F86 = (DM + S - (DK + MF)) / (2.0 * MK);
3282 0 : F89 = (W + MK - GM) / (2.0 * MK);
3283 0 : F96 = F42;
3284 0 : F97 = (GM + S - (GF + MK)) / (2.0 * W);
3285 0 : F98 = (W + MK - GM) / (2.0 * W);
3286 :
3287 0 : A = 0.0; // INITIALIZE RADIOSITY MATRIX COEFFICIENTS
3288 0 : XSOL = 0.0; // INITIALIZE SOLUTION VECTOR COEFFICIENTS
3289 :
3290 : // POPULATE THE COEFFICIENTS OF THE RADIOSITY MATRIX
3291 :
3292 0 : A(1, 1) = 1.0;
3293 0 : A(2, 1) = -RHOBF_DD * F12;
3294 0 : A(3, 1) = -RHOBF_DD * F14;
3295 0 : A(4, 1) = 0.0;
3296 0 : A(5, 1) = 0.0;
3297 0 : A(6, 1) = 0.0;
3298 0 : A(7, 1) = 0.0;
3299 0 : A(8, 1) = Z1_BD;
3300 0 : A(1, 2) = -RHOBF_DD * F21;
3301 0 : A(2, 2) = 1.0;
3302 0 : A(3, 2) = -RHOBF_DD * F24;
3303 0 : A(4, 2) = -TAUFF_DD * F96;
3304 0 : A(5, 2) = -TAUFF_DD * F97;
3305 0 : A(6, 2) = -TAUFF_DD * F98;
3306 0 : A(7, 2) = 0.0;
3307 0 : A(8, 2) = Z2_BD;
3308 0 : A(1, 3) = -RHOBF_DD * F41;
3309 0 : A(2, 3) = -RHOBF_DD * F42;
3310 0 : A(3, 3) = 1.0;
3311 0 : A(4, 3) = 0.0;
3312 0 : A(5, 3) = -TAUFF_DD * F67;
3313 0 : A(6, 3) = -TAUFF_DD * F68;
3314 0 : A(7, 3) = -TAUFF_DD * F69;
3315 0 : A(8, 3) = Z4_BD;
3316 0 : A(1, 4) = -TAUBF_DD * F41;
3317 0 : A(2, 4) = -TAUBF_DD * F42;
3318 0 : A(3, 4) = 0.0;
3319 0 : A(4, 4) = 1.0;
3320 0 : A(5, 4) = -RHOFF_DD * F67;
3321 0 : A(6, 4) = -RHOFF_DD * F68;
3322 0 : A(7, 4) = -RHOFF_DD * F69;
3323 0 : A(8, 4) = Z6_BD;
3324 0 : A(1, 5) = 0.0;
3325 0 : A(2, 5) = 0.0;
3326 0 : A(3, 5) = 0.0;
3327 0 : A(4, 5) = -RHOFF_DD * F76;
3328 0 : A(5, 5) = 1.0;
3329 0 : A(6, 5) = 0.0;
3330 0 : A(7, 5) = -RHOFF_DD * F79;
3331 0 : A(8, 5) = Z7_BD;
3332 0 : A(1, 6) = 0.0;
3333 0 : A(2, 6) = 0.0;
3334 0 : A(3, 6) = 0.0;
3335 0 : A(4, 6) = -RHOFF_DD * F86;
3336 0 : A(5, 6) = 0.0;
3337 0 : A(6, 6) = 1.0;
3338 0 : A(7, 6) = -RHOFF_DD * F89;
3339 0 : A(8, 6) = 0.0;
3340 0 : A(1, 7) = -TAUBF_DD * F21;
3341 0 : A(2, 7) = 0.0;
3342 0 : A(3, 7) = -TAUBF_DD * F24;
3343 0 : A(4, 7) = -RHOFF_DD * F96;
3344 0 : A(5, 7) = -RHOFF_DD * F97;
3345 0 : A(6, 7) = -RHOFF_DD * F98;
3346 0 : A(7, 7) = 1.0;
3347 0 : A(8, 7) = Z9_BD;
3348 :
3349 0 : SOLMATS(N, A, XSOL);
3350 :
3351 0 : J1 = XSOL(1);
3352 0 : J2 = XSOL(2);
3353 0 : J4 = XSOL(3);
3354 0 : J6 = XSOL(4);
3355 0 : J7 = XSOL(5);
3356 0 : J8 = XSOL(6);
3357 0 : J9 = XSOL(7);
3358 :
3359 0 : G1 = F12 * J2 + F14 * J4;
3360 0 : G3 = F31 * J1 + F32 * J2 + F34 * J4;
3361 0 : G5 = F56 * J6 + F57 * J7 + F58 * J8 + F59 * J9;
3362 0 : G7 = F76 * J6 + F79 * J9;
3363 0 : G8 = F86 * J6 + F89 * J9;
3364 :
3365 0 : TAU_BB = (2.0 * (DE - W) * sin_OMEGA_H * TAUFF_BB_PARL + (S * cos_OMEGA_H - (DE - W) * sin_OMEGA_H) * TAUFF_BB_PERP) / (2.0 * S * cos_OMEGA_H);
3366 0 : TAU_BD = (S * G3 + TAUFF_DD * (MK * G8 + MF * G7) + MF * TAUFF_BD_PARL) / (2.0 * S);
3367 0 : RHO_BD = (RHOFF_BT_PARL + TAUBF_DD * G1 + G5) / 2.0;
3368 0 : }
3369 :
3370 0 : void PD_BEAM_CASE_VI(Real64 const S, // pleat spacing (> 0)
3371 : Real64 const W, // pleat depth (>=0, same units as S)
3372 : [[maybe_unused]] Real64 const OMEGA_H, // horizontal profile angle, radians
3373 : [[maybe_unused]] Real64 const DE, // width of illumination on pleat bottom (same units as S)
3374 : Real64 const RHOFF_BT_PARL,
3375 : Real64 const TAUFF_BB_PARL,
3376 : Real64 const TAUFF_BD_PARL,
3377 : [[maybe_unused]] Real64 const RHOBF_BT_PARL,
3378 : [[maybe_unused]] Real64 const TAUBF_BB_PARL,
3379 : [[maybe_unused]] Real64 const TAUBF_BD_PARL,
3380 : [[maybe_unused]] Real64 const RHOFF_BT_PERP,
3381 : [[maybe_unused]] Real64 const TAUFF_BB_PERP,
3382 : [[maybe_unused]] Real64 const TAUFF_BD_PERP,
3383 : [[maybe_unused]] Real64 const RHOBF_BT_PERP,
3384 : [[maybe_unused]] Real64 const TAUBF_BB_PERP,
3385 : [[maybe_unused]] Real64 const TAUBF_BD_PERP,
3386 : Real64 const RHOBF_DD, // fabric back diffuse-diffuse reflectance
3387 : Real64 const RHOFF_DD, // fabric front diffuse-diffuse reflectance
3388 : Real64 const TAUFF_DD, // fabric front diffuse-diffuse transmittance
3389 : Real64 const TAUBF_DD, // fabric back diffuse-diffuse transmittance
3390 : Real64 &RHO_BD, // returned: drape front beam-diffuse reflectance
3391 : Real64 &TAU_BD, // returned: drape front beam-diffuse transmittance
3392 : Real64 &TAU_BB // returned: drape front beam-beam transmittance
3393 : )
3394 : {
3395 :
3396 : // SUBROUTINE INFORMATION:
3397 : // AUTHOR John L. Wright, University of Waterloo,
3398 : // Mechanical Engineering, Advanced Glazing System Laboratory
3399 :
3400 : // PURPOSE OF THIS SUBROUTINE:
3401 : // calculates the effective front-side solar optical properties of a drapery layer.
3402 : // METHODOLOGY EMPLOYED:
3403 : // EIGHT SURFACE FLAT-FABRIC MODEL WITH RECTANGULAR ENCLOSURE
3404 :
3405 : // fabric properties at current (off-normal) incidence
3406 : // _PARL = surface parallel to window (pleat top/bot)
3407 : // _PERP = surface perpendicular to window (pleat side)
3408 : // SUBROUTINE PARAMETER DEFINITIONS:
3409 0 : int constexpr N(6);
3410 :
3411 : Real64 AK; // length of diagonal strings
3412 : Real64 CG;
3413 : Real64 Z1_BD; // diffuse source terms
3414 : Real64 Z7_BD;
3415 : // shape factors
3416 : Real64 F12;
3417 : Real64 F14;
3418 : Real64 F21;
3419 : Real64 F24;
3420 : Real64 F31;
3421 : Real64 F32;
3422 : Real64 F34;
3423 : Real64 F41;
3424 : Real64 F42;
3425 : Real64 F56;
3426 : Real64 F57;
3427 : Real64 F58;
3428 : Real64 F67;
3429 : Real64 F68;
3430 : Real64 F76;
3431 : Real64 F78;
3432 : Real64 F86;
3433 : Real64 F87;
3434 : Real64 J1; // radiosity, surface i
3435 : Real64 J2;
3436 : Real64 J4;
3437 : Real64 J6;
3438 : Real64 J7;
3439 : Real64 J8;
3440 : Real64 G1; // irradiance, surface i
3441 : Real64 G3;
3442 : Real64 G5;
3443 : Real64 G7;
3444 0 : Array2D<Real64> A(N + 2, N); // coefficients of the radiosity equations matrix
3445 0 : Array1D<Real64> XSOL(N); // solution vector (obtained after solving the radiosity equations matrix)
3446 :
3447 0 : AK = std::sqrt(W * W + S * S);
3448 0 : CG = AK;
3449 :
3450 0 : Z1_BD = TAUFF_BD_PARL;
3451 0 : Z7_BD = RHOFF_BT_PARL;
3452 :
3453 0 : F12 = (S + W - AK) / (2.0 * S);
3454 0 : F14 = (S + W - CG) / (2.0 * S);
3455 0 : F21 = (S + W - AK) / (2.0 * W);
3456 0 : F24 = (AK + CG - 2.0 * S) / (2.0 * W);
3457 0 : F31 = (AK + CG - 2.0 * W) / (2.0 * S);
3458 0 : F32 = F12;
3459 0 : F34 = F14;
3460 0 : F41 = F21;
3461 0 : F42 = F24;
3462 0 : F56 = F12;
3463 0 : F57 = F31;
3464 0 : F58 = F14;
3465 0 : F67 = F41;
3466 0 : F68 = F24;
3467 0 : F76 = F14;
3468 0 : F78 = F14;
3469 0 : F86 = F42;
3470 0 : F87 = F21;
3471 :
3472 0 : A = 0.0;
3473 0 : XSOL = 0.0;
3474 :
3475 : // POPULATE THE COEFFICIENTS OF THE RADIOSITY MATRIX
3476 :
3477 0 : A(1, 1) = 1.0;
3478 0 : A(2, 1) = -RHOBF_DD * F12;
3479 0 : A(3, 1) = -RHOBF_DD * F14;
3480 0 : A(4, 1) = 0.0;
3481 0 : A(5, 1) = 0.0;
3482 0 : A(6, 1) = 0.0;
3483 0 : A(7, 1) = Z1_BD;
3484 0 : A(1, 2) = -RHOBF_DD * F21;
3485 0 : A(2, 2) = 1.0;
3486 0 : A(3, 2) = -RHOBF_DD * F24;
3487 0 : A(4, 2) = -TAUFF_DD * F86;
3488 0 : A(5, 2) = -TAUFF_DD * F87;
3489 0 : A(6, 2) = 0.0;
3490 0 : A(7, 2) = 0.0;
3491 0 : A(1, 3) = -RHOBF_DD * F41;
3492 0 : A(2, 3) = -RHOBF_DD * F42;
3493 0 : A(3, 3) = 1.0;
3494 0 : A(4, 3) = 0.0;
3495 0 : A(5, 3) = -TAUFF_DD * F67;
3496 0 : A(6, 3) = -TAUFF_DD * F68;
3497 0 : A(7, 3) = 0.0;
3498 0 : A(1, 4) = -TAUBF_DD * F41;
3499 0 : A(2, 4) = -TAUBF_DD * F42;
3500 0 : A(3, 4) = 0.0;
3501 0 : A(4, 4) = 1.0;
3502 0 : A(5, 4) = -RHOFF_DD * F67;
3503 0 : A(6, 4) = -RHOFF_DD * F68;
3504 0 : A(7, 4) = 0.0;
3505 0 : A(1, 5) = 0.0;
3506 0 : A(2, 5) = 0.0;
3507 0 : A(3, 5) = 0.0;
3508 0 : A(4, 5) = -RHOFF_DD * F76;
3509 0 : A(5, 5) = 1.0;
3510 0 : A(6, 5) = -RHOFF_DD * F78;
3511 0 : A(7, 5) = Z7_BD;
3512 0 : A(1, 6) = -TAUBF_DD * F21;
3513 0 : A(2, 6) = 0.0;
3514 0 : A(3, 6) = -TAUBF_DD * F24;
3515 0 : A(4, 6) = -RHOFF_DD * F86;
3516 0 : A(5, 6) = -RHOFF_DD * F87;
3517 0 : A(6, 6) = 1.0;
3518 0 : A(7, 6) = 0.0;
3519 :
3520 0 : SOLMATS(N, A, XSOL);
3521 :
3522 0 : J1 = XSOL(1);
3523 0 : J2 = XSOL(2);
3524 0 : J4 = XSOL(3);
3525 0 : J6 = XSOL(4);
3526 0 : J7 = XSOL(5);
3527 0 : J8 = XSOL(6);
3528 :
3529 0 : G1 = F12 * J2 + F14 * J4;
3530 0 : G3 = F31 * J1 + F32 * J2 + F34 * J4;
3531 0 : G5 = F56 * J6 + F57 * J7 + F58 * J8;
3532 0 : G7 = F76 * J6 + F78 * J8;
3533 :
3534 0 : TAU_BB = TAUFF_BB_PARL;
3535 0 : TAU_BD = (G3 + TAUFF_DD * G7 + TAUFF_BD_PARL) / 2.0;
3536 0 : RHO_BD = (RHOFF_BT_PARL + TAUBF_DD * G1 + G5) / 2.0;
3537 0 : }
3538 :
3539 1304 : void VB_DIFF(EnergyPlusData &state,
3540 : Real64 const S, // slat spacing (any length units; same units as W)
3541 : Real64 const W, // slat tip-to-tip width (any length units; same units as S)
3542 : Real64 const PHI, // slat angle, radians (-PI/2 <= PHI <= PI/2)
3543 : Real64 const RHODFS_SLAT, // reflectance of downward-facing slat surfaces (concave?)
3544 : Real64 const RHOUFS_SLAT, // reflectance of upward-facing slat surfaces (convex?)
3545 : Real64 const TAU_SLAT, // diffuse transmittance of slats
3546 : Real64 &RHOFVB, // returned: front side effective diffuse reflectance of venetian blind
3547 : Real64 &TAUVB // returned: effective diffuse transmittance of venetian blind
3548 : )
3549 : {
3550 : // SUBROUTINE INFORMATION:
3551 : // AUTHOR John L. Wright, University of Waterloo,
3552 : // Mechanical Engineering, Advanced Glazing System Laboratory
3553 :
3554 : // PURPOSE OF THIS SUBROUTINE:
3555 : // Calculates the venetian blind layer effective diffuse transmittance and reflectance.
3556 : // METHODOLOGY EMPLOYED:
3557 : // four surface flat-slat model with slat transmittance
3558 :
3559 : // SUBROUTINE ARGUMENT DEFINITIONS:
3560 : // must be > 0
3561 : // ltyVBHOR: + = front-side slat tip below horizontal
3562 : // ltyVBVER: + = front-side slat tip is counter-
3563 : // clockwise from normal (viewed from above)
3564 : // SUBROUTINE PARAMETER DEFINITIONS:
3565 : static constexpr std::string_view Tau_Name("VB_DIFF Tau");
3566 : static constexpr std::string_view RhoF_Name("VB_DIFF RhoF");
3567 :
3568 : Real64 CD; // lengths of the diagonal strings used in the four-surface model
3569 : Real64 AF;
3570 : Real64 F13; // shape factors
3571 : Real64 F14;
3572 : Real64 F12;
3573 : Real64 F31;
3574 : Real64 F41;
3575 : Real64 FSS;
3576 : Real64 C3; // temporaries
3577 : Real64 B3;
3578 : Real64 C4;
3579 : Real64 B4;
3580 : Real64 K3;
3581 : Real64 K4;
3582 : Real64 DEN;
3583 :
3584 1304 : Real64 const W_cos_PHI_2(pow_2(W * std::cos(PHI)));
3585 1304 : Real64 const W_sin_PHI(W * std::sin(PHI));
3586 1304 : CD = std::sqrt(W_cos_PHI_2 + pow_2(S + W_sin_PHI));
3587 1304 : AF = std::sqrt(W_cos_PHI_2 + pow_2(S - W_sin_PHI));
3588 :
3589 1304 : F13 = (W + S - CD) / (2.0 * S); // SHAPE FACTOR FRONT OPENING TO TOP SLAT
3590 1304 : F14 = (W + S - AF) / (2.0 * S); // SHAPE FACTOR FRONT OPENING TO BOTTOM SLAT
3591 1304 : FSS = 1.0 - (S / W) * (F13 + F14); // SLAT-TO-SLAT SHAPE FACTOR
3592 1304 : F31 = (S / W) * F13; // SHAPE FACTOR - TOP TO FRONT
3593 1304 : F41 = (S / W) * F14; // SHAPE FACTOR - BOTTOM TO FRONT
3594 1304 : F12 = 1.0 - F13 - F14; // FRONT OPENING TO BACK OPENING SHAPE FACTOR
3595 1304 : DEN = 1.0 - (TAU_SLAT * FSS); // DENOMINATOR - USED FOUR TIMES
3596 1304 : C3 = (RHODFS_SLAT * F31 + TAU_SLAT * F41) / DEN;
3597 1304 : B3 = (RHODFS_SLAT * FSS) / DEN;
3598 1304 : C4 = (RHOUFS_SLAT * F41 + TAU_SLAT * F31) / DEN;
3599 1304 : B4 = (RHOUFS_SLAT * FSS) / DEN;
3600 :
3601 1304 : K3 = (C3 + (B3 * C4)) / (1.0 - (B3 * B4));
3602 1304 : K4 = (C4 + (B4 * C3)) / (1.0 - (B3 * B4));
3603 : // transmittance of VB (equal front/back)
3604 1304 : TAUVB = P01(state, F12 + (F14 * K3) + (F13 * K4), Tau_Name);
3605 : // diffuse reflectance of VB front-side
3606 1304 : RHOFVB = P01(state, (F13 * K3) + (F14 * K4), RhoF_Name);
3607 1304 : }
3608 :
3609 1146 : Real64 VB_SLAT_RADIUS_RATIO(Real64 const W, // slat tip-to-tip (chord) width (any units; same units as C) must be > 0
3610 : Real64 const C // slat crown height (any units, same units as W) must be >= 0
3611 : )
3612 : {
3613 : // AUTHOR ASHRAE 1311-RP
3614 :
3615 : // PURPOSE OF THIS FUNCTION:
3616 : // Returns curved slat radius ratio (W / R)
3617 :
3618 1146 : if (C <= 0.0 || W <= 0.0) {
3619 : // it is flat
3620 1146 : return 0.0;
3621 : } else {
3622 0 : Real64 CX = min(C, W / 2.001);
3623 0 : return 2.0 * W * CX / (CX * CX + W * W / 4);
3624 : }
3625 : }
3626 :
3627 1640 : void VB_SOL46_CURVE(EnergyPlusData const &state,
3628 : Real64 const S, // slat spacing (any length units; same units as W)
3629 : Real64 const W, // slat tip-to-tip (chord) width (any length units; same units as S)
3630 : Real64 const SL_WR, // slat curvature radius ratio (= W/R)
3631 : Real64 const PHIx, // slat angle, radians (-PI/2 <= PHI <= PI/2)
3632 : Real64 const OMEGAx, // incident beam profile angle (radians)
3633 : Real64 const RHODFS_SLAT, // SW (solar) reflectance downward-facing slat surfaces (concave?)
3634 : Real64 const RHOUFS_SLAT, // SW (solar) reflectance upward-facing slat surfaces (convex?)
3635 : Real64 const TAU_SLAT, // SW (solar) transmittance of slats
3636 : Real64 &RHO_BD, // returned: effective SW (solar) beam-to-diffuse reflectance front side
3637 : Real64 &TAU_BB, // returned: effective SW (solar) beam-to-beam transmittance front side
3638 : Real64 &TAU_BD // returned: effective SW (solar) beam-to-diffuse transmittance front side
3639 : )
3640 : {
3641 : // SUBROUTINE INFORMATION:
3642 : // AUTHOR John L. Wright, University of Waterloo,
3643 : // Mechanical Engineering, Advanced Glazing System Laboratory
3644 :
3645 : // PURPOSE OF THIS SUBROUTINE:
3646 : // Calculates the venetian blind layer effective solar transmittance and reflectance.
3647 : // METHODOLOGY EMPLOYED:
3648 : // Four and six surface curve-slat model with slat transmittance. For back side
3649 : // reflectance call this routine a second time with the same input data - except
3650 : // negative the slat angle, PHI_DEG.
3651 :
3652 : // SUBROUTINE ARGUMENT DEFINITIONS:
3653 : // must be > 0
3654 : // must be > 0
3655 : // 0 = flat
3656 : // ltyVBHOR: + = front-side slat tip below horizontal
3657 : // ltyVBVER: + = front-side slat tip is counter-
3658 : // clockwise from normal (viewed from above)
3659 : // ltyVBHOR: +=above horizontal
3660 : // ltyVBVER: +=clockwise when viewed from above
3661 : // Note: All solar slat properties are incident-to-diffuse
3662 : // Specular effects not covered by model
3663 :
3664 : Real64 DE; // distance from front tip of any slat to shadow (caused by the adjacent slat) on
3665 : // the plane of the same slat; DE may be greater than the slat width, W
3666 : Real64 PHI;
3667 : Real64 OMEGA;
3668 : Real64 SL_RAD;
3669 : Real64 SL_THETA;
3670 : Real64 Slope;
3671 : Real64 T_CORR_D;
3672 : Real64 T_CORR_F;
3673 : Real64 RHO_TEMP;
3674 : Real64 TAU_TEMP;
3675 : Real64 XA;
3676 : Real64 XB;
3677 : Real64 XC;
3678 : Real64 XD;
3679 : Real64 XE;
3680 1640 : Real64 XF(0);
3681 : Real64 YA;
3682 : Real64 YB;
3683 : Real64 YC;
3684 : Real64 YD;
3685 : Real64 YE;
3686 1640 : Real64 YF(0);
3687 : int CORR;
3688 :
3689 1640 : DE = 0.0; // INITIALIZE DE
3690 1640 : CORR = 1;
3691 :
3692 : // limit slat angle to +/- 90 deg
3693 1640 : PHI = max(-Constant::DegToRad * 90.0, min(Constant::DegToRad * 90.0, PHIx));
3694 : // limit profile angle to +/- 89.5 deg
3695 1640 : OMEGA = max(-Constant::DegToRad * 89.5, min(Constant::DegToRad * 89.5, OMEGAx));
3696 :
3697 1640 : SL_RAD = W / max(SL_WR, 0.0000001);
3698 1640 : SL_THETA = 2.0 * std::asin(0.5 * SL_WR);
3699 :
3700 1640 : if (CORR > 0) { // CORRECT FOR SLAT CURVATURE BY SETTING CORR = 1
3701 :
3702 : // DETERMINE BOUNDS FOR CURVATURE CORRECTION AND APPLY CORRECTION TO BEAM-BEAM TRANSMITTANCE
3703 1640 : if (std::abs(PHI + OMEGA) < SL_THETA / 2.0) {
3704 : // CALCULATE BEAM TRANSMISSION
3705 0 : XA = SL_RAD * std::sin(-SL_THETA / 2.0); // Glass-side end coordinate
3706 0 : YA = SL_RAD * std::cos(-SL_THETA / 2.0);
3707 0 : XB = -XA; // Indoor-side end coordinate
3708 0 : YB = YA;
3709 0 : YC = SL_RAD * std::cos(PHI + OMEGA); // Tangent to slat in irradiance direction
3710 0 : XC = std::sqrt(pow_2(SL_RAD) - pow_2(YC));
3711 0 : Slope = -XC / YC;
3712 0 : if (std::abs(Slope) < state.dataWindowEquivalentLayer->SMALL_ERROR) {
3713 0 : XD = 0.0;
3714 0 : YD = YA;
3715 0 : XE = 0.0;
3716 0 : YE = YD;
3717 : // Bug XF, YF not set but used below (XE, YE are set but NOT used)
3718 : } else {
3719 0 : if ((PHI + OMEGA) < 0.0) {
3720 0 : XC = -XC;
3721 0 : Slope = -Slope;
3722 0 : XD = (YB - Slope * XB) / (-1.0 / Slope - Slope);
3723 0 : XF = (YA - Slope * XA) / (-1.0 / Slope - Slope);
3724 0 : XE = XA + 2.0 * std::abs(XA - XF);
3725 : } else {
3726 0 : XD = (YA - Slope * XA) / (-1.0 / Slope - Slope);
3727 0 : XF = (YB - Slope * XB) / (-1.0 / Slope - Slope);
3728 0 : XE = XB - 2.0 * std::abs(XB - XF);
3729 : }
3730 0 : YD = -XD / Slope;
3731 0 : YE = -XE / Slope;
3732 0 : YF = -XF / Slope;
3733 : }
3734 :
3735 0 : T_CORR_D = std::sqrt(pow_2(XC - XD) + pow_2(YC - YD)); // Slat thickness perpendicular to light direction
3736 0 : T_CORR_F = std::sqrt(pow_2(XC - XF) + pow_2(YC - YF));
3737 :
3738 0 : TAU_BB = 1.0 - T_CORR_D / (S * std::cos(OMEGA));
3739 :
3740 : } else {
3741 : // DO NOT APPLY CURVATURE CORRECTION TO BEAM-BEAM TRANSMITTANCE
3742 1640 : if (std::abs(OMEGA + PHI) < 0.0001) {
3743 161 : DE = S * 1000000.0;
3744 : } else {
3745 1479 : DE = S * std::abs(std::cos(OMEGA) / std::sin(OMEGA + PHI));
3746 : }
3747 : // CHECK TO SEE IF THERE IS DIRECT BEAM TRANSMISSION
3748 1640 : if ((DE / W) > (1.0 - state.dataWindowEquivalentLayer->SMALL_ERROR)) { // YES
3749 926 : TAU_BB = max(0.0, (DE - W) / DE);
3750 : } else { // NO
3751 714 : TAU_BB = 0.0;
3752 : }
3753 : }
3754 :
3755 : // CHECK TO SEE IF CURVATURE CORRECTION INCLUDES DOUBLE BLOCKAGE
3756 : // (TAU_BB < 0.0 AND SET TAU_BB = 0.0)
3757 1640 : if (TAU_BB < 0.0) { // YES, THERE IS DOUBLE BLOCKAGE
3758 :
3759 0 : TAU_BB = 0.0;
3760 :
3761 : // DO NOT APPLY CURVATURE CORRECTION TO RHO_BD, TAU_BD IF TAU_BB < 0.0
3762 0 : if (std::abs(OMEGA + PHI) < 0.0001) {
3763 0 : DE = S * 1000000.0;
3764 : } else {
3765 0 : DE = S * std::abs(std::cos(OMEGA) / std::sin(OMEGA + PHI));
3766 : }
3767 0 : if ((DE / W) > (1.0 - state.dataWindowEquivalentLayer->SMALL_ERROR)) { // YES
3768 0 : VB_SOL4(state, S, W, OMEGA, DE, PHI, RHODFS_SLAT, RHOUFS_SLAT, TAU_SLAT, RHO_BD, TAU_BD);
3769 :
3770 : } else { // NO
3771 0 : VB_SOL6(state, S, W, OMEGA, DE, PHI, RHODFS_SLAT, RHOUFS_SLAT, TAU_SLAT, RHO_BD, TAU_BD);
3772 : }
3773 :
3774 : } else { // NO, THERE IS NO DOUBLE BLOCKAGE
3775 :
3776 1640 : if (std::abs(PHI + OMEGA) < (SL_THETA / 2.0)) { // YES, APPLY CURVATURE CORRECTION
3777 :
3778 0 : XA = SL_RAD * std::sin(-SL_THETA / 2.0); // Glass-side end coordinate
3779 0 : YA = SL_RAD * std::cos(-SL_THETA / 2.0);
3780 0 : XB = -XA; // Indoor-side end coordinate
3781 0 : YB = YA;
3782 0 : YC = SL_RAD * std::cos(PHI + OMEGA); // Tangent to slat in irradiance direction
3783 0 : XC = std::sqrt(pow_2(SL_RAD) - pow_2(YC));
3784 0 : Slope = -XC / YC;
3785 0 : if (std::abs(Slope) < state.dataWindowEquivalentLayer->SMALL_ERROR) {
3786 0 : XD = 0.0;
3787 0 : YD = YA;
3788 0 : XE = 0.0;
3789 0 : YE = YD;
3790 : // Bug XF, YF not set but used below (XE, YE are set but NOT used)
3791 : } else {
3792 0 : if ((PHI + OMEGA) < 0.0) {
3793 0 : XC = -XC;
3794 0 : Slope = -Slope;
3795 0 : XD = (YB - Slope * XB) / (-1.0 / Slope - Slope);
3796 0 : XF = (YA - Slope * XA) / (-1.0 / Slope - Slope);
3797 0 : XE = XA + 2.0 * std::abs(XA - XF);
3798 : } else {
3799 0 : XD = (YA - Slope * XA) / (-1.0 / Slope - Slope);
3800 0 : XF = (YB - Slope * XB) / (-1.0 / Slope - Slope);
3801 0 : XE = XB - 2.0 * std::abs(XB - XF);
3802 : }
3803 0 : YD = -XD / Slope;
3804 0 : YE = -XE / Slope;
3805 0 : YF = -XF / Slope;
3806 : }
3807 0 : T_CORR_D = std::sqrt(pow_2(XC - XD) + pow_2(YC - YD)); // Slat thickness perpendicular to light direction
3808 0 : T_CORR_F = std::sqrt(pow_2(XC - XF) + pow_2(YC - YF));
3809 :
3810 0 : if ((PHI + OMEGA) >= 0.0) { // Slat is lit from above
3811 0 : DE = XC - XA;
3812 0 : VB_SOL6(state, S, W, OMEGA, DE, PHI, RHODFS_SLAT, RHOUFS_SLAT, TAU_SLAT, RHO_BD, TAU_BD);
3813 0 : Real64 const S_cos_OMEGA_inv(1.0 / (S * std::cos(OMEGA)));
3814 0 : RHO_BD *= T_CORR_D * S_cos_OMEGA_inv;
3815 0 : TAU_BD *= T_CORR_D * S_cos_OMEGA_inv;
3816 : } else { // Slat is lit from below
3817 0 : DE = XC - XA;
3818 0 : VB_SOL6(state, S, W, OMEGA, DE, PHI, RHODFS_SLAT, RHOUFS_SLAT, TAU_SLAT, RHO_BD, TAU_BD);
3819 0 : Real64 const S_cos_OMEGA_inv(1.0 / (S * std::cos(OMEGA)));
3820 0 : RHO_TEMP = RHO_BD * T_CORR_F * S_cos_OMEGA_inv;
3821 0 : TAU_TEMP = TAU_BD * T_CORR_F * S_cos_OMEGA_inv;
3822 0 : DE = std::abs(XB - XF);
3823 0 : VB_SOL6(state, S, W, OMEGA, DE, PHI, RHODFS_SLAT, RHOUFS_SLAT, TAU_SLAT, RHO_BD, TAU_BD);
3824 0 : RHO_BD = RHO_BD * (T_CORR_D - T_CORR_F) * S_cos_OMEGA_inv + RHO_TEMP;
3825 0 : TAU_BD = TAU_BD * (T_CORR_D - T_CORR_F) * S_cos_OMEGA_inv + TAU_TEMP;
3826 : }
3827 :
3828 : } else { // NO, DO NOT APPLY CURVATURE CORRECTION
3829 1640 : if (std::abs(OMEGA + PHI) < 0.0001) {
3830 161 : DE = S * 1000000.0;
3831 : } else {
3832 1479 : DE = S * std::abs(std::cos(OMEGA) / std::sin(OMEGA + PHI));
3833 : }
3834 1640 : if (DE / W > 1.0 - state.dataWindowEquivalentLayer->SMALL_ERROR) { // YES
3835 926 : VB_SOL4(state, S, W, OMEGA, DE, PHI, RHODFS_SLAT, RHOUFS_SLAT, TAU_SLAT, RHO_BD, TAU_BD);
3836 :
3837 : } else { // NO
3838 714 : VB_SOL6(state, S, W, OMEGA, DE, PHI, RHODFS_SLAT, RHOUFS_SLAT, TAU_SLAT, RHO_BD, TAU_BD);
3839 : }
3840 : }
3841 : }
3842 :
3843 : } else { // DO NOT CORRECT FOR SLAT CURVATURE
3844 :
3845 : // CHECK TO SEE IF BEAM IS ALLIGNED WITH SLATS
3846 0 : if (std::abs(PHI + OMEGA) < state.dataWindowEquivalentLayer->SMALL_ERROR) { // YES!
3847 0 : RHO_BD = 0.0;
3848 0 : TAU_BB = 1.0;
3849 0 : TAU_BD = 0.0;
3850 :
3851 : } else { // BEAM NOT ALIGNED WITH SLATS
3852 0 : RHO_BD = 0.0;
3853 0 : TAU_BB = 0.0;
3854 0 : TAU_BD = 0.0;
3855 0 : DE = S * std::abs(std::cos(OMEGA) / std::sin(OMEGA + PHI));
3856 : // CHECK TO SEE IF THERE IS DIRECT BEAM TRANSMISSION
3857 0 : if ((DE / W) > (1.0 - state.dataWindowEquivalentLayer->SMALL_ERROR)) { // YES
3858 0 : TAU_BB = (DE - W) / DE;
3859 0 : if (TAU_BB < 0.0) {
3860 0 : TAU_BB = 0.0;
3861 : }
3862 0 : VB_SOL4(state, S, W, OMEGA, DE, PHI, RHODFS_SLAT, RHOUFS_SLAT, TAU_SLAT, RHO_BD, TAU_BD);
3863 : } else { // NO
3864 0 : TAU_BB = 0.0;
3865 0 : VB_SOL6(state, S, W, OMEGA, DE, PHI, RHODFS_SLAT, RHOUFS_SLAT, TAU_SLAT, RHO_BD, TAU_BD);
3866 : } // END CHECK FOR DIRECT BEAM TRANSMISSION
3867 : } // END CHECK TO SEE IF BEAM ALLIGNED WITH SLATS
3868 : }
3869 1640 : }
3870 :
3871 926 : void VB_SOL4(EnergyPlusData const &state,
3872 : Real64 const S, // slat spacing (any length units; same units as W)
3873 : Real64 const W, // slat tip-to-tip width (any length units; same units as S)
3874 : Real64 const OMEGA, // incident beam profile angle (radians)
3875 : Real64 const DE, // distance from front tip of any slat to shadow (caused by the adjacent slat) on
3876 : Real64 const PHI, // slat angle, radians (-PI/2 <= PHI <= PI/2)
3877 : Real64 const RHODFS_SLAT, // solar reflectance downward-facing slat surfaces (concave?)
3878 : Real64 const RHOUFS_SLAT, // solar reflectance upward-facing slat surfaces (convex?)
3879 : Real64 const TAU_SLAT, // solar transmittance of slat
3880 : Real64 &RHO_BD, // returned: solar beam-to-diffuse reflectance the venetian blind (front side)
3881 : Real64 &TAU_BD // returned: solar beam-to-diffuse transmittance of the venetian blind (front side)
3882 : )
3883 : {
3884 : // SUBROUTINE INFORMATION:
3885 : // AUTHOR John L. Wright, University of Waterloo,
3886 : // Mechanical Engineering, Advanced Glazing System Laboratory
3887 :
3888 : // PURPOSE OF THIS SUBROUTINE:
3889 : // Calculates the venetian blind layer effective solar transmittance and reflectance.
3890 : // METHODOLOGY EMPLOYED:
3891 : // Four surface Flat-Plate Model with slat transmittance
3892 :
3893 : // SUBROUTINE ARGUMENT DEFINITIONS:
3894 : // must be > 0
3895 : // must be > 0
3896 : // ltyVBHOR: +=above horizontal
3897 : // ltyVBVER: +=clockwise when viewed from above
3898 : // the plane of the same slat de may be greater than the slat width, w
3899 : // ltyVBHOR: + = front-side slat tip below horizontal
3900 : // ltyVBVER: + = front-side slat tip is counter-
3901 : // clockwise from normal (viewed from above)
3902 : // Note: all solar slat properties - incident-to-diffuse
3903 :
3904 : Real64 AF; // lengths of diagonal strings used in the four-surface model
3905 : Real64 CD;
3906 : Real64 F13; // Shape factors
3907 : Real64 F14;
3908 : Real64 F23;
3909 : Real64 F24;
3910 : Real64 F34;
3911 : Real64 F43;
3912 : Real64 Z3; // diffuse source terms from surfaces 3 and 4 due to incident beam radiation
3913 : Real64 Z4;
3914 : Real64 J3; // radiosity, surface i
3915 : Real64 J4;
3916 : Real64 B3; // temporaries
3917 : Real64 B4;
3918 : Real64 C3;
3919 : Real64 C4;
3920 :
3921 926 : Real64 const W_cos_PHI_2(pow_2(W * std::cos(PHI)));
3922 926 : Real64 const W_sin_PHI(W * std::sin(PHI));
3923 926 : AF = std::sqrt(W_cos_PHI_2 + pow_2(S - W_sin_PHI));
3924 926 : CD = std::sqrt(W_cos_PHI_2 + pow_2(S + W_sin_PHI));
3925 : // CHECK TO SEE WHICH SIDE OF SLAT IS SUNLIT
3926 926 : if (PHI + OMEGA >= 0.0) { // SUN SHINES ON TOP OF SLAT
3927 :
3928 534 : Z3 = TAU_SLAT * S / DE;
3929 534 : Z4 = RHOUFS_SLAT * S / DE;
3930 : // PRINT *, PHI, OMEGA, DE, 'TOPLIT'
3931 :
3932 : } else { // SUN SHINES ON BOTTOM OF SLAT
3933 392 : Z3 = RHODFS_SLAT * S / DE;
3934 392 : Z4 = TAU_SLAT * S / DE;
3935 : // PRINT *, PHI, OMEGA, DE, 'BOTLIT'
3936 : }
3937 : // CHECK TO SEE IF VENETIAN BLIND IS CLOSED
3938 926 : if (std::abs(PHI - Constant::PiOvr2) < state.dataWindowEquivalentLayer->SMALL_ERROR) { // VENETIAN BLIND IS CLOSED
3939 :
3940 : // CHECK TO SEE IF THERE ARE GAPS IN BETWEEN SLATS WHEN THE BLIND IS CLOSED
3941 0 : if (W < S) { // YES, THERE ARE GAPS IN BETWEEN SLATS
3942 0 : RHO_BD = (W / S) * RHOUFS_SLAT;
3943 0 : TAU_BD = (W / S) * TAU_SLAT;
3944 : } else { // NO, THERE ARE NO GAPS IN BETWEEN SLATS
3945 0 : RHO_BD = RHOUFS_SLAT;
3946 0 : TAU_BD = TAU_SLAT;
3947 : } // END OF CHECK FOR GAPS IN BETWEEN SLATS
3948 :
3949 : } else { // VENETIAN BLIND IS OPENED
3950 :
3951 926 : F13 = (S + W - CD) / (2.0 * S);
3952 926 : F14 = (S + W - AF) / (2.0 * S);
3953 926 : F23 = (S + W - AF) / (2.0 * S);
3954 926 : F24 = (S + W - CD) / (2.0 * S);
3955 926 : F34 = (CD + AF - 2.0 * S) / (2.0 * W);
3956 926 : F43 = (CD + AF - 2.0 * S) / (2.0 * W);
3957 :
3958 926 : C3 = 1.0 / (1.0 - TAU_SLAT * F43);
3959 926 : B3 = (RHODFS_SLAT * F34) / (1.0 - TAU_SLAT * F43);
3960 926 : C4 = 1.0 / (1.0 - TAU_SLAT * F34);
3961 926 : B4 = (RHOUFS_SLAT * F43) / (1.0 - TAU_SLAT * F34);
3962 926 : J3 = (C3 * Z3 + B3 * C4 * Z4) / (1.0 - B3 * B4);
3963 926 : J4 = (C4 * Z4 + B4 * C3 * Z3) / (1.0 - B3 * B4);
3964 :
3965 926 : RHO_BD = F13 * J3 + F14 * J4;
3966 926 : TAU_BD = F23 * J3 + F24 * J4;
3967 :
3968 : } // END OF CHECK FOR CLOSED BLIND
3969 926 : }
3970 :
3971 714 : void VB_SOL6(EnergyPlusData const &state,
3972 : Real64 const S, // slat spacing (any length units; same units as W)
3973 : Real64 const W, // slat tip-to-tip width (any length units; same units as S)
3974 : Real64 const OMEGA, // incident beam profile angle (radians)
3975 : Real64 const DE, // distance from front tip of any slat to shadow (caused by the adjacent slat) on
3976 : Real64 const PHI, // slat angle, radians (-PI/2 <= PHI <= PI/2)
3977 : Real64 const RHODFS_SLAT, // solar reflectance downward-facing slat surfaces (concave)
3978 : Real64 const RHOUFS_SLAT, // solar reflectance upward-facing slat surfaces (convex)
3979 : Real64 const TAU_SLAT, // solar transmittance of slat
3980 : Real64 &RHO_BD, // returned: solar beam-to-diffuse reflectance the venetian blind (front side)
3981 : Real64 &TAU_BD // returned: solar beam-to-diffuse transmittance of the venetian blind (front side)
3982 : )
3983 : {
3984 : // SUBROUTINE INFORMATION:
3985 : // AUTHOR John L. Wright, University of Waterloo,
3986 : // Mechanical Engineering, Advanced Glazing System Laboratory
3987 :
3988 : // PURPOSE OF THIS SUBROUTINE:
3989 : // Calculates the venetian blind layer effective solar transmittance and reflectance.
3990 : // METHODOLOGY EMPLOYED:
3991 : // six surface flat-slat model with slat transmittance. If you want the back
3992 : // side reflectance call the routine a second time with the same input data
3993 : // except negative the slat angle, PHI_DEG
3994 :
3995 : // SUBROUTINE ARGUMENT DEFINITIONS:
3996 : // must be > 0
3997 : // must be > 0
3998 : // ltyVBHOR: +=above horizontal
3999 : // ltyVBVER: +=clockwise when viewed from above
4000 : // the plane of the same slat DE may be greater than the slat width, w
4001 : // ltyVBHOR: + = front-side slat tip below horizontal
4002 : // ltyVBVER: + = front-side slat tip is counter-
4003 : // clockwise from normal (viewed from above)
4004 : // Note: all solar slat properties - incident-to-diffuse
4005 714 : int constexpr N(4);
4006 :
4007 : Real64 AB; // lengths of slat segments and diagonal strings
4008 : Real64 AE;
4009 : Real64 AF;
4010 : Real64 BC;
4011 : Real64 BD;
4012 : Real64 BF;
4013 : Real64 CD;
4014 : Real64 CE;
4015 : Real64 EF;
4016 : // used in the six-surface model
4017 : Real64 F13; // shape factors
4018 : Real64 F14;
4019 : Real64 F23;
4020 : Real64 F24;
4021 : Real64 F34;
4022 : Real64 F36;
4023 : Real64 F15;
4024 : Real64 F16;
4025 : Real64 F43;
4026 : Real64 F45;
4027 : Real64 F54;
4028 : Real64 F56;
4029 : Real64 F63;
4030 : Real64 F65;
4031 : Real64 F25;
4032 : Real64 F26;
4033 : Real64 Z3; // diffuse source terms from surfaces 3 and 4 due to incident beam radiation
4034 : Real64 Z4;
4035 : Real64 J3; // radiosity, surface i
4036 : Real64 J4;
4037 : Real64 J5;
4038 : Real64 J6;
4039 714 : Array2D<Real64> A(N + 2, N); // coefficients of the radiosity equations matrix
4040 714 : Array1D<Real64> XSOL(N); // solution vector (obtained after solving the radiosity equations matrix)
4041 :
4042 : // CHECK TO SEE WHICH SIDE OF SLAT IS SUNLIT
4043 714 : if ((PHI + OMEGA) >= 0.0) { // SUN SHINES ON TOP OF SLAT
4044 714 : Z3 = TAU_SLAT * S / DE;
4045 714 : Z4 = RHOUFS_SLAT * S / DE;
4046 : // PRINT *, PHI, OMEGA, DE, 'TOPLIT'
4047 :
4048 : } else { // SUN SHINES ON BOTTOM OF SLAT
4049 0 : Z3 = RHODFS_SLAT * S / DE;
4050 0 : Z4 = TAU_SLAT * S / DE;
4051 : // PRINT *, PHI, OMEGA, DE, 'BOTLIT'
4052 : }
4053 :
4054 : // CHECK TO SEE IF VENETIAN BLIND IS CLOSED
4055 714 : if (std::abs(PHI - Constant::PiOvr2) < state.dataWindowEquivalentLayer->SMALL_ERROR) { // VENETIAN BLIND IS CLOSED
4056 :
4057 : // CHECK TO SEE IF THERE ARE GAPS IN BETWEEN SLATS WHEN THE BLIND IS CLOSED
4058 0 : if (W < S) { // YES, THERE ARE GAPS IN BETWEEN SLATS
4059 0 : RHO_BD = (W / S) * RHOUFS_SLAT;
4060 0 : TAU_BD = (W / S) * TAU_SLAT;
4061 : } else { // NO, THERE ARE NO GAPS IN BETWEEN SLATS
4062 0 : RHO_BD = RHOUFS_SLAT;
4063 0 : TAU_BD = TAU_SLAT;
4064 : } // END OF CHECK FOR GAPS IN BETWEEN SLATS
4065 :
4066 : } else { // VENETIAN BLIND IS OPENED
4067 714 : AB = DE;
4068 714 : Real64 const cos_PHI(std::cos(PHI));
4069 714 : Real64 const sin_PHI(std::sin(PHI));
4070 714 : Real64 const W_cos_PHI_2(pow_2(W * cos_PHI));
4071 714 : AF = std::sqrt(W_cos_PHI_2 + pow_2(S - W * sin_PHI));
4072 714 : BC = W - AB;
4073 714 : EF = BC;
4074 714 : Real64 const DE_cos_PHI_2(pow_2(DE * cos_PHI));
4075 714 : Real64 const EF_cos_PHI_2(pow_2(EF * cos_PHI));
4076 714 : BD = std::sqrt(DE_cos_PHI_2 + pow_2(S + DE * sin_PHI));
4077 714 : BF = std::sqrt(EF_cos_PHI_2 + pow_2(S - EF * sin_PHI));
4078 714 : CD = std::sqrt(W_cos_PHI_2 + pow_2(S + W * sin_PHI));
4079 714 : CE = std::sqrt(EF_cos_PHI_2 + pow_2(S + EF * sin_PHI));
4080 714 : AE = std::sqrt(DE_cos_PHI_2 + pow_2(S - DE * sin_PHI));
4081 :
4082 714 : F13 = (S + AB - BD) / (2.0 * S);
4083 714 : F14 = (S + DE - AE) / (2.0 * S);
4084 714 : F15 = (W + BD - (AB + CD)) / (2.0 * S);
4085 714 : F16 = (W + AE - (AF + DE)) / (2.0 * S);
4086 714 : F23 = (W + BF - (BC + AF)) / (2.0 * S);
4087 714 : F24 = (W + CE - (CD + EF)) / (2.0 * S);
4088 714 : F25 = (S + BC - BF) / (2.0 * S);
4089 714 : F26 = (S + EF - CE) / (2.0 * S);
4090 714 : F34 = (AE + BD - 2.0 * S) / (2.0 * AB);
4091 714 : F36 = (AF + S - (AE + BF)) / (2.0 * AB);
4092 714 : F43 = (AE + BD - 2.0 * S) / (2.0 * DE);
4093 714 : F45 = (CD + S - (BD + CE)) / (2.0 * DE);
4094 714 : F54 = (CD + S - (BD + CE)) / (2.0 * BC);
4095 714 : F56 = (CE + BF - 2.0 * S) / (2.0 * BC);
4096 714 : F63 = (AF + S - (AE + BF)) / (2.0 * EF);
4097 714 : F65 = (BF + CE - 2.0 * S) / (2.0 * EF);
4098 :
4099 : // POPULATE THE COEFFICIENTS OF THE RADIOSITY MATRIX
4100 :
4101 714 : A(1, 1) = 1.0 - TAU_SLAT * F43;
4102 714 : A(2, 1) = -RHODFS_SLAT * F34;
4103 714 : A(3, 1) = -TAU_SLAT * F45;
4104 714 : A(4, 1) = -RHODFS_SLAT * F36;
4105 714 : A(5, 1) = Z3;
4106 714 : A(1, 2) = -RHOUFS_SLAT * F43;
4107 714 : A(2, 2) = 1.0 - TAU_SLAT * F34;
4108 714 : A(3, 2) = -RHOUFS_SLAT * F45;
4109 714 : A(4, 2) = -TAU_SLAT * F36;
4110 714 : A(5, 2) = Z4;
4111 714 : A(1, 3) = -TAU_SLAT * F63;
4112 714 : A(2, 3) = -RHODFS_SLAT * F54;
4113 714 : A(3, 3) = 1.0 - TAU_SLAT * F65;
4114 714 : A(4, 3) = -RHODFS_SLAT * F56;
4115 714 : A(5, 3) = 0.0;
4116 714 : A(1, 4) = -RHOUFS_SLAT * F63;
4117 714 : A(2, 4) = -TAU_SLAT * F54;
4118 714 : A(3, 4) = -RHOUFS_SLAT * F65;
4119 714 : A(4, 4) = 1.0 - TAU_SLAT * F56;
4120 714 : A(5, 4) = 0.0;
4121 :
4122 714 : SOLMATS(N, A, XSOL);
4123 :
4124 714 : J3 = XSOL(1);
4125 714 : J4 = XSOL(2);
4126 714 : J5 = XSOL(3);
4127 714 : J6 = XSOL(4);
4128 :
4129 714 : RHO_BD = F13 * J3 + F14 * J4 + F15 * J5 + F16 * J6;
4130 714 : TAU_BD = F23 * J3 + F24 * J4 + F25 * J5 + F26 * J6;
4131 : } // END OF CHECK FOR CLOSED BLIND
4132 714 : }
4133 :
4134 26490 : void SOLMATS(int const N, // # of active rows in A
4135 : Array2S<Real64> A, // matrix, minimum required dimensions: A( N, N+2)
4136 : Array1D<Real64> &XSOL // returned: solution vector, min req dimension: XSOL( N)
4137 : )
4138 : {
4139 : // SUBROUTINE INFORMATION:
4140 : // AUTHOR John L. Wright, University of Waterloo,
4141 : // Mechanical Engineering, Advanced Glazing System Laboratory
4142 :
4143 : // PURPOSE OF THIS SUBROUTINE:
4144 : // Matrix solver.
4145 : // METHODOLOGY EMPLOYED:
4146 : // Solves matrix by the elimination method supplemented by a search for the
4147 : // largest pivotal element at each stage
4148 :
4149 26490 : int NM1 = N - 1;
4150 26490 : int NP1 = N + 1;
4151 26490 : int NP2 = N + 2;
4152 :
4153 258494 : for (int I = 1; I <= N; ++I) {
4154 232004 : A(NP2, I) = 0.0;
4155 : // DO 1 J=1,NP1 ! TODO ?
4156 : }
4157 :
4158 258494 : for (int I = 1; I <= N; ++I) {
4159 2565348 : for (int J = 1; J <= NP1; ++J) {
4160 2333344 : A(NP2, I) += A(J, I);
4161 : }
4162 : }
4163 :
4164 232004 : for (int L = 1; L <= N - 1; ++L) {
4165 205514 : Real64 CMAX = A(L, L);
4166 205514 : int LP = L + 1;
4167 205514 : int NOS = L;
4168 :
4169 1140182 : for (int I = LP; I <= N; ++I) {
4170 934668 : if (std::abs(CMAX) < std::abs(A(L, I))) {
4171 29886 : CMAX = A(L, I);
4172 29886 : NOS = I;
4173 : }
4174 : }
4175 :
4176 : // Swap rows
4177 205514 : if (NOS != L) {
4178 375597 : for (int J = 1; J <= NP2; ++J) {
4179 345711 : Real64 TEMP = A(J, L);
4180 345711 : A(J, L) = A(J, NOS);
4181 345711 : A(J, NOS) = TEMP;
4182 : }
4183 : }
4184 :
4185 1140182 : for (int I = LP; I <= N; ++I) {
4186 934668 : Real64 C = 0.0;
4187 934668 : Real64 Y = -A(L, I) / A(L, L);
4188 9260348 : for (int J = L; J <= NP2; ++J) {
4189 8325680 : A(J, I) += Y * A(J, L);
4190 : }
4191 8325680 : for (int J = L; J <= NP1; ++J) {
4192 7391012 : C += A(J, I);
4193 : }
4194 : }
4195 : }
4196 :
4197 : // back-substitute
4198 26490 : XSOL(N) = A(NP1, N) / A(N, N);
4199 232004 : for (int I = 1; I <= NM1; ++I) {
4200 205514 : int NI = N - I;
4201 205514 : Real64 D = 0.0;
4202 1140182 : for (int J = 1; J <= I; ++J) {
4203 934668 : int NJ = N + 1 - J;
4204 934668 : D += A(NJ, NI) * XSOL(NJ);
4205 : }
4206 205514 : XSOL(NI) = (A(NP1, NI) - D) / A(NI, NI);
4207 : }
4208 26490 : }
4209 :
4210 2356 : void ASHWAT_ThermalCalc(EnergyPlusData &state,
4211 : CFSTY &FS, // fenestration system
4212 : Real64 const TIN, // indoor / outdoor air temperature, K
4213 : Real64 const TOUT,
4214 : Real64 const HCIN, // indoor / outdoor convective heat transfer
4215 : Real64 const HCOUT,
4216 : Real64 const TRMOUT,
4217 : Real64 const TRMIN, // indoor / outdoor mean radiant temp, K
4218 : Array1S<Real64> const SOURCE, // absorbed solar by layer, W/m2
4219 : Real64 const TOL, // convergence tolerance, usually
4220 : Array1D<Real64> &QOCF, // returned: heat flux to layer i from gaps i-1 and i
4221 : Real64 &QOCFRoom, // returned: open channel heat gain to room, W/m2
4222 : Array1D<Real64> &T, // returned: layer temperatures, 1=outside-most layer, K
4223 : Array1D<Real64> &Q, // returned: heat flux at ith gap (betw layers i and i+1), W/m2
4224 : Array1D<Real64> &JF, // returned: front (outside facing) radiosity of surfaces, W/m2
4225 : Array1D<Real64> &JB, // returned: back (inside facing) radiosity, W/m2
4226 : Array1D<Real64> &HC // returned: gap convective heat transfer coefficient, W/m2K
4227 : )
4228 : {
4229 : // SUBROUTINE INFORMATION:
4230 : // AUTHOR JOHN L. WRIGHT (University of Waterloo, Mechanical Engineering)
4231 : // Chip Barnaby (WrightSoft)
4232 : // DATE WRITTEN LATEST MODIFICATIONS, February 2008
4233 : // MODIFIED Bereket Nigusse, June 2013
4234 : // added standard 155099 inside convection
4235 : // coefficient calculation for U-Factor
4236 :
4237 : // PURPOSE OF THIS SUBROUTINE:
4238 : // Subroutine to calculate the glazing temperatures of the
4239 : // various elements of a window/shade array while solving an energy
4240 : // balance which accounts for absorbed solar radiation, indoor-
4241 : // outdoor temperature difference, any combination of hemispherical
4242 : // IR optical properties of the various glazings/shading layers.
4243 : // Mean radiant temperatures can differ from air temperature on
4244 : // both the indoor and outdoor sides.
4245 : // It is also possible to allow air-flow between the two layers
4246 : // adjacent to the indoor side and/or the two layers adjacent the
4247 : // outdoor side. U-factor and SHGC calculations are also included (optional)
4248 :
4249 : // METHODOLOGY EMPLOYED:
4250 : // Uses the net radiation method developed for ASHWAT fenestration
4251 : // model by John Wright, the University of WaterLoo
4252 :
4253 : // REFERENCES:
4254 : // ASHRAE RP-1311
4255 :
4256 : // Argument array dimensioning
4257 2356 : EP_SIZE_CHECK(QOCF, FS.NL);
4258 2356 : EP_SIZE_CHECK(T, FS.NL);
4259 2356 : EP_SIZE_CHECK(JF, FS.NL + 1);
4260 2356 : EP_SIZE_CHECK(JB, FS.NL + 1);
4261 2356 : EP_SIZE_CHECK(HC, FS.NL + 1);
4262 :
4263 : // Locals
4264 : // FUNCTION ARGUMENT DEFINITIONS:
4265 : // FS.NL determines # of layers modelled
4266 : // coefficient, W/m2K
4267 : // = outside direct + outside diffuse + inside diffuse
4268 : // 0.001 (good) or 0.0001 (tight)
4269 : // due to open channel flow, W/m2
4270 : // + = heat flow indoor to outdoor
4271 : // JF( NL+1) = room radiosity
4272 : // JB[ 0] = outside environment radiosity
4273 : // 0=outside, 1=betw layer 1-2, ..., NL=inside
4274 :
4275 : // FUNCTION PARAMETER DEFINITIONS:
4276 2356 : constexpr int MaxIter(100); // maximum number of iterations allowed
4277 : static constexpr std::string_view RoutineName("ASHWAT_ThermalCalc: ");
4278 :
4279 : Real64 ALPHA;
4280 : Real64 HCOCFout;
4281 2356 : Array2D<Real64> A(3 * FS.NL + 4, 3 * FS.NL + 2);
4282 2356 : Array1D<Real64> XSOL(3 * FS.NL + 2);
4283 : Real64 MAXERR;
4284 2356 : Array1D<Real64> TNEW(FS.NL); // latest estimate of layer temperatures, K
4285 2356 : Array1D<Real64> EB({0, FS.NL + 1}); // black emissive power by layer, W/m2
4286 : // EB( 0) = outdoor environment, EB( NL+1) = indoor environment
4287 2356 : Array1D<Real64> HHAT({0, FS.NL}); // convective heat transfer coefficient (W/m2.K4)
4288 : // based on EB, NOT temperature difference
4289 : Real64 RHOF_ROOM; // effective longwave room-side properties
4290 : Real64 TAU_ROOM;
4291 : Real64 EPSF_ROOM;
4292 : Real64 RHOB_OUT; // effective longwave outdoor environment properties
4293 : Real64 TAU_OUT;
4294 : Real64 EPSB_OUT;
4295 2356 : Array1D<Real64> QNET(FS.NL); // checksum - net heat flux to a layer - should be zero - not needed
4296 : int ADIM; // dimension of the A matrix
4297 : int CONVRG;
4298 : int NL;
4299 : int I;
4300 : int J;
4301 : int ITRY;
4302 2356 : Array1D_int ISDL({0, FS.NL + 1}); // Flag to mark diathermanous layers, 0=opaque
4303 2356 : Array1D<Real64> QOCF_F(FS.NL); // heat flux to outdoor-facing surface of layer i, from gap i-1,
4304 : // due to open channel flow, W/m2
4305 2356 : Array1D<Real64> QOCF_B(FS.NL); // heat flux to indoor-facing surface of layer i, from gap i,
4306 : // due to open channel flow, W/m2
4307 2356 : Array1D<Real64> HR({0, FS.NL}); // Radiant heat transfer coefficient [W/m2K]
4308 2356 : Array1D<Real64> HJR(FS.NL); // radiative and convective jump heat transfer coefficients
4309 2356 : Array1D<Real64> HJC(FS.NL);
4310 2356 : Array1D<Real64> RHOF({0, FS.NL + 1}); // longwave reflectance, front ! these variables help simplify
4311 2356 : Array1D<Real64> RHOB({0, FS.NL + 1}); // longwave reflectance, back ! the code because it is useful to
4312 2356 : Array1D<Real64> EPSF({0, FS.NL + 1}); // longwave emissivity, front ! increase the scope of the arrays
4313 2356 : Array1D<Real64> EPSB({0, FS.NL + 1}); // longwave emissivity, back ! to include indoor and outdoor
4314 2356 : Array1D<Real64> TAU({0, FS.NL + 1}); // longwave transmittance ! nodes - more general
4315 2356 : Array2D<Real64> HC2D(6, 6); // convective heat transfer coefficients between layers i and j
4316 2356 : Array2D<Real64> HR2D(6, 6); // radiant heat transfer coefficients between layers i and j
4317 2356 : Array1D<Real64> HCIout(6); // convective and radiant heat transfer coefficients between
4318 2356 : Array1D<Real64> HRIout(6);
4319 : // layer i and outdoor air or mean radiant temperature, resp.
4320 2356 : Array1D<Real64> HCIin(6); // convective and radiant heat transfer coefficients between
4321 2356 : Array1D<Real64> HRIin(6);
4322 : // layer i and indoor air or mean radiant temperature, resp.
4323 : // Indoor side convection coefficients - used for Open Channel Flow on indoor side
4324 : Real64 HFS; // nominal height of fen system (assumed 1 m)
4325 : Real64 TOC_EFF; // effective thickness of open channel, m
4326 : Real64 ConvF; // convection factor: accounts for enhanced convection
4327 : // for e.g. VB adjacent to open channel
4328 : Real64 HC_GA; // convection - glass to air
4329 : Real64 HC_SA; // convection - shade (both sides) to air
4330 : Real64 HC_GS; // convection - glass to shade (one side)
4331 2356 : Array1D<Real64> SOURCEdv(FS.NL + 1); // indices of merit
4332 : Real64 QGAIN; // total gain to conditioned space [[W/m2]
4333 :
4334 2356 : NL = FS.NL; // working copy
4335 2356 : if (NL < 1) {
4336 0 : return;
4337 : }
4338 :
4339 2356 : HCOCFout = HCOUT; // outdoor side
4340 :
4341 2356 : HHAT = 0.0;
4342 2356 : HC = 0.0;
4343 2356 : HR = 0.0;
4344 2356 : T = 0.0;
4345 2356 : TNEW = 0.0;
4346 2356 : EB = 0.0;
4347 2356 : JF = 0.0;
4348 2356 : JB = 0.0;
4349 2356 : Q = 0.0;
4350 2356 : QOCF_F = 0.0;
4351 2356 : QOCF_B = 0.0;
4352 2356 : QOCF = 0.0;
4353 2356 : QOCFRoom = 0.0;
4354 2356 : QNET = 0.0;
4355 2356 : QGAIN = 0.0;
4356 2356 : TAU = 0.0;
4357 2356 : RHOF = 0.0;
4358 2356 : RHOB = 0.0;
4359 2356 : EPSF = 0.0;
4360 2356 : EPSB = 0.0;
4361 2356 : HC_GA = 0.0;
4362 2356 : HC_SA = 0.0;
4363 2356 : HC_GS = 0.0;
4364 :
4365 2356 : ITRY = 0;
4366 :
4367 2356 : EB(0) = Constant::StefanBoltzmann * pow_4(TOUT);
4368 2356 : EB(NL + 1) = Constant::StefanBoltzmann * pow_4(TIN);
4369 :
4370 2356 : ADIM = 3 * NL + 2; // DIMENSION OF A-MATRIX
4371 :
4372 : // organize longwave radiant properties - book-keeping
4373 :
4374 2356 : TAU_ROOM = 0.0; // must always be zero
4375 2356 : RHOF_ROOM = 0.0; // almost always zero
4376 2356 : EPSF_ROOM = 1.0 - TAU_ROOM - RHOF_ROOM; // almost always unity
4377 2356 : RHOF(NL + 1) = RHOF_ROOM;
4378 2356 : EPSF(NL + 1) = EPSF_ROOM;
4379 2356 : TAU(NL + 1) = TAU_ROOM;
4380 :
4381 8532 : for (I = 1; I <= NL; ++I) {
4382 6176 : EPSF(I) = FS.L(I).LWP_EL.EPSLF;
4383 6176 : EPSB(I) = FS.L(I).LWP_EL.EPSLB;
4384 6176 : TAU(I) = FS.L(I).LWP_EL.TAUL;
4385 6176 : RHOF(I) = 1.0 - FS.L(I).LWP_EL.EPSLF - FS.L(I).LWP_EL.TAUL;
4386 6176 : RHOB(I) = 1.0 - FS.L(I).LWP_EL.EPSLB - FS.L(I).LWP_EL.TAUL;
4387 : }
4388 :
4389 2356 : TAU_OUT = 0.0; // must always be zero
4390 2356 : RHOB_OUT = 0.0; // DON'T CHANGE
4391 2356 : EPSB_OUT = 1.0 - TAU_OUT - RHOB_OUT; // should always be unity
4392 2356 : TAU(0) = TAU_OUT;
4393 2356 : EPSB(0) = EPSB_OUT;
4394 2356 : RHOB(0) = RHOB_OUT;
4395 :
4396 : // Later could add RHOF_ROOM to the parameter list
4397 : // Relaxation needed to keep solver stable if OCF is present
4398 :
4399 2356 : ALPHA = 1.0;
4400 2356 : if (NL >= 2) {
4401 2356 : if (FS.G(NL - 1).GTYPE == state.dataWindowEquivalentLayer->gtyOPENin) {
4402 962 : ALPHA = 0.5;
4403 : }
4404 2356 : if (FS.G(1).GTYPE == state.dataWindowEquivalentLayer->gtyOPENout) {
4405 434 : ALPHA = 0.10;
4406 : }
4407 : }
4408 :
4409 : // FIRST ESTIMATE OF GLAZING TEMPERATURES AND BLACK EMISSIVE POWERS
4410 8532 : for (I = 1; I <= NL; ++I) {
4411 6176 : T(I) = TOUT + double(I) / double(NL + 1) * (TIN - TOUT);
4412 6176 : EB(I) = Constant::StefanBoltzmann * pow_4(T(I));
4413 : }
4414 :
4415 2356 : CONVRG = 0;
4416 :
4417 : // Start the solver
4418 : // ITERATION RE-ENTRY
4419 :
4420 2356 : Real64 const TIN_2(pow_2(TIN));
4421 2356 : Real64 const TOUT_2(pow_2(TOUT));
4422 2356 : Real64 const TRMOUT_4(pow_4(TRMOUT));
4423 2356 : Real64 const TRMIN_4(pow_4(TRMIN));
4424 :
4425 25564 : for (ITRY = 1; ITRY <= MaxIter; ++ITRY) {
4426 :
4427 : // CALCULATE GAS LAYER CONVECTIVE HEAT TRANSFER COEFFICIENTS
4428 :
4429 : // start by assuming no open channel flow on indoor side
4430 :
4431 25564 : HC[NL] = HCIN; // default - HC[NL] supplied by calling routine
4432 : // use this for HBX
4433 : // or
4434 : // trigger calculation of HC[NL] using ASHRAE correlation
4435 : // HC[NL] = HIC_ASHRAE(1.0d0, T(NL), TIN) ! h - flat plate
4436 : // Add by BAN June 2013 for standard ratings U-value and SHGC calc only
4437 : // if (present(HCInFlag)) {
4438 : // if (HCInFlag) HC[NL] = HCInWindowStandardRatings(Height, T(NL), TIN);
4439 : // }
4440 25564 : HC[0] = HCOUT; // HC[0] supplied by calling routine as HCOUT
4441 :
4442 : // Check for open channels - only possible with at least two layers
4443 25564 : if (NL >= 2) {
4444 :
4445 25564 : int hin_scheme = 3; // different schemes for calculating convection
4446 : // coefficients glass-to-air and shade-to-air
4447 : // if open channel air flow is allowed
4448 : // see the corresponding subroutines for detail
4449 : // = 1 gives dependence of height, spacing, delta-T
4450 : // = 2 gives dependence of spacing, delta-T but
4451 : // returns unrealistic values for large spacing
4452 : // = 3 glass-shade spacing dependence only on HCIN
4453 : // = negative, applies HCIN without adjusting for
4454 : // temperature, height, spacing, slat angle
4455 : // Recommended -> hin_scheme=3 for use with HBX,
4456 : // simplicity, right trends wrt spacing
4457 :
4458 58910 : for (I = 1; I <= NL - 1; ++I) { // Scan gaps between layers
4459 :
4460 : // DEAL WITH INDOOR OPEN CHANNEL FLOW HERE
4461 33346 : if ((I == NL - 1) && (FS.G(I).GTYPE == state.dataWindowEquivalentLayer->gtyOPENin)) {
4462 :
4463 : // TOC_EFF = FS%G( I)%TAS_EFF / 1000. ! effective thickness of OC gap, m
4464 8449 : TOC_EFF = FS.G(I).TAS_EFF; // effective thickness of OC gap, m Modified by BAN May 9, 2013
4465 8449 : HFS = 1.0; // nominal height of system (m)
4466 :
4467 : // convection - glass to air
4468 8449 : GLtoAMB(state, TOC_EFF, HFS, T(NL - 1), TIN, HCIN, HC_GA, hin_scheme);
4469 : // CALL GLtoAMB( 1.0, HFS, T( NL-1), TIN, HCIN, HC_GA, hin_scheme)
4470 : // ^ VERY WIDE GAP
4471 :
4472 : // convection - shade (both sides) to air
4473 8449 : ConvF = ConvectionFactor(FS.L(I + 1));
4474 8449 : HC_SA = ConvF * SLtoAMB(state, TOC_EFF, HFS, T(NL), TIN, HCIN, hin_scheme);
4475 : // HC_SA = ConvF * SLtoAMB( 1.0, HFS, T(NL), TIN, HCIN, hin_scheme)
4476 : // ^ VERY WIDE GAP
4477 :
4478 : // convection - glass to shade (one side)
4479 8449 : SLtoGL(state, TOC_EFF, T(NL), T(NL - 1), HC_GS, 1);
4480 : // CALL SLtoGL( 1.0, T(NL), T(NL-1), HC_GS, 2) ! REMOVE LATER
4481 : // ^ VERY WIDE GAP, should return near zero
4482 : // Don't use hin_scheme as last parameter - set manually
4483 : // 1 = Conduction, 2 = slight Ra penalty
4484 : // Set negative for default HC_GS=0
4485 : // Recommended: 2
4486 8449 : HC[NL - 1] = HC_GS;
4487 8449 : HC[NL] = HCIN * ConvF;
4488 8449 : QOCF_B(NL - 1) = (TIN - T(NL - 1)) * HC_GA;
4489 8449 : QOCF_F(NL) = (TIN - T(NL)) * (HC_SA - HC[NL]);
4490 8449 : QOCFRoom = -QOCF_B(NL - 1) - QOCF_F(NL);
4491 : // end of gap open to indoor side
4492 :
4493 24897 : } else if ((I == 1) && (FS.G(I).GTYPE == state.dataWindowEquivalentLayer->gtyOPENout)) {
4494 : // outdoor open channel
4495 13995 : QOCF_B(1) = (TOUT - T(1)) * HCOCFout;
4496 13995 : QOCF_F(2) = (TOUT - T(2)) * HCOCFout;
4497 13995 : HC[1] = 0.0;
4498 13995 : HC[0] = HCOCFout;
4499 : } else {
4500 : // normal gap
4501 10902 : HC[I] = HConvGap(FS.G(I), T(I), T(I + 1));
4502 : }
4503 : } // end scan through gaps
4504 :
4505 : // total OCF gain to each layer
4506 25564 : QOCF = QOCF_F + QOCF_B;
4507 :
4508 : } // end IF (NL .GE. 2)
4509 :
4510 : // CONVERT TEMPERATURE POTENTIAL CONVECTIVE COEFFICIENTS to
4511 : // BLACK EMISSIVE POWER POTENTIAL CONVECTIVE COEFFICIENTS
4512 :
4513 25564 : HHAT(0) = HC[0] * (1.0 / Constant::StefanBoltzmann) / ((TOUT_2 + pow_2(T(1))) * (TOUT + T(1)));
4514 :
4515 25564 : Real64 T_I_2(pow_2(T(1))), T_IP_2;
4516 58910 : for (I = 1; I <= NL - 1; ++I) { // Scan the cavities
4517 33346 : T_IP_2 = pow_2(T(I + 1));
4518 33346 : HHAT(I) = HC[I] * (1.0 / Constant::StefanBoltzmann) / ((T_I_2 + T_IP_2) * (T(I) + T(I + 1)));
4519 33346 : T_I_2 = T_IP_2;
4520 : }
4521 :
4522 25564 : HHAT(NL) = HC[NL] * (1.0 / Constant::StefanBoltzmann) / ((pow_2(T(NL)) + TIN_2) * (T(NL) + TIN));
4523 :
4524 : // SET UP MATRIX
4525 25564 : XSOL = 0.0;
4526 25564 : A = 0.0;
4527 :
4528 25564 : int L = 1;
4529 25564 : A(1, L) = 1.0;
4530 25564 : A(2, L) = -1.0 * RHOB(0); // -1.0 * RHOB_OUT
4531 25564 : A(ADIM + 1, L) = EPSB_OUT * Constant::StefanBoltzmann * TRMOUT_4;
4532 :
4533 84474 : for (I = 1; I <= NL; ++I) {
4534 58910 : L = 3 * I - 1;
4535 58910 : A(3 * I - 2, L) = RHOF(I);
4536 58910 : A(3 * I - 1, L) = -1.0;
4537 58910 : A(3 * I, L) = EPSF(I); // LWP( I)%EPSLF
4538 58910 : A(3 * I + 2, L) = TAU(I); // LWP( I)%TAUL
4539 58910 : A(ADIM + 1, L) = 0.0;
4540 :
4541 58910 : L = 3 * I;
4542 58910 : if (NL == 1) {
4543 0 : A(1, L) = 1.0; // Single layer
4544 0 : A(2, L) = -1.0;
4545 0 : A(3, L) = -1.0 * (HHAT(0) + HHAT(1));
4546 0 : A(4, L) = -1.0;
4547 0 : A(5, L) = 1.0;
4548 0 : A(ADIM + 1, L) = -1.0 * (HHAT(0) * EB(0) + HHAT(1) * EB(2) + SOURCE(1) + QOCF(1));
4549 58910 : } else if (I == 1) {
4550 25564 : A(1, L) = 1.0; // Outdoor layer
4551 25564 : A(2, L) = -1.0;
4552 25564 : A(3, L) = -1.0 * (HHAT(0) + HHAT(1));
4553 25564 : A(4, L) = -1.0;
4554 25564 : A(5, L) = 1.0;
4555 25564 : A(6, L) = HHAT(1);
4556 25564 : A(ADIM + 1, L) = -1.0 * (HHAT(0) * EB(0) + SOURCE(1) + QOCF(1));
4557 33346 : } else if (I == NL) {
4558 25564 : A(3 * NL - 3, L) = HHAT(NL - 1); // Indoor layer
4559 25564 : A(3 * NL - 2, L) = 1.0;
4560 25564 : A(3 * NL - 1, L) = -1.0;
4561 25564 : A(3 * NL, L) = -1.0 * (HHAT(NL) + HHAT(NL - 1));
4562 25564 : A(3 * NL + 1, L) = -1.0;
4563 25564 : A(3 * NL + 2, L) = 1.0;
4564 25564 : A(ADIM + 1, L) = -1.0 * (HHAT(NL) * EB(NL + 1) + SOURCE(NL) + QOCF(NL));
4565 : } else {
4566 7782 : A(3 * I - 3, L) = HHAT(I - 1);
4567 7782 : A(3 * I - 2, L) = 1.0;
4568 7782 : A(3 * I - 1, L) = -1.0;
4569 7782 : A(3 * I, L) = -1.0 * (HHAT(I) + HHAT(I - 1));
4570 7782 : A(3 * I + 1, L) = -1.0;
4571 7782 : A(3 * I + 2, L) = 1.0;
4572 7782 : A(3 * I + 3, L) = HHAT(I);
4573 7782 : A(ADIM + 1, L) = -1.0 * (SOURCE(I) + QOCF(I));
4574 : }
4575 58910 : L = 3 * I + 1;
4576 58910 : A(3 * I - 2, L) = TAU(I); // LWP( I)%TAUL
4577 58910 : A(3 * I, L) = EPSB(I); // LWP( I)%EPSLB
4578 58910 : A(3 * I + 1, L) = -1.0;
4579 58910 : A(3 * I + 2, L) = RHOB(I);
4580 58910 : A(ADIM + 1, L) = 0.0;
4581 : }
4582 :
4583 25564 : L = 3 * NL + 2;
4584 25564 : A(3 * NL + 1, L) = -1.0 * RHOF(NL + 1); // - 1.0 * RHOF_ROOM
4585 25564 : A(3 * NL + 2, L) = 1.0;
4586 25564 : A(ADIM + 1, L) = EPSF_ROOM * Constant::StefanBoltzmann * TRMIN_4;
4587 :
4588 : // SOLVE MATRIX
4589 : // Call SOLMATS for single precision matrix solution
4590 25564 : SOLMATS(ADIM, A, XSOL);
4591 :
4592 : // UNPACK SOLUTION VECTOR AND RECORD LARGEST TEMPERATURE CHANGE
4593 25564 : JB[0] = XSOL(1);
4594 :
4595 25564 : MAXERR = 0.0;
4596 84474 : for (I = 1; I <= NL; ++I) {
4597 58910 : J = 3 * I - 1;
4598 58910 : JF(I) = XSOL(J);
4599 58910 : ++J;
4600 58910 : EB(I) = max(1.0, XSOL(J)); // prevent impossible temps
4601 58910 : TNEW(I) = root_4(EB(I) / Constant::StefanBoltzmann);
4602 58910 : ++J;
4603 58910 : JB[I] = XSOL(J);
4604 58910 : MAXERR = max(MAXERR, std::abs(TNEW(I) - T(I)) / TNEW(I));
4605 : }
4606 :
4607 25564 : JF(NL + 1) = XSOL(ADIM);
4608 :
4609 : // CALCULATE HEAT FLUX AT EACH GAP, Q
4610 110038 : for (I = 0; I <= NL; ++I) { // Loop gaps (including inside and outside
4611 84474 : Q(I) = JF(I + 1) - JB[I] + HHAT(I) * (EB(I + 1) - EB(I));
4612 : }
4613 :
4614 : // A CHECK - NET HEAT FLUX INTO ANY LAYER, AT STEADY-STATE,
4615 : // SHOULD BE ZERO
4616 84474 : for (I = 1; I <= NL; ++I) {
4617 58910 : QNET(I) = SOURCE(I) + QOCF(I) + Q(I) - Q(I - 1);
4618 : }
4619 :
4620 : // UPDATE GLAZING TEMPERATURES AND BLACK EMISSIVE POWERS
4621 84474 : for (I = 1; I <= NL; ++I) {
4622 58910 : T(I) += ALPHA * (TNEW(I) - T(I));
4623 58910 : EB(I) = Constant::StefanBoltzmann * pow_4(T(I));
4624 : }
4625 :
4626 : // CHECK FOR CONVERGENCE
4627 25564 : if (CONVRG > 0) {
4628 2356 : break;
4629 : }
4630 23208 : if (MAXERR < TOL) {
4631 2356 : ++CONVRG;
4632 : }
4633 :
4634 : } // main iteration
4635 :
4636 2356 : if (CONVRG == 0) {
4637 :
4638 0 : if (FS.WEQLSolverErrorIndex < 1) {
4639 0 : ++FS.WEQLSolverErrorIndex;
4640 0 : ShowSevereError(state, format("CONSTRUCTION:WINDOWEQUIVALENTLAYER = \"{}\"", FS.Name));
4641 0 : ShowContinueError(state, format("{}Net radiation analysis did not converge", RoutineName));
4642 0 : ShowContinueError(state, format("...Maximum error is = {:.6T}", MAXERR));
4643 0 : ShowContinueError(state, format("...Convergence tolerance is = {:.6T}", TOL));
4644 0 : ShowContinueErrorTimeStamp(state, "");
4645 : } else {
4646 0 : ShowRecurringWarningErrorAtEnd(state,
4647 0 : "CONSTRUCTION:WINDOWEQUIVALENTLAYER = \"" + FS.Name + "\"; " + std::string{RoutineName} +
4648 : "Net radiation analysis did not converge error continues.",
4649 0 : FS.WEQLSolverErrorIndex);
4650 : }
4651 : }
4652 :
4653 : // NOTE: HC_SA, HC_GA and HC_SG are only available if there is
4654 : // an open channel on the indoor side and the calculation of
4655 : // these coefficients was triggered earlier
4656 2356 : QGAIN = SOURCE(NL + 1) + HC[NL] * (T(NL) - TIN) + JB[NL] - JF(NL + 1);
4657 : // Modified by BAN May 3, 2013 to avoid zero layer index
4658 2356 : if (NL >= 2) {
4659 2356 : if (FS.G(NL - 1).GTYPE == state.dataWindowEquivalentLayer->gtyOPENin) {
4660 962 : QGAIN = SOURCE(NL + 1) + (HC_SA / 2.0) * (T(NL) - TIN) + JB[NL] - JF(NL + 1);
4661 962 : QGAIN += HC_GA * (T(NL - 1) - TIN) + (HC_SA / 2.0) * (T(NL) - TIN);
4662 : }
4663 : }
4664 2356 : }
4665 :
4666 24 : bool ASHWAT_ThermalRatings(EnergyPlusData &state,
4667 : CFSTY const &FS, // fenestration system
4668 : Real64 const TIN, // indoor / outdoor air temperature, K
4669 : Real64 const TOUT,
4670 : Real64 const HCIN, // indoor / outdoor convective heat transfer
4671 : Real64 const HCOUT,
4672 : Real64 const TRMOUT,
4673 : Real64 const TRMIN, // indoor / outdoor mean radiant temp, K
4674 : Real64 const ISOL, // total incident solar, W/m2 (values used for SOURCE derivation)
4675 : Array1S<Real64> const SOURCE, // absorbed solar by layer, W/m2
4676 : Real64 const TOL, // convergence tolerance, usually
4677 : Array1D<Real64> &QOCF, // returned: heat flux to layer i from gaps i-1 and i
4678 : Real64 &QOCFRoom, // returned: open channel heat gain to room, W/m2
4679 : Array1D<Real64> &T, // returned: layer temperatures, 1=outside-most layer, K
4680 : Array1D<Real64> &Q, // returned: heat flux at ith gap (betw layers i and i+1), W/m2
4681 : Array1D<Real64> &JF, // returned: front (outside facing) radiosity of surfaces, W/m2
4682 : Array1D<Real64> &JB, // returned: back (inside facing) radiosity, W/m2
4683 : Array1D<Real64> &HC, // returned: gap convective heat transfer coefficient, W/m2K
4684 : Real64 &UCG, // returned: center-glass U-factor, W/m2-K
4685 : Real64 &SHGC, // returned: center-glass SHGC (Solar Heat Gain Coefficient)
4686 : bool const HCInFlag // If true uses ISO Std 150099 routine for HCIn calc
4687 : )
4688 : {
4689 : // SUBROUTINE INFORMATION:
4690 : // AUTHOR JOHN L. WRIGHT (University of Waterloo, Mechanical Engineering)
4691 : // Chip Barnaby (WrightSoft)
4692 : // DATE WRITTEN LATEST MODIFICATIONS, February 2008
4693 : // MODIFIED Bereket Nigusse, June 2013
4694 : // added standard 155099 inside convection
4695 : // coefficient calculation for U-Factor
4696 :
4697 : // PURPOSE OF THIS SUBROUTINE:
4698 : // Subroutine to calculate the glazing temperatures of the
4699 : // various elements of a window/shade array while solving an energy
4700 : // balance which accounts for absorbed solar radiation, indoor-
4701 : // outdoor temperature difference, any combination of hemispherical
4702 : // IR optical properties of the various glazings/shading layers.
4703 : // Mean radiant temperatures can differ from air temperature on
4704 : // both the indoor and outdoor sides.
4705 : // It is also possible to allow air-flow between the two layers
4706 : // adjacent to the indoor side and/or the two layers adjacent the
4707 : // outdoor side. U-factor and SHGC calculations are also included (optional)
4708 :
4709 : // METHODOLOGY EMPLOYED:
4710 : // Uses the net radiation method developed for ASHWAT fenestration
4711 : // model by John Wright, the University of WaterLoo
4712 :
4713 : // REFERENCES:
4714 : // ASHRAE RP-1311
4715 :
4716 : bool ASHWAT_ThermalRatings;
4717 :
4718 : // Argument array dimensioning
4719 24 : EP_SIZE_CHECK(QOCF, FS.NL);
4720 24 : EP_SIZE_CHECK(T, FS.NL);
4721 24 : EP_SIZE_CHECK(JF, FS.NL + 1);
4722 24 : EP_SIZE_CHECK(JB, FS.NL + 1);
4723 24 : EP_SIZE_CHECK(HC, FS.NL + 1);
4724 :
4725 : // Locals
4726 : // FUNCTION ARGUMENT DEFINITIONS:
4727 : // FS.NL determines # of layers modelled
4728 : // coefficient, W/m2K
4729 : // = outside direct + outside diffuse + inside diffuse
4730 : // 0.001 (good) or 0.0001 (tight)
4731 : // due to open channel flow, W/m2
4732 : // + = heat flow indoor to outdoor
4733 : // JF( NL+1) = room radiosity
4734 : // JB[ 0] = outside environment radiosity
4735 : // 0=outside, 1=betw layer 1-2, ..., NL=inside
4736 :
4737 : // FUNCTION PARAMETER DEFINITIONS:
4738 24 : Real64 constexpr Height(1.0); // Window height (m) for standard ratings calculation
4739 24 : int constexpr MaxIter(100); // maximum number of iterations allowed
4740 :
4741 : Real64 ALPHA;
4742 : Real64 HCOCFout;
4743 24 : Array2D<Real64> A(3 * FS.NL + 4, 3 * FS.NL + 2);
4744 24 : Array1D<Real64> XSOL(3 * FS.NL + 2);
4745 : Real64 MAXERR;
4746 24 : Array1D<Real64> TNEW(FS.NL); // latest estimate of layer temperatures, K
4747 24 : Array1D<Real64> EB({0, FS.NL + 1}); // black emissive power by layer, W/m2
4748 : // EB( 0) = outdoor environment, EB( NL+1) = indoor environment
4749 24 : Array1D<Real64> HHAT({0, FS.NL}); // convective heat transfer coefficient (W/m2.K4)
4750 : // based on EB, NOT temperature difference
4751 : Real64 RHOF_ROOM; // effective longwave room-side properties
4752 : Real64 TAU_ROOM;
4753 : Real64 EPSF_ROOM;
4754 : Real64 RHOB_OUT; // effective longwave outdoor environment properties
4755 : Real64 TAU_OUT;
4756 : Real64 EPSB_OUT;
4757 24 : Array1D<Real64> QNET(FS.NL); // checksum - net heat flux to a layer - should be zero - not needed
4758 : int ADIM; // dimension of the A matrix
4759 : int CONVRG;
4760 : int NL;
4761 : int I;
4762 : int J;
4763 : int ITRY;
4764 24 : Array1D_int ISDL({0, FS.NL + 1}); // Flag to mark diathermanous layers, 0=opaque
4765 : int NDLIAR; // Number of Diathermanous Layers In A Row (i.e., consecutive)
4766 : int IB; // Counter begin and end limits
4767 : int IE;
4768 : int IDV; // Integer dummy variable, general utility
4769 24 : Array1D<Real64> QOCF_F(FS.NL); // heat flux to outdoor-facing surface of layer i, from gap i-1,
4770 : // due to open channel flow, W/m2
4771 24 : Array1D<Real64> QOCF_B(FS.NL); // heat flux to indoor-facing surface of layer i, from gap i,
4772 : // due to open channel flow, W/m2
4773 : Real64 Rvalue; // R-value in IP units [hr.ft2.F/BTU]
4774 : Real64 TAE_IN; // Indoor and outdoor effective ambient temperatures [K]
4775 : Real64 TAE_OUT;
4776 24 : Array1D<Real64> HR({0, FS.NL}); // Radiant heat transfer coefficient [W/m2K]
4777 24 : Array1D<Real64> HJR(FS.NL); // radiative and convective jump heat transfer coefficients
4778 24 : Array1D<Real64> HJC(FS.NL);
4779 : Real64 FHR_OUT; // hre/(hre+hce) fraction radiant h, outdoor or indoor, used for TAE
4780 : Real64 FHR_IN;
4781 : Real64 Q_IN; // net gain to the room [W/m2], including transmitted solar
4782 24 : Array1D<Real64> RHOF({0, FS.NL + 1}); // longwave reflectance, front ! these variables help simplify
4783 24 : Array1D<Real64> RHOB({0, FS.NL + 1}); // longwave reflectance, back ! the code because it is useful to
4784 24 : Array1D<Real64> EPSF({0, FS.NL + 1}); // longwave emissivity, front ! increase the scope of the arrays
4785 24 : Array1D<Real64> EPSB({0, FS.NL + 1}); // longwave emissivity, back ! to include indoor and outdoor
4786 24 : Array1D<Real64> TAU({0, FS.NL + 1}); // longwave transmittance ! nodes - more general
4787 : Real64 RTOT; // total resistance from TAE_OUT to TAE_IN [m2K/W]
4788 24 : Array2D<Real64> HC2D(6, 6); // convective heat transfer coefficients between layers i and j
4789 24 : Array2D<Real64> HR2D(6, 6); // radiant heat transfer coefficients between layers i and j
4790 24 : Array1D<Real64> HCIout(6); // convective and radiant heat transfer coefficients between
4791 24 : Array1D<Real64> HRIout(6);
4792 : // layer i and outdoor air or mean radiant temperature, resp.
4793 24 : Array1D<Real64> HCIin(6); // convective and radiant heat transfer coefficients between
4794 24 : Array1D<Real64> HRIin(6);
4795 : // layer i and indoor air or mean radiant temperature, resp.
4796 : Real64 HCinout; // convective and radiant heat transfer coefficients between
4797 : Real64 HRinout;
4798 : // indoor and outdoor air or mean radiant temperatures
4799 : // (almost always zero)
4800 : // Indoor side convection coefficients - used for Open Channel Flow on indoor side
4801 : Real64 HFS; // nominal height of fen system (assumed 1 m)
4802 : Real64 TOC_EFF; // effective thickness of open channel, m
4803 : Real64 ConvF; // convection factor: accounts for enhanced convection
4804 : // for e.g. VB adjacent to open channel
4805 : Real64 HC_GA; // convection - glass to air
4806 : Real64 HC_SA; // convection - shade (both sides) to air
4807 : Real64 HC_GS; // convection - glass to shade (one side)
4808 : Real64 TINdv; // dummy variables used
4809 : Real64 TOUTdv;
4810 : Real64 TRMINdv; // for boundary conditions in calculating
4811 : Real64 TRMOUTdv;
4812 24 : Array1D<Real64> SOURCEdv(FS.NL + 1); // indices of merit
4813 : Real64 QGAIN; // total gain to conditioned space [[W/m2]
4814 : Real64 SaveHCNLm; // place to save HC[NL-1] - two resistance networks differ
4815 : Real64 SaveHCNL; // place to save HC[NL] - two resistance networks differ
4816 : // in their definitions of these heat transfer coefficients
4817 :
4818 24 : ASHWAT_ThermalRatings = false; // init to failure
4819 24 : NL = FS.NL; // working copy
4820 24 : if (NL < 1) {
4821 0 : return ASHWAT_ThermalRatings;
4822 : }
4823 :
4824 24 : HCOCFout = HCOUT; // outdoor side
4825 :
4826 24 : HHAT = 0.0;
4827 24 : HC = 0.0;
4828 24 : HR = 0.0;
4829 24 : T = 0.0;
4830 24 : TNEW = 0.0;
4831 24 : EB = 0.0;
4832 24 : JF = 0.0;
4833 24 : JB = 0.0;
4834 24 : Q = 0.0;
4835 24 : QOCF_F = 0.0;
4836 24 : QOCF_B = 0.0;
4837 24 : QOCF = 0.0;
4838 24 : QOCFRoom = 0.0;
4839 24 : QNET = 0.0;
4840 24 : QGAIN = 0.0;
4841 24 : TAU = 0.0;
4842 24 : RHOF = 0.0;
4843 24 : RHOB = 0.0;
4844 24 : EPSF = 0.0;
4845 24 : EPSB = 0.0;
4846 24 : HC_GA = 0.0;
4847 24 : HC_SA = 0.0;
4848 24 : HC_GS = 0.0;
4849 :
4850 24 : ITRY = 0;
4851 :
4852 24 : EB(0) = Constant::StefanBoltzmann * pow_4(TOUT);
4853 24 : EB(NL + 1) = Constant::StefanBoltzmann * pow_4(TIN);
4854 :
4855 24 : ADIM = 3 * NL + 2; // DIMENSION OF A-MATRIX
4856 :
4857 : // organize longwave radiant properties - book-keeping
4858 :
4859 24 : TAU_ROOM = 0.0; // must always be zero
4860 24 : RHOF_ROOM = 0.0; // almost always zero
4861 24 : EPSF_ROOM = 1.0 - TAU_ROOM - RHOF_ROOM; // almost always unity
4862 24 : RHOF(NL + 1) = RHOF_ROOM;
4863 24 : EPSF(NL + 1) = EPSF_ROOM;
4864 24 : TAU(NL + 1) = TAU_ROOM;
4865 :
4866 85 : for (I = 1; I <= NL; ++I) {
4867 61 : EPSF(I) = FS.L(I).LWP_EL.EPSLF;
4868 61 : EPSB(I) = FS.L(I).LWP_EL.EPSLB;
4869 61 : TAU(I) = FS.L(I).LWP_EL.TAUL;
4870 61 : RHOF(I) = 1.0 - FS.L(I).LWP_EL.EPSLF - FS.L(I).LWP_EL.TAUL;
4871 61 : RHOB(I) = 1.0 - FS.L(I).LWP_EL.EPSLB - FS.L(I).LWP_EL.TAUL;
4872 : }
4873 :
4874 24 : TAU_OUT = 0.0; // must always be zero
4875 24 : RHOB_OUT = 0.0; // DON'T CHANGE
4876 24 : EPSB_OUT = 1.0 - TAU_OUT - RHOB_OUT; // should always be unity
4877 24 : TAU(0) = TAU_OUT;
4878 24 : EPSB(0) = EPSB_OUT;
4879 24 : RHOB(0) = RHOB_OUT;
4880 :
4881 : // Later could add RHOF_ROOM to the parameter list
4882 : // Relaxation needed to keep solver stable if OCF is present
4883 :
4884 24 : ALPHA = 1.0;
4885 24 : if (NL >= 2) {
4886 24 : if (FS.G(NL - 1).GTYPE == state.dataWindowEquivalentLayer->gtyOPENin) {
4887 9 : ALPHA = 0.5;
4888 : }
4889 24 : if (FS.G(1).GTYPE == state.dataWindowEquivalentLayer->gtyOPENout) {
4890 3 : ALPHA = 0.10;
4891 : }
4892 : }
4893 :
4894 : // FIRST ESTIMATE OF GLAZING TEMPERATURES AND BLACK EMISSIVE POWERS
4895 85 : for (I = 1; I <= NL; ++I) {
4896 61 : T(I) = TOUT + double(I) / double(NL + 1) * (TIN - TOUT);
4897 61 : EB(I) = Constant::StefanBoltzmann * pow_4(T(I));
4898 : }
4899 :
4900 24 : CONVRG = 0;
4901 :
4902 : // Start the solver
4903 : // ITERATION RE-ENTRY
4904 :
4905 24 : Real64 const TIN_2(pow_2(TIN));
4906 24 : Real64 const TOUT_2(pow_2(TOUT));
4907 24 : Real64 const TRMOUT_4(pow_4(TRMOUT));
4908 24 : Real64 const TRMIN_4(pow_4(TRMIN));
4909 :
4910 107 : for (ITRY = 1; ITRY <= MaxIter; ++ITRY) {
4911 :
4912 : // CALCULATE GAS LAYER CONVECTIVE HEAT TRANSFER COEFFICIENTS
4913 :
4914 : // start by assuming no open channel flow on indoor side
4915 :
4916 107 : HC[NL] = HCIN; // default - HC[NL] supplied by calling routine
4917 : // use this for HBX
4918 : // or
4919 : // trigger calculation of HC[NL] using ASHRAE correlation
4920 : // HC[NL] = HIC_ASHRAE(1.0d0, T(NL), TIN) ! h - flat plate
4921 : // Add by BAN June 2013 for standard ratings U-value and SHGC calc only
4922 107 : if (HCInFlag) {
4923 107 : HC[NL] = HCInWindowStandardRatings(state, Height, T(NL), TIN);
4924 : }
4925 107 : HC[0] = HCOUT; // HC[0] supplied by calling routine as HCOUT
4926 :
4927 : // Check for open channels - only possible with at least two layers
4928 107 : if (NL >= 2) {
4929 :
4930 107 : int hin_scheme = 3; // different schemes for calculating convection
4931 : // coefficients glass-to-air and shade-to-air
4932 : // if open channel air flow is allowed
4933 : // see the corresponding subroutines for detail
4934 : // = 1 gives dependence of height, spacing, delta-T
4935 : // = 2 gives dependence of spacing, delta-T but
4936 : // returns unrealistic values for large spacing
4937 : // = 3 glass-shade spacing dependence only on HCIN
4938 : // = negative, applies HCIN without adjusting for
4939 : // temperature, height, spacing, slat angle
4940 : // Recommended -> hin_scheme=3 for use with HBX,
4941 : // simplicity, right trends wrt spacing
4942 :
4943 257 : for (I = 1; I <= NL - 1; ++I) { // Scan gaps between layers
4944 :
4945 : // DEAL WITH INDOOR OPEN CHANNEL FLOW HERE
4946 150 : if ((I == NL - 1) && (FS.G(I).GTYPE == state.dataWindowEquivalentLayer->gtyOPENin)) {
4947 :
4948 : // TOC_EFF = FS%G( I)%TAS_EFF / 1000. ! effective thickness of OC gap, m
4949 36 : TOC_EFF = FS.G(I).TAS_EFF; // effective thickness of OC gap, m Modified by BAN May 9, 2013
4950 36 : HFS = 1.0; // nominal height of system (m)
4951 :
4952 : // convection - glass to air
4953 36 : GLtoAMB(state, TOC_EFF, HFS, T(NL - 1), TIN, HCIN, HC_GA, hin_scheme);
4954 : // CALL GLtoAMB( 1.0, HFS, T( NL-1), TIN, HCIN, HC_GA, hin_scheme)
4955 : // ^ VERY WIDE GAP
4956 :
4957 : // convection - shade (both sides) to air
4958 36 : ConvF = ConvectionFactor(FS.L(I + 1));
4959 36 : HC_SA = ConvF * SLtoAMB(state, TOC_EFF, HFS, T(NL), TIN, HCIN, hin_scheme);
4960 : // HC_SA = ConvF * SLtoAMB( 1.0, HFS, T(NL), TIN, HCIN, hin_scheme)
4961 : // ^ VERY WIDE GAP
4962 :
4963 : // convection - glass to shade (one side)
4964 36 : SLtoGL(state, TOC_EFF, T(NL), T(NL - 1), HC_GS, 1);
4965 : // CALL SLtoGL( 1.0, T(NL), T(NL-1), HC_GS, 2) ! REMOVE LATER
4966 : // ^ VERY WIDE GAP, should return near zero
4967 : // Don't use hin_scheme as last parameter - set manually
4968 : // 1 = Conduction, 2 = slight Ra penalty
4969 : // Set negative for default HC_GS=0
4970 : // Recommended: 2
4971 36 : HC[NL - 1] = HC_GS;
4972 36 : HC[NL] = HCIN * ConvF;
4973 36 : QOCF_B(NL - 1) = (TIN - T(NL - 1)) * HC_GA;
4974 36 : QOCF_F(NL) = (TIN - T(NL)) * (HC_SA - HC[NL]);
4975 36 : QOCFRoom = -QOCF_B(NL - 1) - QOCF_F(NL);
4976 : // end of gap open to indoor side
4977 :
4978 114 : } else if ((I == 1) && (FS.G(I).GTYPE == state.dataWindowEquivalentLayer->gtyOPENout)) {
4979 : // outdoor open channel
4980 35 : QOCF_B(1) = (TOUT - T(1)) * HCOCFout;
4981 35 : QOCF_F(2) = (TOUT - T(2)) * HCOCFout;
4982 35 : HC[1] = 0.0;
4983 35 : HC[0] = HCOCFout;
4984 : } else {
4985 : // normal gap
4986 79 : HC[I] = HConvGap(FS.G(I), T(I), T(I + 1));
4987 : }
4988 : } // end scan through gaps
4989 :
4990 : // total OCF gain to each layer
4991 107 : QOCF = QOCF_F + QOCF_B;
4992 :
4993 : } // end IF (NL .GE. 2)
4994 :
4995 : // CONVERT TEMPERATURE POTENTIAL CONVECTIVE COEFFICIENTS to
4996 : // BLACK EMISSIVE POWER POTENTIAL CONVECTIVE COEFFICIENTS
4997 :
4998 107 : HHAT(0) = HC[0] * (1.0 / Constant::StefanBoltzmann) / ((TOUT_2 + pow_2(T(1))) * (TOUT + T(1)));
4999 :
5000 107 : Real64 T_I_2(pow_2(T(1))), T_IP_2;
5001 257 : for (I = 1; I <= NL - 1; ++I) { // Scan the cavities
5002 150 : T_IP_2 = pow_2(T(I + 1));
5003 150 : HHAT(I) = HC[I] * (1.0 / Constant::StefanBoltzmann) / ((T_I_2 + T_IP_2) * (T(I) + T(I + 1)));
5004 150 : T_I_2 = T_IP_2;
5005 : }
5006 :
5007 107 : HHAT(NL) = HC[NL] * (1.0 / Constant::StefanBoltzmann) / ((pow_2(T(NL)) + TIN_2) * (T(NL) + TIN));
5008 :
5009 : // SET UP MATRIX
5010 107 : XSOL = 0.0;
5011 107 : A = 0.0;
5012 :
5013 107 : int L = 1;
5014 107 : A(1, L) = 1.0;
5015 107 : A(2, L) = -1.0 * RHOB(0); // -1.0 * RHOB_OUT
5016 107 : A(ADIM + 1, L) = EPSB_OUT * Constant::StefanBoltzmann * TRMOUT_4;
5017 :
5018 364 : for (I = 1; I <= NL; ++I) {
5019 257 : L = 3 * I - 1;
5020 257 : A(3 * I - 2, L) = RHOF(I);
5021 257 : A(3 * I - 1, L) = -1.0;
5022 257 : A(3 * I, L) = EPSF(I); // LWP( I)%EPSLF
5023 257 : A(3 * I + 2, L) = TAU(I); // LWP( I)%TAUL
5024 257 : A(ADIM + 1, L) = 0.0;
5025 :
5026 257 : L = 3 * I;
5027 257 : if (NL == 1) {
5028 0 : A(1, L) = 1.0; // Single layer
5029 0 : A(2, L) = -1.0;
5030 0 : A(3, L) = -1.0 * (HHAT(0) + HHAT(1));
5031 0 : A(4, L) = -1.0;
5032 0 : A(5, L) = 1.0;
5033 0 : A(ADIM + 1, L) = -1.0 * (HHAT(0) * EB(0) + HHAT(1) * EB(2) + SOURCE(1) + QOCF(1));
5034 257 : } else if (I == 1) {
5035 107 : A(1, L) = 1.0; // Outdoor layer
5036 107 : A(2, L) = -1.0;
5037 107 : A(3, L) = -1.0 * (HHAT(0) + HHAT(1));
5038 107 : A(4, L) = -1.0;
5039 107 : A(5, L) = 1.0;
5040 107 : A(6, L) = HHAT(1);
5041 107 : A(ADIM + 1, L) = -1.0 * (HHAT(0) * EB(0) + SOURCE(1) + QOCF(1));
5042 150 : } else if (I == NL) {
5043 107 : A(3 * NL - 3, L) = HHAT(NL - 1); // Indoor layer
5044 107 : A(3 * NL - 2, L) = 1.0;
5045 107 : A(3 * NL - 1, L) = -1.0;
5046 107 : A(3 * NL, L) = -1.0 * (HHAT(NL) + HHAT(NL - 1));
5047 107 : A(3 * NL + 1, L) = -1.0;
5048 107 : A(3 * NL + 2, L) = 1.0;
5049 107 : A(ADIM + 1, L) = -1.0 * (HHAT(NL) * EB(NL + 1) + SOURCE(NL) + QOCF(NL));
5050 : } else {
5051 43 : A(3 * I - 3, L) = HHAT(I - 1);
5052 43 : A(3 * I - 2, L) = 1.0;
5053 43 : A(3 * I - 1, L) = -1.0;
5054 43 : A(3 * I, L) = -1.0 * (HHAT(I) + HHAT(I - 1));
5055 43 : A(3 * I + 1, L) = -1.0;
5056 43 : A(3 * I + 2, L) = 1.0;
5057 43 : A(3 * I + 3, L) = HHAT(I);
5058 43 : A(ADIM + 1, L) = -1.0 * (SOURCE(I) + QOCF(I));
5059 : }
5060 257 : L = 3 * I + 1;
5061 257 : A(3 * I - 2, L) = TAU(I); // LWP( I)%TAUL
5062 257 : A(3 * I, L) = EPSB(I); // LWP( I)%EPSLB
5063 257 : A(3 * I + 1, L) = -1.0;
5064 257 : A(3 * I + 2, L) = RHOB(I);
5065 257 : A(ADIM + 1, L) = 0.0;
5066 : }
5067 :
5068 107 : L = 3 * NL + 2;
5069 107 : A(3 * NL + 1, L) = -1.0 * RHOF(NL + 1); // - 1.0 * RHOF_ROOM
5070 107 : A(3 * NL + 2, L) = 1.0;
5071 107 : A(ADIM + 1, L) = EPSF_ROOM * Constant::StefanBoltzmann * TRMIN_4;
5072 :
5073 : // SOLVE MATRIX
5074 : // Call SOLMATS for single precision matrix solution
5075 107 : SOLMATS(ADIM, A, XSOL);
5076 :
5077 : // UNPACK SOLUTION VECTOR AND RECORD LARGEST TEMPERATURE CHANGE
5078 107 : JB[0] = XSOL(1);
5079 :
5080 107 : MAXERR = 0.0;
5081 364 : for (I = 1; I <= NL; ++I) {
5082 257 : J = 3 * I - 1;
5083 257 : JF(I) = XSOL(J);
5084 257 : ++J;
5085 257 : EB(I) = max(1.0, XSOL(J)); // prevent impossible temps
5086 257 : TNEW(I) = root_4(EB(I) / Constant::StefanBoltzmann);
5087 257 : ++J;
5088 257 : JB[I] = XSOL(J);
5089 257 : MAXERR = max(MAXERR, std::abs(TNEW(I) - T(I)) / TNEW(I));
5090 : }
5091 :
5092 107 : JF(NL + 1) = XSOL(ADIM);
5093 :
5094 : // CALCULATE HEAT FLUX AT EACH GAP, Q
5095 471 : for (I = 0; I <= NL; ++I) { // Loop gaps (including inside and outside
5096 364 : Q(I) = JF(I + 1) - JB[I] + HHAT(I) * (EB(I + 1) - EB(I));
5097 : }
5098 :
5099 : // A CHECK - NET HEAT FLUX INTO ANY LAYER, AT STEADY-STATE,
5100 : // SHOULD BE ZERO
5101 364 : for (I = 1; I <= NL; ++I) {
5102 257 : QNET(I) = SOURCE(I) + QOCF(I) + Q(I) - Q(I - 1);
5103 : }
5104 :
5105 : // UPDATE GLAZING TEMPERATURES AND BLACK EMISSIVE POWERS
5106 364 : for (I = 1; I <= NL; ++I) {
5107 257 : T(I) += ALPHA * (TNEW(I) - T(I));
5108 257 : EB(I) = Constant::StefanBoltzmann * pow_4(T(I));
5109 : }
5110 :
5111 : // CHECK FOR CONVERGENCE
5112 107 : if (CONVRG > 0) {
5113 24 : break;
5114 : }
5115 83 : if (MAXERR < TOL) {
5116 24 : ++CONVRG;
5117 : }
5118 :
5119 : } // main iteration
5120 :
5121 : // if (CONVRG == 0) {
5122 :
5123 : // if (FS.WEQLSolverErrorIndex < 1) {
5124 : // ++FS.WEQLSolverErrorIndex;
5125 : // ShowSevereError(state, format("CONSTRUCTION:WINDOWEQUIVALENTLAYER = \"{}\"", FS.Name));
5126 : // ShowContinueError(state, format("{}Net radiation analysis did not converge", RoutineName));
5127 : // ShowContinueError(state, format("...Maximum error is = {:.6T}", MAXERR));
5128 : // ShowContinueError(state, format("...Convergence tolerance is = {:.6T}", TOL));
5129 : // ShowContinueErrorTimeStamp(state, "");
5130 : // } else {
5131 : // ShowRecurringWarningErrorAtEnd(state, "CONSTRUCTION:WINDOWEQUIVALENTLAYER = \"" + FS.Name + "\"; " + std::string{RoutineName} +
5132 : // "Net radiation analysis did not converge error continues.",
5133 : // FS.WEQLSolverErrorIndex);
5134 : // }
5135 : //}
5136 :
5137 : // NOTE: HC_SA, HC_GA and HC_SG are only available if there is
5138 : // an open channel on the indoor side and the calculation of
5139 : // these coefficients was triggered earlier
5140 24 : QGAIN = SOURCE(NL + 1) + HC[NL] * (T(NL) - TIN) + JB[NL] - JF(NL + 1);
5141 : // Modified by BAN May 3, 2013 to avoid zero layer index
5142 24 : if (NL >= 2) {
5143 24 : if (FS.G(NL - 1).GTYPE == state.dataWindowEquivalentLayer->gtyOPENin) {
5144 9 : QGAIN = SOURCE(NL + 1) + (HC_SA / 2.0) * (T(NL) - TIN) + JB[NL] - JF(NL + 1);
5145 9 : QGAIN += HC_GA * (T(NL - 1) - TIN) + (HC_SA / 2.0) * (T(NL) - TIN);
5146 : }
5147 : }
5148 :
5149 24 : ASHWAT_ThermalRatings = true;
5150 :
5151 : // New code follows from here - for calculating Ucg and SHGC
5152 : // NOTE: This code can be bypassed if
5153 : // indices of merit are not needed
5154 :
5155 : // Initialize various things
5156 24 : HR = 0.0;
5157 24 : HJC = 0.0;
5158 24 : HJR = 0.0;
5159 24 : TAE_OUT = 0.0;
5160 24 : TAE_IN = 0.0;
5161 24 : FHR_OUT = 0.0;
5162 24 : FHR_IN = 0.0;
5163 24 : Q_IN = 0.0;
5164 24 : RTOT = 0.0;
5165 24 : UCG = 0.0;
5166 24 : SHGC = 0.0;
5167 24 : Rvalue = 0.0;
5168 24 : HC2D = 0.0;
5169 24 : HR2D = 0.0;
5170 24 : HCIout = 0.0;
5171 24 : HRIout = 0.0;
5172 24 : HCIin = 0.0;
5173 24 : HRIin = 0.0;
5174 24 : HCinout = 0.0;
5175 24 : HRinout = 0.0;
5176 24 : TNEW = 0.0;
5177 24 : TINdv = 0.0;
5178 24 : TOUTdv = 0.0;
5179 24 : TRMINdv = 0.0;
5180 24 : TRMOUTdv = 0.0;
5181 24 : SOURCEdv = 0.0;
5182 :
5183 : // Identify the diathermanous layers
5184 24 : ISDL = 0;
5185 85 : for (I = 1; I <= NL; ++I) {
5186 61 : if (FS.L(I).LWP_EL.TAUL > 0.001) {
5187 13 : ISDL(I) = 1; // layer is diathermanous
5188 : }
5189 : // of tau_lw > 0.001 (ie 0.1%)
5190 : // Note: ISDL(0) and ISDL(NL+1)
5191 : // must both be zero
5192 : } // end loop to calculate ISDL(i)
5193 :
5194 : // determine the largest number of consecutive diathermanous layers, NDLIAR
5195 : // i.e., the number of diathermanous layers in a row
5196 24 : NDLIAR = 0;
5197 24 : IDV = 0;
5198 85 : for (I = 1; I <= NL; ++I) {
5199 61 : if (ISDL(I) == 1) {
5200 13 : ++IDV;
5201 : } else {
5202 48 : IDV = 0;
5203 : }
5204 61 : if (IDV > NDLIAR) {
5205 13 : NDLIAR = IDV;
5206 : }
5207 : } // end loop to calculate NDLIAR
5208 :
5209 24 : if (NDLIAR > 1) {
5210 0 : return ASHWAT_ThermalRatings; // cannot handle two (or more) consecutive
5211 : }
5212 : // diathermanous layers, U/SHGC calculation
5213 : // will be skipped entirely
5214 : // CHANGE TO (NDLIAR .GT. 2) ONCE
5215 : // SUBROUTINE DL2_RES IS AVAILABLE
5216 :
5217 : // calculate radiant heat transfer coefficients between adjacent opaque
5218 : // layers
5219 109 : for (I = 0; I <= NL; ++I) { // scan through all gaps - including indoor/outdoor
5220 85 : if ((ISDL(I) == 0) && (ISDL(I + 1) == 0)) {
5221 59 : if (I == 0) { // outdoor side
5222 24 : HR(I) = HRadPar(T(1), TRMOUT, EPSF(1), EPSB(0));
5223 35 : } else if (I == NL) { // indoor side
5224 11 : HR(I) = HRadPar(T(NL), TRMIN, EPSF(NL + 1), EPSB(NL));
5225 : } else { // cavities
5226 24 : HR(I) = HRadPar(T(I), T(I + 1), EPSF(I + 1), EPSB(I));
5227 : }
5228 : }
5229 : } // end loop through gaps
5230 :
5231 : // calculate radiant heat transfer coefficients at single diathermanous
5232 : // layers,three coefficients in each case
5233 :
5234 85 : for (I = 0; I <= NL - 1; ++I) { // scan through all layers - look for single DL
5235 : // layers between two opaque layers
5236 61 : if ((ISDL(I) == 0) && (ISDL(I + 1) == 1) && (ISDL(I + 2) == 0)) {
5237 13 : if (I == 0) { // outdoor layer is diathermanous
5238 0 : if (NL == 1) {
5239 0 : DL_RES_r2(TRMOUT, T(1), TRMIN, RHOB(0), RHOF(1), RHOB(1), TAU(1), RHOF(2), HJR(1), HR(0), HR(1));
5240 : } else {
5241 0 : DL_RES_r2(TRMOUT, T(1), T(2), RHOB(0), RHOF(1), RHOB(1), TAU(1), RHOF(2), HJR(1), HR(0), HR(1));
5242 : }
5243 : } else { // with IF (I .EQ. 0) i.e., i != 0
5244 13 : if (I == NL - 1) { // indoor layer is diathermanous
5245 13 : DL_RES_r2(T(NL - 1), T(NL), TRMIN, RHOB(NL - 1), RHOF(NL), RHOB(NL), TAU(NL), RHOF(NL + 1), HJR(NL), HR(NL - 1), HR(NL));
5246 : } else { // some intermediate layer is diathermanous
5247 0 : DL_RES_r2(T(I), T(I + 1), T(I + 2), RHOB(I), RHOF(I + 1), RHOB(I + 1), TAU(I + 1), RHOF(I + 2), HJR(I + 1), HR(I), HR(I + 1));
5248 : } // end of IF/ELSE (I .EQ. NL-1)
5249 : } // end of IF/ELSE (I .EQ. 0)
5250 : } // end of IF(ISDL(I) .EQ. 0) .AND. .....
5251 : } // end of scan through all layers
5252 :
5253 : // calculate radiant heat transfer coefficients at double diathermanous
5254 : // layers,six coefficients in each case
5255 : // THIS SECTION NOT ACTIVE YET
5256 :
5257 24 : if (NL >= 2) {
5258 61 : for (I = 0; I <= NL - 2; ++I) { // scan through all layers - look for double DL
5259 : // layers between two opaque layers
5260 37 : if ((ISDL(I) == 0) && (ISDL(I + 1) == 1) && (ISDL(I + 2) == 1) && (ISDL(I + 3) == 0)) {
5261 0 : if (I == 0) {
5262 : // CALL DL2_RES(TRMOUT, T(1), T(2), T(3) etc)
5263 : } else {
5264 0 : if (I == NL - 2) {
5265 : // CALL DL2_RES(T(NL-2), T(NL-1), T(NL), TRMIN, etc)
5266 : } else {
5267 : // CALL DL2_RES(T(I), T(I+1), T(I+2), T(I+3) etc)
5268 : } // end of IF/ELSE (I .EQ. NL-1)
5269 : } // end of IF/ELSE (I .EQ. 0)
5270 : } // end of IF(ISDL(I) .EQ. 0) .AND. .....
5271 : } // end of scan through all layers
5272 :
5273 : // calculate convective OCF/jump heat transfer coefficients
5274 : // no OCF unless at least two layers exist
5275 : // It is not possible for both of the following cases to be
5276 : // true for the same gap (i.e., for NL=2)
5277 :
5278 24 : if (FS.G(NL - 1).GTYPE == state.dataWindowEquivalentLayer->gtyOPENin) {
5279 9 : SaveHCNLm = HC[NL - 1];
5280 9 : SaveHCNL = HC[NL];
5281 9 : HC[NL - 1] = HC_GS;
5282 9 : HC[NL] = HC_SA;
5283 9 : HJC(NL) = HC_GA;
5284 : }
5285 :
5286 24 : HC[0] = HCOUT;
5287 24 : if (FS.G(1).GTYPE == state.dataWindowEquivalentLayer->gtyOPENout) {
5288 3 : HC[0] = HCOUT + HCOCFout;
5289 3 : HJC(1) = HCOCFout;
5290 : }
5291 : }
5292 :
5293 : // copy convective heat transfer coefficients to 2D arrays
5294 : // adjacent layers
5295 24 : IB = 1;
5296 24 : IE = NL - 1;
5297 24 : if (IB <= IE) {
5298 61 : for (I = IB; I <= IE; ++I) {
5299 37 : HC2D(I + 1, I) = HC[I];
5300 37 : HC2D(I, I + 1) = HC2D(I + 1, I);
5301 : }
5302 : }
5303 :
5304 : // jumpers
5305 24 : IB = 2;
5306 24 : IE = NL - 1;
5307 24 : if (IB <= IE) {
5308 26 : for (I = IB; I <= IE; ++I) {
5309 13 : HC2D(I + 1, I - 1) = HJC(I);
5310 13 : HC2D(I - 1, I + 1) = HC2D(I + 1, I - 1);
5311 : }
5312 : }
5313 :
5314 : // double jumpers - NOT ACTIVE YET
5315 24 : IB = 2;
5316 24 : IE = NL - 2;
5317 24 : if (IB <= IE) {
5318 0 : for (I = IB; I <= IE; ++I) {
5319 : // HC2D(I-1,I+2) = H2JC(I)
5320 : // HC2D(I+2,I-1) = HC2D(I-1,I+2)
5321 : }
5322 : }
5323 :
5324 : // outdoor side
5325 24 : HCIout(1) = HC[0];
5326 24 : if (NL >= 2) {
5327 24 : HCIout(2) = HJC(1);
5328 : }
5329 :
5330 : // indoor side
5331 24 : HCIin(NL) = HC[NL];
5332 24 : if (NL >= 2) {
5333 24 : HCIin(NL - 1) = HJC(NL);
5334 : }
5335 :
5336 : // special case - indoor-to-outdoor convection (?)
5337 24 : HCinout = 0.0;
5338 :
5339 : // copy radiative heat transfer coefficients to 2D arrays
5340 : // adjacent layers
5341 24 : IB = 1;
5342 24 : IE = NL - 1;
5343 24 : if (IB <= IE) {
5344 61 : for (I = IB; I <= IE; ++I) {
5345 37 : HR2D(I + 1, I) = HR(I);
5346 37 : HR2D(I, I + 1) = HR2D(I + 1, I);
5347 : }
5348 : }
5349 :
5350 : // jumpers
5351 24 : IB = 2;
5352 24 : IE = NL - 1;
5353 24 : if (IB <= IE) {
5354 26 : for (I = IB; I <= IE; ++I) {
5355 13 : HR2D(I + 1, I - 1) = HJR(I);
5356 13 : HR2D(I - 1, I + 1) = HR2D(I + 1, I - 1);
5357 : }
5358 : }
5359 :
5360 : // double jumpers
5361 24 : IB = 2;
5362 24 : IE = NL - 2;
5363 24 : if (IB <= IE) {
5364 0 : for (I = IB; I <= IE; ++I) {
5365 : // HR2D(I-1,I+2) = H2JR(I)
5366 : // HR2D(I+2,I-1) = HR2D(I-1,I+2)
5367 : }
5368 : }
5369 :
5370 : // outdoor side
5371 24 : HRIout(1) = HR(0);
5372 24 : if (NL >= 2) {
5373 24 : HRIout(2) = HJR(1);
5374 : }
5375 :
5376 : // indoor side
5377 24 : HRIin(NL) = HR(NL);
5378 24 : if (NL >= 2) {
5379 24 : HRIin(NL - 1) = HJR(NL);
5380 : }
5381 :
5382 : // special case - indoor-to-outdoor radiation
5383 24 : if (NL == 1) {
5384 0 : HRinout = HJR(1);
5385 : }
5386 : // IF(NL .EQ. 2) HRinout=H2JR(1)
5387 :
5388 : // CONFIRM VALIDITY OF CODE
5389 :
5390 : // if (1 == 0) { // was used for debugging - successfully
5391 : // // and can now be bypassed
5392 : // // - code in this section generates the
5393 : // // same solution of temperatures (TNEW(i))
5394 : // // that was found by the net radiation
5395 : // // solver above (T(i))
5396 :
5397 : // ADIM = NL;
5398 : // A = 0.0;
5399 : // XSOL = 0.0;
5400 : // TOUTdv = TOUT; // solution for TNEW should
5401 : // TRMOUTdv = TRMOUT; // match existing solution
5402 : // TINdv = TIN; // for T
5403 : // TRMINdv = TRMIN;
5404 : // SOURCEdv = SOURCE;
5405 :
5406 : // for (I = 1; I <= NL; ++I) {
5407 : // A(ADIM + 1, I) = HCIout(I) * TOUTdv + HRIout(I) * TRMOUTdv + HCIin(I) * TINdv + HRIin(I) * TRMINdv + SOURCEdv(I);
5408 : // A(I, I) = HCIout(I) + HRIout(I) + HCIin(I) + HRIin(I);
5409 : // for (J = 1; J <= NL; ++J) {
5410 : // if (J != I) {
5411 : // A(I, I) += HC2D(J, I) + HR2D(J, I);
5412 : // A(J, I) = -1.0 * (HC2D(J, I) + HR2D(J, I));
5413 : // }
5414 : // }
5415 : // }
5416 :
5417 : // // SOLVE MATRIX
5418 : // // Call SOLMATS for single precision matrix solution
5419 : // SOLMATS(ADIM, A, XSOL);
5420 :
5421 : // // UNPACK SOLUTION VECTOR
5422 :
5423 : // SUMERR = 0.0;
5424 : // for (I = 1; I <= NL; ++I) {
5425 : // TNEW(I) = XSOL(I);
5426 : // SUMERR += std::abs(TNEW(I) - T(I));
5427 : // }
5428 :
5429 : //} // end (1 .EQ. 0) code disabled
5430 :
5431 : // calculate U-factor
5432 :
5433 24 : ADIM = NL;
5434 24 : A = 0.0;
5435 24 : XSOL = 0.0;
5436 24 : TNEW = 0.0;
5437 24 : TOUTdv = 1.0;
5438 24 : TRMOUTdv = 1.0;
5439 24 : TINdv = 0.0;
5440 24 : TRMINdv = 0.0;
5441 24 : SOURCEdv = 0.0;
5442 :
5443 85 : for (I = 1; I <= NL; ++I) {
5444 61 : A(ADIM + 1, I) = HCIout(I) * TOUTdv + HRIout(I) * TRMOUTdv + HCIin(I) * TINdv + HRIin(I) * TRMINdv + SOURCEdv(I);
5445 61 : A(I, I) = HCIout(I) + HRIout(I) + HCIin(I) + HRIin(I);
5446 222 : for (J = 1; J <= NL; ++J) {
5447 161 : if (J != I) {
5448 100 : A(I, I) += HC2D(J, I) + HR2D(J, I);
5449 100 : A(J, I) = -1.0 * (HC2D(J, I) + HR2D(J, I));
5450 : }
5451 : }
5452 : }
5453 :
5454 : // SOLVE MATRIX
5455 : // Call SOLMATS for single precision matrix solution
5456 24 : SOLMATS(ADIM, A, XSOL);
5457 : // UNPACK SOLUTION VECTOR
5458 :
5459 85 : for (I = 1; I <= NL; ++I) {
5460 61 : TNEW(I) = XSOL(I);
5461 : }
5462 :
5463 24 : Q_IN = HCinout * (TOUTdv - TINdv) + HRinout * (TRMOUTdv - TRMINdv);
5464 85 : for (I = 1; I <= NL; ++I) {
5465 61 : Q_IN += HCIin(I) * (TNEW(I) - TINdv) + HRIin(I) * (TNEW(I) - TRMINdv);
5466 : }
5467 24 : Q_IN += SOURCEdv(NL + 1); // this line not needed
5468 24 : UCG = Q_IN;
5469 24 : Rvalue = 5.678 / UCG;
5470 :
5471 : // calculate SHGC
5472 :
5473 24 : SHGC = 0.0;
5474 24 : if (std::abs(ISOL) > 0.01) {
5475 7 : ADIM = NL;
5476 7 : A = 0.0;
5477 7 : XSOL = 0.0;
5478 7 : TNEW = 0.0;
5479 7 : TOUTdv = 0.0;
5480 7 : TRMOUTdv = 0.0;
5481 7 : TINdv = 0.0;
5482 7 : TRMINdv = 0.0;
5483 32 : for (I = 1; I <= NL + 1; ++I) {
5484 25 : SOURCEdv(I) = SOURCE(I);
5485 : }
5486 :
5487 25 : for (I = 1; I <= NL; ++I) {
5488 18 : A(ADIM + 1, I) = HCIout(I) * TOUTdv + HRIout(I) * TRMOUTdv + HCIin(I) * TINdv + HRIin(I) * TRMINdv + SOURCEdv(I);
5489 18 : A(I, I) = HCIout(I) + HRIout(I) + HCIin(I) + HRIin(I);
5490 66 : for (J = 1; J <= NL; ++J) {
5491 48 : if (J != I) {
5492 30 : A(I, I) += HC2D(J, I) + HR2D(J, I);
5493 30 : A(J, I) = -1.0 * (HC2D(J, I) + HR2D(J, I));
5494 : }
5495 : }
5496 : }
5497 :
5498 : // SOLVE MATRIX
5499 : // Call SOLMATS for single precision matrix solution
5500 7 : SOLMATS(ADIM, A, XSOL);
5501 :
5502 : // UNPACK SOLUTION VECTOR
5503 25 : for (I = 1; I <= NL; ++I) {
5504 18 : TNEW(I) = XSOL(I);
5505 : }
5506 :
5507 7 : Q_IN = HCinout * (TOUTdv - TINdv) + HRinout * (TRMOUTdv - TRMINdv);
5508 25 : for (I = 1; I <= NL; ++I) {
5509 18 : Q_IN += HCIin(I) * (TNEW(I) - TINdv) + HRIin(I) * (TNEW(I) - TRMINdv);
5510 : }
5511 7 : Q_IN += SOURCEdv(NL + 1);
5512 :
5513 7 : SHGC = Q_IN / ISOL; // only executed if ISOL > 0.01 [W/m2]
5514 :
5515 : } // end if (ABS(ISOL) .GT. 0.01)
5516 :
5517 : // calculate FHR_OUT
5518 :
5519 24 : ADIM = NL;
5520 24 : A = 0.0;
5521 24 : XSOL = 0.0;
5522 24 : TNEW = 0.0;
5523 24 : TOUTdv = 1.0;
5524 24 : TRMOUTdv = 0.0;
5525 24 : TINdv = 0.0;
5526 24 : TRMINdv = 0.0;
5527 24 : SOURCEdv = 0.0;
5528 :
5529 85 : for (I = 1; I <= NL; ++I) {
5530 61 : A(ADIM + 1, I) = HCIout(I) * TOUTdv + HRIout(I) * TRMOUTdv + HCIin(I) * TINdv + HRIin(I) * TRMINdv + SOURCEdv(I);
5531 61 : A(I, I) = HCIout(I) + HRIout(I) + HCIin(I) + HRIin(I);
5532 222 : for (J = 1; J <= NL; ++J) {
5533 161 : if (J != I) {
5534 100 : A(I, I) += HC2D(J, I) + HR2D(J, I);
5535 100 : A(J, I) = -1.0 * (HC2D(J, I) + HR2D(J, I));
5536 : }
5537 : }
5538 : }
5539 :
5540 : // SOLVE MATRIX
5541 : // Call SOLMATS for single precision matrix solution
5542 24 : SOLMATS(ADIM, A, XSOL);
5543 :
5544 : // UNPACK SOLUTION VECTOR
5545 :
5546 85 : for (I = 1; I <= NL; ++I) {
5547 61 : TNEW(I) = XSOL(I);
5548 : }
5549 :
5550 24 : Q_IN = HCinout * (TOUTdv - TINdv) + HRinout * (TRMOUTdv - TRMINdv);
5551 85 : for (I = 1; I <= NL; ++I) {
5552 61 : Q_IN += HCIin(I) * (TNEW(I) - TINdv) + HRIin(I) * (TNEW(I) - TRMINdv);
5553 : }
5554 24 : Q_IN += SOURCEdv(NL + 1);
5555 :
5556 24 : FHR_OUT = 1.0 - (Q_IN / UCG);
5557 24 : TAE_OUT = FHR_OUT * TRMOUT + (1.0 - FHR_OUT) * TOUT;
5558 :
5559 : // calculate FHR_IN
5560 :
5561 24 : ADIM = NL;
5562 24 : A = 0.0;
5563 24 : XSOL = 0.0;
5564 24 : TNEW = 0.0;
5565 24 : TOUTdv = 0.0;
5566 24 : TRMOUTdv = 0.0;
5567 24 : TINdv = 1.0;
5568 24 : TRMINdv = 0.0;
5569 24 : SOURCEdv = 0.0;
5570 :
5571 85 : for (I = 1; I <= NL; ++I) {
5572 61 : A(ADIM + 1, I) = HCIout(I) * TOUTdv + HRIout(I) * TRMOUTdv + HCIin(I) * TINdv + HRIin(I) * TRMINdv + SOURCEdv(I);
5573 61 : A(I, I) = HCIout(I) + HRIout(I) + HCIin(I) + HRIin(I);
5574 222 : for (J = 1; J <= NL; ++J) {
5575 161 : if (J != I) {
5576 100 : A(I, I) += HC2D(J, I) + HR2D(J, I);
5577 100 : A(J, I) = -1.0 * (HC2D(J, I) + HR2D(J, I));
5578 : }
5579 : }
5580 : }
5581 :
5582 : // SOLVE MATRIX
5583 : // Call SOLMATS for single precision matrix solution
5584 24 : SOLMATS(ADIM, A, XSOL);
5585 :
5586 : // UNPACK SOLUTION VECTOR
5587 :
5588 85 : for (I = 1; I <= NL; ++I) {
5589 61 : TNEW(I) = XSOL(I);
5590 : }
5591 :
5592 24 : Q_IN = HCinout * (TOUTdv - TINdv) + HRinout * (TRMOUTdv - TRMINdv);
5593 85 : for (I = 1; I <= NL; ++I) {
5594 61 : Q_IN += HCIin(I) * (TNEW(I) - TINdv) + HRIin(I) * (TNEW(I) - TRMINdv);
5595 : }
5596 24 : Q_IN += SOURCEdv(NL + 1);
5597 :
5598 24 : FHR_IN = 1.0 + (Q_IN / UCG);
5599 24 : TAE_IN = FHR_IN * TRMIN + (1.0 - FHR_IN) * TIN;
5600 :
5601 : // double check heat gain to room
5602 : // Q_IN calculated this way should be equal to QGAIN calculated
5603 : // above with raw results from the net radiation solution
5604 : // The difference between the two is printed below
5605 : // Both include the directly transmitted solar gain
5606 :
5607 24 : Q_IN = UCG * (TAE_OUT - TAE_IN) + SHGC * ISOL;
5608 :
5609 : // End of new code - for calculating Ucg and SHGC
5610 : // restore convective heat transfer coefficients if altered earlier
5611 : // for more general resistor network - otherwise mainline will
5612 : // receive faulty data
5613 24 : if (NL >= 2) { // no OCF unless at least two layers exist
5614 24 : if (FS.G(NL - 1).GTYPE == state.dataWindowEquivalentLayer->gtyOPENin) {
5615 9 : HC[NL - 1] = SaveHCNLm;
5616 9 : HC[NL] = SaveHCNL;
5617 : }
5618 : }
5619 :
5620 24 : return ASHWAT_ThermalRatings;
5621 24 : }
5622 :
5623 13 : void DL_RES_r2(Real64 const Tg, // mean glass layer temperature, {K}
5624 : Real64 const Td, // mean diathermanous layer temperature, {K}
5625 : Real64 const Tm, // mean radiant room temperature, {K}
5626 : Real64 const rhog, // reflectance of glass layer, {-}
5627 : Real64 const rhodf, // front reflectance of diathermanous layer, {-}
5628 : Real64 const rhodb, // back reflectance of diathermanous layer, {-}
5629 : Real64 const taud, // transmittance of diathermanous layer, {-}
5630 : Real64 const rhom, // reflectance of the room, {-}
5631 : Real64 &hr_gm, // heat transfer coefficient between left and right surface {W/m2K}
5632 : Real64 &hr_gd, // heat transfer coefficient between left and middle surface {W/m2K}
5633 : Real64 &hr_md // heat transfer coefficient between right and middle surface {W/m2K}
5634 : )
5635 : {
5636 : // SUBROUTINE INFORMATION:
5637 : // AUTHOR John L. Wright, University of Waterloo,
5638 : // Mechanical Engineering, Advanced Glazing System Laboratory
5639 :
5640 : // PURPOSE OF THIS SUBROUTINE:
5641 : // Returns the radiant heat transfer coefficients between parallel surfaces:
5642 : // METHODOLOGY EMPLOYED:
5643 : // Solves radiant heat transfer coefficients between three parallel surfaces.
5644 : // The left and right surfaces are opaque with reflectance rhog and rhom, respectively.
5645 : // And the middle layer is diathermanous with transmittance taud AND reflectance rhodf
5646 : // and rhodb on the left and right sides, respectively.
5647 : // The subscripts g, d and m apply to Glass, Diathermanous layer, and mean-radiant room
5648 : // temperature in a configuration of a window with an indoor-side shading attachment
5649 : // but the analysis can be applied to any three layers in the configuration described
5650 : // above.
5651 :
5652 : Real64 Epsg;
5653 : Real64 Epsdf;
5654 : Real64 Epsdb;
5655 : Real64 Epsm;
5656 13 : Array2D<Real64> A(22, 20);
5657 13 : Array1D<Real64> X(20);
5658 : // real FSg_g, FSdf_g, FSdb_g, FSm_g
5659 : Real64 FSg_df;
5660 : Real64 FSm_df;
5661 : Real64 FSg_db;
5662 : Real64 FSm_db;
5663 : Real64 FSg_m;
5664 :
5665 : // Calculate 4 emissivities/absorptivities
5666 :
5667 13 : Epsg = 1.0 - rhog;
5668 13 : Epsdf = 1.0 - rhodf - taud;
5669 13 : Epsdb = 1.0 - rhodb - taud;
5670 13 : Epsm = 1.0 - rhom;
5671 :
5672 : // Calculate script F shape factors
5673 : // FSx_y is the portion of radiation emitted
5674 : // by surface x that arrives at surface y
5675 : // via any path - including reflections
5676 : // By reciprocity FSxy=FSyx
5677 :
5678 : // step 1: unit emission from (g) only
5679 :
5680 13 : SETUP4x4_A(rhog, rhodf, rhodb, taud, rhom, A);
5681 13 : A(5, 1) = 1.0; // unit source of radiation
5682 13 : SOLMATS(4, A, X);
5683 13 : FSg_df = X(1);
5684 : // FSg_g = X(2)
5685 13 : FSg_m = X(3);
5686 13 : FSg_db = X(4);
5687 :
5688 : // step 2: unit emission from (df) only
5689 :
5690 : // call SETUP4x4_A(rhog,rhodf,rhodb,taud,rhom,A)
5691 : // A(2,5) = 1.0 ! unit source of radiation
5692 : // call SOLMATS(4,A,X)
5693 : // FSdf_df = X(1)
5694 : // FSdf_g = X(2)
5695 : // FSdf_m = X(3)
5696 : // FSdf_db = X(4)
5697 :
5698 : // step 3: unit emission from (db) only
5699 :
5700 : // call SETUP4x4_A(rhog,rhodf,rhodb,taud,rhom,A)
5701 : // A(3,5) = 1.0 ! unit source of radiation
5702 : // call SOLMATS(4,A,X)
5703 : // FSdb_df = X(1)
5704 : // FSdb_g = X(2)
5705 : // FSdb_m = X(3)
5706 : // FSdb_db = X(4)
5707 :
5708 : // step 4: unit emission from (m) only
5709 :
5710 13 : SETUP4x4_A(rhog, rhodf, rhodb, taud, rhom, A);
5711 13 : A(5, 4) = 1.0; // unit source of radiation
5712 13 : SOLMATS(4, A, X);
5713 13 : FSm_df = X(1);
5714 : // FSm_g = X(2)
5715 : // FSm_m = X(3)
5716 13 : FSm_db = X(4);
5717 :
5718 : // calculate heat transfer coefficients
5719 : // hr_xy is the heat transfer coefficient from x to y [W/m2]
5720 : // Note: If the emissivity of either surface x or surface y is zero
5721 : // then q_xy will also be zero
5722 : // Note: This code has no problem with temperatures being equal
5723 :
5724 13 : Real64 const Td_2(pow_2(Td));
5725 13 : Real64 const Tg_2(pow_2(Tg));
5726 13 : Real64 const Tm_2(pow_2(Tm));
5727 13 : hr_gm = Epsg * Epsm * FSg_m * Constant::StefanBoltzmann * (Tg + Tm) * (Tg_2 + Tm_2);
5728 13 : hr_gd = Epsg * Epsdf * FSg_df * Constant::StefanBoltzmann * (Td + Tg) * (Td_2 + Tg_2) +
5729 13 : Epsg * Epsdb * FSg_db * Constant::StefanBoltzmann * (Td + Tg) * (Td_2 + Tg_2);
5730 13 : hr_md = Epsm * Epsdf * FSm_df * Constant::StefanBoltzmann * (Td + Tm) * (Td_2 + Tm_2) +
5731 13 : Epsm * Epsdb * FSm_db * Constant::StefanBoltzmann * (Td + Tm) * (Td_2 + Tm_2);
5732 13 : }
5733 :
5734 26 : void SETUP4x4_A(Real64 const rhog, Real64 const rhodf, Real64 const rhodb, Real64 const taud, Real64 const rhom, Array2A<Real64> A)
5735 : {
5736 : // SUBROUTINE INFORMATION:
5737 : // AUTHOR John L. Wright, University of Waterloo,
5738 : // Mechanical Engineering, Advanced Glazing System Laboratory
5739 :
5740 : // PURPOSE OF THIS SUBROUTINE:
5741 : // Returns the 4 X 4 matrix for DL_RES_r2 routine:
5742 : // METHODOLOGY EMPLOYED:
5743 : // fills in the matrix coefficients
5744 :
5745 : // Argument array dimensioning
5746 26 : A.dim(22, 20);
5747 :
5748 26 : A = 0.0;
5749 26 : A(1, 1) = 1.0;
5750 26 : A(2, 1) = -1.0 * rhog;
5751 26 : A(1, 2) = -1.0 * rhodf;
5752 26 : A(2, 2) = 1.0;
5753 26 : A(4, 2) = -1.0 * taud;
5754 26 : A(1, 3) = -1.0 * taud;
5755 26 : A(3, 3) = 1.0;
5756 26 : A(4, 3) = -1.0 * rhodb;
5757 26 : A(3, 4) = -1.0 * rhom;
5758 26 : A(4, 4) = 1.0;
5759 26 : }
5760 :
5761 10981 : Real64 FRA(Real64 const TM, // mean gas temp, K
5762 : Real64 const T, // gas layer thickness, m
5763 : Real64 const DT, // temp difference across layer, K
5764 : Real64 const AK, // gas conductance coeffs, K = AK + BK*TM + CK*TM*TM
5765 : Real64 const BK,
5766 : Real64 const CK,
5767 : Real64 const ACP, // gas specific heat coeffs, CP = ACP + BCP*TM + CCP*TM*TM
5768 : Real64 const BCP,
5769 : [[maybe_unused]] Real64 const CCP,
5770 : Real64 const AVISC, // gas viscosity coeffs, VISC = AVISC + BVISC*TM + CVISC*TM*TM
5771 : Real64 const BVISC,
5772 : [[maybe_unused]] Real64 const CVISC,
5773 : Real64 const RHOGAS // gas density, kg/m3
5774 : )
5775 : {
5776 : // AUTHOR (John Wright, University of WaterLoo, ASHRAE 1311-RP)
5777 : // MODIFIED Bereket Nigusse, FSEC/UCF, May 2013
5778 :
5779 : // PURPOSE OF THIS FUNCTION:
5780 : // Returns Rayleigh number given surface temperatures, and coefficients of
5781 : // quadratic correlations as a function of temperature for gas properties
5782 :
5783 : // METHODOLOGY EMPLOYED:
5784 : // Ra = Gr * Pr
5785 :
5786 : // REFERENCES:
5787 : // ASHRAE 1311-RP
5788 :
5789 : // FUNCTION ARGUMENT DEFINITIONS:
5790 : // (as adjusted e.g. re VB models)
5791 :
5792 10981 : Real64 Z = 1.0;
5793 10981 : Real64 K = AK + BK * TM + CK * TM * TM;
5794 10981 : Real64 CP = ACP + BCP * TM + BCP * TM * TM;
5795 10981 : Real64 VISC = AVISC + BVISC * TM + BVISC * TM * TM;
5796 :
5797 10981 : return (Constant::Gravity * RHOGAS * RHOGAS * DT * T * T * T * CP) / (VISC * K * TM * Z * Z);
5798 : }
5799 :
5800 10981 : Real64 FNU(Real64 const RA) // Rayleigh number
5801 : {
5802 : // AUTHOR (John Wright, University of WaterLoo, ASHRAE 1311-RP)
5803 : // MODIFIED Bereket Nigusse, FSEC/UCF, May 2013
5804 :
5805 : // PURPOSE OF THIS FUNCTION:
5806 : // Returns Nusselt number given Rayleigh number
5807 :
5808 : // METHODOLOGY EMPLOYED:
5809 : // Uses empirical correlation
5810 :
5811 : // REFERENCES:
5812 : // ASHRAE 1311-RP
5813 :
5814 10981 : Real64 const ARA(std::abs(RA));
5815 10981 : if (ARA <= 10000.0) {
5816 10981 : return 1.0 + 1.75967e-10 * std::pow(ARA, 2.2984755);
5817 0 : } else if (ARA <= 50000.0) {
5818 0 : return 0.028154 * std::pow(ARA, 0.413993);
5819 : } else {
5820 0 : return 0.0673838 * std::pow(ARA, 1.0 / 3.0);
5821 : }
5822 : }
5823 :
5824 10981 : Real64 HConvGap(CFSGAP const &G, // gap
5825 : Real64 const T1, // bounding surface temps (K)
5826 : Real64 const T2)
5827 : {
5828 : // AUTHOR (University of WaterLoo, ASHRAE 1311-RP)
5829 : // MODIFIED Bereket Nigusse, FSEC/UCF, May 2013
5830 : // PURPOSE OF THIS FUNCTION:
5831 : // Returns convective coefficient for a gap separated between two surfaces at
5832 : // temperatures T1 and T2 , W/m2-K
5833 : // METHODOLOGY EMPLOYED:
5834 : // HConv = "Nusselt Number" * "Conductivity Of Gas" / "Thickness Of Gap"
5835 : // REFERENCES:
5836 : // ASHRAE 1311-RP
5837 :
5838 : Real64 TM; // Mean temperature, K
5839 : Real64 DT; // temperature difference, (K)
5840 : Real64 RA; // Rayleigh Number, (-)
5841 : Real64 NU; // Nusselt Number, (-)
5842 : Real64 KGAS; // Gas conductivity at film temp, (W/m.K)
5843 : Real64 T; // effective gap spacing, m
5844 :
5845 10981 : T = G.TAS_EFF;
5846 10981 : TM = (T1 + T2) / 2.0;
5847 10981 : DT = T1 - T2;
5848 10981 : RA = FRA(TM, T, DT, G.FG.AK, G.FG.BK, G.FG.CK, G.FG.ACP, G.FG.BCP, G.FG.CCP, G.FG.AVISC, G.FG.BVISC, G.FG.CVISC, G.RHOGAS);
5849 10981 : NU = FNU(RA);
5850 :
5851 10981 : KGAS = G.FG.AK + G.FG.BK * TM + G.FG.CK * TM * TM;
5852 10981 : return NU * KGAS / T;
5853 : }
5854 :
5855 59 : Real64 HRadPar(Real64 const T1, // bounding surface temps [K]
5856 : Real64 const T2,
5857 : Real64 const E1, // bounding surface emissivities
5858 : Real64 const E2)
5859 : {
5860 : // AUTHOR ASHRAE 1311-RP
5861 : // PURPOSE OF THIS FUNCTION:
5862 : // Returns radiative coefficient between two surfaces, hr, W/m2-K
5863 : // METHODOLOGY EMPLOYED:
5864 : // Radiative coefficient for parallel, opaque plates configuration and
5865 : // automatically reverts to small-object-in-large-enclosure if one of
5866 : // the emissivities is set to unity i.e., set E1=1 and surface 2 is the
5867 : // small object with hr based on area A2 If one emissivity is zero then
5868 : // hr=0, division by zero is, avoided even if T1=T2.
5869 : // REFERENCES:
5870 : // ASHRAE 1311-RP
5871 :
5872 : // Return value
5873 : Real64 HRadPar;
5874 :
5875 : Real64 DV; // dummy variable
5876 :
5877 59 : HRadPar = 0.0;
5878 59 : if ((E1 > 0.001) && (E2 > 0.001)) {
5879 59 : DV = (1.0 / E1) + (1.0 / E2) - 1.0;
5880 59 : HRadPar = (Constant::StefanBoltzmann / DV) * (T1 + T2) * (pow_2(T1) + pow_2(T2));
5881 : }
5882 59 : return HRadPar;
5883 : }
5884 :
5885 0 : Real64 HIC_ASHRAE(Real64 const L, // glazing height, m
5886 : Real64 const TG, // glazing inside surf temp, C or K
5887 : Real64 const TI // inside air temp, C or K
5888 : )
5889 : {
5890 : // AUTHOR ASHRAE 1311-RP
5891 : // PURPOSE OF THIS FUNCTION:
5892 : // Returns inside surface convective coefficient, W/m2-K
5893 :
5894 : // REFERENCES:
5895 : // Footnote on Table 2, p. 31.6 (Fenestration) HOF 2005
5896 :
5897 : // Return value
5898 : Real64 HIC_ASHRAE;
5899 :
5900 0 : HIC_ASHRAE = 1.46 * root_4(std::abs(TG - TI) / max(L, 0.001));
5901 0 : return HIC_ASHRAE;
5902 : }
5903 :
5904 8485 : void SLtoGL(EnergyPlusData const &state,
5905 : Real64 const breal, // distance from shade to glass (m)
5906 : Real64 const Ts, // shade temperature (K)
5907 : Real64 const Tg, // glass temperature (K)
5908 : Real64 &hsg, // the heat transfer coefficient, shade-to-glass, {W/m2K}
5909 : int const scheme)
5910 : {
5911 : // SUBROUTINE INFORMATION:
5912 : // AUTHOR John L. Wright, University of Waterloo,
5913 : // Mechanical Engineering, Advanced Glazing System Laboratory
5914 :
5915 : // PURPOSE OF THIS SUBROUTINE:
5916 : // Returns the heat transfer coefficient, shade-to-glass
5917 :
5918 : Real64 b;
5919 : Real64 Tavg;
5920 : Real64 rho;
5921 : Real64 beta;
5922 : Real64 dvisc;
5923 : Real64 Cp;
5924 : Real64 k;
5925 : Real64 Rabsg;
5926 : Real64 Nubsg;
5927 :
5928 8485 : hsg = 0.0; // default - large spacing, b
5929 :
5930 8485 : if (scheme == 1) { // simple conduction layer, Nu=1
5931 :
5932 8485 : b = breal;
5933 8485 : if (b < 0.00001) {
5934 0 : b = 0.00001; // avoid division by zero in
5935 : }
5936 : // calculation of this scheme
5937 :
5938 8485 : Tavg = (Ts + Tg) / 2.0; // T for properties calculations
5939 8485 : k = 0.02538 + ((Tavg - 290.0) / 10.0) * (0.02614 - 0.02538); // conductivity (W/m.K)
5940 8485 : hsg = k / b;
5941 :
5942 0 : } else if (scheme == 2) { // similar to Nu=1 but small penalty at
5943 : // larger Ra (Collins)
5944 0 : b = breal;
5945 0 : if (b < 0.00001) {
5946 0 : b = 0.00001; // avoid division by zero in
5947 : }
5948 : // calculation of this scheme
5949 :
5950 0 : Tavg = (Ts + Tg) / 2.0; // T for properties calculations
5951 :
5952 : // properties of AIR
5953 0 : rho = state.dataWindowEquivalentLayer->PAtmSeaLevel / (287.097 * Tavg); // density (kg/m3) <- temperature in (K)
5954 0 : beta = 1.0 / Tavg; // thermal expansion coeff (/K)
5955 0 : dvisc = (18.05 + ((Tavg - 290.0) / 10.0) * (18.53 - 18.05)) * 1.0e-6;
5956 : // dynamic viscosity (kg/m.sec) or (N.sec/m2)
5957 0 : Cp = 1044.66 - 0.31597 * Tavg + 0.000707908 * pow_2(Tavg) - 0.00000027034 * pow_3(Tavg);
5958 : // specific heat at constant pressure (J/kg.K)
5959 0 : k = 0.02538 + ((Tavg - 290.0) / 10.0) * (0.02614 - 0.02538); // conductivity (W/m.K)
5960 :
5961 0 : Rabsg = (9.81 * beta * pow_3(b) * std::abs(Ts - Tg) * pow_2(rho) * Cp) / (dvisc * k);
5962 0 : Nubsg = 1.0 + 0.2 * (1.0 - std::exp(-0.005 * Rabsg));
5963 :
5964 0 : hsg = Nubsg * k / b;
5965 : } // end of scheme .eq. 2
5966 8485 : }
5967 :
5968 8485 : Real64 SLtoAMB(EnergyPlusData const &state,
5969 : Real64 const b, // distance from shade to glass (m) where air flow takes place
5970 : Real64 const L, // window height, m (usually taken as 1 m)
5971 : Real64 const Ts, // shade temperature, K
5972 : Real64 const Tamb, // room air temperature, K
5973 : Real64 const hc_in, // indoor (room) convective transfer coeff, W/m2K)
5974 : int const scheme // flag to select model, scheme=2 has problems
5975 : )
5976 : {
5977 : // AUTHOR ASHRAE 1311-RP
5978 : // PURPOSE OF THIS FUNCTION:
5979 : // Returns shade to room air heat transfer coefficient
5980 : // METHODOLOGY EMPLOYED:
5981 : // fill gas is always air, orientation is always vertical
5982 : // hsamb should be h-flatplate at b=0 and 2*h-flatplate at b=large. Note
5983 : // that hsamb is the same at slat angle = 0, 90, -90 degrees but increase
5984 : // by 20% at slat angle =45 degrees to mimic air pumping between slats
5985 : // therefore, specify slat angle=0 or 90 or -90 is shade is other than
5986 : // a venetian blind
5987 :
5988 : // Return value
5989 : Real64 SLtoAMB;
5990 :
5991 : // FUNCTION ARGUMENT DEFINITIONS:
5992 : // scheme=3 recommended
5993 :
5994 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
5995 : // a
5996 : Real64 Tavg;
5997 : Real64 rho;
5998 : Real64 beta;
5999 : Real64 dvisc;
6000 : Real64 Cp;
6001 : Real64 k;
6002 : Real64 Rabsa;
6003 : Real64 hfp;
6004 :
6005 8485 : SLtoAMB = 2.0 * hc_in; // DEFAULT - convection from both sides
6006 : // of shading layer - large spacing, b
6007 :
6008 8485 : if (scheme == 1) {
6009 : // properties of AIR
6010 0 : Tavg = (Ts + Tamb) / 2.0;
6011 0 : rho = state.dataWindowEquivalentLayer->PAtmSeaLevel / (287.097 * Tavg); // density (kg/m3) <- temperature in (K)
6012 0 : beta = 1.0 / Tavg; // thermal expansion coeff (/K)
6013 0 : dvisc = (18.05 + ((Tavg - 290.0) / 10.0) * (18.53 - 18.05)) * 1.0e-6;
6014 : // dynamic viscosity (kg/m.sec) or (N.sec/m2)
6015 0 : Cp = 1044.66 - 0.31597 * Tavg + 0.000707908 * pow_2(Tavg) - 0.00000027034 * pow_3(Tavg);
6016 : // specific heat at constant pressure (J/kg.K)
6017 0 : k = 0.02538 + ((Tavg - 290.0) / 10.0) * (0.02614 - 0.02538); // conductivity (W/m.K)
6018 :
6019 0 : Rabsa = (9.81 * beta * pow_3(b) * std::abs(Ts - Tamb) * pow_2(rho) * Cp) / (dvisc * k);
6020 0 : if (Rabsa <= 1.0) {
6021 0 : Rabsa = 1.0;
6022 : }
6023 :
6024 0 : hfp = HIC_ASHRAE(L, Ts, Tamb); // h - flat plate, influence by
6025 : // window height and temperature
6026 : // difference. Note: hfp goes to
6027 : // zero as delta-T goes to zero
6028 :
6029 : // now adjust for distance from window glass
6030 0 : SLtoAMB = hfp * (1.0 + std::exp(-6000.0 / Rabsa));
6031 : // SLtoAmb goes to 2*hfp at large b and hfp at small b and small (20%)
6032 : // penalty is applied if slat angle is not zero or +/- 90 degrees
6033 : // Note: influence of distance is lost if delta-T goes to zero
6034 : // Note: as delta-T -> zero, Rabga->0, SLtoAmb -> hfp, not 2hfp,
6035 : // for any spacing, even large b. This is a problem
6036 :
6037 8485 : } else if (scheme == 2) {
6038 : // properties of AIR
6039 0 : Tavg = (Ts + Tamb) / 2.0;
6040 0 : rho = state.dataWindowEquivalentLayer->PAtmSeaLevel / (287.097 * Tavg); // density (kg/m3) <- temperature in (K)
6041 0 : beta = 1.0 / Tavg; // thermal expansion coeff (/K)
6042 0 : dvisc = (18.05 + ((Tavg - 290.0) / 10.0) * (18.53 - 18.05)) * 1.0e-6;
6043 : // dynamic viscosity (kg/m.sec) or (N.sec/m2)
6044 0 : Cp = 1044.66 - 0.31597 * Tavg + 0.000707908 * pow_2(Tavg) - 0.00000027034 * pow_3(Tavg);
6045 : // specific heat at constant pressure (J/kg.K)
6046 0 : k = 0.02538 + ((Tavg - 290.0) / 10.0) * (0.02614 - 0.02538); // conductivity (W/m.K)
6047 :
6048 0 : Rabsa = (9.81 * beta * pow_3(b) * std::abs(Ts - Tamb) * pow_2(rho) * Cp) / (dvisc * k);
6049 0 : if (Rabsa <= 1.0) {
6050 0 : Rabsa = 1.0;
6051 : }
6052 :
6053 0 : hfp = hc_in; // h - flat plate - from calling routine
6054 : // Note: using this approach, L no longer has influence on hfp
6055 :
6056 : // now adjust for distance from window glass
6057 0 : SLtoAMB = hfp * (1.0 + std::exp(-6000.0 / Rabsa));
6058 : // Note: as delta-T -> zero, Rabga->0, SLtoAmb -> hfp, not 2hfp,
6059 : // for any spacing, even large b. This is a problem
6060 :
6061 8485 : } else if (scheme == 3) {
6062 :
6063 8485 : hfp = hc_in; // h - flat plate - from calling routine
6064 : // now adjust for distance from window glass
6065 8485 : SLtoAMB = hfp * (2.0 - std::exp(-4.6 * b / 0.1));
6066 : // Note: using this approach, L and temperatures no longer have
6067 : // influence on result
6068 : // SLtoAmb = 2*hc_in when glass/shade spacing, b, is large
6069 : // SLtoAmb = hc_in when glass/shade spacing, b, is zero
6070 : // The exponential decay is 99% complete at b=4 inches = 0.1 m
6071 : // ln(0.01) = -4.6
6072 : // This coefficient could be fine tuned in future versions, perhaps
6073 : // as a function of boundary layer thickness for specific values
6074 : // of glass and shade temperatures
6075 : } // end of scheme .eq. 3
6076 8485 : return SLtoAMB;
6077 : }
6078 :
6079 8485 : void GLtoAMB(EnergyPlusData const &state,
6080 : Real64 const b, // distance from shade to glass {m}
6081 : Real64 const L, // window height {m}, usually taken as 1 meter
6082 : Real64 const Tg, // glass temperature {K}
6083 : Real64 const Tamb, // room air temperature, {K}
6084 : Real64 const hc_in, // inside convection coefficient, {W/m2K}
6085 : Real64 &hgamb, // glass to room air heat transfer coefficient
6086 : int const scheme)
6087 : {
6088 : // SUBROUTINE INFORMATION:
6089 : // AUTHOR John L. Wright, University of Waterloo,
6090 : // Mechanical Engineering, Advanced Glazing System Laboratory
6091 :
6092 : // PURPOSE OF THIS SUBROUTINE:
6093 : // Returns the glass to room air heat transfer coefficient
6094 : // METHODOLOGY EMPLOYED:
6095 : // scheme = flag to select model, scheme=2 has problems, scheme=3 recommended
6096 : // fill gas is always air, orientation is always vertical
6097 : // hgamb should be zero at b=0, h-flatplate at b=large
6098 :
6099 : Real64 Tavg;
6100 : Real64 rho;
6101 : Real64 beta;
6102 : Real64 dvisc;
6103 : Real64 Cp;
6104 : Real64 k;
6105 : Real64 Rabga;
6106 : Real64 hfp;
6107 :
6108 8485 : hgamb = hc_in; // default - good for large glass/shade spacing
6109 :
6110 8485 : if (scheme == 1) { // Collins
6111 :
6112 0 : Tavg = (Tg + Tamb) / 2.0; // T for properties calculations
6113 :
6114 : // properties of AIR
6115 0 : rho = state.dataWindowEquivalentLayer->PAtmSeaLevel / (287.097 * Tavg); // density (kg/m3) <- temperature in (K)
6116 0 : beta = 1.0 / Tavg; // thermal expansion coeff (/K)
6117 0 : dvisc = (18.05 + ((Tavg - 290.0) / 10.0) * (18.53 - 18.05)) * 1.0e-6;
6118 : // dynamic viscosity (kg/m.sec) or (N.sec/m2)
6119 0 : Cp = 1044.66 - 0.31597 * Tavg + 0.000707908 * pow_2(Tavg) - 0.00000027034 * pow_3(Tavg);
6120 : // specific heat at constant pressure (J/kg.K)
6121 0 : k = 0.02538 + ((Tavg - 290.0) / 10.0) * (0.02614 - 0.02538); // conductivity (W/m.K)
6122 :
6123 0 : Rabga = (9.81 * beta * pow_3(b) * std::abs(Tg - Tamb) * pow_2(rho) * Cp) / (dvisc * k);
6124 0 : if (Rabga <= 1.0) {
6125 0 : Rabga = 1.0;
6126 : }
6127 :
6128 0 : hfp = HIC_ASHRAE(L, Tg, Tamb); // h - flat plate
6129 : // Note: as delta-T goes to zero, hfp will also go to zero
6130 :
6131 0 : hgamb = hfp * std::exp(-50.0 / Rabga);
6132 : // Note: as delta-T -> zero, Rabga->0, hgamb -> zero too
6133 : // for any spacing, even large b. This is a problem
6134 :
6135 8485 : } else if (scheme == 2) {
6136 :
6137 0 : Tavg = (Tg + Tamb) / 2.0; // T for properties calculations
6138 :
6139 : // properties of AIR
6140 0 : rho = state.dataWindowEquivalentLayer->PAtmSeaLevel / (287.097 * Tavg); // density (kg/m3) <- temperature in (K)
6141 0 : beta = 1.0 / Tavg; // thermal expansion coeff (/K)
6142 0 : dvisc = (18.05 + ((Tavg - 290.0) / 10.0) * (18.53 - 18.05)) * 1.0e-6;
6143 : // dynamic viscosity (kg/m.sec) or (N.sec/m2)
6144 0 : Cp = 1044.66 - 0.31597 * Tavg + 0.000707908 * pow_2(Tavg) - 0.00000027034 * pow_3(Tavg);
6145 : // specific heat at constant pressure (J/kg.K)
6146 0 : k = 0.02538 + ((Tavg - 290.0) / 10.0) * (0.02614 - 0.02538); // conductivity (W/m.K)
6147 :
6148 0 : Rabga = (9.81 * beta * pow_3(b) * std::abs(Tg - Tamb) * pow_2(rho) * Cp) / (dvisc * k);
6149 0 : if (Rabga <= 1.0) {
6150 0 : Rabga = 1.0;
6151 : }
6152 :
6153 0 : hfp = hc_in; // h - flat plate - from calling routine
6154 : // Note: using this approach, L no longer has influence on result
6155 : // but temperature does and it will drive hgamb to zero when
6156 : // the temperature difference goes to zero
6157 :
6158 0 : hgamb = hfp * std::exp(-50.0 / Rabga);
6159 : // Note: as delta-T -> zero, Rabga->0, hgamb -> zero too
6160 : // for any spacing, even large b. This is a problem
6161 :
6162 8485 : } else if (scheme == 3) {
6163 :
6164 8485 : hfp = hc_in; // h - flat plate - from calling routine
6165 8485 : hgamb = hfp * (1.0 - std::exp(-4.6 * b / 0.1));
6166 : // Note: using this approach, L and temperatures no longer have
6167 : // influence on result
6168 : // hgamb = hc_in when glass/shade spacing, b, is large
6169 : // hgamb = zero when glass/shade spacing, b, is zero
6170 : // The exponential decay is 99% complete at b=4 inches = 0.1 m
6171 : // ln(0.01) = -4.6
6172 : // This coefficient could be fine tuned in future versions, perhaps
6173 : // as a function of boundary layer thickness for specific values
6174 : // of glass and shade temperatures
6175 :
6176 : } // end of scheme .eq. 3
6177 8485 : }
6178 :
6179 8485 : Real64 ConvectionFactor(CFSLAYER const &L) // window layer
6180 : {
6181 : // AUTHOR ASHRAE 1311-RP
6182 : // PURPOSE OF THIS FUNCTION:
6183 : // Modifies convection rate per shade configuration, layer convection enhancement
6184 :
6185 8485 : if (L.LTYPE == LayerType::VBHOR) {
6186 : // horiz VB: enhanced convection at +/- 45 due to "pumping"
6187 0 : Real64 SlatADeg = min(90.0, std::abs(L.PHI_DEG));
6188 0 : return 1.0 + 0.2 * std::sin(2.0 * SlatADeg);
6189 : } else {
6190 8485 : return 1.0;
6191 : }
6192 : }
6193 :
6194 17 : bool CFSUFactor(EnergyPlusData &state,
6195 : CFSTY const &FS, // fenestration system
6196 : Real64 const TOUT, // outdoor temperature, C (air and MRT)
6197 : Real64 const HCOUT, // outdoor convective coefficient, W/m2-K
6198 : Real64 const TIN, // indoor air temperature, C
6199 : Real64 const HCIN, // indoor convective coefficient, W/m2-K
6200 : Real64 &U // returned: U factor, W/m2-K
6201 : )
6202 : {
6203 : // FUNCTION INFORMATION:
6204 : // AUTHOR unknown (University of WaterLoo, ASHRAE 1311-RP)
6205 : // MODIFIED Bereket Nigusse, FSEC/UCF, June 2013
6206 :
6207 : // PURPOSE OF THIS FUNCTION:
6208 : // ! returns .TRUE. if the U-value calculation succeeded, .FALSE. if error
6209 :
6210 : // METHODOLOGY EMPLOYED:
6211 : // uses net radiation method to solve for window surface temperatures and
6212 : // heat fluxes. Then calculates the U-value from the flux and over all
6213 : // temperature difference.
6214 :
6215 : // REFERENCES:
6216 : // ASHRAE 1311-RP
6217 :
6218 : // Return value
6219 : bool CFSUFactor;
6220 :
6221 : // Locals
6222 : // FUNCTION ARGUMENT DEFINITIONS:
6223 : // for conditions specified (no incident solar)
6224 : // FUNCTION PARAMETER DEFINITIONS:
6225 17 : Real64 constexpr TOL(0.01); // 0.0001d0
6226 :
6227 : int NL;
6228 : Real64 TOABS;
6229 : Real64 TRMOUT;
6230 : Real64 TIABS;
6231 : Real64 TRMIN;
6232 17 : Array1D<Real64> QOCF(FS.NL);
6233 : Real64 QOCFRoom;
6234 17 : Array1D<Real64> JB({0, FS.NL});
6235 17 : Array1D<Real64> JF({1, FS.NL + 1});
6236 17 : Array1D<Real64> T(FS.NL);
6237 17 : Array1D<Real64> Q({0, FS.NL});
6238 17 : Array1D<Real64> H({0, FS.NL + 1});
6239 17 : Array1D<Real64> SOURCE(FS.NL + 1);
6240 : Real64 ISOL;
6241 : Real64 SHGC;
6242 :
6243 17 : CFSUFactor = false;
6244 17 : if (std::abs(TOUT - TIN) < 0.01) {
6245 0 : U = -1.0;
6246 0 : return CFSUFactor;
6247 : }
6248 :
6249 17 : TOABS = TOUT + Constant::Kelvin;
6250 17 : TRMOUT = TOABS;
6251 17 : TIABS = TIN + Constant::Kelvin;
6252 17 : TRMIN = TIABS;
6253 :
6254 17 : NL = FS.NL;
6255 17 : ISOL = 0.0; // no solar winter condition
6256 17 : SOURCE = 0.0;
6257 :
6258 17 : CFSUFactor = ASHWAT_ThermalRatings(
6259 34 : state, FS, TIABS, TOABS, HCIN, HCOUT, TRMOUT, TRMIN, ISOL, SOURCE({1, NL + 1}), TOL, QOCF, QOCFRoom, T, Q, JF, JB, H, U, SHGC, true);
6260 :
6261 17 : return CFSUFactor;
6262 17 : }
6263 :
6264 1450 : void ASHWAT_Solar(int const NL, // # of layers
6265 : Array1S<CFSSWP> const LSWP_ON, // layer SW (solar) properties (off-normal adjusted)
6266 : CFSSWP const &SWP_ROOM, // effective SW (solar) properties of room
6267 : Real64 const IBEAM, // incident beam insolation (W/m2 aperture)
6268 : Real64 const IDIFF, // incident diffuse insolation (W/m2 aperture)
6269 : Real64 const ILIGHTS, // incident diffuse insolation (W/m2 aperture)
6270 : Array1S<Real64> SOURCE, // returned: layer-by-layer flux of absorbed
6271 : ObjexxFCL::Optional<Array1S<Real64>> SourceBD // returned: layer-by-layer flux of absorbed
6272 : )
6273 : {
6274 : // SUBROUTINE INFORMATION:
6275 : // AUTHOR JOHN L. WRIGHT and NATHAN KOTEY,
6276 : // DATE WRITTEN June, 2006
6277 : // MODIFIED Bereket Nigusse, JUNE 2013
6278 : // RE-ENGINEERED na
6279 :
6280 : // PURPOSE OF THIS SUBROUTINE:
6281 : // Returns the optical properties of multi-layer fenestration system model given optical
6282 : // properties of the layers
6283 : // METHODOLOGY EMPLOYED:
6284 : // Use combination net radiation method and TDMA solver
6285 : // REFERENCES:
6286 : // JOHN L. WRIGHT and NATHAN KOTEY (2006). Solar Absorption By each Element in a Glazing/Shading
6287 : // Layer Array, ASHRAE Transactions, Vol. 112, Pt. 2. pp. 3-12.
6288 : // University of Waterloo, Mechanical Engineering
6289 : // Advanced Glazing System Laboratory
6290 :
6291 : // SUBROUTINE ARGUMENT DEFINITIONS:
6292 : // 1=outside .. NL=inside
6293 : // generally black or minimally reflective
6294 : // on inside surface (e.g., from lights)
6295 : // solar radiation (beam-beam + beam-diffuse) (W/m2)
6296 : // SOURCE(NL+1) is the flux of solar radiation
6297 : // absorbed in conditioned space (W/m2 aperture area)
6298 : // beam-diffuse solar radiation (W/m2)
6299 : // SOURCE_BD(NL+1) is the flux of beam-diffuse solar radiation
6300 : // absorbed in conditioned space (W/m2 aperture area)
6301 : // or this beam-diffuse solar transmittance of the system
6302 :
6303 1450 : Array1D<Real64> BPLUS({0, NL}); // beam solar fluxes flowing in outward and inward directions
6304 1450 : Array1D<Real64> BMINUS({0, NL});
6305 : // correspond to Edwards QPLUS and QMINUS (except note
6306 : // reverse layer numbering)
6307 1450 : Array1D<Real64> CPLUS({0, NL}); // diffuse solar fluxes caused by BPLUS and BMINUS;
6308 1450 : Array1D<Real64> CMINUS({0, NL});
6309 : // appear as sources in diffuse calculation
6310 1450 : Array1D<Real64> DPLUS({0, NL}); // diffuse solar fluxes flowing in outward and inward
6311 1450 : Array1D<Real64> DMINUS({0, NL});
6312 : // directions (W/m2)
6313 1450 : Array1D<Real64> AP(2 * NL);
6314 1450 : Array1D<Real64> AE(2 * NL);
6315 1450 : Array1D<Real64> AW(2 * NL);
6316 1450 : Array1D<Real64> BP(2 * NL);
6317 1450 : Array1D<Real64> X(2 * NL);
6318 : Real64 CHKSUM;
6319 1450 : Array1D<Real64> BeamDiffuseAbs(NL + 1); // beam-diffuse absorbed fraction of beam radiation (W/m2)
6320 : int N_TDMA;
6321 : int I;
6322 : int LINE;
6323 :
6324 1450 : if (NL < 1) {
6325 0 : return;
6326 : }
6327 :
6328 : // STEP ONE: THE BEAM-BEAM ANALYSIS TO FIND BPLUS AND BMINUS
6329 1450 : NETRAD(NL, LSWP_ON, SWP_ROOM.RHOSFBB, IBEAM, BPLUS, BMINUS);
6330 :
6331 : // STEP TWO: CALCULATE THE DIFFUSE-CAUSED-BY-BEAM SOURCES CPLUS AND CMINUS
6332 1450 : CPLUS(NL) = SWP_ROOM.RHOSFBD * BMINUS(NL);
6333 5492 : for (I = NL; I >= 1; --I) { // March through layers, indoor to outdoor
6334 4042 : CPLUS(I - 1) = LSWP_ON(I).RHOSFBD * BMINUS(I - 1) + LSWP_ON(I).TAUSBBD * BPLUS(I);
6335 4042 : CMINUS(I) = LSWP_ON(I).RHOSBBD * BPLUS(I) + LSWP_ON(I).TAUSFBD * BMINUS(I - 1);
6336 : }
6337 1450 : CMINUS(0) = 0.0;
6338 :
6339 : // STEP THREE: DIFFUSE FLUXES, DPLUS AND DMINUS,
6340 : // CAUSED BY DIFFUSE INCIDENT, IDIFF ON THE OUTDOOR SIDE
6341 : // AND BY ILIGHTS ON THE INDOOR SIDE, AND BY
6342 : // DIFFUSE SOURCE (FROM BEAM) FLUXES, CPLUS AND CMINUS
6343 :
6344 1450 : N_TDMA = 2 * NL;
6345 :
6346 5492 : for (I = 1; I <= NL; ++I) {
6347 4042 : LINE = (2 * I) - 1;
6348 4042 : AP(LINE) = LSWP_ON(I).RHOSBDD;
6349 4042 : AE(LINE) = 1.0;
6350 4042 : if (LINE != 1) { // default
6351 2592 : AW(LINE) = -1.0 * LSWP_ON(I).TAUS_DD;
6352 2592 : BP(LINE) = -1.0 * CMINUS(I);
6353 : } else { // special case at west-most node
6354 1450 : AW(1) = 0.0;
6355 1450 : BP(1) = -1.0 * LSWP_ON(1).TAUS_DD * IDIFF - CMINUS(1);
6356 : }
6357 :
6358 4042 : LINE = (2 * I);
6359 4042 : AW(LINE) = 1.0;
6360 4042 : if (LINE != N_TDMA) { // default
6361 2592 : AP(LINE) = LSWP_ON(I + 1).RHOSFDD;
6362 2592 : AE(LINE) = -1.0 * LSWP_ON(I + 1).TAUS_DD;
6363 2592 : BP(LINE) = -1.0 * CPLUS(I);
6364 : } else { // special case at east-most node
6365 1450 : AP(LINE) = SWP_ROOM.RHOSFDD;
6366 1450 : BP(N_TDMA) = -1.0 * (CPLUS(NL) + ILIGHTS);
6367 1450 : AE(N_TDMA) = 0.0;
6368 : }
6369 : }
6370 :
6371 1450 : AUTOTDMA(X, AP, AE, AW, BP, N_TDMA);
6372 :
6373 : // UNPACK TDMA SOLUTION VECTOR
6374 5492 : for (I = 1; I <= NL; ++I) {
6375 4042 : LINE = (2 * I) - 1;
6376 4042 : DPLUS(I) = X(LINE);
6377 4042 : LINE = (2 * I);
6378 4042 : DMINUS(I) = X(LINE);
6379 : }
6380 :
6381 : // Finish up diffuse calculations
6382 1450 : DMINUS(0) = IDIFF;
6383 1450 : DPLUS(0) = LSWP_ON(1).RHOSFDD * DMINUS(0) + LSWP_ON(1).TAUS_DD * DPLUS(1) + CPLUS(0);
6384 :
6385 : // STEP FOUR: ABSORBED SOLAR RADIATION AT EACH LAYER/NODE
6386 1450 : SOURCE = 0.0;
6387 1450 : SOURCE(NL + 1) = BMINUS(NL) - BPLUS(NL) + DMINUS(NL) - DPLUS(NL) + ILIGHTS; // SOLAR FLUX | TRANSMITTED TO | ROOM
6388 :
6389 : // NOTE: In calculating SOURCE(room) there is a trick included in the
6390 : // previous line: ILIGHTS is added because it is included
6391 : // in DPLUS(NL) but ILIGHTS should not be included in this
6392 : // type of calculation of SOURCE(i). No similar adjustment
6393 : // is needed for any of the other values of SOURCE(i)
6394 : // As an alternative get the same result using:
6395 : // SOURCE(NL+1) = BMINUS(NL)*(1.0 - SWP_ROOM%RHOSFBB - SWP_ROOM%RHOSFBD) +
6396 : // & DMINUS(NL)*(1.0 - SWP_ROOM%RHOSFDD)
6397 : // Take your pick
6398 :
6399 : // Added by BAN, June 7, 2013 to extract the beam-diffuse component for use
6400 : // in the EnergyPLus heat balance. EnergyPlus requires the beam-beam and
6401 : // Beam-diffuse components separately.
6402 1450 : BeamDiffuseAbs = 0.0;
6403 1450 : BeamDiffuseAbs(NL + 1) = DMINUS(NL) - DPLUS(NL); // beam-diffuse transmitted to the room
6404 5492 : for (I = 1; I <= NL; ++I) {
6405 4042 : SOURCE(I) = BPLUS(I) - BMINUS(I) - BPLUS(I - 1) + BMINUS(I - 1) + DPLUS(I) - DMINUS(I) - DPLUS(I - 1) + DMINUS(I - 1);
6406 : // Added by BAN June 7, 2013
6407 4042 : BeamDiffuseAbs(I) = 0.0;
6408 : }
6409 :
6410 1450 : if (present(SourceBD)) {
6411 794 : SourceBD = BeamDiffuseAbs;
6412 : }
6413 : // CHECKSUM - ALL INCOMING SOLAR FLUX MUST GO SOMEWHERE, SHOULD EQUAL ZERO
6414 1450 : CHKSUM = IBEAM + IDIFF + ILIGHTS - BPLUS(0) - DPLUS(0);
6415 6942 : for (I = 1; I <= NL + 1; ++I) {
6416 5492 : CHKSUM -= SOURCE(I);
6417 : }
6418 1450 : }
6419 :
6420 1450 : void NETRAD(int const NL, // # of layers, 1=outside .. NL=inside
6421 : Array1S<CFSSWP> const LSWP_ON, // layer SW (solar) properties (off-normal adjusted)
6422 : Real64 const RHO_room, // effective solar reflectance of room (at inside)
6423 : Real64 const ISOL, // incident flux (W/m2)
6424 : Array1D<Real64> &QPLUS, // returned: see Edwards paper
6425 : Array1D<Real64> &QMINUS // returned: see Edwards paper
6426 : )
6427 : {
6428 : // SUBROUTINE INFORMATION:
6429 : // AUTHOR JOHN L. WRIGHT
6430 : // DATE WRITTEN unknown
6431 : // MODIFIED na
6432 : // RE-ENGINEERED Autodesk:F2C++ Reworked to avoid complex member array usage
6433 :
6434 : // PURPOSE OF THIS SUBROUTINE:
6435 : // Returns the solar radiant fluxes between glazing layers
6436 : // METHODOLOGY EMPLOYED:
6437 : // Net Radiation Method by LARGELY EDWARDS
6438 : // TED, RED, QPLUS, QMINUS correspond to variables found in "Edwards"
6439 : // but with reversed layers order indexing (layer 1=outside .. NL=inside)
6440 : // GAP I is between layer I and I+1
6441 :
6442 1450 : if (NL < 1) {
6443 0 : return;
6444 : }
6445 :
6446 1450 : Array1D<Real64> TED(NL + 1);
6447 1450 : Array1D<Real64> RED(NL + 1);
6448 :
6449 : // Reflectance and Transmittance
6450 :
6451 1450 : RED(NL + 1) = RHO_room;
6452 1450 : TED(NL + 1) = 0.0;
6453 5492 : for (int i = NL; i >= 1; --i) {
6454 4042 : CFSSWP const &LSWP_ON_i(LSWP_ON(i));
6455 4042 : TED(i) = LSWP_ON_i.TAUSFBB / max(0.00001, 1.0 - LSWP_ON_i.RHOSBBB * RED(i + 1));
6456 4042 : RED(i) = LSWP_ON_i.RHOSBBB + TED(i) * LSWP_ON_i.TAUSBBB * RED(i + 1);
6457 : }
6458 :
6459 : // Outward and Inward Solar Fluxes, QPLUS AND QMINUS, Respectively
6460 1450 : QMINUS(0) = ISOL;
6461 1450 : QPLUS(0) = QMINUS(0) * RED(1);
6462 5492 : for (int i = 1; i <= NL; ++i) {
6463 4042 : QMINUS(i) = QMINUS(i - 1) * TED(i);
6464 4042 : QPLUS(i) = QMINUS(i) * RED(i + 1);
6465 : }
6466 1450 : }
6467 :
6468 0 : void TDMA_R(
6469 : Array1D<Real64> &X, const Array1D<Real64> &AP, const Array1D<Real64> &AE, const Array1D<Real64> &AW, const Array1D<Real64> &BP, int const N)
6470 : {
6471 : // SUBROUTINE INFORMATION:
6472 : // AUTHOR JOHN L. WRIGHT
6473 : // DATE WRITTEN unknown
6474 : // MODIFIED na
6475 : // RE-ENGINEERED na
6476 :
6477 : // PURPOSE OF THIS SUBROUTINE:
6478 : // TDMA solver
6479 : // METHODOLOGY EMPLOYED:
6480 : // 1-D TDMA reverse solver. East/West sweep followed by West/East sweep
6481 :
6482 : int J;
6483 0 : Array1D<Real64> ALPHA(N);
6484 0 : Array1D<Real64> BETA(N);
6485 :
6486 0 : ALPHA(N) = AW(N) / AP(N);
6487 0 : BETA(N) = BP(N) / AP(N);
6488 :
6489 0 : for (J = N - 1; J >= 1; --J) {
6490 0 : ALPHA(J) = AW(J) / (AP(J) - (ALPHA(J + 1) * AE(J)));
6491 0 : BETA(J) = ((AE(J) * BETA(J + 1)) + BP(J)) / (AP(J) - (ALPHA(J + 1) * AE(J)));
6492 : }
6493 :
6494 0 : X(1) = BETA(1);
6495 0 : for (J = 2; J <= N; ++J) {
6496 0 : X(J) = (ALPHA(J) * X(J - 1)) + BETA(J);
6497 : }
6498 0 : }
6499 :
6500 1450 : void TDMA(Array1D<Real64> &X, const Array1D<Real64> &AP, const Array1D<Real64> &AE, const Array1D<Real64> &AW, const Array1D<Real64> &BP, int const N)
6501 : {
6502 : // SUBROUTINE INFORMATION:
6503 : // AUTHOR JOHN L. WRIGHT
6504 : // DATE WRITTEN unknown
6505 : // MODIFIED na
6506 : // RE-ENGINEERED na
6507 :
6508 : // PURPOSE OF THIS SUBROUTINE:
6509 : // Matrix solver
6510 : // METHODOLOGY EMPLOYED:
6511 : // 1-D TDMA solver.
6512 :
6513 : int J;
6514 1450 : Array1D<Real64> ALPHA(N);
6515 1450 : Array1D<Real64> BETA(N);
6516 : Real64 D;
6517 :
6518 1450 : ALPHA(1) = AE(1) / AP(1);
6519 1450 : BETA(1) = BP(1) / AP(1);
6520 :
6521 8084 : for (J = 2; J <= N; ++J) {
6522 6634 : D = AP(J) - (ALPHA(J - 1) * AW(J));
6523 6634 : if (std::abs(D) < 0.0001) {
6524 0 : ALPHA(J) = 0.0;
6525 0 : BETA(J) = 0.0;
6526 : } else {
6527 6634 : ALPHA(J) = AE(J) / D;
6528 6634 : BETA(J) = ((AW(J) * BETA(J - 1)) + BP(J)) / D;
6529 : }
6530 : }
6531 :
6532 1450 : X(N) = BETA(N);
6533 8084 : for (J = N - 1; J >= 1; --J) {
6534 6634 : X(J) = (ALPHA(J) * X(J + 1)) + BETA(J);
6535 : }
6536 1450 : }
6537 :
6538 1450 : void AUTOTDMA(Array1D<Real64> &X, Array1D<Real64> &AP, const Array1D<Real64> &AE, const Array1D<Real64> &AW, const Array1D<Real64> &BP, int &N)
6539 : {
6540 : // SUBROUTINE INFORMATION:
6541 : // AUTHOR JOHN L. WRIGHT
6542 : // DATE WRITTEN unknown
6543 : // MODIFIED na
6544 : // RE-ENGINEERED na
6545 :
6546 : // PURPOSE OF THIS SUBROUTINE:
6547 : // Matrix solver manager routine
6548 : // METHODOLOGY EMPLOYED:
6549 : // 1-D TDMA solver.
6550 :
6551 : // Call TDMA for forward (i.e., west-to-east and back) calculation
6552 : // or TDMA_R for reverse (i.e., east-to-west and back) calculation
6553 : // TDMA won't tolerate RHOSFxx(1)=0 (i.e., ap(1)=0)
6554 : // but TDMA_R won't tolerate RHOSBxx(N-1)=0 (i.e., ap(n)=0)
6555 : // where n-1 refers to the outdoor layer (glazing or shading layer)
6556 :
6557 : // This if-statement will catch the situation where RHOSFxx(1)=0.
6558 : // i.e., AP(1)=0.
6559 :
6560 1450 : if (AP(1) < AP(N)) {
6561 0 : TDMA_R(X, AP, AE, AW, BP, N);
6562 : } else {
6563 : // This "fix" (on the next line) is only used as a last resort
6564 : // The if-statement will catch the very unusual situation where both
6565 : // RHOSBxx(N-1)=0. AND RHOSFxx(1)=0.
6566 1450 : if (AP(1) < 0.0001) {
6567 0 : AP(1) = 0.0001;
6568 : }
6569 1450 : TDMA(X, AP, AE, AW, BP, N);
6570 : }
6571 1450 : }
6572 :
6573 2082 : void ASHWAT_OffNormalProperties(EnergyPlusData &state,
6574 : CFSLAYER const &L, // layer for which to derive off-normal properties
6575 : Real64 const THETA, // solar beam angle of incidence, from normal, radians
6576 : Real64 const OMEGA_V, // solar beam vertical profile angle, +=above horizontal, radians
6577 : Real64 const OMEGA_H, // solar beam horizontal profile angle, +=clockwise when viewed
6578 : CFSSWP &LSWP_ON // returned: off-normal properties
6579 : )
6580 : {
6581 : // SUBROUTINE INFORMATION:
6582 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
6583 : // Advanced Glazing System Laboratory
6584 : // DATE WRITTEN unknown
6585 : // MODIFIED na
6586 : // RE-ENGINEERED na
6587 :
6588 : // PURPOSE OF THIS SUBROUTINE:
6589 : // Returns off-normal properties (total solar, beam-beam and beam diffuse) given
6590 : // direct-normal, total solar, beam-beam and beam diffuse properties of layers
6591 :
6592 : // SUBROUTINE ARGUMENT DEFINITIONS:
6593 : // Used: LTYPE, SWP_EL, geometry
6594 : // Note: not altered (return is in LSWP_ON)
6595 : // 0 <= THETA <= PI/2
6596 : // = solar elevation angle for a vertical wall with
6597 : // wall-solar azimuth angle equal to zero
6598 : // from above (radians)
6599 : // = wall-solar azimuth angle for a vertical wall
6600 : // Used for PD and vertical VB
6601 :
6602 2082 : LSWP_ON = L.SWP_EL; // init to normal properties
6603 : // calls below modify in place
6604 :
6605 2082 : if (IsGlazeLayerX(L)) {
6606 : // specular glazing
6607 : // HBX note: ltyGZS here iff modelOption F=x; spectral cases elsewhere
6608 1588 : Specular_SWP(LSWP_ON, THETA);
6609 494 : } else if (L.LTYPE == LayerType::VBHOR) {
6610 325 : VB_SWP(state, L, LSWP_ON, OMEGA_V);
6611 169 : } else if (L.LTYPE == LayerType::VBVER) {
6612 169 : VB_SWP(state, L, LSWP_ON, OMEGA_H);
6613 0 : } else if (L.LTYPE == LayerType::DRAPE) {
6614 0 : PD_SWP(state, L, LSWP_ON, OMEGA_V, OMEGA_H);
6615 0 : } else if (L.LTYPE == LayerType::ROLLB) {
6616 0 : RB_SWP(state, L, LSWP_ON, THETA);
6617 0 : } else if (L.LTYPE == LayerType::INSCRN) {
6618 0 : IS_SWP(state, L, LSWP_ON, THETA);
6619 0 : } else if (L.LTYPE == LayerType::NONE || L.LTYPE == LayerType::ROOM) {
6620 : // none or room: do nothing
6621 : } else {
6622 : // placeholder for add'l non-specular layers
6623 : }
6624 2082 : }
6625 :
6626 1588 : bool Specular_OffNormal(Real64 const THETA, // solar beam angle of incidence, from normal radians
6627 : Real64 &RAT_1MR, // returned: ratio of off-normal to normal solar (1-reflectance)
6628 : Real64 &RAT_TAU // returned: ratio of off-normal to normal solar transmittance
6629 : )
6630 : {
6631 : // FUNCTION INFORMATION:
6632 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
6633 : // Advanced Glazing System Laboratory
6634 : // DATE WRITTEN unknown
6635 : // MODIFIED na
6636 : // RE-ENGINEERED na
6637 :
6638 : // PURPOSE OF THIS FUNCTION:
6639 : // Returns ratio of off-normal to normal of optical properties.
6640 : // METHODOLOGY EMPLOYED:
6641 : // Uses a reference glass property.
6642 : // returns TRUE if RAT_TAU < 1 or RAT_1MR < 1 (and thus Specular_Adjust s/b called)
6643 : // else FALSE
6644 : // Return value
6645 : bool Specular_OffNormal;
6646 :
6647 : // FUNCTION ARGUMENT DEFINITIONS:
6648 : // 0 <= THETA <= PI/2
6649 : // NOTE: rhoAdj = 1-(1-rho)*RAT_1MR
6650 :
6651 : Real64 TAU0;
6652 : Real64 RHO0;
6653 : Real64 THETA1;
6654 : Real64 THETA2;
6655 : Real64 TAU_ON;
6656 : Real64 RHO_ON;
6657 : Real64 TAU_A;
6658 : Real64 RPERP; // interface reflectance with respect to perpendicular
6659 : Real64 RPARL;
6660 : // and parallel polarization components of solar radiation
6661 : Real64 TAUPERP;
6662 : Real64 TAUPARL;
6663 : Real64 RHOPERP;
6664 : Real64 RHOPARL;
6665 : Real64 N2; // reference refractive index for generating general off-normal
6666 : // curves for specular glazings
6667 : Real64 KL; // extinction coefficient - thickness product, also used as a
6668 : // reference value to generate off-normal curves for specular layers
6669 :
6670 1588 : Specular_OffNormal = true;
6671 1588 : THETA1 = std::abs(THETA);
6672 1588 : if (THETA1 > Constant::PiOvr2 - Constant::DegToRad) {
6673 : // theta > 89 deg
6674 0 : RAT_TAU = 0.0;
6675 0 : RAT_1MR = 0.0;
6676 1588 : } else if (THETA1 >= Constant::DegToRad) {
6677 : // theta >= 1 deg
6678 1572 : N2 = 1.526;
6679 1572 : KL = 55.0 * 0.006;
6680 1572 : TAU_A = std::exp(-1.0 * KL);
6681 1572 : RPERP = pow_2((N2 - 1.0) / (N2 + 1.0));
6682 1572 : TAU0 = TAU_A * (1.0 - RPERP) * (1.0 - RPERP) / (1.0 - (RPERP * RPERP * TAU_A * TAU_A));
6683 1572 : RHO0 = RPERP * (1.0 + (TAU_A * TAU0));
6684 1572 : THETA2 = std::asin((std::sin(THETA1)) / N2);
6685 1572 : TAU_A = std::exp(-1.0 * KL / std::cos(THETA2));
6686 1572 : RPERP = pow_2(std::sin(THETA2 - THETA1) / std::sin(THETA2 + THETA1));
6687 1572 : RPARL = pow_2(std::tan(THETA2 - THETA1) / std::tan(THETA2 + THETA1));
6688 1572 : TAUPERP = TAU_A * (1.0 - RPERP) * (1.0 - RPERP) / (1.0 - (RPERP * RPERP * TAU_A * TAU_A));
6689 1572 : TAUPARL = TAU_A * (1.0 - RPARL) * (1.0 - RPARL) / (1.0 - (RPARL * RPARL * TAU_A * TAU_A));
6690 1572 : RHOPERP = RPERP * (1.0 + (TAU_A * TAUPERP));
6691 1572 : RHOPARL = RPARL * (1.0 + (TAU_A * TAUPARL));
6692 1572 : TAU_ON = (TAUPERP + TAUPARL) / 2.0;
6693 1572 : RHO_ON = (RHOPERP + RHOPARL) / 2.0;
6694 1572 : RAT_TAU = TAU_ON / TAU0;
6695 1572 : RAT_1MR = (1.0 - RHO_ON) / (1.0 - RHO0);
6696 : } else {
6697 16 : Specular_OffNormal = false;
6698 16 : RAT_TAU = 1.0;
6699 16 : RAT_1MR = 1.0;
6700 : }
6701 1588 : return Specular_OffNormal;
6702 : }
6703 :
6704 1588 : void Specular_SWP(CFSSWP &SWP, // short wave properties (adjusted in place)
6705 : Real64 const OMEGA // incident angle, radians
6706 : )
6707 : {
6708 : // SUBROUTINE INFORMATION:
6709 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
6710 : // Advanced Glazing System Laboratory
6711 : // DATE WRITTEN unknown
6712 : // MODIFIED na
6713 : // RE-ENGINEERED na
6714 :
6715 : // PURPOSE OF THIS SUBROUTINE:
6716 : // Manages the off-normal solar properties calculation
6717 :
6718 : Real64 RAT_1MR; // adjustment factors, see Specular_OffNormal()
6719 : Real64 RAT_TAU; // adjustment factors, see Specular_OffNormal()
6720 :
6721 1588 : bool Specular_OffNormalReturn = Specular_OffNormal(OMEGA, RAT_1MR, RAT_TAU);
6722 1588 : if (Specular_OffNormalReturn) {
6723 1572 : Specular_Adjust(SWP, RAT_1MR, RAT_TAU);
6724 : }
6725 1588 : }
6726 :
6727 1572 : void Specular_Adjust(CFSSWP &SWP, // short wave properties (adjusted in place)
6728 : Real64 const RAT_1MR, // adjustment factors, see Specular_OffNormal()
6729 : Real64 const RAT_TAU // adjustment factors, see Specular_OffNormal()
6730 : )
6731 : {
6732 : // SUBROUTINE INFORMATION:
6733 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
6734 : // Advanced Glazing System Laboratory
6735 : // DATE WRITTEN unknown
6736 : // MODIFIED na
6737 : // RE-ENGINEERED na
6738 :
6739 : // PURPOSE OF THIS SUBROUTINE:
6740 : // adjusts the off-normal solar properties
6741 :
6742 1572 : SWP.TAUSFBB *= RAT_TAU;
6743 1572 : SWP.TAUSBBB *= RAT_TAU;
6744 1572 : SWP.RHOSFBB = 1.0 - RAT_1MR * (1.0 - SWP.RHOSFBB);
6745 1572 : SWP.RHOSBBB = 1.0 - RAT_1MR * (1.0 - SWP.RHOSBBB);
6746 1572 : }
6747 :
6748 0 : void Specular_RATDiff(EnergyPlusData &state, Real64 &RAT_1MRDiff, Real64 &RAT_TAUDiff)
6749 : {
6750 : // SUBROUTINE INFORMATION:
6751 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
6752 : // Advanced Glazing System Laboratory
6753 : // DATE WRITTEN unknown
6754 : // MODIFIED na
6755 : // RE-ENGINEERED na
6756 :
6757 : // PURPOSE OF THIS SUBROUTINE:
6758 : // Returns property ratios for estimating diffuse properties.
6759 :
6760 0 : Array1D<Real64> P(state.dataWindowEquivalentLayer->hipDIM);
6761 :
6762 0 : if (state.dataWindowEquivalentLayer->XTAUDiff < 0.0) {
6763 : // calculate and save on first call
6764 0 : state.dataWindowEquivalentLayer->X1MRDiff = HEMINT(state, Specular_F, state.dataWindowEquivalentLayer->hipRHO, P);
6765 0 : state.dataWindowEquivalentLayer->XTAUDiff = HEMINT(state, Specular_F, state.dataWindowEquivalentLayer->hipTAU, P);
6766 : }
6767 0 : RAT_TAUDiff = state.dataWindowEquivalentLayer->XTAUDiff;
6768 0 : RAT_1MRDiff = state.dataWindowEquivalentLayer->X1MRDiff;
6769 0 : }
6770 :
6771 0 : Real64 Specular_F(EnergyPlusData const &state,
6772 : Real64 const THETA, // incidence angle, radians
6773 : int const OPT, // options (unused)
6774 : [[maybe_unused]] const Array1D<Real64> &P // parameters (none defined)
6775 : )
6776 : {
6777 : // FUNCTION INFORMATION:
6778 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
6779 : // Advanced Glazing System Laboratory
6780 : // DATE WRITTEN unknown
6781 : // MODIFIED na
6782 : // RE-ENGINEERED na
6783 :
6784 : // PURPOSE OF THIS FUNCTION:
6785 : // integrand fcn for specular properties.
6786 :
6787 : // Return value
6788 : Real64 Specular_F;
6789 :
6790 : // Argument array dimensioning
6791 : // EP_SIZE_CHECK(P, hipDIM);
6792 :
6793 : // FUNCTION ARGUMENT DEFINITIONS:
6794 : // 1: reflectance
6795 : // 2: transmittance
6796 :
6797 : Real64 RAT_TAU;
6798 : Real64 RAT_1MR;
6799 :
6800 : // Modified by BAN April 19, 2013
6801 0 : Specular_OffNormal(THETA, RAT_1MR, RAT_TAU);
6802 :
6803 0 : if (OPT == state.dataWindowEquivalentLayer->hipRHO) {
6804 0 : Specular_F = RAT_1MR;
6805 0 : } else if (OPT == state.dataWindowEquivalentLayer->hipTAU) {
6806 0 : Specular_F = RAT_TAU;
6807 : } else {
6808 0 : Specular_F = -1.0;
6809 : }
6810 0 : return Specular_F;
6811 : }
6812 :
6813 0 : void Specular_EstimateDiffuseProps(EnergyPlusData &state, CFSSWP &SWP) // short wave properties
6814 : {
6815 : // SUBROUTINE INFORMATION:
6816 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
6817 : // Advanced Glazing System Laboratory
6818 : // DATE WRITTEN unknown
6819 : // MODIFIED na
6820 : // RE-ENGINEERED na
6821 :
6822 : // PURPOSE OF THIS SUBROUTINE:
6823 : // Estimates diffuse-diffuse properties.
6824 :
6825 : Real64 RAT_TAU;
6826 : Real64 RAT_1MR;
6827 :
6828 : // #if 1
6829 0 : Specular_RATDiff(state, RAT_1MR, RAT_TAU);
6830 : // #else
6831 : // ! estimate diffuse properties as 60 deg angle of incidence
6832 : // CALL Specular_RAT60( RAT_TAU, RAT_1MR)
6833 : // #endif
6834 0 : SWP.TAUS_DD = RAT_TAU * SWP.TAUSFBB;
6835 0 : SWP.RHOSFDD = 1.0 - RAT_1MR * (1.0 - SWP.RHOSFBB);
6836 0 : SWP.RHOSBDD = 1.0 - RAT_1MR * (1.0 - SWP.RHOSBBB);
6837 0 : }
6838 :
6839 0 : bool RB_LWP(CFSLAYER const &L, // RB layer
6840 : CFSLWP &LLWP // returned: equivalent layer long wave properties
6841 : )
6842 : {
6843 : // FUNCTION INFORMATION:
6844 : // AUTHOR ASHRAE 1311-RP
6845 : // DATE WRITTEN unknown
6846 : // MODIFIED na
6847 : // RE-ENGINEERED na
6848 :
6849 : // PURPOSE OF THIS FUNCTION:
6850 : // Modifies roller blind longwave properties. If not roller blind layer
6851 : // returns False.
6852 :
6853 : // Return value
6854 : bool RB_LWP;
6855 :
6856 : Real64 TAULX;
6857 : Real64 OPENNESS;
6858 :
6859 0 : RB_LWP = false;
6860 0 : if (L.LTYPE != LayerType::ROLLB) {
6861 0 : return RB_LWP;
6862 : }
6863 :
6864 0 : OPENNESS = L.SWP_MAT.TAUSFBB;
6865 :
6866 0 : OPENNESS_LW(OPENNESS, L.LWP_MAT.EPSLF, L.LWP_MAT.TAUL, LLWP.EPSLF, LLWP.TAUL);
6867 :
6868 0 : OPENNESS_LW(OPENNESS, L.LWP_MAT.EPSLB, L.LWP_MAT.TAUL, LLWP.EPSLB, TAULX);
6869 :
6870 0 : RB_LWP = true;
6871 0 : return RB_LWP;
6872 : }
6873 :
6874 0 : bool RB_SWP(EnergyPlusData &state,
6875 : CFSLAYER const &L, // RB layer
6876 : CFSSWP &LSWP, // returned: equivalent layer properties set
6877 : const Real64 THETA // incident angle, 0 <= theta <= PI/2
6878 : )
6879 : {
6880 : // FUNCTION INFORMATION:
6881 : // AUTHOR ASHRAE 1311-RP
6882 : // DATE WRITTEN unknown
6883 : // MODIFIED Jason W. DeGraw 2023
6884 : // RE-ENGINEERED na
6885 :
6886 : // PURPOSE OF THIS FUNCTION:
6887 : // Modifies roller blind shortwave properties. If not roller blind layer
6888 : // returns False.
6889 :
6890 : // FUNCTION ARGUMENT DEFINITIONS:
6891 : // sets ONLY RHOSFDD, RHOSBDD, TAUS_DD
6892 : // if missing, derive diffuse properties
6893 :
6894 0 : if (L.LTYPE != LayerType::ROLLB) {
6895 0 : return false;
6896 : }
6897 :
6898 : // normal beam-total properties of fabric
6899 0 : Real64 RHOFF_BT0 = L.SWP_MAT.RHOSFBB + L.SWP_MAT.RHOSFBD; // front rho
6900 0 : Real64 RHOBF_BT0 = L.SWP_MAT.RHOSBBB + L.SWP_MAT.RHOSBBD; // back rho
6901 :
6902 0 : Real64 TAUFF_BT0 = L.SWP_MAT.TAUSFBB + L.SWP_MAT.TAUSFBD; // front tau
6903 0 : Real64 TAUBF_BT0 = L.SWP_MAT.TAUSBBB + L.SWP_MAT.TAUSBBD; // back tau
6904 :
6905 0 : RB_BEAM(state, THETA, RHOFF_BT0, TAUFF_BT0, L.SWP_MAT.TAUSFBB, LSWP.RHOSFBD, LSWP.TAUSFBB, LSWP.TAUSFBD);
6906 :
6907 0 : RB_BEAM(state, THETA, RHOBF_BT0, TAUBF_BT0, L.SWP_MAT.TAUSBBB, LSWP.RHOSBBD, LSWP.TAUSBBB, LSWP.TAUSBBD);
6908 :
6909 0 : return true;
6910 : }
6911 :
6912 0 : bool RB_SWP(EnergyPlusData &state,
6913 : CFSLAYER const &L, // RB layer
6914 : CFSSWP &LSWP // returned: equivalent layer properties set
6915 : )
6916 : {
6917 : // FUNCTION INFORMATION:
6918 : // AUTHOR ASHRAE 1311-RP
6919 : // DATE WRITTEN unknown
6920 : // MODIFIED Jason W. DeGraw 2023
6921 : // RE-ENGINEERED na
6922 :
6923 : // PURPOSE OF THIS FUNCTION:
6924 : // Modifies roller blind shortwave properties. If not roller blind layer
6925 : // returns False.
6926 :
6927 : // FUNCTION ARGUMENT DEFINITIONS:
6928 : // sets ONLY RHOSFDD, RHOSBDD, TAUS_DD
6929 : // if missing, derive diffuse properties
6930 :
6931 0 : if (L.LTYPE != LayerType::ROLLB) {
6932 0 : return false;
6933 : }
6934 :
6935 : // normal beam-total properties of fabric
6936 0 : Real64 RHOFF_BT0 = L.SWP_MAT.RHOSFBB + L.SWP_MAT.RHOSFBD; // front rho
6937 0 : Real64 RHOBF_BT0 = L.SWP_MAT.RHOSBBB + L.SWP_MAT.RHOSBBD; // back rho
6938 :
6939 0 : Real64 TAUFF_BT0 = L.SWP_MAT.TAUSFBB + L.SWP_MAT.TAUSFBD; // front tau
6940 0 : Real64 TAUBF_BT0 = L.SWP_MAT.TAUSBBB + L.SWP_MAT.TAUSBBD; // back tau
6941 :
6942 : // front
6943 0 : RB_DIFF(state, RHOFF_BT0, TAUFF_BT0, L.SWP_MAT.TAUSFBB, LSWP.RHOSFDD, LSWP.TAUS_DD);
6944 : // back
6945 : Real64 TAUX; // This gets used as output of RB_DIFF and is then discarded
6946 0 : RB_DIFF(state, RHOBF_BT0, TAUBF_BT0, L.SWP_MAT.TAUSBBB, LSWP.RHOSBDD, TAUX);
6947 :
6948 0 : return true;
6949 : }
6950 :
6951 0 : bool IS_LWP(CFSLAYER const &L, // IS layer
6952 : CFSLWP &LLWP // returned: equivalent layer long wave properties
6953 : )
6954 : {
6955 : // FUNCTION INFORMATION:
6956 : // AUTHOR ASHRAE 1311-RP
6957 : // DATE WRITTEN unknown
6958 : // MODIFIED na
6959 : // RE-ENGINEERED na
6960 :
6961 : // PURPOSE OF THIS FUNCTION:
6962 : // Modifies Insect Screen longwave properties. If not Insect Screen layer
6963 : // returns False.
6964 :
6965 : // Return value
6966 : bool IS_LWP;
6967 :
6968 : Real64 OPENNESS;
6969 : Real64 TAULX;
6970 :
6971 0 : IS_LWP = false;
6972 0 : if (L.LTYPE != LayerType::INSCRN) {
6973 0 : return IS_LWP;
6974 : }
6975 :
6976 0 : OPENNESS = L.SWP_MAT.TAUSFBB;
6977 :
6978 0 : OPENNESS_LW(OPENNESS, L.LWP_MAT.EPSLF, L.LWP_MAT.TAUL, LLWP.EPSLF, LLWP.TAUL);
6979 :
6980 0 : OPENNESS_LW(OPENNESS, L.LWP_MAT.EPSLB, L.LWP_MAT.TAUL, LLWP.EPSLB, TAULX);
6981 0 : IS_LWP = true;
6982 0 : return IS_LWP;
6983 : }
6984 :
6985 0 : bool IS_SWP(EnergyPlusData &state,
6986 : CFSLAYER const &L, // PD layer
6987 : CFSSWP &LSWP, // returned: equivalent layer properties set
6988 : const Real64 THETA // incident angle, 0 <= theta <= PI/2
6989 : )
6990 : {
6991 : // FUNCTION INFORMATION:
6992 : // AUTHOR ASHRAE 1311-RP
6993 : // DATE WRITTEN unknown
6994 : // MODIFIED Jason W. DeGraw 2023
6995 : // RE-ENGINEERED na
6996 :
6997 : // PURPOSE OF THIS FUNCTION:
6998 : // Modifies Insect Screen shortwave properties. If not Insect Screen layer
6999 : // returns False.
7000 :
7001 : // FUNCTION ARGUMENT DEFINITIONS:
7002 : // sets ONLY RHOSFDD, RHOSBDD, TAUS_DD
7003 : // if missing, derive diffuse properties
7004 :
7005 0 : if (L.LTYPE != LayerType::INSCRN) {
7006 0 : return false;
7007 : }
7008 :
7009 : // normal beam-total properties
7010 0 : Real64 RHOFF_BT0 = L.SWP_MAT.RHOSFBB + L.SWP_MAT.RHOSFBD; // front rho
7011 0 : Real64 RHOBF_BT0 = L.SWP_MAT.RHOSBBB + L.SWP_MAT.RHOSBBD; // back rho
7012 :
7013 0 : Real64 TAUFF_BT0 = L.SWP_MAT.TAUSFBB + L.SWP_MAT.TAUSFBD; // front tau
7014 0 : Real64 TAUBF_BT0 = L.SWP_MAT.TAUSBBB + L.SWP_MAT.TAUSBBD; // back tau
7015 :
7016 : // front
7017 0 : IS_BEAM(state, THETA, RHOFF_BT0, TAUFF_BT0, L.SWP_MAT.TAUSFBB, LSWP.RHOSFBD, LSWP.TAUSFBB, LSWP.TAUSFBD);
7018 :
7019 : // back -- call with reverse material properties
7020 0 : IS_BEAM(state, THETA, RHOBF_BT0, TAUBF_BT0, L.SWP_MAT.TAUSBBB, LSWP.RHOSBBD, LSWP.TAUSBBB, LSWP.TAUSBBD);
7021 :
7022 0 : return true;
7023 : }
7024 :
7025 0 : bool IS_SWP(EnergyPlusData &state,
7026 : CFSLAYER const &L, // PD layer
7027 : CFSSWP &LSWP // returned: equivalent layer properties set
7028 : )
7029 : {
7030 : // FUNCTION INFORMATION:
7031 : // AUTHOR ASHRAE 1311-RP
7032 : // DATE WRITTEN unknown
7033 : // MODIFIED Jason W. DeGraw 2023
7034 : // RE-ENGINEERED na
7035 :
7036 : // PURPOSE OF THIS FUNCTION:
7037 : // Modifies Insect Screen shortwave properties. If not Insect Screen layer
7038 : // returns False.
7039 :
7040 : // FUNCTION ARGUMENT DEFINITIONS:
7041 : // sets ONLY RHOSFDD, RHOSBDD, TAUS_DD
7042 : // if missing, derive diffuse properties
7043 :
7044 0 : if (L.LTYPE != LayerType::INSCRN) {
7045 0 : return false;
7046 : }
7047 :
7048 : // normal beam-total properties
7049 0 : Real64 RHOFF_BT0 = L.SWP_MAT.RHOSFBB + L.SWP_MAT.RHOSFBD; // front rho
7050 0 : Real64 RHOBF_BT0 = L.SWP_MAT.RHOSBBB + L.SWP_MAT.RHOSBBD; // back rho
7051 :
7052 0 : Real64 TAUFF_BT0 = L.SWP_MAT.TAUSFBB + L.SWP_MAT.TAUSFBD; // front tau
7053 0 : Real64 TAUBF_BT0 = L.SWP_MAT.TAUSBBB + L.SWP_MAT.TAUSBBD; // back tau
7054 :
7055 : // front
7056 0 : IS_DIFF(state, RHOFF_BT0, TAUFF_BT0, L.SWP_MAT.TAUSFBB, LSWP.RHOSFDD, LSWP.TAUS_DD);
7057 : // back
7058 : Real64 TAUX; // This gets used as output of IS_DIFF and is then discarded
7059 0 : IS_DIFF(state, RHOBF_BT0, TAUBF_BT0, L.SWP_MAT.TAUSBBB, LSWP.RHOSBDD, TAUX);
7060 :
7061 0 : return true;
7062 : }
7063 :
7064 0 : void Fabric_EstimateDiffuseProps(EnergyPlusData &state, CFSSWP &SWP) // fabric short wave properties
7065 : {
7066 : // SUBROUTINE INFORMATION:
7067 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
7068 : // Advanced Glazing System Laboratory
7069 : // DATE WRITTEN unknown
7070 : // MODIFIED na
7071 : // RE-ENGINEERED na
7072 :
7073 : // PURPOSE OF THIS SUBROUTINE:
7074 : // Estimates diffuse properties of drape fabrics.
7075 : // sets RHOSFDD, RHOSBDD, TAUS_DD
7076 :
7077 : Real64 RHOBF_BT0; // total back reflectance
7078 : Real64 RHOFF_BT0; // total front reflectance
7079 : Real64 TAUBF_BT0; // total back transmittance
7080 : Real64 TAUFF_BT0; // total front transmittance
7081 : Real64 TAUX;
7082 :
7083 0 : RHOFF_BT0 = SWP.RHOSFBB + SWP.RHOSFBD; // front rho
7084 0 : RHOBF_BT0 = SWP.RHOSBBB + SWP.RHOSBBD; // back rho
7085 0 : TAUFF_BT0 = SWP.TAUSFBB + SWP.TAUSFBD; // front tau
7086 0 : TAUBF_BT0 = SWP.TAUSBBB + SWP.TAUSBBD; // back tau
7087 0 : FM_DIFF(state, RHOFF_BT0, TAUFF_BT0, SWP.TAUSFBB, SWP.RHOSFDD, SWP.TAUS_DD);
7088 0 : FM_DIFF(state, RHOBF_BT0, TAUBF_BT0, SWP.TAUSBBB, SWP.RHOSBDD, TAUX);
7089 0 : }
7090 :
7091 0 : bool PD_LWP(EnergyPlusData &state,
7092 : CFSLAYER const &L, // PD layer
7093 : CFSLWP &LLWP // returned: equivalent layer long wave properties
7094 : )
7095 : {
7096 : // FUNCTION INFORMATION:
7097 : // AUTHOR ASHRAE 1311-RP
7098 : // DATE WRITTEN unknown
7099 : // MODIFIED na
7100 : // RE-ENGINEERED na
7101 :
7102 : // PURPOSE OF THIS FUNCTION:
7103 : // Modifies Drape longwave properties for openness. If not Drape Fabric layer
7104 : // returns False.
7105 :
7106 : // Return value
7107 : bool PD_LWP;
7108 :
7109 : Real64 TAULX;
7110 : Real64 OPENNESS_FABRIC;
7111 :
7112 0 : PD_LWP = false;
7113 0 : if (L.LTYPE != LayerType::DRAPE) {
7114 0 : return PD_LWP;
7115 : }
7116 :
7117 0 : OPENNESS_FABRIC = L.SWP_MAT.TAUSFBB;
7118 :
7119 0 : PD_LW(state, L.S, L.W, OPENNESS_FABRIC, L.LWP_MAT.EPSLF, L.LWP_MAT.EPSLB, L.LWP_MAT.TAUL, LLWP.EPSLF, LLWP.TAUL);
7120 :
7121 0 : PD_LW(state, L.S, L.W, OPENNESS_FABRIC, L.LWP_MAT.EPSLB, L.LWP_MAT.EPSLF, L.LWP_MAT.TAUL, LLWP.EPSLB, TAULX);
7122 :
7123 0 : PD_LWP = true;
7124 0 : return PD_LWP;
7125 : }
7126 :
7127 0 : bool PD_SWP(EnergyPlusData &state,
7128 : CFSLAYER const &L, // PD layer
7129 : CFSSWP &LSWP, // returned: equivalent layer properties set
7130 : const Real64 OHM_V_RAD, // vertical VB profile angles, radians
7131 : const Real64 OHM_H_RAD // horizontal VB profile angles, radians
7132 : )
7133 : {
7134 : // FUNCTION INFORMATION:
7135 : // AUTHOR ASHRAE 1311-RP
7136 : // DATE WRITTEN unknown
7137 : // MODIFIED Jason W. DeGraw 2023
7138 : // RE-ENGINEERED na
7139 :
7140 : // PURPOSE OF THIS FUNCTION:
7141 : // Modifies drape fabric shortwave properties for openness. If not drape Fabric layer
7142 : // returns false. If profile angles not specified diffuse properties are returned.
7143 :
7144 0 : if (!(L.LTYPE == LayerType::DRAPE)) {
7145 0 : return false;
7146 : }
7147 :
7148 : // normal beam-total properties of fabric
7149 0 : Real64 RHOFF_BT0 = L.SWP_MAT.RHOSFBB + L.SWP_MAT.RHOSFBD; // front rho
7150 0 : Real64 RHOBF_BT0 = L.SWP_MAT.RHOSBBB + L.SWP_MAT.RHOSBBD; // back rho
7151 :
7152 : // drape front properties
7153 0 : PD_BEAM(state,
7154 0 : L.S,
7155 0 : L.W,
7156 : OHM_V_RAD,
7157 : OHM_H_RAD,
7158 : RHOFF_BT0,
7159 0 : L.SWP_MAT.TAUSFBB,
7160 0 : L.SWP_MAT.TAUSFBD,
7161 0 : L.SWP_MAT.RHOSFDD,
7162 0 : L.SWP_MAT.TAUS_DD,
7163 : RHOBF_BT0,
7164 0 : L.SWP_MAT.TAUSBBB,
7165 0 : L.SWP_MAT.TAUSBBD,
7166 0 : L.SWP_MAT.RHOSBDD,
7167 0 : L.SWP_MAT.TAUS_DD,
7168 0 : LSWP.RHOSFBD,
7169 0 : LSWP.TAUSFBB,
7170 0 : LSWP.TAUSFBD);
7171 :
7172 : // drape back properties: call with reversed fabric properties
7173 0 : PD_BEAM(state,
7174 0 : L.S,
7175 0 : L.W,
7176 : OHM_V_RAD,
7177 : OHM_H_RAD,
7178 : RHOBF_BT0,
7179 0 : L.SWP_MAT.TAUSBBB,
7180 0 : L.SWP_MAT.TAUSBBD,
7181 0 : L.SWP_MAT.RHOSBDD,
7182 0 : L.SWP_MAT.TAUS_DD,
7183 : RHOFF_BT0,
7184 0 : L.SWP_MAT.TAUSFBB,
7185 0 : L.SWP_MAT.TAUSFBD,
7186 0 : L.SWP_MAT.RHOSFDD,
7187 0 : L.SWP_MAT.TAUS_DD,
7188 0 : LSWP.RHOSBBD,
7189 0 : LSWP.TAUSBBB,
7190 0 : LSWP.TAUSBBD);
7191 :
7192 0 : return true;
7193 : }
7194 :
7195 0 : bool PD_SWP(EnergyPlusData &state,
7196 : CFSLAYER const &L, // PD layer
7197 : CFSSWP &LSWP // returned: equivalent layer properties set
7198 : )
7199 : {
7200 : // FUNCTION INFORMATION:
7201 : // AUTHOR ASHRAE 1311-RP
7202 : // DATE WRITTEN unknown
7203 : // MODIFIED Jason W. DeGraw
7204 : // RE-ENGINEERED na
7205 :
7206 : // PURPOSE OF THIS FUNCTION:
7207 : // Modifies drape fabric shortwave properties for openness. If not drape Fabric layer
7208 : // returns false. If profile angles not specified diffuse properties are returned.
7209 :
7210 : Real64 TAUX; // This gets used as output of PD_DIFF and is then discarded
7211 :
7212 0 : if (!(L.LTYPE == LayerType::DRAPE)) {
7213 0 : return false;
7214 : }
7215 :
7216 0 : PD_DIFF(state, L.S, L.W, L.SWP_MAT.RHOSFDD, L.SWP_MAT.RHOSBDD, L.SWP_MAT.TAUS_DD, LSWP.RHOSFDD, LSWP.TAUS_DD);
7217 :
7218 0 : PD_DIFF(state, L.S, L.W, L.SWP_MAT.RHOSBDD, L.SWP_MAT.RHOSFDD, L.SWP_MAT.TAUS_DD, LSWP.RHOSBDD, TAUX);
7219 :
7220 0 : return true;
7221 : }
7222 :
7223 326 : bool VB_LWP(EnergyPlusData &state,
7224 : CFSLAYER const &L, // VB layer
7225 : CFSLWP &LLWP // returned: equivalent layer long wave properties
7226 : )
7227 : {
7228 : // FUNCTION INFORMATION:
7229 : // AUTHOR ASHRAE 1311-RP
7230 : // DATE WRITTEN unknown
7231 : // MODIFIED na
7232 : // RE-ENGINEERED na
7233 :
7234 : // PURPOSE OF THIS FUNCTION:
7235 : // Return venetian blind longwave properties from slat properties and geometry.
7236 : // If not VB layer returns False.
7237 :
7238 : // Return value
7239 : bool VB_LWP;
7240 :
7241 : Real64 RHODFS_SLAT;
7242 : Real64 RHOUFS_SLAT;
7243 : Real64 RHOLF;
7244 : Real64 RHOLB;
7245 : Real64 TAULX;
7246 :
7247 326 : VB_LWP = false;
7248 326 : if (!IsVBLayer(L)) {
7249 0 : return VB_LWP;
7250 : }
7251 :
7252 : // slat reflectances
7253 326 : RHODFS_SLAT = 1.0 - L.LWP_MAT.EPSLB - L.LWP_MAT.TAUL; // downward surface
7254 326 : RHOUFS_SLAT = 1.0 - L.LWP_MAT.EPSLF - L.LWP_MAT.TAUL; // upward surface
7255 :
7256 : // TODO: are there cases where 2 calls not needed (RHODFS_SLAT == RHOUFS_SLAT??)
7257 326 : VB_DIFF(state, L.S, L.W, Constant::DegToRad * L.PHI_DEG, RHODFS_SLAT, RHOUFS_SLAT, L.LWP_MAT.TAUL, RHOLF, LLWP.TAUL);
7258 326 : LLWP.EPSLF = 1.0 - RHOLF - LLWP.TAUL;
7259 :
7260 326 : VB_DIFF(state, L.S, L.W, -Constant::DegToRad * L.PHI_DEG, RHODFS_SLAT, RHOUFS_SLAT, L.LWP_MAT.TAUL, RHOLB, TAULX);
7261 326 : LLWP.EPSLB = 1.0 - RHOLB - LLWP.TAUL;
7262 :
7263 326 : VB_LWP = true;
7264 326 : return VB_LWP;
7265 : }
7266 :
7267 820 : bool VB_SWP(EnergyPlusData const &state,
7268 : CFSLAYER const &L, // VB layer
7269 : CFSSWP &LSWP, // returned: equivalent off-normal properties
7270 : const Real64 OMEGA // incident profile angle (radians)
7271 : )
7272 : {
7273 : // FUNCTION INFORMATION:
7274 : // AUTHOR ASHRAE 1311-RP
7275 : // DATE WRITTEN unknown
7276 : // MODIFIED Jason W. DeGraw
7277 : // RE-ENGINEERED na
7278 :
7279 : // PURPOSE OF THIS FUNCTION:
7280 : // Returns venetian blind off-normal short wave properties. If not VB layer
7281 : // returns False.
7282 :
7283 : // FUNCTION ARGUMENT DEFINITIONS:
7284 : // sets: RHOSFBD, TAUSFBB, TAUSFBD
7285 :
7286 820 : if (!IsVBLayer(L)) {
7287 0 : return false;
7288 : }
7289 :
7290 820 : Real64 SL_WR = VB_SLAT_RADIUS_RATIO(L.W, L.C);
7291 :
7292 : // modify angle-dependent values for actual profile angle
7293 820 : VB_SOL46_CURVE(state,
7294 820 : L.S,
7295 820 : L.W,
7296 : SL_WR,
7297 820 : Constant::DegToRad * L.PHI_DEG,
7298 : OMEGA,
7299 820 : L.SWP_MAT.RHOSBDD,
7300 820 : L.SWP_MAT.RHOSFDD,
7301 820 : L.SWP_MAT.TAUS_DD,
7302 820 : LSWP.RHOSFBD,
7303 820 : LSWP.TAUSFBB,
7304 820 : LSWP.TAUSFBD);
7305 :
7306 820 : VB_SOL46_CURVE(state,
7307 820 : L.S,
7308 820 : L.W,
7309 : SL_WR,
7310 820 : -Constant::DegToRad * L.PHI_DEG,
7311 : OMEGA,
7312 820 : L.SWP_MAT.RHOSBDD,
7313 820 : L.SWP_MAT.RHOSFDD,
7314 820 : L.SWP_MAT.TAUS_DD,
7315 820 : LSWP.RHOSBBD,
7316 820 : LSWP.TAUSBBB,
7317 820 : LSWP.TAUSBBD);
7318 :
7319 820 : return true;
7320 : }
7321 :
7322 326 : bool VB_SWP(EnergyPlusData &state,
7323 : CFSLAYER const &L, // VB layer
7324 : CFSSWP &LSWP // returned: equivalent off-normal properties
7325 : )
7326 : {
7327 : // FUNCTION INFORMATION:
7328 : // AUTHOR ASHRAE 1311-RP
7329 : // DATE WRITTEN unknown
7330 : // MODIFIED Jason W. DeGraw
7331 : // RE-ENGINEERED na
7332 :
7333 : // PURPOSE OF THIS FUNCTION:
7334 : // Returns venetian blind off-normal short wave properties. If not VB layer
7335 : // returns False.
7336 :
7337 : // FUNCTION ARGUMENT DEFINITIONS:
7338 : // sets: RHOSFBD, TAUSFBB, TAUSFBD
7339 :
7340 : Real64 SL_WR;
7341 : Real64 TAUX; // This gets used as output of VB_DIFF and is then discarded
7342 :
7343 326 : if (!IsVBLayer(L)) {
7344 0 : return false;
7345 : }
7346 :
7347 326 : SL_WR = VB_SLAT_RADIUS_RATIO(L.W, L.C);
7348 :
7349 326 : VB_DIFF(state, L.S, L.W, Constant::DegToRad * L.PHI_DEG, L.SWP_MAT.RHOSBDD, L.SWP_MAT.RHOSFDD, L.SWP_MAT.TAUS_DD, LSWP.RHOSFDD, LSWP.TAUS_DD);
7350 :
7351 326 : VB_DIFF(state, L.S, L.W, -Constant::DegToRad * L.PHI_DEG, L.SWP_MAT.RHOSBDD, L.SWP_MAT.RHOSFDD, L.SWP_MAT.TAUS_DD, LSWP.RHOSBDD, TAUX);
7352 :
7353 326 : return true;
7354 : }
7355 :
7356 642 : bool VB_ShadeControl(EnergyPlusData const &state,
7357 : CFSLAYER &L, // VB layer
7358 : Real64 const OMEGA_DEG // incident profile angle (degrees)
7359 : )
7360 : {
7361 : // FUNCTION INFORMATION:
7362 : // AUTHOR ASHRAE 1311-RP
7363 : // DATE WRITTEN unknown
7364 : // MODIFIED na
7365 : // RE-ENGINEERED na
7366 :
7367 : // PURPOSE OF THIS FUNCTION:
7368 : // Modifies slat angle if shade control is true. If not uses the fixed
7369 : // slate angle and returns false.
7370 :
7371 : // Return value
7372 : bool VB_ShadeControl;
7373 :
7374 : // FUNCTION ARGUMENT DEFINITIONS:
7375 : // see comments elsewhere re sign convention
7376 : // < 0 = diffuse
7377 :
7378 : Real64 SLATA;
7379 :
7380 642 : SLATA = L.PHI_DEG;
7381 :
7382 642 : if (L.CNTRL == state.dataWindowEquivalentLayer->lscVBPROF) {
7383 : // slatA = profA (max gain)
7384 321 : if (OMEGA_DEG < 0.0) {
7385 0 : SLATA = -30.0;
7386 : } else {
7387 321 : SLATA = -OMEGA_DEG;
7388 : }
7389 321 : } else if (L.CNTRL == state.dataWindowEquivalentLayer->lscVBNOBM) {
7390 : // slatA set to just exclude beam
7391 321 : if (OMEGA_DEG < 0.0) {
7392 0 : SLATA = VB_CriticalSlatAngle(30.0); // assume 30 deg for diffuse
7393 : } else {
7394 321 : SLATA = VB_CriticalSlatAngle(OMEGA_DEG);
7395 : }
7396 : }
7397 :
7398 642 : VB_ShadeControl = std::abs(SLATA - L.PHI_DEG) > 0.01;
7399 642 : if (VB_ShadeControl) {
7400 322 : L.PHI_DEG = SLATA;
7401 : }
7402 642 : return VB_ShadeControl;
7403 : }
7404 :
7405 322 : Real64 VB_CriticalSlatAngle(Real64 const OMEGA_DEG // incident profile angle (degrees)
7406 : )
7407 : {
7408 : // FUNCTION INFORMATION:
7409 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
7410 : // Advanced Glazing System Laboratory
7411 : // DATE WRITTEN unknown
7412 : // MODIFIED na
7413 : // RE-ENGINEERED na
7414 :
7415 : // PURPOSE OF THIS FUNCTION:
7416 : // Returns slat angle that just excludes beam radiation.
7417 :
7418 : // Return value
7419 : Real64 VB_CriticalSlatAngle;
7420 :
7421 : // TODO handle vert blind cases etc
7422 : // the slat normal points along the profile angle to block the beam solar
7423 322 : VB_CriticalSlatAngle = 90.0 - OMEGA_DEG; //
7424 :
7425 322 : return VB_CriticalSlatAngle;
7426 : }
7427 :
7428 642 : bool DoShadeControl(EnergyPlusData &state,
7429 : CFSLAYER &L, // layer (returned updated)
7430 : Real64 const THETA, // solar beam angle of incidence, from normal, (radians)
7431 : Real64 const OMEGA_V, // solar beam vertical profile angle, +=above horizontal (radians)
7432 : Real64 const OMEGA_H // solar beam horizontal profile angle, +=clockwise when viewed
7433 : )
7434 : {
7435 : // FUNCTION INFORMATION:
7436 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
7437 : // Advanced Glazing System Laboratory
7438 : // DATE WRITTEN unknown
7439 : // MODIFIED na
7440 : // RE-ENGINEERED na
7441 :
7442 : // PURPOSE OF THIS FUNCTION:
7443 : // Returns .TRUE. if L is modified for shade control.
7444 :
7445 : // Return value
7446 : bool DoShadeControl;
7447 :
7448 : // FUNCTION ARGUMENT DEFINITIONS:
7449 : // 0 <= THETA <= PI/2
7450 : // = solar elevation angle for a vertical wall with
7451 : // wall-solar azimuth angle equal to zero
7452 : // from above (radians)
7453 : // = wall-solar azimuth angle for a vertical wall
7454 : // Used for PD and vertical VB
7455 :
7456 : Real64 OMEGA_DEG; // controlling profile angel, degrees
7457 :
7458 642 : DoShadeControl = false; // default: no shade controls implemented
7459 :
7460 : // must be consistent with IsControlledShade()
7461 642 : if (IsVBLayer(L) && L.CNTRL != state.dataWindowEquivalentLayer->lscNONE) {
7462 642 : if (THETA < 0.0 || THETA >= Constant::PiOvr2) {
7463 0 : OMEGA_DEG = -1.0; // diffuse only
7464 642 : } else if (L.LTYPE == LayerType::VBHOR) {
7465 : // horiz VB
7466 642 : OMEGA_DEG = state.dataWindowEquivalentLayer->RadiansToDeg * OMEGA_V;
7467 : } else {
7468 : // vert VB
7469 0 : OMEGA_DEG = state.dataWindowEquivalentLayer->RadiansToDeg * OMEGA_H;
7470 : }
7471 642 : if (VB_ShadeControl(state, L, OMEGA_DEG)) {
7472 322 : FinalizeCFSLAYER(state, L);
7473 322 : DoShadeControl = true;
7474 : }
7475 : }
7476 642 : return DoShadeControl;
7477 : }
7478 :
7479 351 : void FinalizeCFSLAYER(EnergyPlusData &state, CFSLAYER &L) // layer, input: LTYPE, LWP_MAT, SWP_MAT
7480 : {
7481 : // SUBROUTINE INFORMATION:
7482 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
7483 : // Advanced Glazing System Laboratory
7484 : // PURPOSE OF THIS SUBROUTINE:
7485 : // Sets equivalent layer properties of a construction.
7486 :
7487 : // SUBROUTINE ARGUMENT DEFINITIONS:
7488 : // geometry (per LTYPE)
7489 : // output: LWP_EL, SWP_EL
7490 :
7491 : bool LOK;
7492 : bool DOK;
7493 : bool BOK;
7494 : bool CFSLAYERFlag;
7495 :
7496 351 : if (IsVBLayer(L)) {
7497 326 : LOK = VB_LWP(state, L, L.LWP_EL);
7498 326 : DOK = VB_SWP(state, L, L.SWP_EL); // SW diffuse
7499 326 : BOK = VB_SWP(state, L, L.SWP_EL, 0.0); // SW properties w/ profile ang = 0
7500 : } else {
7501 25 : L.PHI_DEG = 0.0; // phi, C, CNTRL are VB only
7502 25 : L.C = 0.0;
7503 25 : L.CNTRL = state.dataWindowEquivalentLayer->lscNONE;
7504 25 : if (L.LTYPE == LayerType::DRAPE) {
7505 0 : LOK = PD_LWP(state, L, L.LWP_EL);
7506 0 : DOK = PD_SWP(state, L, L.SWP_EL); // SW diffuse
7507 0 : BOK = PD_SWP(state, L, L.SWP_EL, 0.0, 0.0); // SW properties w/ profile angs = 0
7508 25 : } else if (L.LTYPE == LayerType::INSCRN) {
7509 0 : LOK = IS_LWP(L, L.LWP_EL); // LW
7510 0 : DOK = IS_SWP(state, L, L.SWP_EL); // SW diffuse
7511 0 : BOK = IS_SWP(state, L, L.SWP_EL, 0.0); // SW beam w/ theta = 0
7512 : } else {
7513 25 : L.S = 0.0; // geometry mbrs unused
7514 25 : L.W = 0.0;
7515 25 : if (L.LTYPE == LayerType::ROLLB) {
7516 0 : LOK = RB_LWP(L, L.LWP_EL); // LW
7517 0 : DOK = RB_SWP(state, L, L.SWP_EL); // SW diffuse
7518 0 : BOK = RB_SWP(state, L, L.SWP_EL, 0.0); // SW beam w/ theta = 0
7519 : // ELSE IF (ISGZSLayer( L)) THEN
7520 : // spectral glazing. Set layer xxx_MAT from GZS file data
7521 : // BOK = GZSLayerInit( L) .EQ. 0
7522 : // L%SWP_EL = L%SWP_MAT
7523 : // L%LWP_EL = L%LWP_MAT
7524 : // LOK = .TRUE.
7525 : // DOK = .TRUE.
7526 : } else {
7527 : // glazing
7528 25 : L.SWP_EL = L.SWP_MAT;
7529 25 : L.LWP_EL = L.LWP_MAT;
7530 25 : LOK = true;
7531 25 : DOK = true;
7532 25 : BOK = true;
7533 : }
7534 : }
7535 : }
7536 351 : CFSLAYERFlag = LOK && DOK && BOK;
7537 351 : }
7538 :
7539 494 : bool IsGZSLayer(CFSLAYER const &L)
7540 : {
7541 : // FUNCTION INFORMATION:
7542 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
7543 : // Advanced Glazing System Laboratory
7544 :
7545 : // PURPOSE OF THIS FUNCTION:
7546 : // Returns .TRUE. if Layer has glazing data from external file or returns .FALSE.
7547 :
7548 : // Return value
7549 : bool IsGZSLayer;
7550 :
7551 494 : IsGZSLayer = L.LTYPE == LayerType::GZS;
7552 494 : return IsGZSLayer;
7553 : }
7554 :
7555 2082 : bool IsGlazeLayerX(CFSLAYER const &L)
7556 : {
7557 : // FUNCTION INFORMATION:
7558 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
7559 : // Advanced Glazing System Laboratory
7560 :
7561 : // PURPOSE OF THIS FUNCTION:
7562 : // Returns .TRUE. if Layer has glazing (including GZS) or returns .FALSE.
7563 :
7564 : // Return value
7565 : bool IsGlazeLayerX;
7566 :
7567 2082 : IsGlazeLayerX = L.LTYPE == LayerType::GLAZE || IsGZSLayer(L);
7568 2082 : return IsGlazeLayerX;
7569 : }
7570 :
7571 1944 : bool IsControlledShade(EnergyPlusData const &state, CFSLAYER const &L)
7572 : {
7573 : // FUNCTION INFORMATION:
7574 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
7575 : // Advanced Glazing System Laboratory
7576 :
7577 : // PURPOSE OF THIS FUNCTION:
7578 : // Returns .TRUE. if Layer is Venetian blind and is controlled or returns .FALSE.
7579 :
7580 1944 : return IsVBLayer(L) && L.CNTRL != state.dataWindowEquivalentLayer->lscNONE;
7581 : }
7582 :
7583 7457 : bool IsVBLayer(CFSLAYER const &L)
7584 : {
7585 : // FUNCTION INFORMATION:
7586 : // AUTHOR JOHN L. WRIGHT, University of Waterloo, Mechanical Engineering
7587 : // Advanced Glazing System Laboratory
7588 :
7589 : // PURPOSE OF THIS FUNCTION:
7590 : // Returns .TRUE. if Layer is Venetian blind, or returns .FALSE.
7591 :
7592 7457 : return L.LTYPE == LayerType::VBHOR || L.LTYPE == LayerType::VBVER;
7593 : }
7594 :
7595 11 : void BuildGap(EnergyPlusData &state,
7596 : CFSGAP &G, // returned
7597 : int const GType, // gap type (gtyOPENin, gtyOPENout or gtySEALED)
7598 : Real64 &TAS // gap thickness, m
7599 : )
7600 : {
7601 :
7602 : // SUBROUTINE INFORMATION:
7603 : // AUTHOR ASHRAE 1311-RP
7604 : // MODIFIED Bereket Nigusse, June 2013, Jason W. DeGraw 2023
7605 :
7606 : // PURPOSE OF THIS SUBROUTINE:
7607 : // fills in the effective gap thickness and calculates the gas density
7608 : // The gas density is calculated at a standard manufactured condition
7609 : // if a different condition is not specified.
7610 :
7611 : // SUBROUTINE ARGUMENT DEFINITIONS:
7612 : // at time of manufacture, default = 21 C / 1 ATM
7613 :
7614 : // SUBROUTINE PARAMETER DEFINITIONS:
7615 11 : constexpr Real64 GapThickMin(0.0001); // Minimum gap thickness allowed, m
7616 : static constexpr std::string_view RoutineName("BuildGap: ");
7617 :
7618 11 : if (TAS < GapThickMin) {
7619 0 : ShowSevereError(state, format("{}{}", RoutineName, G.Name));
7620 0 : ShowContinueError(state, "...specified gap thickness is < 0.0001 m. Reset to 0.00001 m");
7621 0 : TAS = GapThickMin;
7622 : }
7623 11 : G.TAS = TAS;
7624 11 : G.TAS_EFF = G.TAS;
7625 : // effective gap thickness will be adjusted later if there is in between
7626 : // venetian blind, see AdjustVBGap() routine
7627 :
7628 11 : G.GTYPE = GType;
7629 11 : G.RHOGAS = DensityCFSFillGas(G.FG, state.dataWindowEquivalentLayer->PAtmSeaLevel, 294.15);
7630 11 : }
7631 :
7632 4 : void AdjustVBGap(CFSGAP &G, // gap, returned updated
7633 : CFSLAYER const &L // adjacent layer
7634 : )
7635 : {
7636 : // SUBROUTINE INFORMATION:
7637 : // AUTHOR ASHRAE 1311-RP
7638 :
7639 : // PURPOSE OF THIS SUBROUTINE:
7640 : // Adjusts thickness of adjacent gaps separated by in between slatted blind.
7641 :
7642 : // METHODOLOGY EMPLOYED:
7643 : // Treat VB layer as if it has 70% of actual thickness
7644 :
7645 : // REFERENCES:
7646 : // Wright, J. L., N. Y. T. Huang, and M. R. Collins. 2008.
7647 : // "Thermal Resistance of a Window with an Enclosed Venetian Blind: A Simplified Model,"
7648 : // ASHRAE Transactions, Vol. 114, Pt. 1.
7649 :
7650 : Real64 VBTHICK;
7651 :
7652 4 : if (!IsVBLayer(L)) {
7653 0 : return; // insurance
7654 : }
7655 :
7656 4 : VBTHICK = L.W * std::cos(L.PHI_DEG); // VB layer thickness at slat angle
7657 4 : G.TAS_EFF = G.TAS + (L.W - 0.7 * VBTHICK) / 2.0;
7658 : }
7659 :
7660 11 : float DensityCFSFillGas(CFSFILLGAS const &FG, // gas properties
7661 : Real64 const P, // pressure, Pa
7662 : Real64 const T // temperature, K
7663 : )
7664 : {
7665 : // FUNCTION INFORMATION:
7666 : // AUTHOR ASHRAE 1311-RP
7667 : // PURPOSE OF THIS FUNCTION:
7668 : // Returns gas density at P and T, kg/m3
7669 : // METHODOLOGY EMPLOYED:
7670 : // Uses ideal gas relations
7671 :
7672 11 : return (P * FG.MHAT) / (Constant::UniversalGasConst * max(T, 1.0));
7673 : }
7674 :
7675 0 : int CFSNGlz(CFSTY const &FS) // CFS
7676 : {
7677 : // FUNCTION INFORMATION:
7678 : // AUTHOR ASHRAE 1311-RP
7679 : // PURPOSE OF THIS FUNCTION:
7680 : // Returns the number of glazing layers
7681 :
7682 0 : int CFSNGlz = 0;
7683 0 : for (int iL = 1; iL <= FS.NL; ++iL) {
7684 0 : if (IsGlazeLayerX(FS.L(iL))) {
7685 0 : ++CFSNGlz;
7686 : }
7687 : }
7688 0 : return CFSNGlz;
7689 : }
7690 :
7691 7 : int CFSHasControlledShade(EnergyPlusData const &state, CFSTY const &FS)
7692 : {
7693 : // FUNCTION INFORMATION:
7694 : // AUTHOR ASHRAE 1311-RP
7695 : // PURPOSE OF THIS FUNCTION:
7696 : // Returns index of the controlled layer in a fenestration. If no
7697 : // controlled layer, then returns zero.
7698 :
7699 7 : int CFSHasControlledShade = 0;
7700 22 : for (int iL = 1; iL <= FS.NL; ++iL) {
7701 18 : if (IsControlledShade(state, FS.L(iL))) {
7702 3 : CFSHasControlledShade = iL;
7703 3 : break;
7704 : }
7705 : }
7706 7 : return CFSHasControlledShade;
7707 : }
7708 :
7709 29 : void CheckAndFixCFSLayer(EnergyPlusData &state, CFSLAYER &Layer)
7710 : {
7711 : // SUBROUTINE INFORMATION:
7712 : // AUTHOR ASHRAE 1311-RP
7713 : // PURPOSE OF THIS SUBROUTINE:
7714 : // Verify CFS layer validity, sets bad items to valid defaults if possible
7715 :
7716 29 : FillDefaultsSWP(state, Layer, Layer.SWP_MAT);
7717 29 : FinalizeCFSLAYER(state, Layer);
7718 29 : }
7719 :
7720 29 : void FillDefaultsSWP(EnergyPlusData &state,
7721 : CFSLAYER const &L, // CFSLayer (input properties must be set)
7722 : CFSSWP &SWP // properties to fill
7723 : )
7724 : {
7725 : // SUBROUTINE INFORMATION:
7726 : // AUTHOR The University of WaterLoo
7727 : // MODIFIED Bereket Nigusse/FSEC, June 2013
7728 :
7729 : // PURPOSE OF THIS SUBROUTINE:
7730 : // Fills in defaulted short wave optical properties for equivalent window layers
7731 :
7732 : // may be within L
7733 : static constexpr std::string_view RoutineName("FillDefaultsSWP: ");
7734 :
7735 : // default back taus to front (often equal)
7736 29 : if (SWP.TAUSBBB < 0.0) {
7737 0 : SWP.TAUSBBB = SWP.TAUSFBB;
7738 : }
7739 29 : if (SWP.TAUSBBD < 0.0) {
7740 0 : SWP.TAUSBBD = SWP.TAUSFBD;
7741 : }
7742 :
7743 29 : if (L.LTYPE == LayerType::GLAZE) {
7744 : // estimate diffuse properties if any < 0 or autocalculate
7745 25 : if (min(SWP.RHOSBDD, SWP.RHOSFDD, SWP.TAUS_DD) < 0.0) {
7746 0 : Specular_EstimateDiffuseProps(state, SWP);
7747 : }
7748 4 : } else if (L.LTYPE == LayerType::VBHOR || L.LTYPE == LayerType::VBVER) {
7749 :
7750 0 : } else if (L.LTYPE == LayerType::DRAPE) {
7751 : // estimate diffuse properties if any < 0
7752 0 : if (min(SWP.RHOSBDD, SWP.RHOSFDD, SWP.TAUS_DD) < 0.0) {
7753 0 : Fabric_EstimateDiffuseProps(state, SWP);
7754 : }
7755 0 : } else if (L.LTYPE == LayerType::ROLLB) {
7756 : // estimate diffuse properties if any < 0
7757 0 : if (min(SWP.RHOSBDD, SWP.RHOSFDD, SWP.TAUS_DD) < 0.0) {
7758 0 : RB_SWP(state, L, SWP); // TODO RB
7759 : }
7760 0 : } else if (L.LTYPE == LayerType::INSCRN) {
7761 0 : if (SWP.TAUSFBB < 0.0) {
7762 0 : SWP.TAUSFBB = IS_OPENNESS(L.S, L.W);
7763 0 : if (SWP.TAUSBBB < 0.0) {
7764 0 : SWP.TAUSBBB = SWP.TAUSFBB;
7765 : }
7766 : }
7767 0 : if (min(SWP.RHOSBDD, SWP.RHOSFDD, SWP.TAUS_DD) < 0.0) {
7768 0 : IS_SWP(state, L, SWP); // TODO IS
7769 : }
7770 0 : } else if (L.LTYPE == LayerType::NONE || L.LTYPE == LayerType::ROOM) {
7771 : // none or room: do nothing
7772 : } else {
7773 0 : ShowSevereError(state, format("{}{}.", RoutineName, L.Name));
7774 0 : ShowContinueError(state, "...invalid layer type specified.");
7775 : }
7776 29 : }
7777 :
7778 7 : void FinalizeCFS(EnergyPlusData &state, CFSTY &FS)
7779 : {
7780 : // SUBROUTINE INFORMATION:
7781 : // AUTHOR The University of WaterLoo
7782 : // MODIFIED Bereket Nigusse/FSEC, May 2013
7783 :
7784 : // PURPOSE OF THIS SUBROUTINE:
7785 : // Complete CFS after BuildCFS by checking the shade type and gap type
7786 :
7787 : static constexpr std::string_view RoutineName("FinalizeCFS: "); // include trailing blank space
7788 :
7789 7 : std::string CurrentModuleObject = "WindowConstruction:EquivalentLayer";
7790 7 : bool ErrorsFound = false;
7791 :
7792 7 : bool LVBPREV = false; // .TRUE. if previous layer is VB
7793 :
7794 25 : for (int iL = 1; iL <= FS.NL; ++iL) {
7795 18 : if (!IsVBLayer(FS.L(iL))) {
7796 14 : LVBPREV = false;
7797 4 : } else if (LVBPREV) {
7798 0 : ShowSevereError(state, format("{}=\"{}\", illegal.", CurrentModuleObject, FS.Name));
7799 0 : ShowContinueError(state, "...adjacent VB layers are specified.");
7800 0 : ErrorsFound = true;
7801 : } else {
7802 4 : LVBPREV = true;
7803 4 : if (iL > 1) {
7804 4 : AdjustVBGap(FS.G(iL - 1), FS.L(iL));
7805 : }
7806 4 : if (iL < FS.NL) {
7807 0 : AdjustVBGap(FS.G(iL), FS.L(iL));
7808 : }
7809 : }
7810 18 : if (iL < FS.NL) {
7811 11 : int gType = FS.G(iL).GTYPE;
7812 11 : if (gType == state.dataWindowEquivalentLayer->gtyOPENout && iL != 1) {
7813 0 : ShowSevereError(state, format("{}=\"{}", CurrentModuleObject, FS.Name));
7814 0 : ShowContinueError(state, format("...invalid EquivalentLayer window gap type specified ={}.", FS.G(iL).Name));
7815 0 : ShowContinueError(state, "...VentedOutDoor gap is not outermost.");
7816 : }
7817 11 : if (gType == state.dataWindowEquivalentLayer->gtyOPENin && iL != FS.NL - 1) {
7818 0 : ShowSevereError(state, format("{}=\"{}", CurrentModuleObject, FS.Name));
7819 0 : ShowContinueError(state, format("...invalid EquivalentLayer window gap type specified ={}.", FS.G(iL).Name));
7820 0 : ShowContinueError(state, "...VentedIndoor gap is not innermost.");
7821 : }
7822 : }
7823 : }
7824 7 : if (ErrorsFound) {
7825 0 : ShowFatalError(state, format("{}Program terminates for preceding reason(s).", RoutineName));
7826 : }
7827 7 : }
7828 :
7829 4719 : Real64 EffectiveEPSLF(CFSTY const &FS) // Complex Fenestration
7830 : {
7831 : // FUNCTION INFORMATION:
7832 : // AUTHOR <unknown>, ASHRAE 1311-RP
7833 : // PURPOSE OF THIS FUNCTION:
7834 : // Returns effective outside Longwave emissivity. Handles partially transparent layers
7835 :
7836 : Real64 E; // Effective emissivity
7837 : Real64 TX; // correction factor
7838 : int iL; // layers index
7839 :
7840 4719 : E = 0.0;
7841 4719 : TX = 1.0;
7842 4719 : for (iL = 1; iL <= FS.NL + 1; ++iL) {
7843 4719 : if (iL == FS.NL + 1) {
7844 0 : E += 0.9 * TX;
7845 : } else {
7846 4719 : E += FS.L(iL).LWP_EL.EPSLF * TX;
7847 4719 : if (FS.L(iL).LWP_EL.TAUL < 0.001) {
7848 4719 : break;
7849 : }
7850 0 : TX *= FS.L(iL).LWP_EL.TAUL;
7851 : }
7852 : }
7853 4719 : return E;
7854 : }
7855 :
7856 30391 : Real64 EffectiveEPSLB(CFSTY const &FS) // Complex Fenestration
7857 : {
7858 : // FUNCTION INFORMATION:
7859 : // AUTHOR <unknown>, ASHRAE 1311-RP
7860 : // PURPOSE OF THIS FUNCTION:
7861 : // Returns effective inside (room side) Longwave emissivity. Handles partially transparent layers
7862 :
7863 30391 : Real64 E = 0.0; // Effective emissivity
7864 30391 : Real64 TX = 1.0; // correction factor
7865 50320 : for (int iL = FS.NL; iL >= 0; --iL) {
7866 50320 : if (iL == 0) {
7867 0 : E += 0.9 * TX;
7868 : } else {
7869 50320 : E += FS.L(iL).LWP_EL.EPSLB * TX;
7870 50320 : if (FS.L(iL).LWP_EL.TAUL < 0.001) {
7871 30391 : break;
7872 : }
7873 19929 : TX *= FS.L(iL).LWP_EL.TAUL;
7874 : }
7875 : }
7876 30391 : return E;
7877 : }
7878 :
7879 10 : bool FEQX(Real64 const a, // values to compare, fractional tolerance
7880 : Real64 const b,
7881 : Real64 const tolF,
7882 : const Real64 tolAbs // absolute tolerance
7883 : )
7884 : {
7885 : // FUNCTION INFORMATION:
7886 : // AUTHOR <unknown>, ASHRAE 1311-RP
7887 : // PURPOSE OF THIS FUNCTION:
7888 : // Returns true if the difference between two real numbers is within the
7889 : // tolerance limit specified.
7890 :
7891 10 : Real64 tolAbsX = max(tolAbs, 1.e-10);
7892 :
7893 10 : Real64 d = std::abs(a - b);
7894 10 : if (d < tolAbsX) {
7895 5 : return true;
7896 : } else {
7897 5 : return (2.0 * d / (std::abs(a) + std::abs(b))) < tolF;
7898 : }
7899 : }
7900 :
7901 0 : Real64 TRadC(Real64 const J, // radiosity, W/m2
7902 : Real64 const Emiss // surface emissivity
7903 : )
7904 : {
7905 : // FUNCTION INFORMATION:
7906 : // AUTHOR <unknown>, ASHRAE 1311-RP
7907 : // PURPOSE OF THIS FUNCTION:
7908 : // Returns equivalent celsius scale temperature from radiosity
7909 :
7910 0 : return root_4(J / (Constant::StefanBoltzmann * max(Emiss, 0.001))) - Constant::Kelvin;
7911 : }
7912 :
7913 1109 : void CalcEQLOpticalProperty(EnergyPlusData &state,
7914 : int const SurfNum,
7915 : SolarArrays const BeamDIffFlag, // identifier index of diffuse and beam SW radiation
7916 : Array2A<Real64> CFSAbs // absorbed beam solar radiation by layers fraction
7917 : )
7918 : {
7919 :
7920 : // SUBROUTINE INFORMATION:
7921 : // AUTHOR Bereket Nigusse
7922 : // DATE WRITTEN May 2013
7923 :
7924 : // PURPOSE OF THIS SUBROUTINE:
7925 : // Calculates the system optical properties from the individual layers
7926 : // properties at each time step. The values returned are the layer-by-layer
7927 : // absorptance and system transmittance for both beam and diffuse radiation.
7928 :
7929 : // METHODOLOGY EMPLOYED:
7930 : // Uses the net radiation method developed for ASHWAT fenestration
7931 : // model (ASHRAE RP-1311) by John Wright, the University of WaterLoo
7932 :
7933 : // Argument array dimensioning
7934 1109 : CFSAbs.dim(2, CFSMAXNL + 1);
7935 :
7936 1109 : Array2D<Real64> Abs1(2, CFSMAXNL + 1);
7937 :
7938 1109 : auto &surf = state.dataSurface->Surface(SurfNum);
7939 :
7940 1109 : auto &CFS = state.dataWindowEquivLayer->CFS;
7941 :
7942 1109 : Real64 IncAng = 0.0; // incident angle degree
7943 1109 : CFSAbs = 0.0;
7944 1109 : Real64 ProfAngHor = 0.0;
7945 1109 : Real64 ProfAngVer = 0.0;
7946 1109 : int ConstrNum = surf.Construction;
7947 1109 : int EQLNum = state.dataConstruction->Construct(surf.Construction).EQLConsPtr;
7948 1109 : if (BeamDIffFlag != SolarArrays::DIFF) {
7949 787 : if (state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) <= 0.0) {
7950 0 : return;
7951 : }
7952 :
7953 2851 : for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
7954 2064 : if (IsVBLayer(CFS(EQLNum).L(Lay))) {
7955 490 : if (CFS(EQLNum).L(Lay).LTYPE == LayerType::VBHOR) {
7956 322 : ProfAngVer = Dayltg::ProfileAngle(state, SurfNum, state.dataEnvrn->SOLCOS, DataWindowEquivalentLayer::Orientation::Horizontal);
7957 168 : } else if (CFS(EQLNum).L(Lay).LTYPE == LayerType::VBVER) {
7958 168 : ProfAngHor = Dayltg::ProfileAngle(state, SurfNum, state.dataEnvrn->SOLCOS, DataWindowEquivalentLayer::Orientation::Vertical);
7959 : }
7960 : }
7961 : }
7962 : // Incident angle
7963 787 : IncAng = std::acos(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum));
7964 787 : CalcEQLWindowOpticalProperty(state, CFS(EQLNum), BeamDIffFlag, Abs1, IncAng, ProfAngVer, ProfAngHor);
7965 787 : CFSAbs(1, {1, CFSMAXNL + 1}) = Abs1(1, {1, CFSMAXNL + 1});
7966 787 : CFSAbs(2, {1, CFSMAXNL + 1}) = Abs1(2, {1, CFSMAXNL + 1});
7967 : } else {
7968 322 : if (state.dataWindowEquivalentLayer->EQLDiffPropFlag(EQLNum)) {
7969 1283 : for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
7970 962 : if (IsVBLayer(CFS(EQLNum).L(Lay))) {
7971 320 : if (CFS(EQLNum).L(Lay).LTYPE == LayerType::VBHOR) {
7972 : ProfAngVer =
7973 320 : Dayltg::ProfileAngle(state, SurfNum, state.dataEnvrn->SOLCOS, DataWindowEquivalentLayer::Orientation::Horizontal);
7974 0 : } else if (CFS(EQLNum).L(Lay).LTYPE == LayerType::VBVER) {
7975 0 : ProfAngHor = Dayltg::ProfileAngle(state, SurfNum, state.dataEnvrn->SOLCOS, DataWindowEquivalentLayer::Orientation::Vertical);
7976 : }
7977 : }
7978 : }
7979 321 : IncAng = std::acos(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum));
7980 321 : CalcEQLWindowOpticalProperty(state, CFS(EQLNum), BeamDIffFlag, Abs1, IncAng, ProfAngVer, ProfAngHor);
7981 321 : CFSAbs(_, {1, CFSMAXNL + 1}) = Abs1(_, {1, CFSMAXNL + 1});
7982 321 : state.dataWindowEquivalentLayer->CFSDiffAbsTrans(_, {1, CFSMAXNL + 1}, EQLNum) = Abs1(_, {1, CFSMAXNL + 1});
7983 321 : state.dataConstruction->Construct(ConstrNum).TransDiff = Abs1(1, CFS(EQLNum).NL + 1);
7984 321 : state.dataConstruction->Construct(ConstrNum).AbsDiffFrontEQL({1, CFSMAXNL}) = Abs1(1, {1, CFSMAXNL});
7985 321 : state.dataConstruction->Construct(ConstrNum).AbsDiffBackEQL({1, CFSMAXNL}) = Abs1(2, {1, CFSMAXNL});
7986 321 : state.dataConstruction->Construct(ConstrNum).ReflectSolDiffFront = CFS(EQLNum).L(1).SWP_EL.RHOSFDD;
7987 321 : state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack = CFS(EQLNum).L(CFS(EQLNum).NL).SWP_EL.RHOSBDD;
7988 321 : if (!CFS(EQLNum).ISControlled) {
7989 1 : state.dataWindowEquivalentLayer->EQLDiffPropFlag(EQLNum) = false;
7990 : }
7991 : } else {
7992 1 : CFSAbs(_, {1, CFSMAXNL + 1}) = state.dataWindowEquivalentLayer->CFSDiffAbsTrans(_, {1, CFSMAXNL + 1}, EQLNum);
7993 1 : state.dataConstruction->Construct(ConstrNum).TransDiff = state.dataWindowEquivalentLayer->CFSDiffAbsTrans(1, CFS(EQLNum).NL + 1, EQLNum);
7994 1 : state.dataConstruction->Construct(ConstrNum).AbsDiffFrontEQL({1, CFSMAXNL}) = CFSAbs(1, {1, CFSMAXNL});
7995 1 : state.dataConstruction->Construct(ConstrNum).AbsDiffBackEQL({1, CFSMAXNL}) = CFSAbs(2, {1, CFSMAXNL});
7996 : }
7997 : }
7998 1109 : if (CFS(EQLNum).VBLayerPtr > 0) {
7999 810 : auto &surfShade = state.dataSurface->surfShades(SurfNum);
8000 810 : surfShade.blind.slatAngDeg = CFS(EQLNum).L(CFS(EQLNum).VBLayerPtr).PHI_DEG;
8001 : }
8002 1109 : }
8003 :
8004 7 : void CalcEQLWindowStandardRatings(EnergyPlusData &state, int const ConstrNum) // construction index
8005 : {
8006 :
8007 : // SUBROUTINE INFORMATION:
8008 : // AUTHOR Bereket Nigusse
8009 : // DATE WRITTEN May 2013
8010 :
8011 : // PURPOSE OF THIS SUBROUTINE:
8012 : // Calculates the U-value, SHGC and Normal Transmittance of equivalent layer fenestration.
8013 :
8014 : // METHODOLOGY EMPLOYED:
8015 : // Uses routine developed for ASHRAE RP-1311 (ASHWAT Model)
8016 :
8017 7 : Real64 UValue = 0.0;
8018 7 : Real64 SHGCSummer = 0.0;
8019 7 : Real64 TransNormal = 0.0;
8020 :
8021 7 : int EQLNum = state.dataConstruction->Construct(ConstrNum).EQLConsPtr;
8022 :
8023 : // calculate fenestration air-to-air U-value
8024 7 : CalcEQLWindowUvalue(state, state.dataWindowEquivLayer->CFS(EQLNum), UValue);
8025 7 : state.dataHeatBal->NominalU(ConstrNum) = UValue;
8026 :
8027 : // calculate the SHGC and Normal Transmittance
8028 7 : CalcEQLWindowSHGCAndTransNormal(state, state.dataWindowEquivLayer->CFS(EQLNum), SHGCSummer, TransNormal);
8029 7 : state.dataConstruction->Construct(ConstrNum).SummerSHGC = SHGCSummer;
8030 7 : state.dataConstruction->Construct(ConstrNum).SolTransNorm = TransNormal;
8031 7 : }
8032 :
8033 28032 : Real64 EQLWindowInsideEffectiveEmiss(EnergyPlusData &state, int const ConstrNum)
8034 : {
8035 : // FUNCTION INFORMATION:
8036 : // AUTHOR Bereket A Nigusse
8037 : // DATE WRITTEN May 2013
8038 :
8039 : // PURPOSE OF THIS FUNCTION:
8040 : // Given the construction number, returns the equivalent layer inside
8041 : // face effective longwave emissivity.
8042 :
8043 28032 : return EffectiveEPSLB(state.dataWindowEquivLayer->CFS(state.dataConstruction->Construct(ConstrNum).EQLConsPtr));
8044 : }
8045 :
8046 2367 : Real64 EQLWindowOutsideEffectiveEmiss(EnergyPlusData &state, int const ConstrNum)
8047 : {
8048 : // FUNCTION INFORMATION:
8049 : // AUTHOR Bereket A Nigusse
8050 : // DATE WRITTEN May 2013
8051 :
8052 : // PURPOSE OF THIS FUNCTION:
8053 : // Given the construction number, returns the equivalent layer outside
8054 : // face effective longwave emissivity.
8055 :
8056 2367 : int EQLNum = state.dataConstruction->Construct(ConstrNum).EQLConsPtr;
8057 2367 : return EffectiveEPSLF(state.dataWindowEquivLayer->CFS(EQLNum));
8058 : }
8059 :
8060 124 : Real64 HCInWindowStandardRatings(EnergyPlusData &state,
8061 : Real64 const Height, // Window height, 1.0 m
8062 : Real64 const TSurfIn, // Inside surface temperature
8063 : Real64 const TAirIn // Zone Air Temperature
8064 : )
8065 : {
8066 : // FUNCTION INFORMATION:
8067 : // AUTHOR Bereket Nigusse
8068 : // DATE WRITTEN June 2013
8069 :
8070 : // PURPOSE OF THIS FUNCTION:
8071 : // Return the inside convection coefficient for fenestration ratings.
8072 : // This procedure is adopted from WindowTempsForNominalCond routine.
8073 : // METHODOLOGY EMPLOYED:
8074 : // Uses ISO Standard 15099 method to calculate the inside surface
8075 : // convection coefficient for fenestration ratings.
8076 :
8077 : using Psychrometrics::PsyRhoAirFnPbTdbW;
8078 :
8079 : static constexpr std::string_view RoutineName("HCInWindowStandardRatings");
8080 :
8081 : Real64 TmeanFilm; // mean film temperature
8082 : Real64 TmeanFilmKelvin; // mean film temperature for property evaluation
8083 : Real64 rho; // density of (apparently dry) air [kg/m3]
8084 : Real64 Cp; // specific heat of air [J/kg-K]
8085 : Real64 lambda; // thermal conductivity of air [W/m-K]
8086 : Real64 mu; // dynamic viscosity of air [kg/m-s]
8087 : Real64 RaH; // Rayleigh number for cavity height [ Non dim]
8088 : Real64 TiltDeg; // glazing tilt in degrees
8089 : Real64 sineTilt; // sine of glazing tilt
8090 : Real64 Nuint; // Nusselt number for interior surface convection
8091 :
8092 124 : TiltDeg = 90.0;
8093 124 : sineTilt = std::sin(TiltDeg * Constant::DegToRad); // degrees as arg
8094 :
8095 : // Begin calculating for ISO 15099 method.
8096 : // mean film temperature
8097 124 : TmeanFilmKelvin = TAirIn + 0.25 * (TSurfIn - TAirIn); // eq. 133 in ISO 15099
8098 124 : TmeanFilm = TmeanFilmKelvin - 273.15;
8099 : // the following properties are constants or linear relations for "standard" type reporting
8100 124 : rho = PsyRhoAirFnPbTdbW(state, 101325.0, TmeanFilm, 0.0, RoutineName); // dry air assumption
8101 :
8102 124 : lambda = 2.873E-3 + 7.76E-5 * TmeanFilmKelvin; // Table B.1 in ISO 15099
8103 124 : mu = 3.723E-6 + 4.94E-8 * TmeanFilmKelvin; // Table B.2 in ISO 15099
8104 124 : Cp = 1002.737 + 1.2324E-2 * TmeanFilmKelvin; // Table B.3 in ISO 15099
8105 :
8106 124 : RaH = (pow_2(rho) * pow_3(Height) * Constant::Gravity * Cp * std::abs(TSurfIn - TAirIn)) / (TmeanFilmKelvin * mu * lambda); // eq 132 in ISO 15099
8107 :
8108 : // eq. 135 in ISO 15099 (only need this one because tilt is 90 deg)
8109 124 : Nuint = 0.56 * root_4(RaH * sineTilt);
8110 124 : return Nuint * lambda / Height;
8111 : }
8112 :
8113 : } // namespace EnergyPlus::WindowEquivalentLayer
|