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