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