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