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