Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <algorithm>
50 : #include <cassert>
51 : #include <cmath>
52 : #include <memory>
53 :
54 : // ObjexxFCL Headers
55 : #include <ObjexxFCL/Array.functions.hh>
56 : #include <ObjexxFCL/Vector3.hh>
57 : #include <ObjexxFCL/member.functions.hh>
58 :
59 : // EnergyPlus Headers
60 : #include <EnergyPlus/CommandLineInterface.hh>
61 : #include <EnergyPlus/Construction.hh>
62 : #include <EnergyPlus/Data/EnergyPlusData.hh>
63 : #include <EnergyPlus/DataDaylightingDevices.hh>
64 : #include <EnergyPlus/DataEnvironment.hh>
65 : #include <EnergyPlus/DataErrorTracking.hh>
66 : #include <EnergyPlus/DataHeatBalSurface.hh>
67 : #include <EnergyPlus/DataHeatBalance.hh>
68 : #include <EnergyPlus/DataIPShortCuts.hh>
69 : #include <EnergyPlus/DataReportingFlags.hh>
70 : #include <EnergyPlus/DataShadowingCombinations.hh>
71 : #include <EnergyPlus/DataStringGlobals.hh>
72 : #include <EnergyPlus/DataSurfaces.hh>
73 : #include <EnergyPlus/DataSystemVariables.hh>
74 : #include <EnergyPlus/DataViewFactorInformation.hh>
75 : #include <EnergyPlus/DataWindowEquivalentLayer.hh>
76 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
77 : #include <EnergyPlus/DaylightingDevices.hh>
78 : #include <EnergyPlus/DaylightingManager.hh>
79 : #include <EnergyPlus/DisplayRoutines.hh>
80 : #include <EnergyPlus/EMSManager.hh>
81 : #include <EnergyPlus/EnergyPlusLogger.hh>
82 : // #include <EnergyPlus/General.hh>
83 : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
84 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
85 : #include <EnergyPlus/OutputProcessor.hh>
86 : #include <EnergyPlus/OutputReportPredefined.hh>
87 : #include <EnergyPlus/PluginManager.hh>
88 : #include <EnergyPlus/ScheduleManager.hh>
89 : #include <EnergyPlus/SolarReflectionManager.hh>
90 : #include <EnergyPlus/SolarShading.hh>
91 : #include <EnergyPlus/UtilityRoutines.hh>
92 : #include <EnergyPlus/Vectors.hh>
93 : #include <EnergyPlus/WindowComplexManager.hh>
94 : #include <EnergyPlus/WindowEquivalentLayer.hh>
95 : #include <EnergyPlus/WindowManager.hh>
96 : #include <EnergyPlus/WindowManagerExteriorData.hh>
97 : #include <EnergyPlus/WindowModel.hh>
98 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
99 : #include <WCEMultiLayerOptics.hpp>
100 :
101 : namespace EnergyPlus::SolarShading {
102 :
103 : // MODULE INFORMATION:
104 : // AUTHOR Rick Strand
105 : // DATE WRITTEN March 1997
106 : // MODIFIED December 1998, FCW
107 : // MODIFIED July 1999, Linda Lawrie, eliminate shadefl.scr,
108 : // do shadowing calculations during simulation
109 : // MODIFIED June 2001, FCW, handle window blinds
110 : // MODIFIED May 2004, LKL, Polygons > 4 sides (not subsurfaces)
111 : // MODIFIED January 2007, LKL, Taking parameters back to original integer (HC)
112 : // MODIFIED August 2011, JHK, Including Complex Fenestration optical calculations
113 : // MODIFIED November 2012, BG, Timestep solar and daylighting calculations
114 : // RE-ENGINEERED na
115 :
116 : // PURPOSE OF THIS MODULE:
117 : // The purpose of this module is to encompass the routines and data
118 : // which are need to perform the solar calculations in EnergyPlus.
119 : // This also requires that shading and geometry routines and data
120 : // which are used by the solar calculations be included in this module.
121 :
122 : // METHODOLOGY EMPLOYED:
123 : // Many of the methods used in this module have been carried over from the
124 : // (I)BLAST program. As such, there is not much documentation on the
125 : // methodology used. The original code was written mainly by George
126 : // Walton and requires coordinate transformations. It calculates
127 : // shading using an overlapping polygon approach.
128 :
129 : // REFERENCES:
130 : // TARP Manual, NIST Publication.
131 : // Passive Solar Extension of the BLAST Program, CERL/UIUC Publication.
132 :
133 : using namespace DataEnvironment;
134 : using namespace DataHeatBalance;
135 : using namespace DataSurfaces;
136 : using namespace DataShadowingCombinations;
137 : using namespace SolarReflectionManager;
138 : using namespace DataVectorTypes;
139 : using namespace Window;
140 : using namespace FenestrationCommon;
141 : using namespace SingleLayerOptics;
142 :
143 : int constexpr NPhi = 6; // Number of altitude angle steps for sky integration
144 : int constexpr NTheta = 24; // Number of azimuth angle steps for sky integration
145 : Real64 constexpr Eps = 1.e-10; // Small number
146 : Real64 constexpr DPhi = Constant::PiOvr2 / NPhi; // Altitude step size
147 : Real64 constexpr DTheta = 2.0 * Constant::Pi / NTheta; // Azimuth step size
148 : Real64 constexpr DThetaDPhi = DTheta * DPhi; // Product of DTheta and DPhi
149 : Real64 constexpr PhiMin = 0.5 * DPhi; // Minimum altitude
150 :
151 : Real64 constexpr HCMULT = 100000.0; // Multiplier used to change meters to .01 millimeters for homogeneous coordinates.
152 : // Homogeneous Coordinates are represented in integers (64 bit). This changes the surface coordinates from meters
153 : // to .01 millimeters -- making that the resolution for shadowing, polygon clipping, etc.
154 : Real64 constexpr sqHCMULT = (HCMULT * HCMULT); // Square of HCMult used in Homogeneous coordinates
155 : Real64 constexpr sqHCMULT_fac = (0.5 / sqHCMULT); // ( 0.5 / sqHCMULT ) factor
156 :
157 : // Parameters for use with the variable OverlapStatus...
158 : int constexpr NoOverlap = 1;
159 : int constexpr FirstSurfWithinSecond = 2;
160 : int constexpr SecondSurfWithinFirst = 3;
161 : int constexpr PartialOverlap = 4;
162 : int constexpr TooManyVertices = 5;
163 : int constexpr TooManyFigures = 6;
164 :
165 119 : void InitSolarCalculations(EnergyPlusData &state)
166 : {
167 :
168 : // SUBROUTINE INFORMATION:
169 : // AUTHOR George Walton
170 : // DATE WRITTEN September 1977
171 : // MODIFIED na
172 : // RE-ENGINEERED Mar97, RKS, Initial EnergyPlus Version
173 :
174 : // PURPOSE OF THIS SUBROUTINE:
175 : // This routine controls the computation of the solar flux multipliers.
176 :
177 : // METHODOLOGY EMPLOYED:
178 : // All shadowing calculations have been grouped under this routine to
179 : // allow segmentation separating it from the hourly loads calculation.
180 :
181 119 : auto &s_surf = state.dataSurface;
182 : #ifdef EP_Count_Calls
183 : ++state.dataTimingsData->NumInitSolar_Calls;
184 : #endif
185 119 : if (state.dataGlobal->BeginSimFlag) {
186 114 : if (state.files.outputControl.shd) {
187 114 : state.dataSolarShading->shd_stream =
188 228 : std::make_unique<std::fstream>(state.dataStrGlobals->outputShdFilePath, std::ios_base::out | std::ios_base::trunc);
189 114 : if (!state.dataSolarShading->shd_stream) {
190 0 : ShowFatalError(
191 0 : state, format("InitSolarCalculations: Could not open file \"{}\" for output (write).", state.dataStrGlobals->outputShdFilePath));
192 : }
193 : } else {
194 0 : state.dataSolarShading->shd_stream = std::make_unique<std::iostream>(nullptr);
195 : }
196 :
197 114 : if (state.dataSolarShading->GetInputFlag) {
198 111 : checkShadingSurfaceSchedules(state);
199 111 : processShadowingInput(state);
200 111 : state.dataSolarShading->GetInputFlag = false;
201 222 : state.dataSolarShading->MaxHCV =
202 111 : (((max(15, s_surf->MaxVerticesPerSurface) + 16) / 16) * 16) - 1; // Assure MaxHCV+1 is multiple of 16 for 128 B alignment
203 111 : assert((state.dataSolarShading->MaxHCV + 1) % 16 == 0);
204 : }
205 :
206 114 : if (state.dataSolarShading->firstTime) {
207 112 : DisplayString(state, "Allocate Solar Module Arrays");
208 : }
209 114 : AllocateModuleArrays(state);
210 :
211 114 : if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::FullInteriorExterior) {
212 104 : if (state.dataSolarShading->firstTime) {
213 102 : DisplayString(state, "Computing Interior Solar Absorption Factors");
214 : }
215 104 : ComputeIntSolarAbsorpFactors(state);
216 : }
217 :
218 114 : if (state.dataSolarShading->firstTime) {
219 112 : DisplayString(state, "Determining Shadowing Combinations");
220 : }
221 114 : DetermineShadowingCombinations(state);
222 114 : state.dataSolarShading->shd_stream.reset(); // Done writing to shd file
223 :
224 114 : if (state.dataSolarShading->firstTime) {
225 112 : DisplayString(state, "Computing Window Shade Absorption Factors");
226 : }
227 114 : ComputeWinShadeAbsorpFactors(state);
228 :
229 114 : if (s_surf->CalcSolRefl) {
230 0 : DisplayString(state, "Initializing Solar Reflection Factors");
231 0 : InitSolReflRecSurf(state);
232 : }
233 :
234 114 : if (state.dataSolarShading->firstTime) {
235 112 : DisplayString(state, "Proceeding with Initializing Solar Calculations");
236 : }
237 : }
238 :
239 119 : if (state.dataGlobal->BeginEnvrnFlag) {
240 107 : state.dataSolarShading->SurfSunCosTheta = 0.0;
241 107 : state.dataSolarShading->SurfSunlitArea = 0.0;
242 107 : s_surf->SurfSunlitArea = 0.0;
243 107 : s_surf->SurfSunlitFrac = 0.0;
244 107 : state.dataHeatBal->SurfSunlitFracHR = 0.0;
245 107 : state.dataHeatBal->SurfSunlitFrac = 0.0;
246 107 : state.dataHeatBal->SurfSunlitFracWithoutReveal = 0.0;
247 107 : state.dataHeatBal->SurfWinBackSurfaces = 0;
248 107 : state.dataHeatBal->SurfWinOverlapAreas = 0.0;
249 107 : state.dataHeatBal->SurfCosIncAngHR = 0.0;
250 107 : state.dataHeatBal->SurfCosIncAng = 0.0;
251 107 : state.dataSolarShading->SurfAnisoSkyMult = 1.0; // For isotropic sky; recalculated in AnisoSkyViewFactors if anisotropic radiance
252 : // WithShdgIsoSky=0.0
253 : // WoShdgIsoSky=0.0
254 : // WithShdgHoriz=0.0
255 : // WoShdgHoriz=0.0
256 : // DifShdgRatioIsoSky=0.0
257 : // DifShdgRatioHoriz=0.0
258 107 : state.dataSolarShading->SurfMultIsoSky = 0.0;
259 107 : state.dataSolarShading->SurfMultCircumSolar = 0.0;
260 107 : state.dataSolarShading->SurfMultHorizonZenith = 0.0;
261 107 : state.dataSolarShading->SurfWinRevealStatus = 0;
262 :
263 234 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
264 127 : state.dataHeatBal->ZoneWinHeatGain(zoneNum) = 0.0;
265 127 : state.dataHeatBal->ZoneWinHeatGainRep(zoneNum) = 0.0;
266 127 : state.dataHeatBal->ZoneWinHeatLossRep(zoneNum) = 0.0;
267 127 : state.dataHeatBal->ZoneWinHeatGainRepEnergy(zoneNum) = 0.0;
268 127 : state.dataHeatBal->ZoneWinHeatLossRepEnergy(zoneNum) = 0.0;
269 127 : state.dataHeatBal->ZoneOpaqSurfInsFaceCond(zoneNum) = 0.0;
270 127 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep(zoneNum) = 0.0;
271 127 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep(zoneNum) = 0.0;
272 127 : state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg(zoneNum) = 0.0;
273 127 : state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg(zoneNum) = 0.0;
274 : }
275 242 : for (int enclNum = 1; enclNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclNum) {
276 135 : state.dataHeatBal->ZoneTransSolar(enclNum) = 0.0;
277 135 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclNum) = 0.0;
278 135 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclNum) = 0.0;
279 135 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclNum) = 0.0;
280 135 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclNum) = 0.0;
281 135 : state.dataHeatBal->ZoneDifSolFrIntWinsRep(enclNum) = 0.0;
282 135 : state.dataHeatBal->ZoneTransSolarEnergy(enclNum) = 0.0;
283 135 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclNum) = 0.0;
284 135 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclNum) = 0.0;
285 135 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclNum) = 0.0;
286 135 : state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy(enclNum) = 0.0;
287 : }
288 876 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
289 769 : state.dataHeatBal->SurfQRadSWOutIncident(SurfNum) = 0.0;
290 769 : state.dataHeatBal->SurfQRadSWOutIncidentBeam(SurfNum) = 0.0;
291 769 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = 0.0;
292 769 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) = 0.0;
293 769 : state.dataHeatBal->SurfIntBmIncInsSurfIntensRep(SurfNum) = 0.0;
294 769 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRep(SurfNum) = 0.0;
295 769 : state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse(SurfNum) = 0.0;
296 769 : state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse(SurfNum) = 0.0;
297 769 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd(SurfNum) = 0.0;
298 769 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd(SurfNum) = 0.0;
299 769 : state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs(SurfNum) = 0.0;
300 769 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs(SurfNum) = 0.0;
301 769 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs(SurfNum) = 0.0;
302 769 : state.dataHeatBal->SurfCosIncidenceAngle(SurfNum) = 0.0;
303 769 : state.dataHeatBal->SurfSWInAbsTotalReport(SurfNum) = 0.0;
304 769 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) = 0.0;
305 769 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy(SurfNum) = 0.0;
306 769 : state.dataHeatBal->SurfInitialDifSolInAbsReport(SurfNum) = 0.0;
307 : }
308 234 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
309 271 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
310 144 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
311 144 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
312 144 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
313 190 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
314 :
315 46 : s_surf->SurfWinTransSolar(SurfNum) = 0.0;
316 46 : s_surf->SurfWinBmSolar(SurfNum) = 0.0;
317 46 : s_surf->SurfWinBmBmSolar(SurfNum) = 0.0;
318 46 : s_surf->SurfWinBmDifSolar(SurfNum) = 0.0;
319 46 : s_surf->SurfWinDifSolar(SurfNum) = 0.0;
320 :
321 46 : s_surf->SurfWinTransSolarEnergy(SurfNum) = 0.0;
322 46 : s_surf->SurfWinBmSolarEnergy(SurfNum) = 0.0;
323 46 : s_surf->SurfWinBmBmSolarEnergy(SurfNum) = 0.0;
324 46 : s_surf->SurfWinBmDifSolarEnergy(SurfNum) = 0.0;
325 :
326 46 : s_surf->SurfWinHeatGain(SurfNum) = 0.0;
327 46 : s_surf->SurfWinHeatGainRep(SurfNum) = 0.0;
328 46 : s_surf->SurfWinHeatLossRep(SurfNum) = 0.0;
329 : }
330 190 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
331 46 : s_surf->SurfWinGainConvGlazToZoneRep(SurfNum) = 0.0;
332 46 : s_surf->SurfWinGainIRGlazToZoneRep(SurfNum) = 0.0;
333 46 : s_surf->SurfWinLossSWZoneToOutWinRep(SurfNum) = 0.0;
334 46 : s_surf->SurfWinGainFrameDividerToZoneRep(SurfNum) = 0.0;
335 46 : s_surf->SurfWinGainConvShadeToZoneRep(SurfNum) = 0.0;
336 46 : s_surf->SurfWinGainIRShadeToZoneRep(SurfNum) = 0.0;
337 46 : s_surf->SurfWinGapConvHtFlowRep(SurfNum) = 0.0;
338 46 : s_surf->SurfWinShadingAbsorbedSolar(SurfNum) = 0.0;
339 :
340 46 : s_surf->SurfWinSysSolTransmittance(SurfNum) = 0.0;
341 46 : s_surf->SurfWinSysSolReflectance(SurfNum) = 0.0;
342 46 : s_surf->SurfWinSysSolAbsorptance(SurfNum) = 0.0;
343 : }
344 190 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
345 46 : s_surf->SurfWinDifSolarEnergy(SurfNum) = 0.0;
346 46 : s_surf->SurfWinHeatGainRepEnergy(SurfNum) = 0.0;
347 46 : s_surf->SurfWinHeatLossRepEnergy(SurfNum) = 0.0;
348 46 : s_surf->SurfWinGapConvHtFlowRepEnergy(SurfNum) = 0.0;
349 46 : s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfNum) = 0.0;
350 :
351 46 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfNum) = 0.0;
352 46 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfNum) = 0.0;
353 46 : state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfNum) = 0.0;
354 46 : state.dataHeatBal->SurfWinInitialDifSolInTransReport(SurfNum) = 0.0;
355 :
356 46 : s_surf->SurfWinInsideGlassCondensationFlag(SurfNum) = 0;
357 46 : s_surf->SurfWinInsideFrameCondensationFlag(SurfNum) = 0;
358 46 : s_surf->SurfWinInsideDividerCondensationFlag(SurfNum) = 0;
359 : }
360 127 : }
361 : }
362 : }
363 :
364 : // Initialize these once
365 833 : for (int IPhi = 1; IPhi <= NPhi; ++IPhi) { // Loop over patch altitude values
366 714 : Real64 Phi = PhiMin + (IPhi - 1) * DPhi; // 7.5,22.5,37.5,52.5,67.5,82.5 for NPhi = 6
367 714 : state.dataSolarShading->sin_Phi.push_back(std::sin(Phi));
368 714 : state.dataSolarShading->cos_Phi.push_back(std::cos(Phi));
369 : }
370 :
371 2975 : for (int ITheta = 1; ITheta <= NTheta; ++ITheta) { // Loop over patch azimuth values
372 2856 : Real64 Theta = (ITheta - 1) * DTheta; // 0,15,30,....,330,345 for NTheta = 24
373 2856 : state.dataSolarShading->sin_Theta.push_back(std::sin(Theta));
374 2856 : state.dataSolarShading->cos_Theta.push_back(std::cos(Theta));
375 : }
376 :
377 119 : state.dataSolarShading->firstTime = false;
378 119 : }
379 :
380 112 : void checkShadingSurfaceSchedules(EnergyPlusData &state)
381 : {
382 112 : auto &s_surf = state.dataSurface;
383 :
384 : // Shading surfaces with a transmittance schedule that is always 1.0 are marked IsTransparent during shading surface input processing
385 : // Now that EMS (and other types) actuators are set up, check to see if the schedule has an actuator and reset if needed
386 158 : for (int surfNum = s_surf->ShadingSurfaceFirst; surfNum <= s_surf->ShadingSurfaceLast; ++surfNum) {
387 46 : auto &thisSurface = s_surf->Surface(surfNum);
388 46 : if (!thisSurface.IsTransparent) {
389 42 : continue;
390 : }
391 : // creating some dummy bools here on purpose -- we need to do some renaming and/or consolidate these into a meaningful new global sometime
392 : // for now I want the logic to be as readable as possible, so creating shorthand variables makes it very clear
393 4 : bool const anyPlugins = size(state.dataPluginManager->plugins) > 0;
394 4 : bool const runningByAPI = state.dataGlobal->eplusRunningViaAPI;
395 4 : bool const anyEMS = state.dataGlobal->AnyEnergyManagementSystemInModel;
396 4 : if ((anyEMS && EMSManager::isScheduleManaged(state, thisSurface.shadowSurfSched)) || runningByAPI || anyPlugins) {
397 : // Transmittance schedule definitely has an actuator or may have one via python plugin or API
398 : // Set not transparent so it won't be skipped during shading calcs
399 0 : thisSurface.IsTransparent = false;
400 : // Also set global flags
401 0 : state.dataSolarShading->anyScheduledShadingSurface = true;
402 0 : s_surf->ShadingTransmittanceVaries = true;
403 4 : } else if (!thisSurface.MirroredSurf) {
404 : // Warning moved here from shading surface input processing (skip warning for mirrored surfaces)
405 4 : ShowWarningError(state,
406 4 : format(R"(Shading Surface="{}", Transmittance Schedule Name="{}", is always transparent.)",
407 2 : thisSurface.Name,
408 2 : thisSurface.shadowSurfSched->Name));
409 6 : ShowContinueError(state, "This shading surface will be ignored.");
410 : }
411 : }
412 112 : }
413 :
414 134 : void GetShadowingInput(EnergyPlusData &state)
415 : {
416 : // SUBROUTINE INFORMATION:
417 : // AUTHOR Linda K. Lawrie
418 : // DATE WRITTEN July 1999
419 : // MODIFIED B. Griffith, Nov 2012, add calculation method
420 :
421 : // PURPOSE OF THIS SUBROUTINE:
422 : // This subroutine gets the Shadowing Calculation object.
423 :
424 134 : auto &s_surf = state.dataSurface;
425 :
426 : // Using/Aliasing
427 : using DataSystemVariables::ShadingMethod;
428 :
429 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
430 : int NumItems;
431 : int NumNumbers;
432 : int NumAlphas;
433 : int IOStat;
434 134 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
435 134 : state.dataIPShortCut->rNumericArgs({1, 4}) = 0.0; // so if nothing gotten, defaults will be maintained.
436 134 : state.dataIPShortCut->cAlphaArgs(1) = "";
437 134 : state.dataIPShortCut->cAlphaArgs(2) = "";
438 134 : cCurrentModuleObject = "ShadowCalculation";
439 134 : NumItems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
440 134 : NumAlphas = 0;
441 134 : NumNumbers = 0;
442 134 : if (NumItems > 1) {
443 0 : ShowWarningError(state, format("{}: More than 1 occurrence of this object found, only first will be used.", cCurrentModuleObject));
444 : }
445 :
446 134 : if (NumItems != 0) {
447 46 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
448 : cCurrentModuleObject,
449 : 1,
450 23 : state.dataIPShortCut->cAlphaArgs,
451 : NumAlphas,
452 23 : state.dataIPShortCut->rNumericArgs,
453 : NumNumbers,
454 : IOStat,
455 23 : state.dataIPShortCut->lNumericFieldBlanks,
456 23 : state.dataIPShortCut->lAlphaFieldBlanks,
457 23 : state.dataIPShortCut->cAlphaFieldNames,
458 23 : state.dataIPShortCut->cNumericFieldNames);
459 23 : state.dataSolarShading->ShadowingCalcFrequency = state.dataIPShortCut->rNumericArgs(1);
460 : }
461 :
462 134 : if (state.dataSolarShading->ShadowingCalcFrequency <= 0) {
463 : // Set to default value
464 111 : state.dataSolarShading->ShadowingCalcFrequency = 20;
465 : }
466 134 : if (state.dataSolarShading->ShadowingCalcFrequency > 31) {
467 1 : ShowWarningError(state, format("{}: suspect {}", cCurrentModuleObject, state.dataIPShortCut->cNumericFieldNames(1)));
468 1 : ShowContinueError(state, format("Value entered=[{:.0R}], Shadowing Calculations will be inaccurate.", state.dataIPShortCut->rNumericArgs(1)));
469 : }
470 :
471 134 : if (state.dataIPShortCut->rNumericArgs(2) > 199.0) {
472 23 : state.dataSolarShading->MaxHCS = state.dataIPShortCut->rNumericArgs(2);
473 : } else {
474 111 : state.dataSolarShading->MaxHCS = 15000;
475 : }
476 :
477 134 : int aNum = 1;
478 134 : unsigned pixelRes = 512u;
479 134 : if (NumAlphas >= aNum) {
480 23 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Scheduled")) {
481 0 : state.dataSysVars->shadingMethod = ShadingMethod::Scheduled;
482 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "Scheduled";
483 0 : checkScheduledSurfacePresent(state);
484 23 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Imported")) {
485 0 : if (state.dataSched->ScheduleFileShadingProcessed) {
486 0 : state.dataSysVars->shadingMethod = ShadingMethod::Imported;
487 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "Imported";
488 : } else {
489 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
490 0 : ShowContinueError(state,
491 0 : format("Value entered=\"{}\" while no Schedule:File:Shading object is defined, InternalCalculation will be used.",
492 0 : state.dataIPShortCut->cAlphaArgs(aNum)));
493 : }
494 23 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "PolygonClipping")) {
495 19 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
496 19 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
497 4 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "PixelCounting")) {
498 4 : state.dataSysVars->shadingMethod = ShadingMethod::PixelCounting;
499 4 : state.dataIPShortCut->cAlphaArgs(aNum) = "PixelCounting";
500 4 : if (NumNumbers >= 3) {
501 4 : pixelRes = (unsigned)state.dataIPShortCut->rNumericArgs(3);
502 : }
503 : #ifdef EP_NO_OPENGL
504 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
505 : ShowContinueError(state, format("Value entered=\"{}\"", state.dataIPShortCut->cAlphaArgs(aNum)));
506 : ShowContinueError(state, "This version of EnergyPlus was not compiled to use OpenGL (required for PixelCounting)");
507 : ShowContinueError(state, "PolygonClipping will be used instead");
508 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
509 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
510 : #else
511 4 : if (Penumbra::Penumbra::is_valid_context()) {
512 4 : std::shared_ptr<EnergyPlusLogger> penumbra_logger = std::make_shared<EnergyPlusLogger>(EnergyPlusLogger::Log_level::Info);
513 4 : state.dataSolarShading->LoggerContext = std::make_pair<EnergyPlusData *, std::string>(&state, "");
514 4 : penumbra_logger->set_message_context(&state.dataSolarShading->LoggerContext);
515 4 : state.dataSolarShading->penumbra = std::make_unique<Penumbra::Penumbra>(pixelRes, penumbra_logger);
516 4 : } else {
517 0 : ShowWarningError(state, "No GPU found (required for PixelCounting)");
518 0 : ShowContinueError(state, "PolygonClipping will be used instead");
519 0 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
520 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
521 : }
522 : #endif
523 : } else {
524 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
525 0 : ShowContinueError(state, format("Value entered=\"{}\", PolygonClipping will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
526 : }
527 : } else {
528 111 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
529 111 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
530 : }
531 :
532 134 : aNum++;
533 134 : if (NumAlphas >= aNum) {
534 23 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Periodic")) {
535 14 : state.dataSysVars->DetailedSolarTimestepIntegration = false;
536 14 : state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
537 9 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Timestep")) {
538 9 : state.dataSysVars->DetailedSolarTimestepIntegration = true;
539 9 : state.dataIPShortCut->cAlphaArgs(aNum) = "Timestep";
540 : } else {
541 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
542 0 : ShowContinueError(state, format("Value entered=\"{}\", Periodic will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
543 0 : state.dataSysVars->DetailedSolarTimestepIntegration = false;
544 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
545 : }
546 : } else {
547 111 : state.dataSysVars->DetailedSolarTimestepIntegration = false;
548 111 : state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
549 : }
550 :
551 134 : aNum++;
552 134 : if (NumAlphas >= aNum) {
553 13 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SutherlandHodgman")) {
554 9 : state.dataSysVars->SutherlandHodgman = true;
555 9 : state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
556 4 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "ConvexWeilerAtherton")) {
557 2 : state.dataSysVars->SutherlandHodgman = false;
558 2 : state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
559 2 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SlaterBarskyandSutherlandHodgman")) {
560 2 : state.dataSysVars->SutherlandHodgman = true;
561 2 : state.dataSysVars->SlaterBarsky = true;
562 2 : state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
563 0 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(aNum)) {
564 0 : if (!state.dataSysVars->SutherlandHodgman) { // if already set.
565 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
566 : } else {
567 0 : if (!state.dataSysVars->SlaterBarsky) {
568 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
569 : } else {
570 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
571 : }
572 : }
573 : } else {
574 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
575 0 : if (!state.dataSysVars->SutherlandHodgman) {
576 0 : ShowContinueError(state, format("Value entered=\"{}\", ConvexWeilerAtherton will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
577 : } else {
578 0 : if (!state.dataSysVars->SlaterBarsky) {
579 0 : ShowContinueError(state, format("Value entered=\"{}\", SutherlandHodgman will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
580 : } else {
581 0 : ShowContinueError(
582 : state,
583 0 : format("Value entered=\"{}\", SlaterBarskyandSutherlandHodgman will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
584 : }
585 : }
586 : }
587 : } else {
588 121 : if (!state.dataSysVars->SutherlandHodgman) {
589 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
590 : } else {
591 121 : if (!state.dataSysVars->SlaterBarsky) {
592 121 : state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
593 : } else {
594 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
595 : }
596 : }
597 : }
598 :
599 134 : aNum++;
600 134 : if (NumAlphas >= aNum) {
601 13 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SimpleSkyDiffuseModeling")) {
602 5 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
603 5 : state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
604 8 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "DetailedSkyDiffuseModeling")) {
605 8 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = true;
606 8 : state.dataIPShortCut->cAlphaArgs(aNum) = "DetailedSkyDiffuseModeling";
607 0 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
608 0 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
609 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
610 : } else {
611 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
612 0 : ShowContinueError(state, format("Value entered=\"{}\", SimpleSkyDiffuseModeling will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
613 : }
614 : } else {
615 121 : state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
616 121 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
617 : }
618 :
619 134 : aNum++;
620 134 : if (NumAlphas >= aNum) {
621 2 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
622 0 : state.dataSysVars->ReportExtShadingSunlitFrac = true;
623 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
624 2 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
625 2 : state.dataSysVars->ReportExtShadingSunlitFrac = false;
626 2 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
627 : } else {
628 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
629 0 : ShowContinueError(state, format("Value entered=\"{}\", InternalCalculation will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
630 : }
631 : } else {
632 132 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
633 132 : state.dataSysVars->ReportExtShadingSunlitFrac = false;
634 : }
635 :
636 134 : aNum++;
637 134 : if (NumAlphas >= aNum) {
638 2 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
639 1 : state.dataSysVars->DisableSelfShadingWithinGroup = true;
640 1 : state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
641 1 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
642 1 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
643 : } else {
644 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
645 0 : ShowContinueError(state,
646 0 : format("Value entered=\"{}\", all shading effects would be considered.", state.dataIPShortCut->cAlphaArgs(aNum)));
647 : }
648 : } else {
649 132 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
650 : }
651 :
652 134 : aNum++;
653 134 : if (NumAlphas >= aNum) {
654 2 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
655 0 : state.dataSysVars->DisableSelfShadingBetweenGroup = true;
656 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
657 2 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
658 2 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
659 : } else {
660 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
661 0 : ShowContinueError(state,
662 0 : format("Value entered=\"{}\", all shading effects would be considered.", state.dataIPShortCut->cAlphaArgs(aNum)));
663 : }
664 : } else {
665 132 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
666 : }
667 :
668 134 : if (state.dataSysVars->DisableSelfShadingBetweenGroup && state.dataSysVars->DisableSelfShadingWithinGroup) {
669 0 : state.dataSysVars->DisableAllSelfShading = true;
670 134 : } else if (state.dataSysVars->DisableSelfShadingBetweenGroup || state.dataSysVars->DisableSelfShadingWithinGroup) {
671 1 : state.dataSysVars->DisableGroupSelfShading = true;
672 : }
673 :
674 134 : aNum++;
675 134 : state.dataSysVars->shadingGroupsNum = NumAlphas - (aNum - 1);
676 134 : state.dataSysVars->shadingGroupZoneListNames.allocate(state.dataSysVars->shadingGroupsNum);
677 135 : for (int numZone = 1; numZone <= state.dataSysVars->shadingGroupsNum; ++numZone) {
678 1 : state.dataSysVars->shadingGroupZoneListNames(numZone) = state.dataIPShortCut->cAlphaArgs(aNum - 1 + numZone);
679 : }
680 :
681 134 : if (!state.dataSysVars->DetailedSolarTimestepIntegration && s_surf->ShadingTransmittanceVaries &&
682 0 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
683 :
684 0 : ShowWarningError(state, "GetShadowingInput: The shading transmittance for shading devices may change throughout the year.");
685 0 : ShowContinueError(state,
686 0 : format("Choose Shading Calculation Update Frequency Method = Timestep in the {} object to capture all shading impacts.",
687 : cCurrentModuleObject));
688 : }
689 134 : if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
690 0 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
691 :
692 0 : ShowWarningError(state, "GetShadowingInput: The shading transmittance for shading devices may change throughout the year.");
693 0 : ShowContinueError(state, "Simulation has been reset to use DetailedSkyDiffuseModeling. Simulation continues.");
694 0 : ShowContinueError(state, format("Choose DetailedSkyDiffuseModeling in the {} object to remove this warning.", cCurrentModuleObject));
695 0 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = true;
696 0 : state.dataIPShortCut->cAlphaArgs(2) = "DetailedSkyDiffuseModeling";
697 0 : if (!state.dataSysVars->DetailedSolarTimestepIntegration && state.dataSolarShading->ShadowingCalcFrequency > 1) {
698 0 : ShowContinueError(state,
699 0 : format("Better accuracy may be gained by setting the {} to 1 in the {} object.",
700 0 : state.dataIPShortCut->cNumericFieldNames(1),
701 : cCurrentModuleObject));
702 : }
703 134 : } else if (state.dataSysVars->DetailedSkyDiffuseAlgorithm) {
704 8 : if (!s_surf->ShadingTransmittanceVaries || state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
705 16 : ShowWarningError(state,
706 : "GetShadowingInput: DetailedSkyDiffuseModeling is chosen but not needed as either the shading transmittance for "
707 : "shading devices does not change throughout the year");
708 16 : ShowContinueError(state, " or MinimalShadowing has been chosen.");
709 16 : ShowContinueError(state, "Simulation should be set to use SimpleSkyDiffuseModeling, but is left at Detailed for simulation.");
710 8 : ShowContinueError(state, format("Choose SimpleSkyDiffuseModeling in the {} object to reduce computation time.", cCurrentModuleObject));
711 : }
712 : }
713 :
714 134 : print(state.files.eio,
715 : "{}",
716 : "! <Shadowing/Sun Position Calculations Annual Simulations>, Shading Calculation Method, "
717 : "Shading Calculation Update Frequency Method, Shading Calculation Update Frequency {days}, "
718 : "Maximum Figures in Shadow Overlap Calculations {}, Polygon Clipping Algorithm, Pixel Counting Resolution, Sky Diffuse Modeling "
719 : "Algorithm, Output External Shading Calculation Results, Disable "
720 : "Self-Shading Within Shading Zone Groups, Disable Self-Shading From Shading Zone Groups to Other Zones\n");
721 938 : print(state.files.eio,
722 : "Shadowing/Sun Position Calculations Annual Simulations,{},{},{},{},{},{},{},{},{},{}\n",
723 134 : state.dataIPShortCut->cAlphaArgs(1),
724 134 : state.dataIPShortCut->cAlphaArgs(2),
725 134 : state.dataSolarShading->ShadowingCalcFrequency,
726 134 : state.dataSolarShading->MaxHCS,
727 134 : state.dataIPShortCut->cAlphaArgs(3),
728 : pixelRes,
729 134 : state.dataIPShortCut->cAlphaArgs(4),
730 134 : state.dataIPShortCut->cAlphaArgs(5),
731 134 : state.dataIPShortCut->cAlphaArgs(6),
732 134 : state.dataIPShortCut->cAlphaArgs(7));
733 134 : }
734 :
735 114 : void processShadowingInput(EnergyPlusData &state)
736 : {
737 : // all shadow input processing that needed zones and surfaces to already be read into data (part of fix for Defect #10299)
738 :
739 115 : if ((state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::PixelCounting) &&
740 1 : state.dataSolarShading->anyScheduledShadingSurface) {
741 2 : ShowSevereError(state, "The Shading Calculation Method of choice is \"PixelCounting\"; ");
742 2 : ShowContinueError(state, "and there is at least one shading surface of type ");
743 2 : ShowContinueError(state, "Shading:Site:Detailed, Shading:Building:Detailed, or Shading:Zone:Detailed, ");
744 2 : ShowContinueError(state, "that has an active transmittance schedule value greater than zero or may vary.");
745 2 : ShowContinueError(state, "With \"PixelCounting\" Shading Calculation Method, the shading surfaces will be treated as ");
746 2 : ShowContinueError(state, "completely opaque (transmittance = 0) during the shading calculation, ");
747 2 : ShowContinueError(state, "which may result in inaccurate or unexpected results.");
748 3 : ShowContinueError(state, "It is suggested switching to another Shading Calculation Method, such as \"PolygonClipping\".");
749 : }
750 :
751 114 : if (state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::Imported) {
752 0 : for (auto &surf : state.dataSurface->Surface) {
753 0 : if ((surf.surfExternalShadingSched = Sched::GetSchedule(state, surf.Name + "_shading")) != nullptr) {
754 0 : surf.SurfSchedExternalShadingFrac = true;
755 : } else {
756 0 : ShowWarningError(state,
757 0 : format("processShadowingInput: sunlit fraction schedule not found for {} when using ImportedShading.", surf.Name));
758 0 : ShowContinueError(state, "These values are set to 1.0.");
759 : }
760 0 : }
761 : }
762 :
763 : int SurfZoneGroup, CurZoneGroup;
764 114 : int Found = 0;
765 114 : if (state.dataSysVars->DisableGroupSelfShading) {
766 1 : Array1D_int DisableSelfShadingGroups;
767 1 : int NumOfShadingGroups = state.dataSysVars->shadingGroupsNum;
768 1 : if (NumOfShadingGroups > 0) {
769 1 : DisableSelfShadingGroups.allocate(NumOfShadingGroups);
770 2 : for (int i = 1; i <= NumOfShadingGroups; i++) {
771 1 : Found = Util::FindItemInList(
772 1 : state.dataSysVars->shadingGroupZoneListNames(i), state.dataHeatBal->ZoneList, state.dataHeatBal->NumOfZoneLists);
773 1 : if (Found != 0) {
774 1 : DisableSelfShadingGroups(i) = Found;
775 : }
776 : }
777 :
778 10 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
779 9 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond == 0) { // Loop through all exterior surfaces
780 9 : SurfZoneGroup = 0;
781 : // Check the shading zone group of each exterior surface
782 18 : for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups
783 9 : CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop);
784 11 : for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones;
785 : ZoneNum++) { // Loop through all zones in the zone list
786 9 : if (state.dataSurface->Surface(SurfNum).Zone == state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum)) {
787 7 : SurfZoneGroup = CurZoneGroup;
788 7 : break;
789 : }
790 : }
791 : }
792 : // if a surface is not in any zone group, no self shading is disabled for this surface
793 9 : if (SurfZoneGroup != 0) {
794 : // if DisableSelfShadingWithinGroup, add all zones in the same zone group to the surface's disabled zone list
795 : // if DisableSelfShadingBetweenGroups, add all zones in all other zone groups to the surface's disabled zone list
796 14 : for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups
797 7 : CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop);
798 7 : if (SurfZoneGroup == CurZoneGroup && state.dataSysVars->DisableSelfShadingWithinGroup) {
799 14 : for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones;
800 : ZoneNum++) { // Loop through all zones in the zone list
801 7 : state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back(
802 7 : state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum));
803 : }
804 0 : } else if (SurfZoneGroup != CurZoneGroup && state.dataSysVars->DisableSelfShadingBetweenGroup) {
805 0 : for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones; ZoneNum++) {
806 0 : state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back(
807 0 : state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum));
808 : }
809 : }
810 : }
811 : }
812 : }
813 : }
814 : } else {
815 0 : ShowFatalError(state, "No Shading groups are defined when disabling grouped self shading.");
816 : }
817 1 : }
818 114 : }
819 :
820 1 : void checkScheduledSurfacePresent(EnergyPlusData &state)
821 : {
822 : // User has chosen "Scheduled" for sunlit fraction so check to see which surfaces don't have a schedule
823 1 : int numNotDef = 0;
824 1 : int constexpr maxErrMessages = 50;
825 1 : auto &surfData = state.dataSurface;
826 6 : for (int surfNum = 1; surfNum <= surfData->TotSurfaces; ++surfNum) {
827 5 : auto &thisSurf = surfData->Surface(surfNum);
828 5 : if ((thisSurf.Class == SurfaceClass::Shading || thisSurf.Class == SurfaceClass::Detached_F || thisSurf.Class == SurfaceClass::Detached_B ||
829 4 : thisSurf.Class == SurfaceClass::Overhang || thisSurf.Class == SurfaceClass::Fin)) {
830 2 : continue; // skip shading surfaces
831 : }
832 3 : if (!thisSurf.SurfSchedExternalShadingFrac) {
833 1 : numNotDef += 1;
834 1 : if (numNotDef == 1) {
835 2 : ShowWarningError(
836 : state,
837 2 : format("ShadowCalculation specified Schedule for the Shading Calculation Method but no schedule provided for {}", thisSurf.Name));
838 2 : ShowContinueError(
839 : state, "When Schedule is selected for the Shading Calculation Method and no schedule is provided for a particular surface,");
840 2 : ShowContinueError(
841 : state, "EnergyPlus will assume that the surface is not shaded. Use SurfaceProperty:LocalEnvironment to specify a schedule");
842 3 : ShowContinueError(state, "for sunlit fraction if this was not desired. Otherwise, this surface will not be shaded at all.");
843 0 : } else if (numNotDef <= maxErrMessages) {
844 0 : ShowWarningError(state, format("No schedule was provided for {} either. See above error message for more details", thisSurf.Name));
845 : }
846 : }
847 : }
848 1 : if (numNotDef > maxErrMessages) {
849 0 : ShowContinueError(state, format("This message is only shown for the first {} occurrences of this issue.", maxErrMessages));
850 : }
851 1 : }
852 :
853 141 : void AllocateModuleArrays(EnergyPlusData &state)
854 : {
855 :
856 : // SUBROUTINE INFORMATION:
857 : // AUTHOR Rick Strand
858 : // DATE WRITTEN February 1998
859 : // MODIFIED August 2005 JG - Added output variables for energy in J
860 :
861 : // PURPOSE OF THIS SUBROUTINE:
862 : // This routine allocates all of the arrays at the module level which
863 : // require allocation.
864 :
865 : // METHODOLOGY EMPLOYED:
866 : // Allocation is dependent on the user input file.
867 :
868 : int I;
869 : int NumOfLayers;
870 :
871 141 : auto &s_surf = state.dataSurface;
872 :
873 141 : state.dataSolarShading->SurfSunCosTheta.dimension(s_surf->TotSurfaces, 0.0);
874 141 : state.dataSolarShading->SurfSunlitArea.dimension(s_surf->TotSurfaces, 0.0);
875 141 : if (!state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() || !state.dataWindowManager->winOpticalModel->isSimplifiedModel()) {
876 141 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac.allocate(s_surf->TotSurfaces);
877 141 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac.allocate(s_surf->TotSurfaces);
878 141 : state.dataSolarShading->SurfWinTransBmSolar.allocate(s_surf->TotSurfaces);
879 141 : state.dataSolarShading->SurfWinTransDifSolar.allocate(s_surf->TotSurfaces);
880 141 : state.dataSolarShading->SurfWinTransDifSolarGnd.allocate(s_surf->TotSurfaces);
881 141 : state.dataSolarShading->SurfWinTransDifSolarSky.allocate(s_surf->TotSurfaces);
882 141 : state.dataSolarShading->SurfWinTransBmBmSolar.allocate(s_surf->TotSurfaces);
883 141 : state.dataSolarShading->SurfWinTransBmDifSolar.allocate(s_surf->TotSurfaces);
884 : }
885 141 : state.dataSolarShading->SurfAnisoSkyMult.dimension(s_surf->TotSurfaces, 1.0);
886 141 : state.dataSolarShading->SurfIntAbsFac.dimension(s_surf->TotSurfaces, 0.0);
887 : // For isotropic sky: recalculated in AnisoSkyViewFactors if anisotropic radiance
888 : // ALLOCATE(WithShdgIsoSky(TotSurfaces))
889 : // WithShdgIsoSky=0.0
890 : // ALLOCATE(WoShdgIsoSky(TotSurfaces))
891 : // WoShdgIsoSky=0.0
892 : // ALLOCATE(WithShdgHoriz(TotSurfaces))
893 : // WithShdgHoriz=0.0
894 : // ALLOCATE(WoShdgHoriz(TotSurfaces))
895 : // WoShdgHoriz=0.0
896 : // ALLOCATE(DifShdgRatioIsoSky(TotSurfaces))
897 : // DifShdgRatioIsoSky=0.0
898 : // ALLOCATE(DifShdgRatioHoriz(TotSurfaces))
899 : // DifShdgRatioHoriz=0.0
900 141 : state.dataSolarShading->SurfMultIsoSky.dimension(s_surf->TotSurfaces, 0.0);
901 141 : state.dataSolarShading->SurfMultCircumSolar.dimension(s_surf->TotSurfaces, 0.0);
902 141 : state.dataSolarShading->SurfMultHorizonZenith.dimension(s_surf->TotSurfaces, 0.0);
903 141 : state.dataSolarShading->SurfWinRevealStatus.dimension(24, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0);
904 :
905 : // Weiler-Atherton
906 141 : state.dataSolarShading->MAXHCArrayBounds = 2 * (s_surf->MaxVerticesPerSurface + 1);
907 141 : state.dataSolarShading->MAXHCArrayIncrement = s_surf->MaxVerticesPerSurface + 1;
908 141 : state.dataSolarShading->XTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
909 141 : state.dataSolarShading->YTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
910 141 : state.dataSolarShading->XVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
911 141 : state.dataSolarShading->XVS.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
912 141 : state.dataSolarShading->YVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
913 141 : state.dataSolarShading->YVS.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
914 141 : state.dataSolarShading->ZVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
915 :
916 : // Sutherland-Hodgman
917 141 : state.dataSolarShading->ATEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
918 141 : state.dataSolarShading->BTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
919 141 : state.dataSolarShading->CTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
920 141 : state.dataSolarShading->XTEMP1.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
921 141 : state.dataSolarShading->YTEMP1.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
922 :
923 141 : s_surf->SurfSunCosHourly.allocate(Constant::iHoursInDay);
924 3525 : for (int hour = 1; hour <= Constant::iHoursInDay; hour++) {
925 3384 : s_surf->SurfSunCosHourly(hour) = 0.0;
926 : }
927 141 : s_surf->SurfSunlitArea.dimension(s_surf->TotSurfaces, 0.0);
928 141 : s_surf->SurfSunlitFrac.dimension(s_surf->TotSurfaces, 0.0);
929 141 : s_surf->SurfSkySolarInc.dimension(s_surf->TotSurfaces, 0);
930 141 : s_surf->SurfGndSolarInc.dimension(s_surf->TotSurfaces, 0);
931 141 : s_surf->SurfBmToBmReflFacObs.dimension(s_surf->TotSurfaces, 0.0);
932 141 : s_surf->SurfBmToDiffReflFacObs.dimension(s_surf->TotSurfaces, 0.0);
933 141 : s_surf->SurfBmToDiffReflFacGnd.dimension(s_surf->TotSurfaces, 0.0);
934 141 : s_surf->SurfSkyDiffReflFacGnd.dimension(s_surf->TotSurfaces, 0.0);
935 141 : s_surf->SurfOpaqAI.dimension(s_surf->TotSurfaces, 0.0);
936 141 : s_surf->SurfOpaqAO.dimension(s_surf->TotSurfaces, 0.0);
937 141 : s_surf->SurfWinTransSolar.dimension(s_surf->TotSurfaces, 0.0);
938 141 : s_surf->SurfWinBmSolar.dimension(s_surf->TotSurfaces, 0.0);
939 141 : s_surf->SurfWinBmBmSolar.dimension(s_surf->TotSurfaces, 0.0);
940 141 : s_surf->SurfWinBmDifSolar.dimension(s_surf->TotSurfaces, 0.0);
941 141 : s_surf->SurfWinDifSolar.dimension(s_surf->TotSurfaces, 0.0);
942 141 : s_surf->SurfWinHeatGain.dimension(s_surf->TotSurfaces, 0.0);
943 141 : s_surf->SurfWinHeatGainRep.dimension(s_surf->TotSurfaces, 0.0);
944 141 : s_surf->SurfWinHeatLossRep.dimension(s_surf->TotSurfaces, 0.0);
945 141 : s_surf->SurfWinGainConvGlazToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
946 141 : s_surf->SurfWinGainIRGlazToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
947 141 : s_surf->SurfWinLossSWZoneToOutWinRep.dimension(s_surf->TotSurfaces, 0.0);
948 141 : s_surf->SurfWinGainFrameDividerToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
949 141 : s_surf->SurfWinGainConvShadeToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
950 141 : s_surf->SurfWinGainIRShadeToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
951 141 : s_surf->SurfWinGapConvHtFlowRep.dimension(s_surf->TotSurfaces, 0.0);
952 141 : s_surf->SurfWinShadingAbsorbedSolar.dimension(s_surf->TotSurfaces, 0.0);
953 141 : s_surf->SurfWinSysSolTransmittance.dimension(s_surf->TotSurfaces, 0.0);
954 141 : s_surf->SurfWinSysSolReflectance.dimension(s_surf->TotSurfaces, 0.0);
955 141 : s_surf->SurfWinSysSolAbsorptance.dimension(s_surf->TotSurfaces, 0.0);
956 141 : s_surf->SurfWinInsideGlassCondensationFlag.dimension(s_surf->TotSurfaces, 0);
957 141 : s_surf->SurfWinInsideFrameCondensationFlag.dimension(s_surf->TotSurfaces, 0);
958 141 : s_surf->SurfWinInsideDividerCondensationFlag.dimension(s_surf->TotSurfaces, 0);
959 :
960 141 : state.dataHeatBal->SurfSunlitFracHR.dimension(Constant::iHoursInDay, s_surf->TotSurfaces, 0.0);
961 141 : state.dataHeatBal->SurfSunlitFrac.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
962 141 : state.dataHeatBal->SurfSunlitFracWithoutReveal.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
963 564 : state.dataHeatBal->SurfWinBackSurfaces.dimension(
964 423 : Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, state.dataBSDFWindow->MaxBkSurf, s_surf->TotSurfaces, 0);
965 564 : state.dataHeatBal->SurfWinOverlapAreas.dimension(
966 423 : Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, state.dataBSDFWindow->MaxBkSurf, s_surf->TotSurfaces, 0.0);
967 141 : state.dataHeatBal->SurfCosIncAngHR.dimension(Constant::iHoursInDay, s_surf->TotSurfaces, 0.0);
968 141 : state.dataHeatBal->SurfCosIncAng.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
969 :
970 141 : state.dataHeatBal->ZoneTransSolar.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
971 141 : state.dataHeatBal->ZoneBmSolFrExtWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
972 141 : state.dataHeatBal->ZoneBmSolFrIntWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
973 141 : state.dataHeatBal->EnclSolInitialDifSolReflW.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
974 141 : state.dataHeatBal->ZoneDifSolFrExtWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
975 141 : state.dataHeatBal->ZoneDifSolFrIntWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
976 141 : state.dataHeatBal->ZoneWinHeatGain.dimension(state.dataGlobal->NumOfZones, 0.0);
977 141 : state.dataHeatBal->ZoneWinHeatGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
978 141 : state.dataHeatBal->ZoneWinHeatLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
979 141 : state.dataHeatBal->ZoneOpaqSurfInsFaceCond.dimension(state.dataGlobal->NumOfZones, 0.0);
980 141 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
981 141 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
982 141 : state.dataHeatBal->ZoneOpaqSurfExtFaceCond.dimension(state.dataGlobal->NumOfZones, 0.0);
983 141 : state.dataHeatBal->ZoneOpaqSurfExtFaceCondGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
984 141 : state.dataHeatBal->ZoneOpaqSurfExtFaceCondLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
985 :
986 141 : state.dataHeatBal->SurfQRadSWOutIncident.dimension(s_surf->TotSurfaces, 0.0);
987 141 : state.dataHeatBal->SurfQRadSWOutIncidentBeam.dimension(s_surf->TotSurfaces, 0.0);
988 141 : state.dataHeatBal->SurfBmIncInsSurfIntensRep.dimension(s_surf->TotSurfaces, 0.0);
989 141 : state.dataHeatBal->SurfBmIncInsSurfAmountRep.dimension(s_surf->TotSurfaces, 0.0);
990 : // ALLOCATE(DifIncInsSurfIntensRep(TotSurfaces))
991 : // DifIncInsSurfIntensRep=0.0
992 : // ALLOCATE(DifIncInsSurfAmountRep(TotSurfaces))
993 : // DifIncInsSurfAmountRep=0.0
994 141 : state.dataHeatBal->SurfIntBmIncInsSurfIntensRep.dimension(s_surf->TotSurfaces, 0.0);
995 141 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRep.dimension(s_surf->TotSurfaces, 0.0);
996 : // ALLOCATE(IntDifIncInsSurfIntensRep(TotSurfaces))
997 : // IntDifIncInsSurfIntensRep=0.0
998 : // ALLOCATE(IntDifIncInsSurfAmountRep(TotSurfaces))
999 : // IntDifIncInsSurfAmountRep=0.0
1000 141 : state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse.dimension(s_surf->TotSurfaces, 0.0);
1001 141 : state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse.dimension(s_surf->TotSurfaces, 0.0);
1002 141 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd.dimension(s_surf->TotSurfaces, 0.0);
1003 141 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd.dimension(s_surf->TotSurfaces, 0.0);
1004 141 : state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs.dimension(s_surf->TotSurfaces, 0.0);
1005 141 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs.dimension(s_surf->TotSurfaces, 0.0);
1006 141 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs.dimension(s_surf->TotSurfaces, 0.0);
1007 141 : state.dataHeatBal->SurfCosIncidenceAngle.dimension(s_surf->TotSurfaces, 0.0);
1008 :
1009 141 : state.dataHeatBal->SurfWinBSDFBeamDirectionRep.dimension(s_surf->TotSurfaces, 0);
1010 141 : state.dataHeatBal->SurfWinBSDFBeamThetaRep.dimension(s_surf->TotSurfaces, 0.0);
1011 141 : state.dataHeatBal->SurfWinBSDFBeamPhiRep.dimension(s_surf->TotSurfaces, 0.0);
1012 141 : state.dataHeatBal->SurfWinQRadSWwinAbsTot.dimension(s_surf->TotSurfaces, 0.0);
1013 141 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
1014 141 : state.dataHeatBal->SurfWinFenLaySurfTempFront.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
1015 141 : state.dataHeatBal->SurfWinFenLaySurfTempBack.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
1016 :
1017 141 : state.dataHeatBal->SurfWinSWwinAbsTotalReport.dimension(s_surf->TotSurfaces, 0.0);
1018 141 : state.dataHeatBal->SurfInitialDifSolInAbsReport.dimension(s_surf->TotSurfaces, 0.0);
1019 141 : state.dataHeatBal->SurfWinInitialDifSolInTransReport.dimension(s_surf->TotSurfaces, 0.0);
1020 141 : state.dataHeatBal->SurfSWInAbsTotalReport.dimension(s_surf->TotSurfaces, 0.0);
1021 :
1022 : // energy
1023 141 : s_surf->SurfWinTransSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1024 141 : s_surf->SurfWinBmSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1025 141 : s_surf->SurfWinBmBmSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1026 141 : s_surf->SurfWinBmDifSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1027 :
1028 141 : s_surf->SurfWinDifSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1029 141 : s_surf->SurfWinHeatGainRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1030 141 : s_surf->SurfWinHeatLossRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1031 141 : s_surf->SurfWinGapConvHtFlowRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1032 141 : s_surf->SurfWinHeatTransferRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1033 141 : s_surf->SurfWinShadingAbsorbedSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1034 :
1035 141 : state.dataHeatBal->ZoneTransSolarEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1036 141 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1037 141 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1038 141 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1039 141 : state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1040 141 : state.dataHeatBal->ZoneWinHeatGainRepEnergy.dimension(state.dataGlobal->NumOfZones, 0.0);
1041 141 : state.dataHeatBal->ZoneWinHeatLossRepEnergy.dimension(state.dataGlobal->NumOfZones, 0.0);
1042 :
1043 141 : state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1044 141 : state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1045 141 : state.dataHeatBal->ZnOpqSurfExtFaceCondGnRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1046 141 : state.dataHeatBal->ZnOpqSurfExtFaceCondLsRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1047 : // ALLOCATE(DifIncInsSurfAmountRepEnergy(TotSurfaces))
1048 : // DifIncInsSurfAmountRepEnergy=0.0
1049 141 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1050 141 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1051 : // ALLOCATE(IntDifIncInsSurfAmountRepEnergy(TotSurfaces))
1052 : // IntDifIncInsSurfAmountRepEnergy=0.0
1053 141 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy.dimension(s_surf->TotSurfaces, 0.0);
1054 :
1055 1151 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; SurfNum++) {
1056 1010 : s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) = 0.0;
1057 1010 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) = 0.0;
1058 1010 : s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) = 0.0;
1059 1010 : s_surf->SurfWinBmSolRefldInsReveal(SurfNum) = 0.0;
1060 1010 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) = 0.0;
1061 1010 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) = 0.0;
1062 1010 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) = 0.0;
1063 1010 : s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) = 0.0;
1064 1010 : s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) = 0.0;
1065 1010 : s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) = 0.0;
1066 : }
1067 :
1068 : // Added report variables for inside reveal to debug CR 7596. TH 5/26/2009
1069 1151 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; SurfNum++) {
1070 1010 : s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) = 0.0;
1071 1010 : s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) = 0.0;
1072 1010 : s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) = 0.0;
1073 1010 : s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) = 0.0;
1074 : }
1075 :
1076 141 : DisplayString(state, "Initializing Zone and Enclosure Report Variables");
1077 308 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
1078 167 : std::string &thisEnclosureName = state.dataViewFactor->EnclSolInfo(enclosureNum).Name;
1079 334 : SetupOutputVariable(state,
1080 : "Enclosure Windows Total Transmitted Solar Radiation Rate",
1081 : Constant::Units::W,
1082 167 : state.dataHeatBal->ZoneTransSolar(enclosureNum),
1083 : OutputProcessor::TimeStepType::Zone,
1084 : OutputProcessor::StoreType::Average,
1085 : thisEnclosureName);
1086 334 : SetupOutputVariable(state,
1087 : "Enclosure Exterior Windows Total Transmitted Beam Solar Radiation Rate",
1088 : Constant::Units::W,
1089 167 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum),
1090 : OutputProcessor::TimeStepType::Zone,
1091 : OutputProcessor::StoreType::Average,
1092 : thisEnclosureName);
1093 334 : SetupOutputVariable(state,
1094 : "Enclosure Interior Windows Total Transmitted Beam Solar Radiation Rate",
1095 : Constant::Units::W,
1096 167 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum),
1097 : OutputProcessor::TimeStepType::Zone,
1098 : OutputProcessor::StoreType::Average,
1099 : thisEnclosureName);
1100 334 : SetupOutputVariable(state,
1101 : "Enclosure Exterior Windows Total Transmitted Diffuse Solar Radiation Rate",
1102 : Constant::Units::W,
1103 167 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum),
1104 : OutputProcessor::TimeStepType::Zone,
1105 : OutputProcessor::StoreType::Average,
1106 : thisEnclosureName);
1107 334 : SetupOutputVariable(state,
1108 : "Enclosure Interior Windows Total Transmitted Diffuse Solar Radiation Rate",
1109 : Constant::Units::W,
1110 167 : state.dataHeatBal->ZoneDifSolFrIntWinsRep(enclosureNum),
1111 : OutputProcessor::TimeStepType::Zone,
1112 : OutputProcessor::StoreType::Average,
1113 : thisEnclosureName);
1114 : // Energy variables
1115 334 : SetupOutputVariable(state,
1116 : "Enclosure Windows Total Transmitted Solar Radiation Energy",
1117 : Constant::Units::J,
1118 167 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum),
1119 : OutputProcessor::TimeStepType::Zone,
1120 : OutputProcessor::StoreType::Sum,
1121 : thisEnclosureName);
1122 334 : SetupOutputVariable(state,
1123 : "Enclosure Exterior Windows Total Transmitted Beam Solar Radiation Energy",
1124 : Constant::Units::J,
1125 167 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum),
1126 : OutputProcessor::TimeStepType::Zone,
1127 : OutputProcessor::StoreType::Sum,
1128 : thisEnclosureName);
1129 334 : SetupOutputVariable(state,
1130 : "Enclosure Interior Windows Total Transmitted Beam Solar Radiation Energy",
1131 : Constant::Units::J,
1132 167 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclosureNum),
1133 : OutputProcessor::TimeStepType::Zone,
1134 : OutputProcessor::StoreType::Sum,
1135 : thisEnclosureName);
1136 334 : SetupOutputVariable(state,
1137 : "Enclosure Exterior Windows Total Transmitted Diffuse Solar Radiation Energy",
1138 : Constant::Units::J,
1139 167 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum),
1140 : OutputProcessor::TimeStepType::Zone,
1141 : OutputProcessor::StoreType::Sum,
1142 : thisEnclosureName);
1143 334 : SetupOutputVariable(state,
1144 : "Enclosure Interior Windows Total Transmitted Diffuse Solar Radiation Energy",
1145 : Constant::Units::J,
1146 167 : state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy(enclosureNum),
1147 : OutputProcessor::TimeStepType::Zone,
1148 : OutputProcessor::StoreType::Sum,
1149 : thisEnclosureName);
1150 : }
1151 300 : for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) {
1152 318 : SetupOutputVariable(state,
1153 : "Zone Windows Total Heat Gain Rate",
1154 : Constant::Units::W,
1155 159 : state.dataHeatBal->ZoneWinHeatGainRep(ZoneLoop),
1156 : OutputProcessor::TimeStepType::Zone,
1157 : OutputProcessor::StoreType::Average,
1158 159 : state.dataHeatBal->Zone(ZoneLoop).Name);
1159 318 : SetupOutputVariable(state,
1160 : "Zone Windows Total Heat Loss Rate",
1161 : Constant::Units::W,
1162 159 : state.dataHeatBal->ZoneWinHeatLossRep(ZoneLoop),
1163 : OutputProcessor::TimeStepType::Zone,
1164 : OutputProcessor::StoreType::Average,
1165 159 : state.dataHeatBal->Zone(ZoneLoop).Name);
1166 318 : SetupOutputVariable(state,
1167 : "Zone Windows Total Heat Gain Energy",
1168 : Constant::Units::J,
1169 159 : state.dataHeatBal->ZoneWinHeatGainRepEnergy(ZoneLoop),
1170 : OutputProcessor::TimeStepType::Zone,
1171 : OutputProcessor::StoreType::Sum,
1172 159 : state.dataHeatBal->Zone(ZoneLoop).Name);
1173 318 : SetupOutputVariable(state,
1174 : "Zone Windows Total Heat Loss Energy",
1175 : Constant::Units::J,
1176 159 : state.dataHeatBal->ZoneWinHeatLossRepEnergy(ZoneLoop),
1177 : OutputProcessor::TimeStepType::Zone,
1178 : OutputProcessor::StoreType::Sum,
1179 159 : state.dataHeatBal->Zone(ZoneLoop).Name);
1180 159 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
1181 : // CurrentModuleObject='Zone(Advanced)'
1182 0 : SetupOutputVariable(state,
1183 : "Zone Opaque Surface Inside Faces Total Conduction Heat Gain Rate",
1184 : Constant::Units::W,
1185 0 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep(ZoneLoop),
1186 : OutputProcessor::TimeStepType::Zone,
1187 : OutputProcessor::StoreType::Average,
1188 0 : state.dataHeatBal->Zone(ZoneLoop).Name);
1189 0 : SetupOutputVariable(state,
1190 : "Zone Opaque Surface Inside Faces Total Conduction Heat Loss Rate",
1191 : Constant::Units::W,
1192 0 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep(ZoneLoop),
1193 : OutputProcessor::TimeStepType::Zone,
1194 : OutputProcessor::StoreType::Average,
1195 0 : state.dataHeatBal->Zone(ZoneLoop).Name);
1196 : // Energy variables
1197 0 : SetupOutputVariable(state,
1198 : "Zone Opaque Surface Inside Faces Total Conduction Heat Gain Energy",
1199 : Constant::Units::J,
1200 0 : state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg(ZoneLoop),
1201 : OutputProcessor::TimeStepType::Zone,
1202 : OutputProcessor::StoreType::Sum,
1203 0 : state.dataHeatBal->Zone(ZoneLoop).Name);
1204 0 : SetupOutputVariable(state,
1205 : "Zone Opaque Surface Inside Faces Total Conduction Heat Loss Energy",
1206 : Constant::Units::J,
1207 0 : state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg(ZoneLoop),
1208 : OutputProcessor::TimeStepType::Zone,
1209 : OutputProcessor::StoreType::Sum,
1210 0 : state.dataHeatBal->Zone(ZoneLoop).Name);
1211 : }
1212 : }
1213 :
1214 141 : DisplayString(state, "Initializing Surface (Shading) Report Variables");
1215 : // CurrentModuleObject='Surfaces'
1216 1151 : for (int SurfLoop = 1; SurfLoop <= s_surf->TotSurfaces; ++SurfLoop) {
1217 1010 : auto &surf = s_surf->Surface(SurfLoop);
1218 2020 : SetupOutputVariable(state,
1219 : "Surface Outside Normal Azimuth Angle",
1220 : Constant::Units::deg,
1221 1010 : surf.Azimuth,
1222 : OutputProcessor::TimeStepType::Zone,
1223 : OutputProcessor::StoreType::Average,
1224 1010 : surf.Name);
1225 1010 : if (surf.ExtSolar) {
1226 1388 : SetupOutputVariable(state,
1227 : "Surface Outside Face Sunlit Area",
1228 : Constant::Units::m2,
1229 694 : s_surf->SurfSunlitArea(SurfLoop),
1230 : OutputProcessor::TimeStepType::Zone,
1231 : OutputProcessor::StoreType::Average,
1232 694 : surf.Name);
1233 1388 : SetupOutputVariable(state,
1234 : "Surface Outside Face Sunlit Fraction",
1235 : Constant::Units::None,
1236 694 : s_surf->SurfSunlitFrac(SurfLoop),
1237 : OutputProcessor::TimeStepType::Zone,
1238 : OutputProcessor::StoreType::Average,
1239 694 : surf.Name);
1240 1388 : SetupOutputVariable(state,
1241 : "Surface Outside Face Incident Solar Radiation Rate per Area",
1242 : Constant::Units::W_m2,
1243 694 : state.dataHeatBal->SurfQRadSWOutIncident(SurfLoop),
1244 : OutputProcessor::TimeStepType::Zone,
1245 : OutputProcessor::StoreType::Average,
1246 694 : surf.Name);
1247 1388 : SetupOutputVariable(state,
1248 : "Surface Outside Face Incident Beam Solar Radiation Rate per Area",
1249 : Constant::Units::W_m2,
1250 694 : state.dataHeatBal->SurfQRadSWOutIncidentBeam(SurfLoop),
1251 : OutputProcessor::TimeStepType::Zone,
1252 : OutputProcessor::StoreType::Average,
1253 694 : surf.Name);
1254 1388 : SetupOutputVariable(state,
1255 : "Surface Outside Face Incident Sky Diffuse Solar Radiation Rate per Area",
1256 : Constant::Units::W_m2,
1257 694 : state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse(SurfLoop),
1258 : OutputProcessor::TimeStepType::Zone,
1259 : OutputProcessor::StoreType::Average,
1260 694 : surf.Name);
1261 1388 : SetupOutputVariable(state,
1262 : "Surface Outside Face Incident Ground Diffuse Solar Radiation Rate per Area",
1263 : Constant::Units::W_m2,
1264 694 : state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse(SurfLoop),
1265 : OutputProcessor::TimeStepType::Zone,
1266 : OutputProcessor::StoreType::Average,
1267 694 : surf.Name);
1268 1388 : SetupOutputVariable(state,
1269 : "Surface Outside Face Beam Solar Incident Angle Cosine Value",
1270 : Constant::Units::None,
1271 694 : state.dataHeatBal->SurfCosIncidenceAngle(SurfLoop),
1272 : OutputProcessor::TimeStepType::Zone,
1273 : OutputProcessor::StoreType::Average,
1274 694 : surf.Name);
1275 1388 : SetupOutputVariable(state,
1276 : "Surface Outside Face Incident Sky Diffuse Ground Reflected Solar Radiation Rate per Area",
1277 : Constant::Units::W_m2,
1278 694 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd(SurfLoop),
1279 : OutputProcessor::TimeStepType::Zone,
1280 : OutputProcessor::StoreType::Average,
1281 694 : surf.Name);
1282 1388 : SetupOutputVariable(state,
1283 : "Surface Outside Face Incident Sky Diffuse Surface Reflected Solar Radiation Rate per Area",
1284 : Constant::Units::W_m2,
1285 694 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs(SurfLoop),
1286 : OutputProcessor::TimeStepType::Zone,
1287 : OutputProcessor::StoreType::Average,
1288 694 : surf.Name);
1289 1388 : SetupOutputVariable(state,
1290 : "Surface Outside Face Incident Beam To Beam Surface Reflected Solar Radiation Rate per Area",
1291 : Constant::Units::W_m2,
1292 694 : state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs(SurfLoop),
1293 : OutputProcessor::TimeStepType::Zone,
1294 : OutputProcessor::StoreType::Average,
1295 694 : surf.Name);
1296 1388 : SetupOutputVariable(state,
1297 : "Surface Outside Face Incident Beam To Diffuse Surface Reflected Solar Radiation Rate per Area",
1298 : Constant::Units::W_m2,
1299 694 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs(SurfLoop),
1300 : OutputProcessor::TimeStepType::Zone,
1301 : OutputProcessor::StoreType::Average,
1302 694 : surf.Name);
1303 1388 : SetupOutputVariable(state,
1304 : "Surface Outside Face Incident Beam To Diffuse Ground Reflected Solar Radiation Rate per Area",
1305 : Constant::Units::W_m2,
1306 694 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd(SurfLoop),
1307 : OutputProcessor::TimeStepType::Zone,
1308 : OutputProcessor::StoreType::Average,
1309 694 : surf.Name);
1310 1388 : SetupOutputVariable(state,
1311 : "Surface Anisotropic Sky Multiplier",
1312 : Constant::Units::None,
1313 694 : state.dataSolarShading->SurfAnisoSkyMult(SurfLoop),
1314 : OutputProcessor::TimeStepType::Zone,
1315 : OutputProcessor::StoreType::Average,
1316 694 : surf.Name);
1317 694 : SetupOutputVariable(state,
1318 : "Surface Window BSDF Beam Direction Number",
1319 : Constant::Units::None,
1320 694 : state.dataHeatBal->SurfWinBSDFBeamDirectionRep(SurfLoop),
1321 : OutputProcessor::TimeStepType::Zone,
1322 : OutputProcessor::StoreType::Average,
1323 694 : surf.Name);
1324 1388 : SetupOutputVariable(state,
1325 : "Surface Window BSDF Beam Theta Angle",
1326 : Constant::Units::rad,
1327 694 : state.dataHeatBal->SurfWinBSDFBeamThetaRep(SurfLoop),
1328 : OutputProcessor::TimeStepType::Zone,
1329 : OutputProcessor::StoreType::Average,
1330 694 : surf.Name);
1331 1388 : SetupOutputVariable(state,
1332 : "Surface Window BSDF Beam Phi Angle",
1333 : Constant::Units::rad,
1334 694 : state.dataHeatBal->SurfWinBSDFBeamPhiRep(SurfLoop),
1335 : OutputProcessor::TimeStepType::Zone,
1336 : OutputProcessor::StoreType::Average,
1337 694 : surf.Name);
1338 : }
1339 1010 : if (!surf.HeatTransSurf) {
1340 70 : continue;
1341 : }
1342 :
1343 940 : if (surf.Class == SurfaceClass::Window) {
1344 : // CurrentModuleObject='Windows/GlassDoors'
1345 73 : if (surf.ExtSolar) {
1346 142 : SetupOutputVariable(state,
1347 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
1348 : Constant::Units::W,
1349 71 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
1350 : OutputProcessor::TimeStepType::Zone,
1351 : OutputProcessor::StoreType::Average,
1352 71 : surf.Name);
1353 142 : SetupOutputVariable(state,
1354 : "Surface Window Total Glazing Layers Absorbed Shortwave Radiation Rate",
1355 : Constant::Units::W,
1356 71 : state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfLoop),
1357 : OutputProcessor::TimeStepType::Zone,
1358 : OutputProcessor::StoreType::Average,
1359 71 : surf.Name);
1360 :
1361 71 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF) {
1362 1 : NumOfLayers = state.dataConstruction->Construct(surf.Construction).TotSolidLayers;
1363 : } else {
1364 70 : NumOfLayers = state.dataConstruction->Construct(surf.Construction).TotLayers;
1365 : }
1366 222 : for (I = 1; I <= NumOfLayers; ++I) {
1367 151 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF) {
1368 9 : SetupOutputVariable(state,
1369 6 : format("Surface Window Total Absorbed Shortwave Radiation Rate Layer {}", I),
1370 : Constant::Units::W,
1371 3 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfLoop, I),
1372 : OutputProcessor::TimeStepType::Zone,
1373 : OutputProcessor::StoreType::Average,
1374 3 : surf.Name);
1375 : }
1376 151 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF || (I == 1)) {
1377 219 : SetupOutputVariable(state,
1378 146 : format("Surface Window Front Face Temperature Layer {}", I),
1379 : Constant::Units::C,
1380 73 : state.dataHeatBal->SurfWinFenLaySurfTempFront(SurfLoop, I),
1381 : OutputProcessor::TimeStepType::Zone,
1382 : OutputProcessor::StoreType::Average,
1383 73 : surf.Name);
1384 : }
1385 151 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF || (I == NumOfLayers)) {
1386 219 : SetupOutputVariable(state,
1387 146 : format("Surface Window Back Face Temperature Layer {}", I),
1388 : Constant::Units::C,
1389 73 : state.dataHeatBal->SurfWinFenLaySurfTempBack(SurfLoop, I),
1390 : OutputProcessor::TimeStepType::Zone,
1391 : OutputProcessor::StoreType::Average,
1392 73 : surf.Name);
1393 : }
1394 : }
1395 :
1396 142 : SetupOutputVariable(state,
1397 : "Surface Window Transmitted Solar Radiation Rate",
1398 : Constant::Units::W,
1399 71 : s_surf->SurfWinTransSolar(SurfLoop),
1400 : OutputProcessor::TimeStepType::Zone,
1401 : OutputProcessor::StoreType::Average,
1402 71 : surf.Name);
1403 142 : SetupOutputVariable(state,
1404 : "Surface Window Transmitted Beam Solar Radiation Rate",
1405 : Constant::Units::W,
1406 71 : s_surf->SurfWinBmSolar(SurfLoop),
1407 : OutputProcessor::TimeStepType::Zone,
1408 : OutputProcessor::StoreType::Average,
1409 71 : surf.Name);
1410 :
1411 : // added TH 12/9/2009
1412 142 : SetupOutputVariable(state,
1413 : "Surface Window Transmitted Beam To Beam Solar Radiation Rate",
1414 : Constant::Units::W,
1415 71 : s_surf->SurfWinBmBmSolar(SurfLoop),
1416 : OutputProcessor::TimeStepType::Zone,
1417 : OutputProcessor::StoreType::Average,
1418 71 : surf.Name);
1419 142 : SetupOutputVariable(state,
1420 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Rate",
1421 : Constant::Units::W,
1422 71 : s_surf->SurfWinBmDifSolar(SurfLoop),
1423 : OutputProcessor::TimeStepType::Zone,
1424 : OutputProcessor::StoreType::Average,
1425 71 : surf.Name);
1426 :
1427 142 : SetupOutputVariable(state,
1428 : "Surface Window Transmitted Diffuse Solar Radiation Rate",
1429 : Constant::Units::W,
1430 71 : s_surf->SurfWinDifSolar(SurfLoop),
1431 : OutputProcessor::TimeStepType::Zone,
1432 : OutputProcessor::StoreType::Average,
1433 71 : surf.Name);
1434 142 : SetupOutputVariable(state,
1435 : "Surface Window Heat Gain Rate",
1436 : Constant::Units::W,
1437 71 : s_surf->SurfWinHeatGainRep(SurfLoop),
1438 : OutputProcessor::TimeStepType::Zone,
1439 : OutputProcessor::StoreType::Average,
1440 71 : surf.Name);
1441 142 : SetupOutputVariable(state,
1442 : "Surface Window Heat Loss Rate",
1443 : Constant::Units::W,
1444 71 : s_surf->SurfWinHeatLossRep(SurfLoop),
1445 : OutputProcessor::TimeStepType::Zone,
1446 : OutputProcessor::StoreType::Average,
1447 71 : surf.Name);
1448 142 : SetupOutputVariable(state,
1449 : "Surface Window Gap Convective Heat Transfer Rate",
1450 : Constant::Units::W,
1451 71 : s_surf->SurfWinGapConvHtFlowRep(SurfLoop),
1452 : OutputProcessor::TimeStepType::Zone,
1453 : OutputProcessor::StoreType::Average,
1454 71 : surf.Name);
1455 142 : SetupOutputVariable(state,
1456 : "Surface Window Shading Device Absorbed Solar Radiation Rate",
1457 : Constant::Units::W,
1458 71 : s_surf->SurfWinShadingAbsorbedSolar(SurfLoop),
1459 : OutputProcessor::TimeStepType::Zone,
1460 : OutputProcessor::StoreType::Average,
1461 71 : surf.Name);
1462 142 : SetupOutputVariable(state,
1463 : "Surface Window Net Heat Transfer Rate",
1464 : Constant::Units::W,
1465 71 : s_surf->SurfWinHeatGain(SurfLoop),
1466 : OutputProcessor::TimeStepType::Zone,
1467 : OutputProcessor::StoreType::Average,
1468 71 : surf.Name);
1469 :
1470 71 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
1471 : // CurrentModuleObject='Windows/GlassDoors(Advanced)'
1472 0 : SetupOutputVariable(state,
1473 : "Surface Window Inside Face Glazing Zone Convection Heat Gain Rate",
1474 : Constant::Units::W,
1475 0 : s_surf->SurfWinGainConvGlazToZoneRep(SurfLoop),
1476 : OutputProcessor::TimeStepType::Zone,
1477 : OutputProcessor::StoreType::Average,
1478 0 : surf.Name);
1479 0 : SetupOutputVariable(state,
1480 : "Surface Window Inside Face Glazing Net Infrared Heat Transfer Rate",
1481 : Constant::Units::W,
1482 0 : s_surf->SurfWinGainIRGlazToZoneRep(SurfLoop),
1483 : OutputProcessor::TimeStepType::Zone,
1484 : OutputProcessor::StoreType::Average,
1485 0 : surf.Name);
1486 0 : SetupOutputVariable(state,
1487 : "Surface Window Shortwave from Zone Back Out Window Heat Transfer Rate",
1488 : Constant::Units::W,
1489 0 : s_surf->SurfWinLossSWZoneToOutWinRep(SurfLoop),
1490 : OutputProcessor::TimeStepType::Zone,
1491 : OutputProcessor::StoreType::Average,
1492 0 : surf.Name);
1493 0 : SetupOutputVariable(state,
1494 : "Surface Window Inside Face Frame and Divider Zone Heat Gain Rate",
1495 : Constant::Units::W,
1496 0 : s_surf->SurfWinGainFrameDividerToZoneRep(SurfLoop),
1497 : OutputProcessor::TimeStepType::Zone,
1498 : OutputProcessor::StoreType::Average,
1499 0 : surf.Name);
1500 0 : SetupOutputVariable(state,
1501 : "Surface Window Inside Face Gap between Shade and Glazing Zone Convection Heat Gain Rate",
1502 : Constant::Units::W,
1503 0 : s_surf->SurfWinConvHeatFlowNatural(SurfLoop),
1504 : OutputProcessor::TimeStepType::Zone,
1505 : OutputProcessor::StoreType::Average,
1506 0 : surf.Name);
1507 0 : SetupOutputVariable(state,
1508 : "Surface Window Inside Face Shade Zone Convection Heat Gain Rate",
1509 : Constant::Units::W,
1510 0 : s_surf->SurfWinGainConvShadeToZoneRep(SurfLoop),
1511 : OutputProcessor::TimeStepType::Zone,
1512 : OutputProcessor::StoreType::Average,
1513 0 : surf.Name);
1514 0 : SetupOutputVariable(state,
1515 : "Surface Window Inside Face Shade Net Infrared Heat Transfer Rate",
1516 : Constant::Units::W,
1517 0 : s_surf->SurfWinGainIRShadeToZoneRep(SurfLoop),
1518 : OutputProcessor::TimeStepType::Zone,
1519 : OutputProcessor::StoreType::Average,
1520 0 : surf.Name);
1521 0 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
1522 0 : SetupOutputVariable(state,
1523 : "Surface Window Inside Face Other Convection Heat Gain Rate",
1524 : Constant::Units::W,
1525 0 : s_surf->SurfWinOtherConvHeatGain(SurfLoop),
1526 : OutputProcessor::TimeStepType::Zone,
1527 : OutputProcessor::StoreType::Average,
1528 0 : surf.Name);
1529 : }
1530 : }
1531 :
1532 : // Added TH 12/23/2008 for thermochromic windows
1533 : // CurrentModuleObject='Thermochromic Windows'
1534 71 : if (state.dataConstruction->Construct(surf.Construction).isTCWindow) {
1535 0 : SetupOutputVariable(state,
1536 : "Surface Window Thermochromic Layer Temperature",
1537 : Constant::Units::C,
1538 0 : s_surf->SurfWinTCLayerTemp(SurfLoop),
1539 : OutputProcessor::TimeStepType::Zone,
1540 : OutputProcessor::StoreType::Average,
1541 0 : surf.Name);
1542 0 : SetupOutputVariable(state,
1543 : "Surface Window Thermochromic Layer Property Specification Temperature",
1544 : Constant::Units::C,
1545 0 : s_surf->SurfWinSpecTemp(SurfLoop),
1546 : OutputProcessor::TimeStepType::Zone,
1547 : OutputProcessor::StoreType::Average,
1548 0 : surf.Name);
1549 : }
1550 :
1551 : // Added TH 5/26/2009 for switchable windows to report switching factor (tinted level)
1552 : // CurrentModuleObject='Switchable Windows'
1553 71 : if (surf.HasShadeControl) {
1554 8 : if (s_surf->WindowShadingControl(surf.activeWindowShadingControl).ShadingType == WinShadingType::SwitchableGlazing) {
1555 : // IF (SurfaceWindow(SurfLoop)%ShadingFlag == WinShadingType::SwitchableGlazing) THEN !ShadingFlag is not set to
1556 : // WinShadingType::SwitchableGlazing yet!
1557 0 : SetupOutputVariable(state,
1558 : "Surface Window Switchable Glazing Switching Factor",
1559 : Constant::Units::None,
1560 0 : s_surf->SurfWinSwitchingFactor(SurfLoop),
1561 : OutputProcessor::TimeStepType::Zone,
1562 : OutputProcessor::StoreType::Average,
1563 0 : surf.Name);
1564 0 : SetupOutputVariable(state,
1565 : "Surface Window Switchable Glazing Visible Transmittance",
1566 : Constant::Units::None,
1567 0 : s_surf->SurfWinVisTransSelected(SurfLoop),
1568 : OutputProcessor::TimeStepType::Zone,
1569 : OutputProcessor::StoreType::Average,
1570 0 : surf.Name);
1571 : }
1572 : }
1573 :
1574 71 : if (s_surf->SurfWinFrameArea(SurfLoop) > 0.0) {
1575 : // CurrentModuleObject='Window Frames'
1576 40 : SetupOutputVariable(state,
1577 : "Surface Window Frame Heat Gain Rate",
1578 : Constant::Units::W,
1579 20 : s_surf->SurfWinFrameHeatGain(SurfLoop),
1580 : OutputProcessor::TimeStepType::Zone,
1581 : OutputProcessor::StoreType::Average,
1582 20 : surf.Name);
1583 40 : SetupOutputVariable(state,
1584 : "Surface Window Frame Heat Loss Rate",
1585 : Constant::Units::W,
1586 20 : s_surf->SurfWinFrameHeatLoss(SurfLoop),
1587 : OutputProcessor::TimeStepType::Zone,
1588 : OutputProcessor::StoreType::Average,
1589 20 : surf.Name);
1590 40 : SetupOutputVariable(state,
1591 : "Surface Window Frame Inside Temperature",
1592 : Constant::Units::C,
1593 20 : s_surf->SurfWinFrameTempIn(SurfLoop),
1594 : OutputProcessor::TimeStepType::Zone,
1595 : OutputProcessor::StoreType::Average,
1596 20 : surf.Name);
1597 40 : SetupOutputVariable(state,
1598 : "Surface Window Frame Outside Temperature",
1599 : Constant::Units::C,
1600 20 : s_surf->SurfWinFrameTempSurfOut(SurfLoop),
1601 : OutputProcessor::TimeStepType::Zone,
1602 : OutputProcessor::StoreType::Average,
1603 20 : surf.Name);
1604 : }
1605 71 : if (s_surf->SurfWinDividerArea(SurfLoop) > 0.0) {
1606 : // CurrentModuleObject='Window Dividers'
1607 40 : SetupOutputVariable(state,
1608 : "Surface Window Divider Heat Gain Rate",
1609 : Constant::Units::W,
1610 20 : s_surf->SurfWinDividerHeatGain(SurfLoop),
1611 : OutputProcessor::TimeStepType::Zone,
1612 : OutputProcessor::StoreType::Average,
1613 20 : surf.Name);
1614 40 : SetupOutputVariable(state,
1615 : "Surface Window Divider Heat Loss Rate",
1616 : Constant::Units::W,
1617 20 : s_surf->SurfWinDividerHeatLoss(SurfLoop),
1618 : OutputProcessor::TimeStepType::Zone,
1619 : OutputProcessor::StoreType::Average,
1620 20 : surf.Name);
1621 40 : SetupOutputVariable(state,
1622 : "Surface Window Divider Inside Temperature",
1623 : Constant::Units::C,
1624 20 : s_surf->SurfWinDividerTempIn(SurfLoop),
1625 : OutputProcessor::TimeStepType::Zone,
1626 : OutputProcessor::StoreType::Average,
1627 20 : surf.Name);
1628 40 : SetupOutputVariable(state,
1629 : "Surface Window Divider Outside Temperature",
1630 : Constant::Units::C,
1631 20 : s_surf->SurfWinDividerTempSurfOut(SurfLoop),
1632 : OutputProcessor::TimeStepType::Zone,
1633 : OutputProcessor::StoreType::Average,
1634 20 : surf.Name);
1635 : }
1636 :
1637 : // CurrentModuleObject='Windows'
1638 : // Energy
1639 142 : SetupOutputVariable(state,
1640 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
1641 : Constant::Units::J,
1642 71 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
1643 : OutputProcessor::TimeStepType::Zone,
1644 : OutputProcessor::StoreType::Sum,
1645 71 : surf.Name);
1646 142 : SetupOutputVariable(state,
1647 : "Surface Window Transmitted Solar Radiation Energy",
1648 : Constant::Units::J,
1649 71 : s_surf->SurfWinTransSolarEnergy(SurfLoop),
1650 : OutputProcessor::TimeStepType::Zone,
1651 : OutputProcessor::StoreType::Sum,
1652 71 : surf.Name);
1653 142 : SetupOutputVariable(state,
1654 : "Surface Window Transmitted Beam Solar Radiation Energy",
1655 : Constant::Units::J,
1656 71 : s_surf->SurfWinBmSolarEnergy(SurfLoop),
1657 : OutputProcessor::TimeStepType::Zone,
1658 : OutputProcessor::StoreType::Sum,
1659 71 : surf.Name);
1660 :
1661 : // added TH 12/9/2009
1662 142 : SetupOutputVariable(state,
1663 : "Surface Window Transmitted Beam To Beam Solar Radiation Energy",
1664 : Constant::Units::J,
1665 71 : s_surf->SurfWinBmBmSolarEnergy(SurfLoop),
1666 : OutputProcessor::TimeStepType::Zone,
1667 : OutputProcessor::StoreType::Sum,
1668 71 : surf.Name);
1669 142 : SetupOutputVariable(state,
1670 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Energy",
1671 : Constant::Units::J,
1672 71 : s_surf->SurfWinBmDifSolarEnergy(SurfLoop),
1673 : OutputProcessor::TimeStepType::Zone,
1674 : OutputProcessor::StoreType::Sum,
1675 71 : surf.Name);
1676 :
1677 142 : SetupOutputVariable(state,
1678 : "Surface Window Transmitted Diffuse Solar Radiation Energy",
1679 : Constant::Units::J,
1680 71 : s_surf->SurfWinDifSolarEnergy(SurfLoop),
1681 : OutputProcessor::TimeStepType::Zone,
1682 : OutputProcessor::StoreType::Sum,
1683 71 : surf.Name);
1684 142 : SetupOutputVariable(state,
1685 : "Surface Window Heat Gain Energy",
1686 : Constant::Units::J,
1687 71 : s_surf->SurfWinHeatGainRepEnergy(SurfLoop),
1688 : OutputProcessor::TimeStepType::Zone,
1689 : OutputProcessor::StoreType::Sum,
1690 71 : surf.Name);
1691 142 : SetupOutputVariable(state,
1692 : "Surface Window Heat Loss Energy",
1693 : Constant::Units::J,
1694 71 : s_surf->SurfWinHeatLossRepEnergy(SurfLoop),
1695 : OutputProcessor::TimeStepType::Zone,
1696 : OutputProcessor::StoreType::Sum,
1697 71 : surf.Name);
1698 142 : SetupOutputVariable(state,
1699 : "Surface Window Gap Convective Heat Transfer Energy",
1700 : Constant::Units::J,
1701 71 : s_surf->SurfWinGapConvHtFlowRepEnergy(SurfLoop),
1702 : OutputProcessor::TimeStepType::Zone,
1703 : OutputProcessor::StoreType::Sum,
1704 71 : surf.Name);
1705 142 : SetupOutputVariable(state,
1706 : "Surface Window Shading Device Absorbed Solar Radiation Energy",
1707 : Constant::Units::J,
1708 71 : s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfLoop),
1709 : OutputProcessor::TimeStepType::Zone,
1710 : OutputProcessor::StoreType::Sum,
1711 71 : surf.Name);
1712 142 : SetupOutputVariable(state,
1713 : "Surface Window Net Heat Transfer Energy",
1714 : Constant::Units::J,
1715 71 : s_surf->SurfWinHeatTransferRepEnergy(SurfLoop),
1716 : OutputProcessor::TimeStepType::Zone,
1717 : OutputProcessor::StoreType::Sum,
1718 71 : surf.Name);
1719 :
1720 142 : SetupOutputVariable(state,
1721 : "Surface Window System Solar Transmittance",
1722 : Constant::Units::None,
1723 71 : s_surf->SurfWinSysSolTransmittance(SurfLoop),
1724 : OutputProcessor::TimeStepType::Zone,
1725 : OutputProcessor::StoreType::Average,
1726 71 : surf.Name);
1727 142 : SetupOutputVariable(state,
1728 : "Surface Window System Solar Reflectance",
1729 : Constant::Units::None,
1730 71 : s_surf->SurfWinSysSolReflectance(SurfLoop),
1731 : OutputProcessor::TimeStepType::Zone,
1732 : OutputProcessor::StoreType::Average,
1733 71 : surf.Name);
1734 142 : SetupOutputVariable(state,
1735 : "Surface Window System Solar Absorptance",
1736 : Constant::Units::None,
1737 71 : s_surf->SurfWinSysSolAbsorptance(SurfLoop),
1738 : OutputProcessor::TimeStepType::Zone,
1739 : OutputProcessor::StoreType::Average,
1740 71 : surf.Name);
1741 71 : SetupOutputVariable(state,
1742 : "Surface Window Inside Face Glazing Condensation Status",
1743 : Constant::Units::None,
1744 71 : s_surf->SurfWinInsideGlassCondensationFlag(SurfLoop),
1745 : OutputProcessor::TimeStepType::Zone,
1746 : OutputProcessor::StoreType::Average,
1747 71 : surf.Name);
1748 71 : SetupOutputVariable(state,
1749 : "Surface Window Inside Face Frame Condensation Status",
1750 : Constant::Units::None,
1751 71 : s_surf->SurfWinInsideFrameCondensationFlag(SurfLoop),
1752 : OutputProcessor::TimeStepType::Zone,
1753 : OutputProcessor::StoreType::Average,
1754 71 : surf.Name);
1755 71 : SetupOutputVariable(state,
1756 : "Surface Window Inside Face Divider Condensation Status",
1757 : Constant::Units::None,
1758 71 : s_surf->SurfWinInsideDividerCondensationFlag(SurfLoop),
1759 : OutputProcessor::TimeStepType::Zone,
1760 : OutputProcessor::StoreType::Average,
1761 71 : surf.Name);
1762 :
1763 : // Outside reveal report variables
1764 : // IF (Surface(SurfLoop)%Reveal > 0.0) THEN
1765 142 : SetupOutputVariable(state,
1766 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Rate",
1767 : Constant::Units::W,
1768 71 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfLoop),
1769 : OutputProcessor::TimeStepType::Zone,
1770 : OutputProcessor::StoreType::Average,
1771 71 : surf.Name);
1772 : // Energy
1773 142 : SetupOutputVariable(state,
1774 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Energy",
1775 : Constant::Units::J,
1776 71 : s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfLoop),
1777 : OutputProcessor::TimeStepType::Zone,
1778 : OutputProcessor::StoreType::Sum,
1779 71 : surf.Name);
1780 : // ENDIF
1781 :
1782 : // Inside reveal report variables
1783 71 : if (s_surf->SurfWinInsideReveal(SurfLoop) > 0.0 || s_surf->SurfWinInsideSillDepth(SurfLoop) > 0.0) {
1784 0 : SetupOutputVariable(state,
1785 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Rate",
1786 : Constant::Units::W,
1787 0 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfLoop),
1788 : OutputProcessor::TimeStepType::Zone,
1789 : OutputProcessor::StoreType::Average,
1790 0 : surf.Name);
1791 : // Energy
1792 0 : SetupOutputVariable(state,
1793 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Energy",
1794 : Constant::Units::J,
1795 0 : s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfLoop),
1796 : OutputProcessor::TimeStepType::Zone,
1797 : OutputProcessor::StoreType::Sum,
1798 0 : surf.Name);
1799 :
1800 : // Added report variables for inside reveal to debug CR 7596. TH 5/26/2009
1801 : // All reflected solar by the inside reveal is turned into diffuse
1802 0 : SetupOutputVariable(state,
1803 : "Surface Window Inside Reveal Absorbed Beam Solar Radiation Rate",
1804 : Constant::Units::W,
1805 0 : s_surf->SurfWinBmSolAbsdInsRevealReport(SurfLoop),
1806 : OutputProcessor::TimeStepType::Zone,
1807 : OutputProcessor::StoreType::Average,
1808 0 : surf.Name);
1809 0 : SetupOutputVariable(state,
1810 : "Surface Window Inside Reveal Reflected Diffuse Zone Solar Radiation Rate",
1811 : Constant::Units::W,
1812 0 : s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfLoop),
1813 : OutputProcessor::TimeStepType::Zone,
1814 : OutputProcessor::StoreType::Average,
1815 0 : surf.Name);
1816 0 : SetupOutputVariable(state,
1817 : "Surface Window Inside Reveal Reflected Diffuse Frame Solar Radiation Rate",
1818 : Constant::Units::W,
1819 0 : s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfLoop),
1820 : OutputProcessor::TimeStepType::Zone,
1821 : OutputProcessor::StoreType::Average,
1822 0 : surf.Name);
1823 0 : SetupOutputVariable(state,
1824 : "Surface Window Inside Reveal Reflected Diffuse Glazing Solar Radiation Rate",
1825 : Constant::Units::W,
1826 0 : s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfLoop),
1827 : OutputProcessor::TimeStepType::Zone,
1828 : OutputProcessor::StoreType::Average,
1829 0 : surf.Name);
1830 : }
1831 :
1832 : // Output blind report variables only when blinds are used
1833 71 : auto &surfShade = s_surf->surfShades(SurfLoop);
1834 71 : if (surfShade.blind.matNum > 0) {
1835 : // CurrentModuleObject='Window Blinds'
1836 16 : SetupOutputVariable(state,
1837 : "Surface Window Blind Beam to Beam Solar Transmittance",
1838 : Constant::Units::None,
1839 8 : s_surf->SurfWinBlTsolBmBm(SurfLoop),
1840 : OutputProcessor::TimeStepType::Zone,
1841 : OutputProcessor::StoreType::Average,
1842 8 : surf.Name);
1843 16 : SetupOutputVariable(state,
1844 : "Surface Window Blind Beam to Diffuse Solar Transmittance",
1845 : Constant::Units::None,
1846 8 : s_surf->SurfWinBlTsolBmDif(SurfLoop),
1847 : OutputProcessor::TimeStepType::Zone,
1848 : OutputProcessor::StoreType::Average,
1849 8 : surf.Name);
1850 16 : SetupOutputVariable(state,
1851 : "Surface Window Blind Diffuse to Diffuse Solar Transmittance",
1852 : Constant::Units::None,
1853 8 : s_surf->SurfWinBlTsolDifDif(SurfLoop),
1854 : OutputProcessor::TimeStepType::Zone,
1855 : OutputProcessor::StoreType::Average,
1856 8 : surf.Name);
1857 16 : SetupOutputVariable(state,
1858 : "Surface Window Blind and Glazing System Beam Solar Transmittance",
1859 : Constant::Units::None,
1860 8 : s_surf->SurfWinBlGlSysTsolBmBm(SurfLoop),
1861 : OutputProcessor::TimeStepType::Zone,
1862 : OutputProcessor::StoreType::Average,
1863 8 : surf.Name);
1864 16 : SetupOutputVariable(state,
1865 : "Surface Window Blind and Glazing System Diffuse Solar Transmittance",
1866 : Constant::Units::None,
1867 8 : s_surf->SurfWinBlGlSysTsolDifDif(SurfLoop),
1868 : OutputProcessor::TimeStepType::Zone,
1869 : OutputProcessor::StoreType::Average,
1870 8 : surf.Name);
1871 : }
1872 :
1873 : // Output screen report variables only when screens are used
1874 71 : if (s_surf->SurfaceWindow(SurfLoop).screenNum > 0) {
1875 : // CurrentModuleObject='Window Screens'
1876 0 : SetupOutputVariable(state,
1877 : "Surface Window Screen Beam to Beam Solar Transmittance",
1878 : Constant::Units::None,
1879 0 : s_surf->SurfWinScTsolBmBm(SurfLoop),
1880 : OutputProcessor::TimeStepType::Zone,
1881 : OutputProcessor::StoreType::Average,
1882 0 : surf.Name);
1883 0 : SetupOutputVariable(state,
1884 : "Surface Window Screen Beam to Diffuse Solar Transmittance",
1885 : Constant::Units::None,
1886 0 : s_surf->SurfWinScTsolBmDif(SurfLoop),
1887 : OutputProcessor::TimeStepType::Zone,
1888 : OutputProcessor::StoreType::Average,
1889 0 : surf.Name);
1890 0 : SetupOutputVariable(state,
1891 : "Surface Window Screen Diffuse to Diffuse Solar Transmittance",
1892 : Constant::Units::None,
1893 0 : s_surf->SurfWinScTsolDifDif(SurfLoop),
1894 : OutputProcessor::TimeStepType::Zone,
1895 : OutputProcessor::StoreType::Average,
1896 0 : surf.Name);
1897 0 : SetupOutputVariable(state,
1898 : "Surface Window Screen and Glazing System Beam Solar Transmittance",
1899 : Constant::Units::None,
1900 0 : s_surf->SurfWinScGlSysTsolBmBm(SurfLoop),
1901 : OutputProcessor::TimeStepType::Zone,
1902 : OutputProcessor::StoreType::Average,
1903 0 : surf.Name);
1904 0 : SetupOutputVariable(state,
1905 : "Surface Window Screen and Glazing System Diffuse Solar Transmittance",
1906 : Constant::Units::None,
1907 0 : s_surf->SurfWinScGlSysTsolDifDif(SurfLoop),
1908 : OutputProcessor::TimeStepType::Zone,
1909 : OutputProcessor::StoreType::Average,
1910 0 : surf.Name);
1911 : }
1912 :
1913 : // CurrentModuleObject='Windows'
1914 142 : SetupOutputVariable(state,
1915 : "Surface Window Solar Horizontal Profile Angle",
1916 : Constant::Units::deg,
1917 71 : s_surf->SurfWinProfileAngHor(SurfLoop),
1918 : OutputProcessor::TimeStepType::Zone,
1919 : OutputProcessor::StoreType::Average,
1920 71 : surf.Name);
1921 142 : SetupOutputVariable(state,
1922 : "Surface Window Solar Vertical Profile Angle",
1923 : Constant::Units::deg,
1924 71 : s_surf->SurfWinProfileAngVert(SurfLoop),
1925 : OutputProcessor::TimeStepType::Zone,
1926 : OutputProcessor::StoreType::Average,
1927 71 : surf.Name);
1928 142 : SetupOutputVariable(state,
1929 : "Surface Window Glazing Beam to Beam Solar Transmittance",
1930 : Constant::Units::None,
1931 71 : s_surf->SurfWinGlTsolBmBm(SurfLoop),
1932 : OutputProcessor::TimeStepType::Zone,
1933 : OutputProcessor::StoreType::Average,
1934 71 : surf.Name);
1935 142 : SetupOutputVariable(state,
1936 : "Surface Window Glazing Beam to Diffuse Solar Transmittance",
1937 : Constant::Units::None,
1938 71 : s_surf->SurfWinGlTsolBmDif(SurfLoop),
1939 : OutputProcessor::TimeStepType::Zone,
1940 : OutputProcessor::StoreType::Average,
1941 71 : surf.Name);
1942 142 : SetupOutputVariable(state,
1943 : "Surface Window Glazing Diffuse to Diffuse Solar Transmittance",
1944 : Constant::Units::None,
1945 71 : s_surf->SurfWinGlTsolDifDif(SurfLoop),
1946 : OutputProcessor::TimeStepType::Zone,
1947 : OutputProcessor::StoreType::Average,
1948 71 : surf.Name);
1949 71 : SetupOutputVariable(state,
1950 : "Surface Window Model Solver Iteration Count",
1951 : Constant::Units::None,
1952 71 : s_surf->SurfWinWindowCalcIterationsRep(SurfLoop),
1953 : OutputProcessor::TimeStepType::Zone,
1954 : OutputProcessor::StoreType::Average,
1955 71 : surf.Name);
1956 : } else { // Not ExtSolar
1957 2 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
1958 : // CurrentModuleObject='InteriorWindows(Advanced)'
1959 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
1960 0 : SetupOutputVariable(state,
1961 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
1962 : Constant::Units::W,
1963 0 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
1964 : OutputProcessor::TimeStepType::Zone,
1965 : OutputProcessor::StoreType::Average,
1966 0 : surf.Name);
1967 : }
1968 0 : SetupOutputVariable(state,
1969 : "Surface Window Total Glazing Layers Absorbed Shortwave Radiation Rate",
1970 : Constant::Units::W,
1971 0 : state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfLoop),
1972 : OutputProcessor::TimeStepType::Zone,
1973 : OutputProcessor::StoreType::Average,
1974 0 : surf.Name);
1975 :
1976 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
1977 0 : SetupOutputVariable(state,
1978 : "Surface Window Transmitted Solar Radiation Rate",
1979 : Constant::Units::W,
1980 0 : s_surf->SurfWinTransSolar(SurfLoop),
1981 : OutputProcessor::TimeStepType::Zone,
1982 : OutputProcessor::StoreType::Average,
1983 0 : surf.Name);
1984 : }
1985 0 : SetupOutputVariable(state,
1986 : "Surface Window Transmitted Beam Solar Radiation Rate",
1987 : Constant::Units::W,
1988 0 : s_surf->SurfWinBmSolar(SurfLoop),
1989 : OutputProcessor::TimeStepType::Zone,
1990 : OutputProcessor::StoreType::Average,
1991 0 : surf.Name);
1992 :
1993 : // added TH 12/9/2009
1994 0 : SetupOutputVariable(state,
1995 : "Surface Window Transmitted Beam To Beam Solar Radiation Rate",
1996 : Constant::Units::W,
1997 0 : s_surf->SurfWinBmBmSolar(SurfLoop),
1998 : OutputProcessor::TimeStepType::Zone,
1999 : OutputProcessor::StoreType::Average,
2000 0 : surf.Name);
2001 0 : SetupOutputVariable(state,
2002 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Rate",
2003 : Constant::Units::W,
2004 0 : s_surf->SurfWinBmDifSolar(SurfLoop),
2005 : OutputProcessor::TimeStepType::Zone,
2006 : OutputProcessor::StoreType::Average,
2007 0 : surf.Name);
2008 :
2009 0 : SetupOutputVariable(state,
2010 : "Surface Window Transmitted Diffuse Solar Radiation Rate",
2011 : Constant::Units::W,
2012 0 : s_surf->SurfWinDifSolar(SurfLoop),
2013 : OutputProcessor::TimeStepType::Zone,
2014 : OutputProcessor::StoreType::Average,
2015 0 : surf.Name);
2016 0 : SetupOutputVariable(state,
2017 : "Surface Window Heat Gain Rate",
2018 : Constant::Units::W,
2019 0 : s_surf->SurfWinHeatGainRep(SurfLoop),
2020 : OutputProcessor::TimeStepType::Zone,
2021 : OutputProcessor::StoreType::Average,
2022 0 : surf.Name);
2023 0 : SetupOutputVariable(state,
2024 : "Surface Window Heat Loss Rate",
2025 : Constant::Units::W,
2026 0 : s_surf->SurfWinHeatLossRep(SurfLoop),
2027 : OutputProcessor::TimeStepType::Zone,
2028 : OutputProcessor::StoreType::Average,
2029 0 : surf.Name);
2030 0 : SetupOutputVariable(state,
2031 : "Surface Window Gap Convective Heat Transfer Rate",
2032 : Constant::Units::W,
2033 0 : s_surf->SurfWinGapConvHtFlowRep(SurfLoop),
2034 : OutputProcessor::TimeStepType::Zone,
2035 : OutputProcessor::StoreType::Average,
2036 0 : surf.Name);
2037 0 : SetupOutputVariable(state,
2038 : "Surface Window Shading Device Absorbed Solar Radiation Rate",
2039 : Constant::Units::W,
2040 0 : s_surf->SurfWinShadingAbsorbedSolar(SurfLoop),
2041 : OutputProcessor::TimeStepType::Zone,
2042 : OutputProcessor::StoreType::Average,
2043 0 : surf.Name);
2044 0 : if (s_surf->SurfWinFrameArea(SurfLoop) > 0.0) {
2045 0 : SetupOutputVariable(state,
2046 : "Surface Window Frame Heat Gain Rate",
2047 : Constant::Units::W,
2048 0 : s_surf->SurfWinFrameHeatGain(SurfLoop),
2049 : OutputProcessor::TimeStepType::Zone,
2050 : OutputProcessor::StoreType::Average,
2051 0 : surf.Name);
2052 0 : SetupOutputVariable(state,
2053 : "Surface Window Frame Heat Loss Rate",
2054 : Constant::Units::W,
2055 0 : s_surf->SurfWinFrameHeatLoss(SurfLoop),
2056 : OutputProcessor::TimeStepType::Zone,
2057 : OutputProcessor::StoreType::Average,
2058 0 : surf.Name);
2059 0 : SetupOutputVariable(state,
2060 : "Surface Window Frame Inside Temperature",
2061 : Constant::Units::C,
2062 0 : s_surf->SurfWinFrameTempIn(SurfLoop),
2063 : OutputProcessor::TimeStepType::Zone,
2064 : OutputProcessor::StoreType::Average,
2065 0 : surf.Name);
2066 0 : SetupOutputVariable(state,
2067 : "Surface Window Frame Outside Temperature",
2068 : Constant::Units::C,
2069 0 : s_surf->SurfWinFrameTempSurfOut(SurfLoop),
2070 : OutputProcessor::TimeStepType::Zone,
2071 : OutputProcessor::StoreType::Average,
2072 0 : surf.Name);
2073 : }
2074 0 : if (s_surf->SurfWinDividerArea(SurfLoop) > 0.0) {
2075 0 : SetupOutputVariable(state,
2076 : "Surface Window Divider Heat Gain Rate",
2077 : Constant::Units::W,
2078 0 : s_surf->SurfWinDividerHeatGain(SurfLoop),
2079 : OutputProcessor::TimeStepType::Zone,
2080 : OutputProcessor::StoreType::Average,
2081 0 : surf.Name);
2082 0 : SetupOutputVariable(state,
2083 : "Surface Window Divider Heat Loss Rate",
2084 : Constant::Units::W,
2085 0 : s_surf->SurfWinDividerHeatLoss(SurfLoop),
2086 : OutputProcessor::TimeStepType::Zone,
2087 : OutputProcessor::StoreType::Average,
2088 0 : surf.Name);
2089 0 : SetupOutputVariable(state,
2090 : "Surface Window Divider Inside Temperature",
2091 : Constant::Units::C,
2092 0 : s_surf->SurfWinDividerTempIn(SurfLoop),
2093 : OutputProcessor::TimeStepType::Zone,
2094 : OutputProcessor::StoreType::Average,
2095 0 : surf.Name);
2096 0 : SetupOutputVariable(state,
2097 : "Surface Window Divider Outside Temperature",
2098 : Constant::Units::C,
2099 0 : s_surf->SurfWinDividerTempSurfOut(SurfLoop),
2100 : OutputProcessor::TimeStepType::Zone,
2101 : OutputProcessor::StoreType::Average,
2102 0 : surf.Name);
2103 : }
2104 : // Energy
2105 :
2106 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
2107 0 : SetupOutputVariable(state,
2108 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
2109 : Constant::Units::J,
2110 0 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
2111 : OutputProcessor::TimeStepType::Zone,
2112 : OutputProcessor::StoreType::Sum,
2113 0 : surf.Name);
2114 : }
2115 :
2116 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
2117 0 : SetupOutputVariable(state,
2118 : "Surface Window Transmitted Solar Radiation Energy",
2119 : Constant::Units::J,
2120 0 : s_surf->SurfWinTransSolarEnergy(SurfLoop),
2121 : OutputProcessor::TimeStepType::Zone,
2122 : OutputProcessor::StoreType::Sum,
2123 0 : surf.Name);
2124 : }
2125 0 : SetupOutputVariable(state,
2126 : "Surface Window Transmitted Beam Solar Radiation Energy",
2127 : Constant::Units::J,
2128 0 : s_surf->SurfWinBmSolarEnergy(SurfLoop),
2129 : OutputProcessor::TimeStepType::Zone,
2130 : OutputProcessor::StoreType::Sum,
2131 0 : surf.Name);
2132 :
2133 0 : SetupOutputVariable(state,
2134 : "Surface Window Transmitted Beam To Beam Solar Radiation Energy",
2135 : Constant::Units::J,
2136 0 : s_surf->SurfWinBmBmSolarEnergy(SurfLoop),
2137 : OutputProcessor::TimeStepType::Zone,
2138 : OutputProcessor::StoreType::Sum,
2139 0 : surf.Name);
2140 0 : SetupOutputVariable(state,
2141 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Energy",
2142 : Constant::Units::J,
2143 0 : s_surf->SurfWinBmDifSolarEnergy(SurfLoop),
2144 : OutputProcessor::TimeStepType::Zone,
2145 : OutputProcessor::StoreType::Sum,
2146 0 : surf.Name);
2147 :
2148 0 : SetupOutputVariable(state,
2149 : "Surface Window Transmitted Diffuse Solar Radiation Energy",
2150 : Constant::Units::J,
2151 0 : s_surf->SurfWinDifSolarEnergy(SurfLoop),
2152 : OutputProcessor::TimeStepType::Zone,
2153 : OutputProcessor::StoreType::Sum,
2154 0 : surf.Name);
2155 0 : SetupOutputVariable(state,
2156 : "Surface Window Heat Gain Energy",
2157 : Constant::Units::J,
2158 0 : s_surf->SurfWinHeatGainRepEnergy(SurfLoop),
2159 : OutputProcessor::TimeStepType::Zone,
2160 : OutputProcessor::StoreType::Sum,
2161 0 : surf.Name);
2162 0 : SetupOutputVariable(state,
2163 : "Surface Window Heat Loss Energy",
2164 : Constant::Units::J,
2165 0 : s_surf->SurfWinHeatLossRepEnergy(SurfLoop),
2166 : OutputProcessor::TimeStepType::Zone,
2167 : OutputProcessor::StoreType::Sum,
2168 0 : surf.Name);
2169 0 : SetupOutputVariable(state,
2170 : "Surface Window Gap Convective Heat Transfer Energy",
2171 : Constant::Units::J,
2172 0 : s_surf->SurfWinGapConvHtFlowRepEnergy(SurfLoop),
2173 : OutputProcessor::TimeStepType::Zone,
2174 : OutputProcessor::StoreType::Sum,
2175 0 : surf.Name);
2176 0 : SetupOutputVariable(state,
2177 : "Surface Window Shading Device Absorbed Solar Radiation Energy",
2178 : Constant::Units::J,
2179 0 : s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfLoop),
2180 : OutputProcessor::TimeStepType::Zone,
2181 : OutputProcessor::StoreType::Sum,
2182 0 : surf.Name);
2183 :
2184 0 : SetupOutputVariable(state,
2185 : "Surface Window System Solar Transmittance",
2186 : Constant::Units::None,
2187 0 : s_surf->SurfWinSysSolTransmittance(SurfLoop),
2188 : OutputProcessor::TimeStepType::Zone,
2189 : OutputProcessor::StoreType::Average,
2190 0 : surf.Name);
2191 0 : SetupOutputVariable(state,
2192 : "Surface Window System Solar Reflectance",
2193 : Constant::Units::None,
2194 0 : s_surf->SurfWinSysSolReflectance(SurfLoop),
2195 : OutputProcessor::TimeStepType::Zone,
2196 : OutputProcessor::StoreType::Average,
2197 0 : surf.Name);
2198 0 : SetupOutputVariable(state,
2199 : "Surface Window System Solar Absorptance",
2200 : Constant::Units::None,
2201 0 : s_surf->SurfWinSysSolAbsorptance(SurfLoop),
2202 : OutputProcessor::TimeStepType::Zone,
2203 : OutputProcessor::StoreType::Average,
2204 0 : surf.Name);
2205 0 : SetupOutputVariable(state,
2206 : "Surface Window Inside Face Glazing Condensation Status",
2207 : Constant::Units::None,
2208 0 : s_surf->SurfWinInsideGlassCondensationFlag(SurfLoop),
2209 : OutputProcessor::TimeStepType::Zone,
2210 : OutputProcessor::StoreType::Average,
2211 0 : surf.Name);
2212 0 : SetupOutputVariable(state,
2213 : "Surface Window Inside Face Frame Condensation Status",
2214 : Constant::Units::None,
2215 0 : s_surf->SurfWinInsideFrameCondensationFlag(SurfLoop),
2216 : OutputProcessor::TimeStepType::Zone,
2217 : OutputProcessor::StoreType::Average,
2218 0 : surf.Name);
2219 0 : SetupOutputVariable(state,
2220 : "Surface Window Inside Face Divider Condensation Status",
2221 : Constant::Units::None,
2222 0 : s_surf->SurfWinInsideDividerCondensationFlag(SurfLoop),
2223 : OutputProcessor::TimeStepType::Zone,
2224 : OutputProcessor::StoreType::Average,
2225 0 : surf.Name);
2226 0 : SetupOutputVariable(state,
2227 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Rate",
2228 : Constant::Units::W,
2229 0 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfLoop),
2230 : OutputProcessor::TimeStepType::Zone,
2231 : OutputProcessor::StoreType::Average,
2232 0 : surf.Name);
2233 0 : SetupOutputVariable(state,
2234 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Rate",
2235 : Constant::Units::W,
2236 0 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfLoop),
2237 : OutputProcessor::TimeStepType::Zone,
2238 : OutputProcessor::StoreType::Average,
2239 0 : surf.Name);
2240 : // Energy
2241 0 : SetupOutputVariable(state,
2242 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Energy",
2243 : Constant::Units::J,
2244 0 : s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfLoop),
2245 : OutputProcessor::TimeStepType::Zone,
2246 : OutputProcessor::StoreType::Sum,
2247 0 : surf.Name);
2248 0 : SetupOutputVariable(state,
2249 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Energy",
2250 : Constant::Units::J,
2251 0 : s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfLoop),
2252 : OutputProcessor::TimeStepType::Zone,
2253 : OutputProcessor::StoreType::Sum,
2254 0 : surf.Name);
2255 :
2256 : // Output blind report variables only when blinds are used
2257 0 : auto &surfShade = s_surf->surfShades(SurfLoop);
2258 0 : if (surfShade.blind.matNum > 0) {
2259 0 : SetupOutputVariable(state,
2260 : "Surface Window Blind Beam to Beam Solar Transmittance",
2261 : Constant::Units::None,
2262 0 : s_surf->SurfWinBlTsolBmBm(SurfLoop),
2263 : OutputProcessor::TimeStepType::Zone,
2264 : OutputProcessor::StoreType::Average,
2265 0 : surf.Name);
2266 0 : SetupOutputVariable(state,
2267 : "Surface Window Blind Beam to Diffuse Solar Transmittance",
2268 : Constant::Units::None,
2269 0 : s_surf->SurfWinBlTsolBmDif(SurfLoop),
2270 : OutputProcessor::TimeStepType::Zone,
2271 : OutputProcessor::StoreType::Average,
2272 0 : surf.Name);
2273 0 : SetupOutputVariable(state,
2274 : "Surface Window Blind Diffuse to Diffuse Solar Transmittance",
2275 : Constant::Units::None,
2276 0 : s_surf->SurfWinBlTsolDifDif(SurfLoop),
2277 : OutputProcessor::TimeStepType::Zone,
2278 : OutputProcessor::StoreType::Average,
2279 0 : surf.Name);
2280 0 : SetupOutputVariable(state,
2281 : "Surface Window Blind and Glazing System Beam Solar Transmittance",
2282 : Constant::Units::None,
2283 0 : s_surf->SurfWinBlGlSysTsolBmBm(SurfLoop),
2284 : OutputProcessor::TimeStepType::Zone,
2285 : OutputProcessor::StoreType::Average,
2286 0 : surf.Name);
2287 0 : SetupOutputVariable(state,
2288 : "Surface Window Blind and Glazing System Diffuse Solar Transmittance",
2289 : Constant::Units::None,
2290 0 : s_surf->SurfWinBlGlSysTsolDifDif(SurfLoop),
2291 : OutputProcessor::TimeStepType::Zone,
2292 : OutputProcessor::StoreType::Average,
2293 0 : surf.Name);
2294 : }
2295 :
2296 : // Output screen report variables only when screens are used
2297 0 : if (s_surf->SurfaceWindow(SurfLoop).screenNum > 0) {
2298 0 : SetupOutputVariable(state,
2299 : "Surface Window Screen Beam to Beam Solar Transmittance",
2300 : Constant::Units::None,
2301 0 : s_surf->SurfWinScTsolBmBm(SurfLoop),
2302 : OutputProcessor::TimeStepType::Zone,
2303 : OutputProcessor::StoreType::Average,
2304 0 : surf.Name);
2305 0 : SetupOutputVariable(state,
2306 : "Surface Window Screen Beam to Diffuse Solar Transmittance",
2307 : Constant::Units::None,
2308 0 : s_surf->SurfWinScTsolBmDif(SurfLoop),
2309 : OutputProcessor::TimeStepType::Zone,
2310 : OutputProcessor::StoreType::Average,
2311 0 : surf.Name);
2312 0 : SetupOutputVariable(state,
2313 : "Surface Window Screen Diffuse to Diffuse Solar Transmittance",
2314 : Constant::Units::None,
2315 0 : s_surf->SurfWinScTsolDifDif(SurfLoop),
2316 : OutputProcessor::TimeStepType::Zone,
2317 : OutputProcessor::StoreType::Average,
2318 0 : surf.Name);
2319 0 : SetupOutputVariable(state,
2320 : "Surface Window Screen and Glazing System Beam Solar Transmittance",
2321 : Constant::Units::None,
2322 0 : s_surf->SurfWinScGlSysTsolBmBm(SurfLoop),
2323 : OutputProcessor::TimeStepType::Zone,
2324 : OutputProcessor::StoreType::Average,
2325 0 : surf.Name);
2326 0 : SetupOutputVariable(state,
2327 : "Surface Window Screen and Glazing System Diffuse Solar Transmittance",
2328 : Constant::Units::None,
2329 0 : s_surf->SurfWinScGlSysTsolDifDif(SurfLoop),
2330 : OutputProcessor::TimeStepType::Zone,
2331 : OutputProcessor::StoreType::Average,
2332 0 : surf.Name);
2333 : }
2334 :
2335 0 : SetupOutputVariable(state,
2336 : "Surface Window Solar Horizontal Profile Angle",
2337 : Constant::Units::deg,
2338 0 : s_surf->SurfWinProfileAngHor(SurfLoop),
2339 : OutputProcessor::TimeStepType::Zone,
2340 : OutputProcessor::StoreType::Average,
2341 0 : surf.Name);
2342 0 : SetupOutputVariable(state,
2343 : "Surface Window Solar Vertical Profile Angle",
2344 : Constant::Units::deg,
2345 0 : s_surf->SurfWinProfileAngVert(SurfLoop),
2346 : OutputProcessor::TimeStepType::Zone,
2347 : OutputProcessor::StoreType::Average,
2348 0 : surf.Name);
2349 0 : SetupOutputVariable(state,
2350 : "Surface Window Glazing Beam to Beam Solar Transmittance",
2351 : Constant::Units::None,
2352 0 : s_surf->SurfWinGlTsolBmBm(SurfLoop),
2353 : OutputProcessor::TimeStepType::Zone,
2354 : OutputProcessor::StoreType::Average,
2355 0 : surf.Name);
2356 0 : SetupOutputVariable(state,
2357 : "Surface Window Glazing Beam to Diffuse Solar Transmittance",
2358 : Constant::Units::None,
2359 0 : s_surf->SurfWinGlTsolBmDif(SurfLoop),
2360 : OutputProcessor::TimeStepType::Zone,
2361 : OutputProcessor::StoreType::Average,
2362 0 : surf.Name);
2363 0 : SetupOutputVariable(state,
2364 : "Surface Window Glazing Diffuse to Diffuse Solar Transmittance",
2365 : Constant::Units::None,
2366 0 : s_surf->SurfWinGlTsolDifDif(SurfLoop),
2367 : OutputProcessor::TimeStepType::Zone,
2368 : OutputProcessor::StoreType::Average,
2369 0 : surf.Name);
2370 0 : SetupOutputVariable(state,
2371 : "Surface Window Model Solver Iteration Count",
2372 : Constant::Units::None,
2373 0 : s_surf->SurfWinWindowCalcIterationsRep(SurfLoop),
2374 : OutputProcessor::TimeStepType::Zone,
2375 : OutputProcessor::StoreType::Average,
2376 0 : surf.Name);
2377 : }
2378 : } // end non extsolar reporting as advanced variables
2379 : } // Window Reporting
2380 940 : if (surf.Class == SurfaceClass::Window && surf.ExtBoundCond > 0 && surf.ExtBoundCond != SurfLoop) { // Interzone window
2381 : // CurrentModuleObject='InterzoneWindows'
2382 0 : SetupOutputVariable(state,
2383 : "Surface Window Transmitted Beam Solar Radiation Rate",
2384 : Constant::Units::W,
2385 0 : s_surf->SurfWinBmSolTransThruIntWinRep(SurfLoop),
2386 : OutputProcessor::TimeStepType::Zone,
2387 : OutputProcessor::StoreType::Average,
2388 0 : surf.Name);
2389 : // energy
2390 0 : SetupOutputVariable(state,
2391 : "Surface Window Transmitted Beam Solar Radiation Energy",
2392 : Constant::Units::J,
2393 0 : s_surf->SurfWinBmSolTransThruIntWinRepEnergy(SurfLoop),
2394 : OutputProcessor::TimeStepType::Zone,
2395 : OutputProcessor::StoreType::Sum,
2396 0 : surf.Name);
2397 : }
2398 940 : if (surf.Class == SurfaceClass::TDD_Dome && surf.ExtSolar) {
2399 : // CurrentModuleObject='TDD Domes'
2400 4 : SetupOutputVariable(state,
2401 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
2402 : Constant::Units::W,
2403 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
2404 : OutputProcessor::TimeStepType::Zone,
2405 : OutputProcessor::StoreType::Average,
2406 2 : surf.Name);
2407 4 : SetupOutputVariable(state,
2408 : "Surface Window Transmitted Solar Radiation Rate",
2409 : Constant::Units::W,
2410 2 : s_surf->SurfWinTransSolar(SurfLoop),
2411 : OutputProcessor::TimeStepType::Zone,
2412 : OutputProcessor::StoreType::Average,
2413 2 : surf.Name);
2414 : // energy
2415 4 : SetupOutputVariable(state,
2416 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
2417 : Constant::Units::J,
2418 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
2419 : OutputProcessor::TimeStepType::Zone,
2420 : OutputProcessor::StoreType::Sum,
2421 2 : surf.Name);
2422 4 : SetupOutputVariable(state,
2423 : "Surface Window Transmitted Solar Radiation Energy",
2424 : Constant::Units::J,
2425 2 : s_surf->SurfWinTransSolarEnergy(SurfLoop),
2426 : OutputProcessor::TimeStepType::Zone,
2427 : OutputProcessor::StoreType::Sum,
2428 2 : surf.Name);
2429 : }
2430 940 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
2431 : // CurrentModuleObject='TDD Diffusers'
2432 4 : SetupOutputVariable(state,
2433 : "Surface Outside Face Incident Solar Radiation Rate per Area",
2434 : Constant::Units::W_m2,
2435 2 : state.dataHeatBal->SurfQRadSWOutIncident(SurfLoop),
2436 : OutputProcessor::TimeStepType::Zone,
2437 : OutputProcessor::StoreType::Average,
2438 2 : surf.Name);
2439 4 : SetupOutputVariable(state,
2440 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
2441 : Constant::Units::W,
2442 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
2443 : OutputProcessor::TimeStepType::Zone,
2444 : OutputProcessor::StoreType::Average,
2445 2 : surf.Name);
2446 4 : SetupOutputVariable(state,
2447 : "Surface Window Transmitted Solar Radiation Rate",
2448 : Constant::Units::W,
2449 2 : s_surf->SurfWinTransSolar(SurfLoop),
2450 : OutputProcessor::TimeStepType::Zone,
2451 : OutputProcessor::StoreType::Average,
2452 2 : surf.Name);
2453 : // energy
2454 4 : SetupOutputVariable(state,
2455 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
2456 : Constant::Units::J,
2457 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
2458 : OutputProcessor::TimeStepType::Zone,
2459 : OutputProcessor::StoreType::Sum,
2460 2 : surf.Name);
2461 4 : SetupOutputVariable(state,
2462 : "Surface Window Transmitted Solar Radiation Energy",
2463 : Constant::Units::J,
2464 2 : s_surf->SurfWinTransSolarEnergy(SurfLoop),
2465 : OutputProcessor::TimeStepType::Zone,
2466 : OutputProcessor::StoreType::Sum,
2467 2 : surf.Name);
2468 : }
2469 : }
2470 :
2471 1151 : for (int SurfLoop = 1; SurfLoop <= s_surf->TotSurfaces; ++SurfLoop) {
2472 1010 : auto &surf = s_surf->Surface(SurfLoop);
2473 1010 : if (!surf.HeatTransSurf) {
2474 70 : continue;
2475 : }
2476 : // CurrentModuleObject='Surfaces'
2477 1880 : SetupOutputVariable(state,
2478 : "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Rate per Area",
2479 : Constant::Units::W_m2,
2480 940 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfLoop),
2481 : OutputProcessor::TimeStepType::Zone,
2482 : OutputProcessor::StoreType::Average,
2483 940 : surf.Name);
2484 1880 : SetupOutputVariable(state,
2485 : "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Rate",
2486 : Constant::Units::W,
2487 940 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfLoop),
2488 : OutputProcessor::TimeStepType::Zone,
2489 : OutputProcessor::StoreType::Average,
2490 940 : surf.Name);
2491 1880 : SetupOutputVariable(state,
2492 : "Surface Inside Face Interior Windows Incident Beam Solar Radiation Rate per Area",
2493 : Constant::Units::W_m2,
2494 940 : state.dataHeatBal->SurfIntBmIncInsSurfIntensRep(SurfLoop),
2495 : OutputProcessor::TimeStepType::Zone,
2496 : OutputProcessor::StoreType::Average,
2497 940 : surf.Name);
2498 1880 : SetupOutputVariable(state,
2499 : "Surface Inside Face Interior Windows Incident Beam Solar Radiation Rate",
2500 : Constant::Units::W,
2501 940 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRep(SurfLoop),
2502 : OutputProcessor::TimeStepType::Zone,
2503 : OutputProcessor::StoreType::Average,
2504 940 : surf.Name);
2505 1880 : SetupOutputVariable(state,
2506 : "Surface Inside Face Initial Transmitted Diffuse Absorbed Solar Radiation Rate",
2507 : Constant::Units::W,
2508 940 : state.dataHeatBal->SurfInitialDifSolInAbsReport(SurfLoop),
2509 : OutputProcessor::TimeStepType::Zone,
2510 : OutputProcessor::StoreType::Average,
2511 940 : surf.Name);
2512 1880 : SetupOutputVariable(state,
2513 : "Surface Inside Face Initial Transmitted Diffuse Transmitted Out Window Solar Radiation Rate",
2514 : Constant::Units::W,
2515 940 : state.dataHeatBal->SurfWinInitialDifSolInTransReport(SurfLoop),
2516 : OutputProcessor::TimeStepType::Zone,
2517 : OutputProcessor::StoreType::Average,
2518 940 : surf.Name);
2519 1880 : SetupOutputVariable(state,
2520 : "Surface Inside Face Absorbed Shortwave Radiation Rate",
2521 : Constant::Units::W,
2522 940 : state.dataHeatBal->SurfSWInAbsTotalReport(SurfLoop),
2523 : OutputProcessor::TimeStepType::Zone,
2524 : OutputProcessor::StoreType::Average,
2525 940 : surf.Name);
2526 : // energy
2527 1880 : SetupOutputVariable(state,
2528 : "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Energy",
2529 : Constant::Units::J,
2530 940 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfLoop),
2531 : OutputProcessor::TimeStepType::Zone,
2532 : OutputProcessor::StoreType::Sum,
2533 940 : surf.Name);
2534 1880 : SetupOutputVariable(state,
2535 : "Surface Inside Face Interior Windows Incident Beam Solar Radiation Energy",
2536 : Constant::Units::J,
2537 940 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy(SurfLoop),
2538 : OutputProcessor::TimeStepType::Zone,
2539 : OutputProcessor::StoreType::Sum,
2540 940 : surf.Name);
2541 : }
2542 141 : }
2543 :
2544 71212 : void AnisoSkyViewFactors(EnergyPlusData &state)
2545 : {
2546 :
2547 : // SUBROUTINE INFORMATION:
2548 : // AUTHOR Fred Winkelmann
2549 : // DATE WRITTEN April 1999
2550 : // MODIFIED LKL; Dec 2002 -- Anisotropic is only sky radiance option
2551 : // RE-ENGINEERED na
2552 :
2553 : // PURPOSE OF THIS SUBROUTINE:
2554 : // Calculates view factor multiplier, SurfAnisoSkyMult, for diffuse
2555 : // sky irradiance on exterior surfaces taking into account
2556 : // anisotropic radiance of the sky. Called by InitSurfaceHeatBalance
2557 : // In this case the diffuse sky irradiance on a surface is given by
2558 : // SurfAnisoSkyMult(SurfNum) * DifSolarRad
2559 : // SurfAnisoSkyMult accounts not only for the sky radiance distribution but
2560 : // also for the effects of shading of sky diffuse radiation by
2561 : // shadowing surfaces such as overhangs. It does not account for reflection
2562 : // of sky diffuse radiation from shadowing surfaces.
2563 : // Based on an empirical model described in
2564 : // R. Perez, P. Ineichen, R. Seals, J. Michalsky and R. Stewart,
2565 : // "Modeling Daylight Availability and Irradiance Components from Direct
2566 : // and Global Irradiance," Solar Energy 44, 271-289, 1990.
2567 : // In this model the radiance of the sky consists of three distributions
2568 : // that are superimposed:
2569 :
2570 : // (1) An isotropic distribution that covers the entire sky dome;
2571 : // (2) A circumsolar brightening centered around the position of the sun;
2572 : // (3) A horizon brightening
2573 : // The circumsolar brightening is assumed to be concentrated at a point
2574 : // source at the center of the sun although this region actually begins at the
2575 : // periphery of the solar disk and falls off in intensity with increasing
2576 : // angular distance from the periphery.
2577 : // The horizon brightening is assumed to be concentrated at the horizon and
2578 : // to be independent of azimuth. In actuality, for clear skies, the horizon
2579 : // brightening is highest at the horizon and decreases in intensity away from
2580 : // the horizon. For overcast skies the horizon brightening has a negative value
2581 : // since for such skies the sky radiance increases rather than decreases away
2582 : // from the horizon.
2583 : // The F11R, F12R, etc. values were provided by R. Perez, private communication,
2584 : // 5/21/99. These values have higher precision than those listed in the above
2585 : // paper.
2586 :
2587 : // Using/Aliasing
2588 :
2589 : // Locals
2590 : // SUBROUTINE PARAMETER DEFINITIONS:
2591 : static constexpr std::array<Real64, 7> EpsilonLimit = {
2592 : 1.065, 1.23, 1.5, 1.95, 2.8, 4.5, 6.2}; // Upper limit of bins of the sky clearness parameter, Epsilon
2593 : // Circumsolar brightening coefficients; index corresponds to range of Epsilon, the sky clearness parameter
2594 : static constexpr std::array<Real64, 8> F11R = {-0.0083117, 0.1299457, 0.3296958, 0.5682053, 0.8730280, 1.1326077, 1.0601591, 0.6777470};
2595 : static constexpr std::array<Real64, 8> F12R = {0.5877285, 0.6825954, 0.4868735, 0.1874525, -0.3920403, -1.2367284, -1.5999137, -0.3272588};
2596 : static constexpr std::array<Real64, 8> F13R = {-0.0620636, -0.1513752, -0.2210958, -0.2951290, -0.3616149, -0.4118494, -0.3589221, -0.2504286};
2597 : // Horizon/zenith brightening coefficient array; index corresponds to range of Epsilon, the sky clearness parameter
2598 : static constexpr std::array<Real64, 8> F21R = {-0.0596012, -0.0189325, 0.0554140, 0.1088631, 0.2255647, 0.2877813, 0.2642124, 0.1561313};
2599 : static constexpr std::array<Real64, 8> F22R = {0.0721249, 0.0659650, -0.0639588, -0.1519229, -0.4620442, -0.8230357, -1.1272340, -1.3765031};
2600 : static constexpr std::array<Real64, 8> F23R = {-0.0220216, -0.0288748, -0.0260542, -0.0139754, 0.0012448, 0.0558651, 0.1310694, 0.2506212};
2601 :
2602 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2603 :
2604 : Real64 CosZenithAng; // Cosine of solar zenith angle
2605 : Real64 ZenithAng; // Solar zenith angle (radians)
2606 : Real64 ZenithAngDeg; // Solar zenith angle (degrees)
2607 : Real64 F1; // Circumsolar brightening coefficient
2608 : Real64 F2; // Horizon/zenith brightening coefficient
2609 : Real64 Epsilon; // Sky clearness parameter
2610 : Real64 Delta; // Sky brightness parameter
2611 : Real64 CosIncAngBeamOnSurface; // Cosine of incidence angle of beam solar on surface
2612 : int EpsilonBin; // Sky clearness (Epsilon) bin index
2613 : Real64 AirMass; // Relative air mass
2614 : Real64 AirMassH; // Intermediate variable for relative air mass calculation
2615 : Real64 CircumSolarFac; // Ratio of cosine of incidence angle to cosine of zenith angle
2616 : Real64 KappaZ3; // Intermediate variable
2617 : Real64 ViewFactorSkyGeom; // Geometrical sky view factor
2618 71212 : Real64 constexpr cosine_tolerance(0.0001);
2619 :
2620 71212 : auto &s_surf = state.dataSurface;
2621 :
2622 : #ifdef EP_Count_Calls
2623 : ++state.dataTimingsData->NumAnisoSky_Calls;
2624 : #endif
2625 :
2626 71212 : CosZenithAng = state.dataEnvrn->SOLCOS(3);
2627 71212 : ZenithAng = std::acos(CosZenithAng);
2628 71212 : ZenithAngDeg = ZenithAng / Constant::DegToRad;
2629 :
2630 71212 : state.dataSolarShading->SurfAnisoSkyMult = 0.0;
2631 :
2632 : // Relative air mass
2633 71212 : AirMassH = (1.0 - 0.1 * state.dataEnvrn->Elevation / 1000.0);
2634 71212 : if (ZenithAngDeg <= 75.0) {
2635 56901 : AirMass = AirMassH / CosZenithAng;
2636 : } else {
2637 14311 : AirMass = AirMassH / (CosZenithAng + 0.15 * std::pow(93.9 - ZenithAngDeg, -1.253));
2638 : }
2639 71212 : KappaZ3 = 1.041 * pow_3(ZenithAng);
2640 71212 : Epsilon = ((state.dataEnvrn->BeamSolarRad + state.dataEnvrn->DifSolarRad) / state.dataEnvrn->DifSolarRad + KappaZ3) / (1.0 + KappaZ3);
2641 71212 : Delta = state.dataEnvrn->DifSolarRad * AirMass / 1353.0; // 1353 is average extraterrestrial irradiance (W/m2)
2642 : // Circumsolar (F1) and horizon/zenith (F2) brightening coefficients
2643 487897 : for (EpsilonBin = 0; EpsilonBin < 8; ++EpsilonBin) {
2644 487897 : if (EpsilonBin == 7) {
2645 27701 : break;
2646 : }
2647 460196 : if (Epsilon < EpsilonLimit[EpsilonBin]) {
2648 43511 : break;
2649 : }
2650 : }
2651 71212 : F1 = max(0.0, F11R[EpsilonBin] + F12R[EpsilonBin] * Delta + F13R[EpsilonBin] * ZenithAng);
2652 71212 : F2 = F21R[EpsilonBin] + F22R[EpsilonBin] * Delta + F23R[EpsilonBin] * ZenithAng;
2653 :
2654 462398 : for (int SurfNum : s_surf->AllExtSolarSurfaceList) {
2655 :
2656 391186 : CosIncAngBeamOnSurface = state.dataEnvrn->SOLCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
2657 391186 : state.dataEnvrn->SOLCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
2658 391186 : state.dataEnvrn->SOLCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
2659 :
2660 : // So I believe this should only be a diagnostic error...the calcs should always be within -1,+1; it's just round-off that we need to trap
2661 : // for
2662 391186 : if (CosIncAngBeamOnSurface > 1.0) {
2663 0 : if (CosIncAngBeamOnSurface > (1.0 + cosine_tolerance)) {
2664 0 : ShowSevereError(state, "Cosine of incident angle of beam solar on surface out of range...too high");
2665 0 : ShowContinueError(state, "This is a diagnostic error that should not be encountered under normal circumstances");
2666 0 : ShowContinueError(state, format("Occurs on surface: {}", s_surf->Surface(SurfNum).Name));
2667 0 : ShowContinueError(state, format("Current value = {} ... should be within [-1, +1]", CosIncAngBeamOnSurface));
2668 0 : ShowFatalError(state, "Anisotropic solar calculation causes fatal error");
2669 : }
2670 0 : CosIncAngBeamOnSurface = 1.0;
2671 391186 : } else if (CosIncAngBeamOnSurface < -1.0) {
2672 0 : if (CosIncAngBeamOnSurface < (-1.0 - cosine_tolerance)) {
2673 0 : ShowSevereError(state, "Cosine of incident angle of beam solar on surface out of range...too low");
2674 0 : ShowContinueError(state, "This is a diagnostic error that should not be encountered under normal circumstances");
2675 0 : ShowContinueError(state, format("Occurs on surface: {}", s_surf->Surface(SurfNum).Name));
2676 0 : ShowContinueError(state, format("Current value = {} ... should be within [-1, +1]", CosIncAngBeamOnSurface));
2677 0 : ShowFatalError(state, "Anisotropic solar calculation causes fatal error");
2678 : }
2679 0 : CosIncAngBeamOnSurface = -1.0;
2680 : }
2681 :
2682 391186 : ViewFactorSkyGeom = s_surf->Surface(SurfNum).ViewFactorSky;
2683 391186 : state.dataSolarShading->SurfMultIsoSky(SurfNum) = ViewFactorSkyGeom * (1.0 - F1);
2684 : // 0.0871557 below corresponds to a zenith angle of 85 deg
2685 391186 : CircumSolarFac = max(0.0, CosIncAngBeamOnSurface) / max(0.0871557, CosZenithAng);
2686 : // For near-horizontal roofs, model has an inconsistency that gives sky diffuse
2687 : // irradiance significantly different from DifSolarRad when zenith angle is
2688 : // above 85 deg. The following forces irradiance to be very close to DifSolarRad
2689 : // in this case.
2690 391186 : if (CircumSolarFac > 0.0 && CosZenithAng < 0.0871557 && s_surf->Surface(SurfNum).Tilt < 2.0) {
2691 4187 : CircumSolarFac = 1.0;
2692 : }
2693 391186 : state.dataSolarShading->SurfMultCircumSolar(SurfNum) = F1 * CircumSolarFac;
2694 391186 : state.dataSolarShading->SurfMultHorizonZenith(SurfNum) = F2 * s_surf->Surface(SurfNum).SinTilt;
2695 :
2696 391186 : if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm || !s_surf->ShadingTransmittanceVaries ||
2697 0 : state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
2698 391186 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum) =
2699 391186 : state.dataSolarShading->SurfMultIsoSky(SurfNum) * state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) +
2700 391186 : state.dataSolarShading->SurfMultCircumSolar(SurfNum) *
2701 391186 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) +
2702 391186 : state.dataSolarShading->SurfMultHorizonZenith(SurfNum) * state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum);
2703 : } else {
2704 0 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum) =
2705 0 : state.dataSolarShading->SurfMultIsoSky(SurfNum) *
2706 0 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum) +
2707 0 : state.dataSolarShading->SurfMultCircumSolar(SurfNum) *
2708 0 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) +
2709 0 : state.dataSolarShading->SurfMultHorizonZenith(SurfNum) *
2710 0 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum);
2711 0 : state.dataSolarShading->SurfCurDifShdgRatioIsoSky(SurfNum) =
2712 0 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum);
2713 : }
2714 391186 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum) = max(0.0, state.dataSolarShading->SurfAnisoSkyMult(SurfNum)); // make sure not negative.
2715 71212 : }
2716 71212 : }
2717 :
2718 43 : void CHKBKS(EnergyPlusData &state,
2719 : int const NBS, // Surface Number of the potential back surface
2720 : int const NRS // Surface Number of the potential shadow receiving surface
2721 : )
2722 : {
2723 :
2724 : // SUBROUTINE INFORMATION:
2725 : // AUTHOR Legacy Code
2726 : // DATE WRITTEN
2727 : // MODIFIED Nov 2001, FW: Reverse subroutine arguments NRS and NBS to
2728 : // correspond to how CHKBKS is called
2729 : // Jan 2002, FW: change error message
2730 : // RE-ENGINEERED Lawrie, Oct 2000
2731 : // Sep 2020: Revised the vector computation method to reliably produce CVec,
2732 : // and simplified the warning messages.
2733 :
2734 : // PURPOSE OF THIS SUBROUTINE:
2735 : // Determines whether a any vertices of the back surface are in front of the receiving surface;
2736 : // if so, gives severe error. Only base heat transfer surfaces are checked.
2737 :
2738 : // METHODOLOGY EMPLOYED:
2739 : // na
2740 :
2741 : // REFERENCES:
2742 : // BLAST/IBLAST code, original author George Walton
2743 :
2744 : // Using/Aliasing
2745 : using namespace Vectors;
2746 :
2747 : int N; // Loop Control (vertex counter)
2748 : int NVRS; // Number of vertices of the receiving surface
2749 : int NVBS; // Number of vertices of the back surface
2750 : Real64 DOTP; // Dot product of C and D
2751 :
2752 : // Object Data
2753 43 : Vector CVec(0.0); // Vector perpendicular to surface at vertex 1
2754 43 : Vector DVec(0.0); // Vector from vertex 1 of first surface to vertex 'n' of second surface
2755 :
2756 43 : auto &s_surf = state.dataSurface;
2757 :
2758 43 : NVRS = s_surf->Surface(NRS).Sides;
2759 43 : NVBS = s_surf->Surface(NBS).Sides;
2760 :
2761 : // SEE IF ANY VERTICES OF THE back surface ARE IN FRONT OF THE receiving surface
2762 :
2763 133 : for (N = 2; N < NVRS; N++) {
2764 180 : CVec += cross(s_surf->Surface(NRS).Vertex(N) - s_surf->Surface(NRS).Vertex(1),
2765 270 : s_surf->Surface(NRS).Vertex((N + 1)) - s_surf->Surface(NRS).Vertex(1));
2766 : }
2767 43 : CVec /= (NVRS >= 3 ? NVRS : 3);
2768 :
2769 171 : for (N = 1; N <= NVBS; ++N) {
2770 144 : DVec = s_surf->Surface(NBS).Vertex(N) - s_surf->Surface(NRS).Vertex(1);
2771 144 : DOTP = dot(CVec, DVec);
2772 144 : if (DOTP > 0.0009) {
2773 32 : ShowSevereError(state, "Problem in interior solar distribution calculation (CHKBKS)");
2774 16 : ShowContinueError(state, format(" Solar Distribution = FullInteriorExterior will not work in Zone={}", s_surf->Surface(NRS).ZoneName));
2775 32 : ShowContinueError(state,
2776 32 : format(" because one or more of vertices, such as Vertex {} of back surface={}, is in front of receiving surface={}",
2777 : N,
2778 16 : s_surf->Surface(NBS).Name,
2779 16 : s_surf->Surface(NRS).Name));
2780 16 : ShowContinueError(state, format(" (Dot Product indicator={:20.4F})", DOTP));
2781 32 : ShowContinueError(state,
2782 : " Check surface geometry; if OK, use Solar Distribution = FullExterior instead. Use Output:Diagnostics, "
2783 : "DisplayExtraWarnings; for more details.");
2784 16 : if (!state.dataGlobal->DisplayExtraWarnings) {
2785 16 : break;
2786 : }
2787 : }
2788 : }
2789 43 : }
2790 :
2791 2566 : void CHKGSS(EnergyPlusData &state,
2792 : int const NRS, // Surface number of the potential shadow receiving surface
2793 : int const NSS, // Surface number of the potential shadow casting surface
2794 : Real64 const ZMIN, // Lowest point of the receiving surface
2795 : bool &CannotShade // TRUE if shadow casting surface cannot shade receiving surface.
2796 : )
2797 : {
2798 :
2799 : // SUBROUTINE INFORMATION:
2800 : // AUTHOR Legacy Code
2801 : // DATE WRITTEN
2802 : // MODIFIED na
2803 : // RE-ENGINEERED Lawrie, Oct 2000
2804 :
2805 : // PURPOSE OF THIS SUBROUTINE:
2806 : // Determines the possible shadowing combinations. The
2807 : // routine checks detached shadowing or base heat transfer surfaces
2808 : // for the possibility that they cannot shade a given base heat transfer surface.
2809 :
2810 : // METHODOLOGY EMPLOYED:
2811 : // Shadowing is not possible if:
2812 : // 1. The lowest point of the shadow receiving surface (receiving surface)
2813 : // Is higher than the highest point of the shadow casting surface (s.s.)
2814 : // 2. The shadow casting surface Faces up (e.g. A flat roof)
2815 : // 3. The shadow casting surface Is behind the receiving surface
2816 : // 4. The receiving surface is behind the shadow casting surface
2817 :
2818 : // REFERENCES:
2819 : // BLAST/IBLAST code, original author George Walton
2820 :
2821 : // Using/Aliasing
2822 : using namespace Vectors;
2823 :
2824 : // Object Data
2825 :
2826 2566 : CannotShade = true;
2827 :
2828 2566 : auto &s_surf = state.dataSurface;
2829 :
2830 : // see if no point of shadow casting surface is above low point of receiving surface
2831 :
2832 2566 : auto const &surface_C = s_surf->Surface(NSS);
2833 2566 : if (surface_C.OutNormVec(3) > 0.9999) {
2834 1198 : return; // Shadow Casting Surface is horizontal and facing upward
2835 : }
2836 2062 : auto const &vertex_C = surface_C.Vertex;
2837 2062 : Real64 ZMAX(vertex_C(1).z);
2838 8282 : for (int i = 2, e = surface_C.Sides; i <= e; ++i) {
2839 6220 : ZMAX = std::max(ZMAX, vertex_C(i).z);
2840 : }
2841 2062 : if (ZMAX <= ZMIN) {
2842 694 : return;
2843 : }
2844 :
2845 : // SEE IF ANY VERTICES OF THE Shadow Casting Surface ARE ABOVE THE PLANE OF THE receiving surface
2846 :
2847 1368 : auto const &surface_R = s_surf->Surface(NRS);
2848 1368 : auto const &vertex_R = surface_R.Vertex;
2849 1368 : Vector const &vertex_R_2 = vertex_R(2);
2850 1368 : Vector const AVec = (vertex_R(1) - vertex_R_2); // Vector from vertex 2 to vertex 1 of receiving surface
2851 1368 : Vector const BVec = (vertex_R(3) - vertex_R_2); // Vector from vertex 2 to vertex 3 of receiving surface
2852 :
2853 1368 : Vector const CVec = cross(BVec, AVec); // Vector perpendicular to surface at vertex 2
2854 :
2855 1368 : int const NVSS = surface_C.Sides; // Number of vertices of the shadow casting surface
2856 1368 : Real64 DOTP(0.0); // Dot Product
2857 5725 : for (int I = 1; I <= NVSS; ++I) {
2858 4662 : DOTP = dot(CVec, vertex_C(I) - vertex_R_2);
2859 4662 : if (DOTP > state.dataSolarShading->TolValue) {
2860 305 : break; // DO loop
2861 : }
2862 : }
2863 :
2864 : // SEE IF ANY VERTICES OF THE receiving surface ARE ABOVE THE PLANE OF THE S.S.
2865 :
2866 1368 : if (DOTP > state.dataSolarShading->TolValue) {
2867 :
2868 305 : Vector const &vertex_C_2 = vertex_C(2);
2869 305 : Vector const AVec(vertex_C(1) - vertex_C_2);
2870 305 : Vector const BVec(vertex_C(3) - vertex_C_2);
2871 :
2872 305 : Vector const CVec(cross(BVec, AVec));
2873 :
2874 305 : int const NVRS = surface_R.Sides; // Number of vertices of the receiving surface
2875 1097 : for (int I = 1; I <= NVRS; ++I) {
2876 918 : DOTP = dot(CVec, vertex_R(I) - vertex_C_2);
2877 918 : if (DOTP > state.dataSolarShading->TolValue) {
2878 126 : CannotShade = false;
2879 126 : break; // DO loop
2880 : }
2881 : }
2882 305 : }
2883 1368 : }
2884 :
2885 70 : void CHKSBS(EnergyPlusData &state,
2886 : int const HTS, // Heat transfer surface number of the general receiving surf
2887 : int const GRSNR, // Surface number of general receiving surface
2888 : int const SBSNR // Surface number of subsurface
2889 : )
2890 : {
2891 :
2892 : // SUBROUTINE INFORMATION:
2893 : // AUTHOR Legacy Code
2894 : // DATE WRITTEN
2895 : // MODIFIED na
2896 : // RE-ENGINEERED Lawrie, Oct 2000
2897 :
2898 : // PURPOSE OF THIS SUBROUTINE:
2899 : // Checks that a subsurface is completely
2900 : // enclosed by its base surface.
2901 :
2902 : // REFERENCES:
2903 : // BLAST/IBLAST code, original author George Walton
2904 :
2905 : // 3D Planar Polygons
2906 : // In 3D applications, one sometimes wants to test a point and polygon that are in the same plane.
2907 : // For example, one may have the intersection point of a ray with the plane of a polyhedron's face,
2908 : // and want to test if it is inside the face. Or one may want to know if the base of a 3D perpendicular
2909 : // dropped from a point is inside a planar polygon.
2910 :
2911 : // 3D inclusion is easily determined by projecting the point and polygon into 2D. To do this, one simply
2912 : // ignores one of the 3D coordinates and uses the other two. To optimally select the coordinate to ignore,
2913 : // compute a normal vector to the plane, and select the coordinate with the largest absolute value [Snyder & Barr, 1987].
2914 : // This gives the projection of the polygon with maximum area, and results in robust computations.
2915 : // John M. Snyder & Alan H. Barr, "Ray Tracing Complex Models Containing Surface Tessellations",
2916 : // Computer Graphics 21(4), 119-126 (1987) [also in the Proceedings of SIGGRAPH 1987]
2917 : //--- using adapted routine from Triangulation code -- EnergyPlus.
2918 :
2919 : // MSG - for error message
2920 70 : static Array1D_string const MSG(4, {"misses", "", "within", "overlaps"});
2921 :
2922 : int N; // Loop Control
2923 : int NVT; // Number of vertices
2924 : int NS1; // Number of the figure being overlapped
2925 : int NS2; // Number of the figure doing overlapping
2926 : int NS3; // Location to place results of overlap
2927 :
2928 : bool inside;
2929 :
2930 : bool Out;
2931 : Real64 X1; // ,SX,SY,SZ
2932 : Real64 Y1;
2933 : Real64 Z1;
2934 : Real64 X2;
2935 : Real64 Y2;
2936 : Real64 Z2;
2937 : Real64 BX;
2938 : Real64 BY;
2939 : Real64 BZ;
2940 : Real64 BMAX;
2941 : // INTEGER M
2942 :
2943 70 : auto &s_surf = state.dataSurface;
2944 :
2945 70 : if (state.dataSolarShading->CHKSBSOneTimeFlag) {
2946 33 : state.dataSolarShading->XVT.allocate(s_surf->MaxVerticesPerSurface + 1);
2947 33 : state.dataSolarShading->YVT.allocate(s_surf->MaxVerticesPerSurface + 1);
2948 33 : state.dataSolarShading->ZVT.allocate(s_surf->MaxVerticesPerSurface + 1);
2949 33 : state.dataSolarShading->XVT = 0.0;
2950 33 : state.dataSolarShading->YVT = 0.0;
2951 33 : state.dataSolarShading->ZVT = 0.0;
2952 33 : state.dataSolarShading->CHKSBSOneTimeFlag = false;
2953 : }
2954 :
2955 70 : NS1 = 1;
2956 70 : NS2 = 2;
2957 70 : NS3 = 3;
2958 70 : state.dataSolarShading->HCT(1) = 0.0;
2959 70 : state.dataSolarShading->HCT(2) = 0.0;
2960 :
2961 : // Put coordinates of base surface into clockwise sequence on the x'-y' plane.
2962 :
2963 70 : state.dataSolarShading->XVT = 0.0;
2964 70 : state.dataSolarShading->YVT = 0.0;
2965 70 : state.dataSolarShading->ZVT = 0.0;
2966 70 : state.dataSolarShading->XVS = 0.0;
2967 70 : state.dataSolarShading->YVS = 0.0;
2968 70 : CTRANS(state, GRSNR, HTS, NVT, state.dataSolarShading->XVT, state.dataSolarShading->YVT, state.dataSolarShading->ZVT);
2969 350 : for (N = 1; N <= NVT; ++N) {
2970 280 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVT(NVT + 1 - N);
2971 280 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVT(NVT + 1 - N);
2972 : }
2973 :
2974 70 : HTRANS1(state, NS2, NVT);
2975 :
2976 : // Put coordinates of the subsurface into clockwise sequence.
2977 :
2978 70 : state.dataSolarShading->NVS = s_surf->Surface(SBSNR).Sides;
2979 350 : for (N = 1; N <= state.dataSolarShading->NVS; ++N) {
2980 280 : state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(state.dataSolarShading->NVS + 1 - N);
2981 280 : state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(state.dataSolarShading->NVS + 1 - N);
2982 : }
2983 70 : HTRANS1(state, NS1, state.dataSolarShading->NVS);
2984 :
2985 : // Determine the overlap condition.
2986 :
2987 70 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
2988 :
2989 : // Print error condition if necessary.
2990 :
2991 70 : if (state.dataSolarShading->OverlapStatus != FirstSurfWithinSecond) {
2992 0 : Out = false;
2993 : // C COMPUTE COMPONENTS OF VECTOR
2994 : // C NORMAL TO BASE SURFACE.
2995 0 : X1 = s_surf->Surface(GRSNR).Vertex(1).x - s_surf->Surface(GRSNR).Vertex(2).x; // XV(1,GRSNR)-XV(2,GRSNR)
2996 0 : Y1 = s_surf->Surface(GRSNR).Vertex(1).y - s_surf->Surface(GRSNR).Vertex(2).y; // YV(1,GRSNR)-YV(2,GRSNR)
2997 0 : Z1 = s_surf->Surface(GRSNR).Vertex(1).z - s_surf->Surface(GRSNR).Vertex(2).z; // ZV(1,GRSNR)-ZV(2,GRSNR)
2998 0 : X2 = s_surf->Surface(GRSNR).Vertex(3).x - s_surf->Surface(GRSNR).Vertex(2).x; // XV(3,GRSNR)-XV(2,GRSNR)
2999 0 : Y2 = s_surf->Surface(GRSNR).Vertex(3).y - s_surf->Surface(GRSNR).Vertex(2).y; // YV(3,GRSNR)-YV(2,GRSNR)
3000 0 : Z2 = s_surf->Surface(GRSNR).Vertex(3).z - s_surf->Surface(GRSNR).Vertex(2).z; // ZV(3,GRSNR)-ZV(2,GRSNR)
3001 0 : BX = Y1 * Z2 - Y2 * Z1;
3002 0 : BY = Z1 * X2 - Z2 * X1;
3003 0 : BZ = X1 * Y2 - X2 * Y1;
3004 : // C FIND LARGEST COMPONENT.
3005 0 : BMAX = max(std::abs(BX), std::abs(BY), std::abs(BZ));
3006 : // C
3007 0 : if (std::abs(BX) == BMAX) {
3008 : // write(outputfiledebug,*) ' looking bx-bmax',bmax
3009 0 : for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
3010 0 : inside = polygon_contains_point(
3011 0 : s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), true, false, false);
3012 0 : if (!inside) {
3013 0 : Out = true;
3014 : // do m=1,surface(grsnr)%sides
3015 : // write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
3016 : // write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
3017 : // enddo
3018 : // EXIT
3019 : }
3020 : // Y1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(NV(GRSNR),GRSNR)-YV(N,SBSNR)
3021 : // Z1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(NV(GRSNR),GRSNR)-ZV(N,SBSNR)
3022 : // DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
3023 : // Y2 = Y1
3024 : // Z2 = Z1
3025 : // Y1 = Surface(GRSNR)%Vertex(M)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(M,GRSNR)-YV(N,SBSNR)
3026 : // Z1 = Surface(GRSNR)%Vertex(M)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(M,GRSNR)-ZV(N,SBSNR)
3027 : // SX = Y1*Z2-Y2*Z1
3028 : // IF(SX*BX.LT.-1.0d-6) THEN
3029 : // OUT=.TRUE.
3030 : // write(outputfiledebug,*) 'sx*bx=',sx*bx
3031 : // write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
3032 : // write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
3033 : // endif
3034 : // ENDDO
3035 : // IF (OUT) EXIT
3036 : }
3037 0 : } else if (std::abs(BY) == BMAX) {
3038 : // write(outputfiledebug,*) ' looking by-bmax',bmax
3039 0 : for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
3040 0 : inside = polygon_contains_point(
3041 0 : s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), false, true, false);
3042 0 : if (!inside) {
3043 0 : Out = true;
3044 : // do m=1,surface(grsnr)%sides
3045 : // write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
3046 : // write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
3047 : // enddo
3048 : // EXIT
3049 : }
3050 : // Z1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(NV(GRSNR),GRSNR)-ZV(N,SBSNR)
3051 : // X1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%X-Surface(SBSNR)%Vertex(N)%X !XV(NV(GRSNR),GRSNR)-XV(N,SBSNR)
3052 : // DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
3053 : // Z2 = Z1
3054 : // X2 = X1
3055 : // Z1 = Surface(GRSNR)%Vertex(M)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(M,GRSNR)-ZV(N,SBSNR)
3056 : // X1 = Surface(GRSNR)%Vertex(M)%X-Surface(SBSNR)%Vertex(N)%X !XV(M,GRSNR)-XV(N,SBSNR)
3057 : // SY = Z1*X2-Z2*X1
3058 : // IF(SY*BY.LT.-1.0d-6) THEN
3059 : // OUT=.TRUE.
3060 : // write(outputfiledebug,*) 'sy*by=',sy*by
3061 : // write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
3062 : // write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
3063 : // ENDIF
3064 : // ENDDO
3065 : // IF (OUT) EXIT
3066 : }
3067 : } else {
3068 : // write(outputfiledebug,*) ' looking bz-bmax',bmax
3069 0 : for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
3070 0 : inside = polygon_contains_point(
3071 0 : s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), false, false, true);
3072 0 : if (!inside) {
3073 0 : Out = true;
3074 : // do m=1,surface(grsnr)%sides
3075 : // write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
3076 : // write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
3077 : // enddo
3078 : // EXIT
3079 : }
3080 : // X1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%X-Surface(SBSNR)%Vertex(N)%X !XV(NV(GRSNR),GRSNR)-XV(N,SBSNR)
3081 : // Y1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(NV(GRSNR),GRSNR)-YV(N,SBSNR)
3082 : // DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
3083 : // X2 = X1
3084 : // Y2 = Y1
3085 : // X1 = Surface(GRSNR)%Vertex(M)%X-Surface(SBSNR)%Vertex(N)%X !XV(M,GRSNR)-XV(N,SBSNR)
3086 : // Y1 = Surface(GRSNR)%Vertex(M)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(M,GRSNR)-YV(N,SBSNR)
3087 : // SZ = X1*Y2-X2*Y1
3088 : // IF(SZ*BZ.LT.-1.0d-6) THEN
3089 : // OUT=.TRUE.
3090 : // write(outputfiledebug,*) 'sz*bz=',sz*bz
3091 : // write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
3092 : // write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
3093 : // ENDIF
3094 : // ENDDO
3095 : // IF (OUT) EXIT
3096 : }
3097 : }
3098 : // CALL ShowWarningError(state, 'Base surface does not surround subsurface (CHKSBS), Overlap Status='// &
3099 : // TRIM(cOverLapStatus(OverlapStatus)))
3100 : // CALL ShowContinueError(state, 'Surface "'//TRIM(Surface(GRSNR)%Name)//'" '//TRIM(MSG(OverlapStatus))// &
3101 : // ' SubSurface "'//TRIM(Surface(SBSNR)%Name)//'"')
3102 : // IF (FirstSurroundError) THEN
3103 : // CALL ShowWarningError(state, 'Base Surface does not surround subsurface errors occurring...'// &
3104 : // 'Check that the SurfaceGeometry object is expressing the proper starting corner and '// &
3105 : // 'direction [CounterClockwise/Clockwise]')
3106 : // FirstSurroundError=.FALSE.
3107 : // ENDIF
3108 0 : if (Out) {
3109 0 : state.dataSolarShading->TrackBaseSubSurround.redimension(++state.dataSolarShading->NumBaseSubSurround);
3110 0 : state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).SurfIndex1 = GRSNR;
3111 0 : state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).SurfIndex2 = SBSNR;
3112 0 : state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).MiscIndex =
3113 0 : state.dataSolarShading->OverlapStatus;
3114 : // CALL ShowRecurringWarningErrorAtEnd(state, 'Base surface does not surround subsurface (CHKSBS), Overlap Status='// &
3115 : // TRIM(cOverLapStatus(OverlapStatus)), &
3116 : // TrackBaseSubSurround(GRSNR)%ErrIndex1)
3117 : // CALL ShowRecurringContinueErrorAtEnd(state, 'Surface "'//TRIM(Surface(GRSNR)%Name)//'" '//TRIM(MSG(OverlapStatus))// &
3118 : // ' SubSurface "'//TRIM(Surface(SBSNR)%Name)//'"', &
3119 : // TrackBaseSubSurround(SBSNR)%ErrIndex2)
3120 0 : if (state.dataSolarShading->shd_stream) {
3121 0 : *state.dataSolarShading->shd_stream << "==== Base does not Surround subsurface details ====\n";
3122 0 : *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(GRSNR).Name << ' '
3123 0 : << state.dataSolarShading->cOverLapStatus(state.dataSolarShading->OverlapStatus) << '\n';
3124 0 : *state.dataSolarShading->shd_stream << "Surface#=" << std::setw(5) << GRSNR << " NSides=" << std::setw(5)
3125 0 : << s_surf->Surface(GRSNR).Sides << '\n';
3126 0 : *state.dataSolarShading->shd_stream << std::fixed << std::setprecision(2);
3127 0 : for (N = 1; N <= s_surf->Surface(GRSNR).Sides; ++N) {
3128 0 : Vector const &v(s_surf->Surface(GRSNR).Vertex(N));
3129 0 : *state.dataSolarShading->shd_stream << "Vertex " << std::setw(5) << N << "=(" << std::setw(15) << v.x << ',' << std::setw(15)
3130 0 : << v.y << ',' << std::setw(15) << v.z << ")\n";
3131 : }
3132 0 : *state.dataSolarShading->shd_stream << "SubSurface=" << s_surf->Surface(SBSNR).Name << '\n';
3133 0 : *state.dataSolarShading->shd_stream << "Surface#=" << std::setw(5) << SBSNR << " NSides=" << std::setw(5)
3134 0 : << s_surf->Surface(SBSNR).Sides << '\n';
3135 0 : for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) {
3136 0 : Vector const &v(s_surf->Surface(SBSNR).Vertex(N));
3137 0 : *state.dataSolarShading->shd_stream << "Vertex " << std::setw(5) << N << "=(" << std::setw(15) << v.x << ',' << std::setw(15)
3138 0 : << v.y << ',' << std::setw(15) << v.z << ")\n";
3139 : }
3140 0 : *state.dataSolarShading->shd_stream << "================================\n";
3141 : }
3142 : }
3143 : }
3144 70 : }
3145 :
3146 6 : bool polygon_contains_point(int const nsides, // number of sides (vertices)
3147 : Array1D<Vector> &polygon_3d, // points of polygon
3148 : Vector const &point_3d, // point to be tested
3149 : bool const ignorex,
3150 : bool const ignorey,
3151 : bool const ignorez)
3152 : {
3153 :
3154 : // Function information:
3155 : // Author Linda Lawrie
3156 : // Date written October 2005
3157 : // Modified na
3158 : // Re-engineered na
3159 :
3160 : // Purpose of this function:
3161 : // Determine if a point is inside a simple 2d polygon. For a simple polygon (one whose
3162 : // boundary never crosses itself). The polygon does not need to be convex.
3163 :
3164 : // References:
3165 : // M Shimrat, Position of Point Relative to Polygon, ACM Algorithm 112,
3166 : // Communications of the ACM, Volume 5, Number 8, page 434, August 1962.
3167 :
3168 : // Use statements:
3169 : // Using/Aliasing
3170 : using namespace DataVectorTypes;
3171 :
3172 : // return value, true=inside, false = not inside
3173 :
3174 6 : EP_SIZE_CHECK(polygon_3d, nsides);
3175 :
3176 : int ip1;
3177 :
3178 : // Object Data
3179 6 : Array1D<Vector_2d> polygon(nsides);
3180 6 : Vector_2d point;
3181 :
3182 6 : bool inside = false;
3183 6 : if (ignorex) {
3184 10 : for (int i = 1; i <= nsides; ++i) {
3185 8 : polygon(i).x = polygon_3d(i).y;
3186 8 : polygon(i).y = polygon_3d(i).z;
3187 : }
3188 2 : point.x = point_3d.y;
3189 2 : point.y = point_3d.z;
3190 4 : } else if (ignorey) {
3191 10 : for (int i = 1; i <= nsides; ++i) {
3192 8 : polygon(i).x = polygon_3d(i).x;
3193 8 : polygon(i).y = polygon_3d(i).z;
3194 : }
3195 2 : point.x = point_3d.x;
3196 2 : point.y = point_3d.z;
3197 2 : } else if (ignorez) {
3198 10 : for (int i = 1; i <= nsides; ++i) {
3199 8 : polygon(i).x = polygon_3d(i).x;
3200 8 : polygon(i).y = polygon_3d(i).y;
3201 : }
3202 2 : point.x = point_3d.x;
3203 2 : point.y = point_3d.y;
3204 : } else { // Illegal
3205 0 : assert(false);
3206 : point.x = point.y = 0.0; // Elim possibly used uninitialized warnings
3207 : }
3208 :
3209 30 : for (int i = 1; i <= nsides; ++i) {
3210 :
3211 24 : if (i < nsides) {
3212 18 : ip1 = i + 1;
3213 : } else {
3214 6 : ip1 = 1;
3215 : }
3216 :
3217 24 : if ((polygon(i).y < point.y && point.y <= polygon(ip1).y) || (point.y <= polygon(i).y && polygon(ip1).y < point.y)) {
3218 6 : if ((point.x - polygon(i).x) - (point.y - polygon(i).y) * (polygon(ip1).x - polygon(i).x) / (polygon(ip1).y - polygon(i).y) < 0) {
3219 3 : inside = !inside;
3220 : }
3221 : }
3222 : }
3223 :
3224 6 : return inside;
3225 6 : }
3226 :
3227 104 : void ComputeIntSolarAbsorpFactors(EnergyPlusData &state)
3228 : {
3229 :
3230 : // SUBROUTINE INFORMATION:
3231 : // AUTHOR Legacy Code
3232 : // MODIFIED B. Griffith, Oct 2010, deal with no floor case
3233 : // L. Lawrie, Mar 2012, relax >154 tilt even further (>120 considered non-wall by ASHRAE)
3234 : // RE-ENGINEERED Lawrie, Oct 2000
3235 :
3236 : // PURPOSE OF THIS SUBROUTINE:
3237 : // This routine computes the fractions of diffusely transmitted
3238 : // solar energy absorbed by each zone surface.
3239 :
3240 : // METHODOLOGY EMPLOYED:
3241 : // It is assumed that all transmitted solar energy is incident
3242 : // on the floors of the zone (or enclosure). The fraction directly absorbed in
3243 : // the floor is given by 'ISABSF'. It is proportional to the
3244 : // area * solar absorptance. The remaining solar energy is then
3245 : // distributed uniformly around the room according to
3246 : // area*absorptance product
3247 :
3248 : // REFERENCES:
3249 : // BLAST/IBLAST code, original author George Walton
3250 :
3251 : using namespace DataWindowEquivalentLayer;
3252 :
3253 : Real64 AreaSum; // Intermediate calculation value
3254 : int Lay; // Window glass layer number
3255 : Real64 AbsDiffTotWin; // Sum of a window's glass layer solar absorptances
3256 : Real64 TestFractSum;
3257 : Real64 HorizAreaSum;
3258 :
3259 104 : auto &s_surf = state.dataSurface;
3260 :
3261 235 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
3262 131 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
3263 :
3264 131 : AreaSum = 0.0;
3265 131 : TestFractSum = 0.0;
3266 841 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
3267 710 : if (state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType == StandardZone && s_surf->Surface(SurfNum).CosTilt < -0.5) {
3268 144 : AreaSum += s_surf->Surface(SurfNum).Area;
3269 : }
3270 : }
3271 :
3272 131 : HorizAreaSum = AreaSum;
3273 :
3274 131 : if ((thisEnclosure.FloorArea <= 0.0) && (HorizAreaSum > 0.0)) {
3275 : // fill floor area even though surfs not called "Floor", they are roughly horizontal and face upwards.
3276 0 : thisEnclosure.FloorArea = HorizAreaSum;
3277 0 : ShowWarningError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
3278 0 : ShowContinueError(state, format("...Enclosure=\"{}\" has no floor, but has approximate horizontal surfaces.", thisEnclosure.Name));
3279 0 : ShowContinueError(state, format("...these Tilt > 120 degrees, (area=[{:.2R}] m2) will be used.", HorizAreaSum));
3280 : }
3281 :
3282 : // Compute ISABSF
3283 :
3284 841 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
3285 :
3286 : // only horizontal surfaces. ! !CR 8229, relaxed from -0.99 to -0.5 (Tilt > 154)
3287 : // only horizontal surfaces. ! !CR8769 use ASHRAE std of >120, -0.9 to -0.5 (Tilt > 120)
3288 854 : if ((state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType != StandardZone || s_surf->Surface(SurfNum).CosTilt < -0.5) &&
3289 144 : (state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType == StandardZone || s_surf->Surface(SurfNum).ExtBoundCond > 0)) {
3290 :
3291 144 : int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
3292 144 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
3293 : // last minute V3.1
3294 144 : if (thisConstruct.TransDiff <= 0.0) { // Opaque surface
3295 142 : if (AreaSum > 0.0) {
3296 142 : state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * thisConstruct.InsideAbsorpSolar / AreaSum;
3297 : }
3298 : } else { // Window (floor windows are assumed to have no shading device and no divider,
3299 : // and assumed to be non-switchable)
3300 2 : AbsDiffTotWin = 0.0;
3301 2 : if (!state.dataConstruction->Construct(s_surf->Surface(SurfNum).Construction).WindowTypeEQL) {
3302 6 : for (Lay = 1; Lay <= thisConstruct.TotGlassLayers; ++Lay) {
3303 4 : AbsDiffTotWin += thisConstruct.AbsDiffBack(Lay);
3304 : }
3305 : } else {
3306 0 : for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(thisConstruct.EQLConsPtr).NL; ++Lay) {
3307 0 : AbsDiffTotWin += thisConstruct.AbsDiffBackEQL(Lay);
3308 : }
3309 : }
3310 2 : if (AreaSum > 0.0) {
3311 2 : state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * AbsDiffTotWin / AreaSum;
3312 : }
3313 : }
3314 : }
3315 : // CR 8229 test ISABSF for problems
3316 710 : TestFractSum += state.dataSolarShading->SurfIntAbsFac(SurfNum);
3317 : }
3318 :
3319 131 : if (TestFractSum <= 0.0) {
3320 9 : if (thisEnclosure.ExtWindowArea > 0.0) { // we have a problem, the sun has no floor to go to
3321 3 : if (thisEnclosure.FloorArea <= 0.0) {
3322 0 : ShowSevereError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
3323 0 : ShowContinueError(state, format("but Zone or Enclosure =\"{}\" does not appear to have any floor surfaces.", thisEnclosure.Name));
3324 0 : ShowContinueError(state, "Solar gains will be spread evenly on all surfaces in the zone, and the simulation continues...");
3325 : } else { // Floor Area > 0 but still can't absorb
3326 6 : ShowSevereError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
3327 3 : ShowContinueError(state, format("but Zone or Enclosure =\"{}\" floor cannot absorb any solar gains. ", thisEnclosure.Name));
3328 6 : ShowContinueError(state, "Check the solar absorptance of the inside layer of the floor surface construction/material.");
3329 9 : ShowContinueError(state, "Solar gains will be spread evenly on all surfaces in the zone, and the simulation continues...");
3330 : }
3331 :
3332 : // try again but use an even spread across all the surfaces in the zone, regardless of horizontal
3333 : // so as to not lose solar energy
3334 3 : AreaSum = 0.0;
3335 3 : for (int SurfNum : thisEnclosure.SurfacePtr) {
3336 0 : AreaSum += s_surf->Surface(SurfNum).Area;
3337 : }
3338 :
3339 3 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
3340 0 : int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
3341 0 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
3342 0 : if (thisConstruct.TransDiff <= 0.0) { // Opaque surface
3343 0 : if (AreaSum > 0.0) {
3344 0 : state.dataSolarShading->SurfIntAbsFac(SurfNum) =
3345 0 : s_surf->Surface(SurfNum).Area * thisConstruct.InsideAbsorpSolar / AreaSum;
3346 : }
3347 : } else { // Window (floor windows are assumed to have no shading device and no divider,
3348 : // and assumed to be non-switchable)
3349 0 : AbsDiffTotWin = 0.0;
3350 0 : if (!state.dataConstruction->Construct(s_surf->Surface(SurfNum).Construction).WindowTypeEQL) {
3351 0 : for (Lay = 1; Lay <= thisConstruct.TotGlassLayers; ++Lay) {
3352 0 : AbsDiffTotWin += thisConstruct.AbsDiffBack(Lay);
3353 : }
3354 : } else {
3355 0 : for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(thisConstruct.EQLConsPtr).NL; ++Lay) {
3356 0 : AbsDiffTotWin += thisConstruct.AbsDiffBackEQL(Lay);
3357 : }
3358 : }
3359 :
3360 0 : if (AreaSum > 0.0) {
3361 0 : state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * AbsDiffTotWin / AreaSum;
3362 : }
3363 : }
3364 : }
3365 : }
3366 : }
3367 :
3368 : } // enclosure loop
3369 104 : }
3370 :
3371 11826 : void CLIP(EnergyPlusData &state, int const NVT, Array1D<Real64> &XVT, Array1D<Real64> &YVT, Array1D<Real64> &ZVT)
3372 : {
3373 :
3374 : // SUBROUTINE INFORMATION:
3375 : // AUTHOR Legacy Code
3376 : // DATE WRITTEN
3377 : // MODIFIED na
3378 : // RE-ENGINEERED Lawrie, Oct 2000
3379 :
3380 : // PURPOSE OF THIS SUBROUTINE:
3381 : // This subroutine 'clips' the shadow casting surface polygon so that
3382 : // none of it lies below the plane of the receiving surface polygon. This
3383 : // prevents the casting of 'false' shadows.
3384 :
3385 : // REFERENCES:
3386 : // BLAST/IBLAST code, original author George Walton
3387 :
3388 11826 : int NABOVE(0); // Number of vertices of shadow casting surface. above the plane of receiving surface
3389 11826 : int NEXT(0); // First vertex above plane of receiving surface
3390 11826 : int NON(0); // Number of vertices of shadow casting surface. on plane of receiving surface
3391 11826 : Real64 XIN(0.0); // X of entry point of shadow casting surface. into plane of receiving surface
3392 11826 : Real64 XOUT(0.0); // X of exit point of shadow casting surface. from plane of receiving surface
3393 11826 : Real64 YIN(0.0); // Y of entry point of shadow casting surface. into plane of receiving surface
3394 11826 : Real64 YOUT(0.0); // Y of exit point of shadow casting surface. from plane of receiving surface
3395 : // INTEGER NVS ! Number of vertices of the shadow/clipped surface
3396 :
3397 : // Determine if the shadow casting surface. is above, below, or intersects with the plane of the receiving surface
3398 :
3399 11826 : state.dataSolarShading->NumVertInShadowOrClippedSurface = state.dataSolarShading->NVS;
3400 59098 : for (int N = 1; N <= NVT; ++N) {
3401 47272 : Real64 const ZVT_N(ZVT(N));
3402 47272 : if (ZVT_N > 0.0) {
3403 33104 : ++NABOVE;
3404 14168 : } else if (ZVT_N == 0.0) {
3405 6998 : ++NON;
3406 : }
3407 : }
3408 :
3409 11826 : if (NABOVE + NON == NVT) { // Rename the unclipped shadow casting surface.
3410 :
3411 8241 : state.dataSolarShading->NVS = NVT;
3412 8241 : state.dataSolarShading->NumVertInShadowOrClippedSurface = NVT;
3413 41173 : for (int N = 1; N <= NVT; ++N) {
3414 32932 : state.dataSolarShading->XVC(N) = XVT(N);
3415 32932 : state.dataSolarShading->YVC(N) = YVT(N);
3416 32932 : state.dataSolarShading->ZVC(N) = ZVT(N);
3417 : }
3418 :
3419 3585 : } else if (NABOVE == 0) { // Totally submerged shadow casting surface.
3420 :
3421 0 : state.dataSolarShading->NVS = 0;
3422 0 : state.dataSolarShading->NumVertInShadowOrClippedSurface = 0;
3423 :
3424 : } else { // Remove (clip) that portion of the shadow casting surface. which is below the receiving surface
3425 :
3426 3585 : state.dataSolarShading->NVS = NABOVE + 2;
3427 3585 : state.dataSolarShading->NumVertInShadowOrClippedSurface = NABOVE + 2;
3428 3585 : Real64 ZVT_N, ZVT_P(ZVT(1));
3429 3585 : XVT(NVT + 1) = XVT(1);
3430 3585 : YVT(NVT + 1) = YVT(1);
3431 3585 : ZVT(NVT + 1) = ZVT_P;
3432 17925 : for (int N = 1, P = 2; N <= NVT; ++N, ++P) {
3433 14340 : ZVT_N = ZVT_P;
3434 14340 : ZVT_P = ZVT(P);
3435 14340 : if (ZVT_N >= 0.0 && ZVT_P < 0.0) { // Line enters plane of receiving surface
3436 3585 : Real64 const ZVT_fac(1.0 / (ZVT_P - ZVT_N));
3437 3585 : XIN = (ZVT_P * XVT(N) - ZVT_N * XVT(P)) * ZVT_fac;
3438 3585 : YIN = (ZVT_P * YVT(N) - ZVT_N * YVT(P)) * ZVT_fac;
3439 14340 : } else if (ZVT_N <= 0.0 && ZVT_P > 0.0) { // Line exits plane of receiving surface
3440 3585 : NEXT = N + 1;
3441 3585 : Real64 const ZVT_fac(1.0 / (ZVT_P - ZVT_N));
3442 3585 : XOUT = (ZVT_P * XVT(N) - ZVT_N * XVT(P)) * ZVT_fac;
3443 3585 : YOUT = (ZVT_P * YVT(N) - ZVT_N * YVT(P)) * ZVT_fac;
3444 : }
3445 : }
3446 :
3447 : // Renumber the vertices of the clipped shadow casting surface. so they are still counter-clockwise sequential.
3448 :
3449 3585 : state.dataSolarShading->XVC(1) = XOUT; //? Verify that the IN and OUT values were ever set?
3450 3585 : state.dataSolarShading->YVC(1) = YOUT;
3451 3585 : state.dataSolarShading->ZVC(1) = 0.0;
3452 3585 : state.dataSolarShading->XVC(state.dataSolarShading->NVS) = XIN;
3453 3585 : state.dataSolarShading->YVC(state.dataSolarShading->NVS) = YIN;
3454 3585 : state.dataSolarShading->ZVC(state.dataSolarShading->NVS) = 0.0;
3455 10755 : for (int N = 1; N <= NABOVE; ++N) {
3456 7170 : if (NEXT > NVT) {
3457 3585 : NEXT = 1;
3458 : }
3459 7170 : state.dataSolarShading->XVC(N + 1) = XVT(NEXT);
3460 7170 : state.dataSolarShading->YVC(N + 1) = YVT(NEXT);
3461 7170 : state.dataSolarShading->ZVC(N + 1) = ZVT(NEXT);
3462 7170 : ++NEXT;
3463 : }
3464 : }
3465 11826 : }
3466 :
3467 29799 : void CTRANS(EnergyPlusData &state,
3468 : int const NS, // Surface number whose vertex coordinates are being transformed
3469 : int const NGRS, // Base surface number for surface NS
3470 : int &NVT, // Number of vertices for surface NS
3471 : Array1D<Real64> &XVT, // XYZ coordinates of vertices of NS in plane of NGRS
3472 : Array1D<Real64> &YVT,
3473 : Array1D<Real64> &ZVT)
3474 : {
3475 :
3476 : // SUBROUTINE INFORMATION:
3477 : // AUTHOR Legacy Code
3478 : // DATE WRITTEN
3479 : // MODIFIED na
3480 : // RE-ENGINEERED Lawrie, Oct 2000
3481 :
3482 : // PURPOSE OF THIS SUBROUTINE:
3483 : // Transforms the general coordinates of the vertices
3484 : // of surface NS to coordinates in the plane of the receiving surface NGRS.
3485 : // See subroutine 'CalcCoordinateTransformation' SurfaceGeometry Module.
3486 :
3487 : // REFERENCES:
3488 : // BLAST/IBLAST code, original author George Walton
3489 : // NECAP subroutine 'SHADOW'
3490 :
3491 : Real64 Xdif; // Intermediate Result
3492 : Real64 Ydif; // Intermediate Result
3493 : Real64 Zdif; // Intermediate Result
3494 :
3495 29799 : auto &s_surf = state.dataSurface;
3496 :
3497 : // Tuned
3498 29799 : auto const &surface = s_surf->Surface(NS);
3499 29799 : auto const &base_surface = s_surf->Surface(NGRS);
3500 29799 : auto const &base_lcsx = base_surface.lcsx;
3501 29799 : auto const &base_lcsy = base_surface.lcsy;
3502 29799 : auto const &base_lcsz = base_surface.lcsz;
3503 29799 : Real64 const base_X0 = s_surf->X0(NGRS);
3504 29799 : Real64 const base_Y0 = s_surf->Y0(NGRS);
3505 29799 : Real64 const base_Z0 = s_surf->Z0(NGRS);
3506 :
3507 29799 : NVT = surface.Sides;
3508 :
3509 : // Perform transformation
3510 148963 : for (int N = 1; N <= NVT; ++N) {
3511 119164 : auto const &vertex = surface.Vertex(N);
3512 :
3513 119164 : Xdif = vertex.x - base_X0;
3514 119164 : Ydif = vertex.y - base_Y0;
3515 119164 : Zdif = vertex.z - base_Z0;
3516 :
3517 119164 : if (std::abs(Xdif) <= 1.E-15) {
3518 45200 : Xdif = 0.0;
3519 : }
3520 119164 : if (std::abs(Ydif) <= 1.E-15) {
3521 51546 : Ydif = 0.0;
3522 : }
3523 119164 : if (std::abs(Zdif) <= 1.E-15) {
3524 51492 : Zdif = 0.0;
3525 : }
3526 :
3527 119164 : XVT(N) = base_lcsx.x * Xdif + base_lcsx.y * Ydif + base_lcsx.z * Zdif;
3528 119164 : YVT(N) = base_lcsy.x * Xdif + base_lcsy.y * Ydif + base_lcsy.z * Zdif;
3529 119164 : ZVT(N) = base_lcsz.x * Xdif + base_lcsz.y * Ydif + base_lcsz.z * Zdif;
3530 : }
3531 29799 : }
3532 :
3533 0 : void HTRANS(EnergyPlusData &state,
3534 : int const I, // Mode selector: 0 - Compute H.C. of sides
3535 : int const NS, // Figure Number
3536 : int const NumVertices // Number of vertices
3537 : )
3538 : {
3539 :
3540 : // SUBROUTINE INFORMATION:
3541 : // AUTHOR Legacy Code
3542 : // DATE WRITTEN
3543 : // MODIFIED na
3544 : // RE-ENGINEERED Lawrie, Oct 2000
3545 :
3546 : // PURPOSE OF THIS SUBROUTINE:
3547 : // This subroutine sets up the homogeneous coordinates.
3548 : // This routine converts the cartesian coordinates of a surface
3549 : // or shadow polygon to homogeneous coordinates. It also
3550 : // computes the area of the polygon.
3551 :
3552 : // METHODOLOGY EMPLOYED:
3553 : // Note: Original legacy code used integer arithmetic (tests in subroutines
3554 : // INCLOS and INTCPT are sensitive to round-off error). However, porting to Fortran 77
3555 : // (BLAST/IBLAST) required some variables to become REAL(r64) instead.
3556 :
3557 : // Notes on homogeneous coordinates:
3558 : // A point (X,Y) is represented by a 3-element vector
3559 : // (W*X,W*Y,W), where W may be any REAL(r64) number except 0. a line
3560 : // is also represented by a 3-element vector (A,B,C). The
3561 : // directed line (A,B,C) from point (W*X1,W*Y1,W) to point
3562 : // (V*X2,V*Y2,V) is given by (A,B,C) = (W*X1,W*Y1,W) cross
3563 : // (V*X2,V*Y2,V). The sequence of the cross product is a
3564 : // convention to determine sign. The condition that a point lie
3565 : // on a line is that (A,B,C) dot (W*X,W*Y,W) = 0. 'Normalize'
3566 : // the representation of a point by setting W to 1. Then if
3567 : // (A,B,C) dot (X,Y,1) > 0.0, The point is to the left of the
3568 : // line, and if it is less than zero, the point is to the right
3569 : // of the line. The intercept of two lines is given by
3570 : // (W*X,W*Y,W) = (A1,B1,C1) cross (A2,B2,C3).
3571 :
3572 : // REFERENCES:
3573 : // BLAST/IBLAST code, original author George Walton
3574 : // W. M. Newman & R. F. Sproull, 'Principles of Interactive Computer Graphics', Appendix II, McGraw-Hill, 1973.
3575 : // 'CRC Math Tables', 22 ED, 'Analytic Geometry', P.369
3576 :
3577 : // Using/Aliasing
3578 :
3579 : // Locals
3580 : // SUBROUTINE ARGUMENT DEFINITIONS:
3581 : // 1 - Compute H.C. of vertices & sides
3582 :
3583 0 : if (NS > 2 * state.dataSolarShading->MaxHCS) {
3584 0 : ShowFatalError(state, format("Solar Shading: HTrans: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
3585 : }
3586 :
3587 0 : state.dataSolarShading->HCNV(NS) = NumVertices;
3588 :
3589 : // Tuned Linear indexing
3590 :
3591 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
3592 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
3593 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
3594 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
3595 0 : int const l1(state.dataSolarShading->HCX.index(NS, 1));
3596 0 : if (I != 0) { // Transform vertices of figure ns.
3597 :
3598 : // See comment at top of module regarding HCMULT
3599 0 : int l(l1);
3600 0 : for (int N = 1; N <= NumVertices; ++N, ++l) { // [ l ] == ( NS, N )
3601 0 : state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XVS(N) * HCMULT);
3602 0 : state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YVS(N) * HCMULT);
3603 : }
3604 : }
3605 :
3606 : // Establish extra point for finding lines between points.
3607 :
3608 0 : int l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
3609 0 : Int64 HCX_m = state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]; // [ l ] == ( NS, NumVertices + 1 ), [ l1 ] == ( NS, 1 )
3610 0 : Int64 HCY_m = state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]; // [ l ] == ( NS, NumVertices + 1 ), [ l1 ] == ( NS, 1 )
3611 :
3612 : // Determine lines between points.
3613 0 : l = l1;
3614 0 : int m = l1 + 1u;
3615 : Int64 HCX_l;
3616 : Int64 HCY_l;
3617 0 : Real64 SUM = 0.0; // Sum variable
3618 0 : for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
3619 0 : HCX_l = HCX_m;
3620 0 : HCY_l = HCY_m;
3621 0 : HCX_m = state.dataSolarShading->HCX[m];
3622 0 : HCY_m = state.dataSolarShading->HCY[m];
3623 0 : state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
3624 0 : state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
3625 0 : SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
3626 : }
3627 :
3628 : // Compute area of polygon.
3629 : // SUM=0.0D0
3630 : // DO N = 1, NumVertices
3631 : // SUM = SUM + HCX(N,NS)*HCY(N+1,NS) - HCY(N,NS)*HCX(N+1,NS) ! Since HCX and HCY integerized, value of SUM should be ok
3632 : // END DO
3633 0 : state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
3634 : // HCAREA(NS)=0.5d0*SUM*(kHCMULT)
3635 0 : }
3636 :
3637 34858 : void HTRANS0(EnergyPlusData &state,
3638 : int const NS, // Figure Number
3639 : int const NumVertices // Number of vertices
3640 : )
3641 : {
3642 : // Using/Aliasing
3643 :
3644 : // Locals
3645 :
3646 34858 : if (NS > 2 * state.dataSolarShading->MaxHCS) {
3647 0 : ShowFatalError(state, format("Solar Shading: HTrans0: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
3648 : }
3649 :
3650 34858 : state.dataSolarShading->HCNV(NS) = NumVertices;
3651 :
3652 : // Tuned Linear indexing
3653 :
3654 34858 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
3655 34858 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
3656 34858 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
3657 34858 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
3658 :
3659 34858 : int const l1 = state.dataSolarShading->HCX.index(NS, 1);
3660 :
3661 34858 : int l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
3662 34858 : Int64 HCX_m = state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]; // [ l1 ] == ( NS, 1 )
3663 34858 : Int64 HCY_m = state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]; // [ l1 ] == ( NS, 1 )
3664 :
3665 34858 : l = l1;
3666 34858 : int m = l1 + 1u;
3667 : Int64 HCX_l;
3668 : Int64 HCY_l;
3669 34858 : Real64 SUM(0.0);
3670 149503 : for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
3671 114645 : HCX_l = HCX_m;
3672 114645 : HCY_l = HCY_m;
3673 114645 : HCX_m = state.dataSolarShading->HCX[m];
3674 114645 : HCY_m = state.dataSolarShading->HCY[m];
3675 114645 : state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
3676 114645 : state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
3677 114645 : SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
3678 : }
3679 :
3680 34858 : state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
3681 34858 : }
3682 :
3683 38197 : void HTRANS1(EnergyPlusData &state,
3684 : int const NS, // Figure Number
3685 : int const NumVertices // Number of vertices
3686 : )
3687 : {
3688 : // Using/Aliasing
3689 :
3690 38197 : if (NS > 2 * state.dataSolarShading->MaxHCS) {
3691 0 : ShowFatalError(state, format("Solar Shading: HTrans1: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
3692 : }
3693 :
3694 38197 : state.dataSolarShading->HCNV(NS) = NumVertices;
3695 :
3696 : // Tuned Linear indexing
3697 :
3698 38197 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
3699 38197 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
3700 38197 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
3701 38197 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
3702 :
3703 38197 : int const l1 = state.dataSolarShading->HCX.index(NS, 1);
3704 :
3705 : // only in HTRANS1
3706 38197 : int l = l1;
3707 190953 : for (int N = 1; N <= NumVertices; ++N, ++l) { // [ l ] == ( NS, N )
3708 152756 : state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XVS(N) * HCMULT);
3709 152756 : state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YVS(N) * HCMULT);
3710 : }
3711 :
3712 38197 : l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
3713 38197 : Int64 HCX_m(state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]); // [ l1 ] == ( NS, 1 )
3714 38197 : Int64 HCY_m(state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]);
3715 :
3716 38197 : l = l1;
3717 38197 : int m = l1 + 1u;
3718 : Int64 HCX_l;
3719 : Int64 HCY_l;
3720 38197 : Real64 SUM = 0.0;
3721 190953 : for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
3722 152756 : HCX_l = HCX_m;
3723 152756 : HCY_l = HCY_m;
3724 152756 : HCX_m = state.dataSolarShading->HCX[m];
3725 152756 : HCY_m = state.dataSolarShading->HCY[m];
3726 152756 : state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
3727 152756 : state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
3728 152756 : SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
3729 : }
3730 :
3731 38197 : state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
3732 38197 : }
3733 :
3734 0 : void INCLOS(EnergyPlusData &state,
3735 : int const N1, // Figure number of figure 1
3736 : int const N1NumVert, // Number of vertices of figure 1
3737 : int const N2, // Figure number of figure 2
3738 : int const N2NumVert, // Number of vertices of figure 2
3739 : int &NumVerticesOverlap, // Number of vertices which overlap
3740 : int &NIN // Number of vertices of figure 1 within figure 2
3741 : )
3742 : {
3743 :
3744 : // SUBROUTINE INFORMATION:
3745 : // AUTHOR Legacy Code
3746 : // DATE WRITTEN
3747 : // MODIFIED na
3748 : // RE-ENGINEERED Lawrie, Oct 2000
3749 :
3750 : // PURPOSE OF THIS SUBROUTINE:
3751 : // This subroutine determines which vertices of figure N1 lie within figure N2.
3752 :
3753 : // METHODOLOGY EMPLOYED:
3754 : // For vertex N of figure N1 to lie within figure N2, it must be
3755 : // on or to the right of all sides of figure N2, assuming
3756 : // figure N2 is convex.
3757 :
3758 : // REFERENCES:
3759 : // BLAST/IBLAST code, original author George Walton
3760 :
3761 : int K; // Vertex number of the overlap
3762 : int M; // Side number of figure N2
3763 : int N; // Vertex number of figure N1
3764 : bool CycleMainLoop; // Sets when to cycle main loop
3765 : Real64 HFunct;
3766 :
3767 0 : NIN = 0;
3768 :
3769 0 : for (N = 1; N <= N1NumVert; ++N) {
3770 :
3771 0 : CycleMainLoop = false;
3772 :
3773 : // Eliminate cases where vertex N is to the left of side M.
3774 :
3775 0 : for (M = 1; M <= N2NumVert; ++M) {
3776 0 : HFunct = state.dataSolarShading->HCX(N1, N) * state.dataSolarShading->HCA(N2, M) +
3777 0 : state.dataSolarShading->HCY(N1, N) * state.dataSolarShading->HCB(N2, M) + state.dataSolarShading->HCC(N2, M);
3778 0 : if (HFunct > 0.0) {
3779 0 : CycleMainLoop = true; // Set to cycle to the next value of N
3780 0 : break; // M DO loop
3781 : }
3782 : }
3783 :
3784 0 : if (CycleMainLoop) {
3785 0 : continue;
3786 : }
3787 0 : ++NIN;
3788 :
3789 : // Check for duplication of previously determined points.
3790 :
3791 0 : if (NumVerticesOverlap != 0) {
3792 0 : for (K = 1; K <= NumVerticesOverlap; ++K) {
3793 0 : if ((state.dataSolarShading->XTEMP(K) == state.dataSolarShading->HCX(N1, N)) &&
3794 0 : (state.dataSolarShading->YTEMP(K) == state.dataSolarShading->HCY(N1, N))) {
3795 0 : CycleMainLoop = true; // Set to cycle to the next value of N
3796 0 : break; // K DO loop
3797 : }
3798 : }
3799 0 : if (CycleMainLoop) {
3800 0 : continue;
3801 : }
3802 : }
3803 :
3804 : // Record enclosed vertices in temporary arrays.
3805 :
3806 0 : ++NumVerticesOverlap;
3807 0 : state.dataSolarShading->XTEMP(NumVerticesOverlap) = state.dataSolarShading->HCX(N1, N);
3808 0 : state.dataSolarShading->YTEMP(NumVerticesOverlap) = state.dataSolarShading->HCY(N1, N);
3809 : }
3810 0 : }
3811 :
3812 0 : void INTCPT(EnergyPlusData &state,
3813 : int const NV1, // Number of vertices of figure NS1
3814 : int const NV2, // Number of vertices of figure NS2
3815 : int &NV3, // Number of vertices of figure NS3
3816 : int const NS1, // Number of the figure being overlapped
3817 : int const NS2 // Number of the figure doing overlapping
3818 : )
3819 : {
3820 :
3821 : // SUBROUTINE INFORMATION:
3822 : // AUTHOR Legacy Code
3823 : // DATE WRITTEN
3824 : // MODIFIED na
3825 : // RE-ENGINEERED Lawrie, Oct 2000
3826 :
3827 : // PURPOSE OF THIS SUBROUTINE:
3828 : // This subroutine determines all intercepts between the sides of figure NS1
3829 : // and the sides of figure NS2.
3830 :
3831 : // METHODOLOGY EMPLOYED:
3832 : // The requirements for intersection are that the end points of
3833 : // line N lie on both sides of line M and vice versa. Also
3834 : // eliminate cases where the end point of one line lies exactly
3835 : // on the other to reduce duplication with the enclosed points.
3836 :
3837 : // REFERENCES:
3838 : // BLAST/IBLAST code, original author George Walton
3839 :
3840 : Real64 W; // Normalization factor
3841 : Real64 XUntrunc; // Untruncated X coordinate
3842 : Real64 YUntrunc; // Untruncated Y coordinate
3843 : Int64 I1; // Intermediate result for testing intersection
3844 : Int64 I2; // Intermediate result for testing intersection
3845 : int K;
3846 : int KK;
3847 : int M; // Side number of figure NS2
3848 : int N; // Side number of figure NS1
3849 :
3850 0 : for (N = 1; N <= NV1; ++N) {
3851 0 : for (M = 1; M <= NV2; ++M) {
3852 :
3853 : // Eliminate cases where sides N and M do not intersect.
3854 :
3855 0 : I1 = state.dataSolarShading->HCA(NS1, N) * state.dataSolarShading->HCX(NS2, M) +
3856 0 : state.dataSolarShading->HCB(NS1, N) * state.dataSolarShading->HCY(NS2, M) + state.dataSolarShading->HCC(NS1, N);
3857 0 : I2 = state.dataSolarShading->HCA(NS1, N) * state.dataSolarShading->HCX(NS2, M + 1) +
3858 0 : state.dataSolarShading->HCB(NS1, N) * state.dataSolarShading->HCY(NS2, M + 1) + state.dataSolarShading->HCC(NS1, N);
3859 0 : if (I1 >= 0 && I2 >= 0) {
3860 0 : continue;
3861 : }
3862 0 : if (I1 <= 0 && I2 <= 0) {
3863 0 : continue;
3864 : }
3865 :
3866 0 : I1 = state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCX(NS1, N) +
3867 0 : state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCY(NS1, N) + state.dataSolarShading->HCC(NS2, M);
3868 0 : I2 = state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCX(NS1, N + 1) +
3869 0 : state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCY(NS1, N + 1) + state.dataSolarShading->HCC(NS2, M);
3870 0 : if (I1 >= 0 && I2 >= 0) {
3871 0 : continue;
3872 : }
3873 0 : if (I1 <= 0 && I2 <= 0) {
3874 0 : continue;
3875 : }
3876 :
3877 : // Determine the point of intersection and record in the temporary array.
3878 :
3879 0 : KK = NV3;
3880 0 : ++NV3;
3881 0 : W = state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCA(NS1, N) -
3882 0 : state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCB(NS1, N);
3883 0 : XUntrunc = (state.dataSolarShading->HCC(NS2, M) * state.dataSolarShading->HCB(NS1, N) -
3884 0 : state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCC(NS1, N)) /
3885 : W;
3886 0 : YUntrunc = (state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCC(NS1, N) -
3887 0 : state.dataSolarShading->HCC(NS2, M) * state.dataSolarShading->HCA(NS1, N)) /
3888 : W;
3889 0 : if (NV3 > isize(state.dataSolarShading->XTEMP)) {
3890 0 : state.dataSolarShading->XTEMP.redimension(isize(state.dataSolarShading->XTEMP) + 10, 0.0);
3891 0 : state.dataSolarShading->YTEMP.redimension(isize(state.dataSolarShading->YTEMP) + 10, 0.0);
3892 : }
3893 0 : state.dataSolarShading->XTEMP(NV3) = nint64(XUntrunc);
3894 0 : state.dataSolarShading->YTEMP(NV3) = nint64(YUntrunc);
3895 :
3896 : // Eliminate near-duplicate points.
3897 :
3898 0 : if (KK != 0) {
3899 0 : Real64 const x(state.dataSolarShading->XTEMP(NV3));
3900 0 : Real64 const y(state.dataSolarShading->YTEMP(NV3));
3901 0 : for (K = 1; K <= KK; ++K) {
3902 0 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) {
3903 0 : continue;
3904 : }
3905 0 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) {
3906 0 : continue;
3907 : }
3908 0 : NV3 = KK;
3909 0 : break; // K DO loop
3910 : }
3911 : }
3912 : }
3913 : }
3914 0 : }
3915 :
3916 2349 : inline bool neq(Real64 a, Real64 b)
3917 : {
3918 2349 : return std::abs(a - b) > 2.0;
3919 : }
3920 :
3921 3486 : inline bool d_eq(Real64 a, Real64 b)
3922 : {
3923 3486 : return std::abs(a - b) < 2.0;
3924 : }
3925 :
3926 737 : void CLIPLINE(Real64 &x0, Real64 &x1, Real64 &y0, Real64 &y1, Real64 maxX, Real64 minX, Real64 maxY, Real64 minY, bool &visible)
3927 : {
3928 :
3929 : // Line segment clipping
3930 : // Reference:
3931 : // Liang, Y.D., Barsky, B.A., Slater, M.
3932 : // 2D line and polygon clipping based on space subdivision.
3933 : // The Visual Computer 10, 407–422 (1994).
3934 :
3935 : // Tweaked via microbenchmarking to improve efficiency
3936 :
3937 737 : bool rev = false;
3938 737 : if (x0 > x1) { // reverse for efficiency
3939 311 : std::swap(x0, x1);
3940 311 : std::swap(y0, y1);
3941 311 : rev = true;
3942 : }
3943 :
3944 737 : if (x0 > maxX || x1 < minX) {
3945 : // Both points are outside the clip window, so they can't cross it
3946 52 : return;
3947 : }
3948 :
3949 : // defining variables
3950 685 : Real64 const dx = x1 - x0; // >= 0
3951 685 : Real64 const dy = y1 - y0;
3952 :
3953 685 : Real64 const q1 = x0 - minX;
3954 685 : Real64 const q2 = maxX - x0;
3955 685 : Real64 const q3 = y0 - minY;
3956 685 : Real64 const q4 = maxY - y0;
3957 :
3958 685 : Real64 u1 = 0;
3959 685 : Real64 u2 = 1;
3960 :
3961 685 : if ((dx == 0 && (q1 < 0 || q2 < 0)) || (dy == 0 && (q3 < 0 || q4 < 0))) {
3962 : // Line is parallel to clipping window
3963 98 : return;
3964 : }
3965 587 : if (dx != 0) {
3966 520 : Real64 const r1 = q1 / -dx;
3967 520 : if (r1 > u1) {
3968 138 : u1 = r1;
3969 : }
3970 520 : Real64 const r2 = q2 / dx;
3971 520 : if (r2 < u2) {
3972 136 : u2 = r2;
3973 : }
3974 : }
3975 587 : if (dy != 0) {
3976 341 : Real64 const r3 = q3 / -dy;
3977 341 : Real64 const r4 = q4 / dy;
3978 341 : if (dy > 0) {
3979 173 : if (r3 > u1) {
3980 54 : u1 = r3;
3981 : }
3982 173 : if (r4 < u2) {
3983 16 : u2 = r4;
3984 : }
3985 : } else {
3986 168 : if (r4 > u1) {
3987 16 : u1 = r4;
3988 : }
3989 168 : if (r3 < u2) {
3990 55 : u2 = r3;
3991 : }
3992 : }
3993 : }
3994 :
3995 587 : if (u1 > u2) { // reject
3996 : // Line is outside the clipping window
3997 4 : return;
3998 : }
3999 :
4000 583 : visible = true;
4001 :
4002 583 : Real64 const xn0 = x0 + dx * u1;
4003 583 : Real64 const yn0 = y0 + dy * u1;
4004 :
4005 583 : Real64 const xn1 = x0 + dx * u2;
4006 583 : Real64 const yn1 = y0 + dy * u2;
4007 :
4008 583 : if (rev) {
4009 229 : x0 = xn1;
4010 229 : y0 = yn1;
4011 229 : x1 = xn0;
4012 229 : y1 = yn0;
4013 : } else {
4014 354 : x0 = xn0;
4015 354 : y0 = yn0;
4016 354 : x1 = xn1;
4017 354 : y1 = yn1;
4018 : }
4019 : }
4020 :
4021 157 : void CLIPRECT(EnergyPlusData &state, int const NS2, int const NV1, int &NV3)
4022 : {
4023 : // Polygon clipping by line segment clipping for rectangles
4024 : // Reference:
4025 : // Slater, M., Barsky, B.A.
4026 : // 2D line and polygon clipping based on space subdivision.
4027 : // The Visual Computer 10, 407–422 (1994).
4028 157 : bool INTFLAG = false;
4029 157 : int l = state.dataSolarShading->HCA.index(NS2, 1);
4030 : Real64 maxX, minX, maxY, minY;
4031 157 : if (state.dataSolarShading->HCX[l] > state.dataSolarShading->HCX[l + 2]) {
4032 157 : maxX = state.dataSolarShading->HCX[l];
4033 157 : minX = state.dataSolarShading->HCX[l + 2];
4034 : } else {
4035 0 : maxX = state.dataSolarShading->HCX[l + 2];
4036 0 : minX = state.dataSolarShading->HCX[l];
4037 : }
4038 157 : if (state.dataSolarShading->HCY[l] > state.dataSolarShading->HCY[l + 2]) {
4039 157 : maxY = state.dataSolarShading->HCY[l];
4040 157 : minY = state.dataSolarShading->HCY[l + 2];
4041 : } else {
4042 0 : maxY = state.dataSolarShading->HCY[l + 2];
4043 0 : minY = state.dataSolarShading->HCY[l];
4044 : }
4045 :
4046 : Real64 arrx[20]; // Temp array for output X
4047 : Real64 arry[20]; // Temp array for output Y
4048 157 : int arrc = 0; // Number of items in output
4049 :
4050 797 : for (int j = 0; j < NV1; ++j) {
4051 640 : Real64 x_1 = state.dataSolarShading->XTEMP[j];
4052 640 : Real64 y_1 = state.dataSolarShading->YTEMP[j];
4053 640 : Real64 x_2 = state.dataSolarShading->XTEMP[(j + 1) % NV1];
4054 640 : Real64 y_2 = state.dataSolarShading->YTEMP[(j + 1) % NV1];
4055 640 : Real64 x1 = x_1, x2 = x_2, y1 = y_1, y2 = y_2;
4056 :
4057 640 : bool visible = false;
4058 640 : CLIPLINE(x_1, x_2, y_1, y_2, maxX, minX, maxY, minY, visible);
4059 640 : if (visible) {
4060 514 : if ((x_1 != x1 || y_1 != y1) || (x_2 != x2 || y_2 != y2)) {
4061 274 : INTFLAG = true;
4062 : }
4063 : // if line on edge, or inside, add both points
4064 514 : if (arrc == 0 || ((neq(arrx[arrc - 1], x_1) || neq(arry[arrc - 1], y_1)) && (neq(arrx[0], x_1) || neq(arry[0], y_1)))) {
4065 213 : arrx[arrc] = x_1;
4066 213 : arry[arrc] = y_1;
4067 213 : arrc += 1;
4068 213 : if ((neq(x_1, x_2) || neq(y_1, y_2)) && (neq(arrx[0], x_2) || neq(arry[0], y_2))) {
4069 183 : arrx[arrc] = x_2;
4070 183 : arry[arrc] = y_2;
4071 183 : arrc += 1;
4072 : }
4073 301 : } else if ((neq(arrx[arrc - 1], x_2) || neq(arry[arrc - 1], y_2)) && (neq(arrx[0], x_2) || neq(arry[0], y_2))) {
4074 136 : arrx[arrc] = x_2;
4075 136 : arry[arrc] = y_2;
4076 136 : arrc += 1;
4077 : }
4078 : }
4079 : }
4080 157 : NV3 = arrc;
4081 :
4082 : // Re-populate XTEMP/YTEMP
4083 157 : if (NV3 > 1) {
4084 147 : int LastEdgeIndex = -1, incr = 0;
4085 147 : double cornerXs[4] = {minX, minX, maxX, maxX};
4086 147 : double cornerYs[4] = {minY, maxY, maxY, minY};
4087 147 : Real64 edges[4] = {minX, maxY, maxX, minY};
4088 : Real64 LastEdgeX, LastEdgeY;
4089 826 : for (int i = 0; i <= arrc; i++) {
4090 679 : int k = i % arrc;
4091 :
4092 679 : Real64 currX = arrx[k], currY = arry[k];
4093 :
4094 679 : int edgeCount = 0, EdgeIndex = -1;
4095 3395 : for (int m = 0; m < 4; m++) {
4096 2716 : if (m % 2 == 0 && d_eq(currX, edges[m])) { // MinX or MaxX
4097 486 : edgeCount++;
4098 486 : EdgeIndex = m;
4099 2230 : } else if (m % 2 == 1 && d_eq(currY, edges[m])) {
4100 501 : edgeCount++;
4101 501 : EdgeIndex = m;
4102 : }
4103 : }
4104 679 : if (edgeCount == 0) { // On inside
4105 77 : if (i != arrc) {
4106 77 : state.dataSolarShading->XTEMP[incr] = currX;
4107 77 : state.dataSolarShading->YTEMP[incr] = currY;
4108 77 : incr++;
4109 : }
4110 77 : continue;
4111 602 : } else if (edgeCount > 1) { // On corner
4112 385 : if (d_eq(currX, minX)) {
4113 250 : if (d_eq(currY, minY)) {
4114 8 : EdgeIndex = 3;
4115 : } else {
4116 242 : EdgeIndex = 0;
4117 : }
4118 : } else {
4119 135 : if (d_eq(currY, maxY)) {
4120 131 : EdgeIndex = 1;
4121 : } else {
4122 4 : EdgeIndex = 2;
4123 : }
4124 : }
4125 : }
4126 602 : if ((LastEdgeIndex > -1 && EdgeIndex > -1) && LastEdgeIndex != EdgeIndex) {
4127 386 : int jumpCount = 0;
4128 386 : if ((EdgeIndex == 0 && LastEdgeIndex == 3) || (EdgeIndex - LastEdgeIndex == 1)) {
4129 237 : jumpCount = 1;
4130 149 : } else if (EdgeIndex % 2 == LastEdgeIndex % 2) {
4131 : // Clockwise double jump
4132 112 : jumpCount = 2;
4133 37 : } else if ((EdgeIndex == 3 && LastEdgeIndex == 0) || (LastEdgeIndex - EdgeIndex == 1)) {
4134 : // Clockwise triple jump
4135 37 : jumpCount = 3;
4136 : }
4137 386 : if (jumpCount > 0) {
4138 : Real64 cornerX;
4139 : Real64 cornerY;
4140 386 : int startIndex = (LastEdgeIndex + 1) % 4;
4141 386 : int added = 0;
4142 958 : for (int i1 = startIndex, j1 = 0; j1 < jumpCount; i1 = (i1 + 1) % 4, j1++) {
4143 572 : cornerX = cornerXs[i1];
4144 572 : cornerY = cornerYs[i1];
4145 572 : if (cornerX == LastEdgeX && cornerY == LastEdgeY) {
4146 264 : continue; // skip if jump started on corner
4147 : }
4148 :
4149 308 : bool insideFlag = true;
4150 979 : for (int j = 0; j < NV1; ++j) {
4151 921 : if ((state.dataSolarShading->ATEMP[j] * cornerX) + (cornerY * state.dataSolarShading->BTEMP[j]) +
4152 921 : state.dataSolarShading->CTEMP[j] >
4153 : 0.0) {
4154 250 : insideFlag = false;
4155 250 : break;
4156 : }
4157 : }
4158 :
4159 366 : if (insideFlag &&
4160 58 : (incr == 0 ||
4161 144 : ((neq(cornerX, state.dataSolarShading->XTEMP[incr - 1]) || neq(cornerY, state.dataSolarShading->YTEMP[incr - 1])) &&
4162 84 : (neq(cornerX, state.dataSolarShading->XTEMP[0]) || neq(cornerY, state.dataSolarShading->YTEMP[0]))))) {
4163 56 : state.dataSolarShading->XTEMP[incr] = cornerX;
4164 56 : state.dataSolarShading->YTEMP[incr] = cornerY;
4165 56 : incr++;
4166 56 : added++;
4167 : }
4168 : }
4169 386 : if (jumpCount > 2 && (added == jumpCount && edgeCount == 1)) {
4170 0 : if (i != arrc) {
4171 0 : state.dataSolarShading->XTEMP[incr] = currX;
4172 0 : state.dataSolarShading->YTEMP[incr] = currY;
4173 0 : incr++;
4174 : }
4175 0 : break;
4176 : }
4177 : }
4178 : }
4179 602 : if (i != arrc) {
4180 455 : state.dataSolarShading->XTEMP[incr] = currX;
4181 455 : state.dataSolarShading->YTEMP[incr] = currY;
4182 455 : incr++;
4183 : }
4184 602 : LastEdgeIndex = EdgeIndex;
4185 602 : LastEdgeX = currX;
4186 602 : LastEdgeY = currY;
4187 : }
4188 147 : NV3 = incr;
4189 :
4190 : } else {
4191 10 : if (NV3 == 1) {
4192 0 : state.dataSolarShading->XTEMP[0] = arrx[0];
4193 0 : state.dataSolarShading->YTEMP[0] = arry[0];
4194 : }
4195 10 : if (NV3 == 0) {
4196 10 : double cornerXs[4] = {minX, minX, maxX, maxX};
4197 10 : double cornerYs[4] = {minY, maxY, maxY, minY};
4198 10 : Real64 cornerX = cornerXs[0];
4199 10 : Real64 cornerY = cornerYs[0];
4200 10 : bool insideFlag = true;
4201 50 : for (int j = 0; j < NV1; ++j) {
4202 40 : if ((state.dataSolarShading->ATEMP[j] * cornerX) + (cornerY * state.dataSolarShading->BTEMP[j]) + state.dataSolarShading->CTEMP[j] >=
4203 : 0.0) {
4204 0 : insideFlag = false;
4205 0 : break;
4206 : }
4207 : }
4208 10 : if (insideFlag) {
4209 50 : for (int i1 = 0; i1 < 4; i1++) {
4210 40 : state.dataSolarShading->XTEMP[i1] = cornerXs[i1];
4211 40 : state.dataSolarShading->YTEMP[i1] = cornerYs[i1];
4212 : }
4213 10 : NV3 = 4;
4214 10 : INTFLAG = true;
4215 : }
4216 : }
4217 : }
4218 :
4219 : // update homogeneous edges A,B,C
4220 157 : if (NV3 > 0) {
4221 157 : Real64 const X_0(state.dataSolarShading->XTEMP[0]);
4222 157 : Real64 const Y_0(state.dataSolarShading->YTEMP[0]);
4223 157 : Real64 XP_0 = X_0, XP_1;
4224 157 : Real64 YP_0 = Y_0, YP_1;
4225 628 : for (int P = 0; P < NV3 - 1; ++P) {
4226 471 : XP_1 = state.dataSolarShading->XTEMP[P + 1];
4227 471 : YP_1 = state.dataSolarShading->YTEMP[P + 1];
4228 :
4229 471 : state.dataSolarShading->ATEMP[P] = YP_0 - YP_1;
4230 471 : state.dataSolarShading->BTEMP[P] = XP_1 - XP_0;
4231 471 : state.dataSolarShading->CTEMP[P] = XP_0 * YP_1 - YP_0 * XP_1;
4232 471 : XP_0 = XP_1;
4233 471 : YP_0 = YP_1;
4234 : }
4235 :
4236 157 : state.dataSolarShading->ATEMP[NV3 - 1] = YP_1 - Y_0;
4237 157 : state.dataSolarShading->BTEMP[NV3 - 1] = X_0 - XP_1;
4238 157 : state.dataSolarShading->CTEMP[NV3 - 1] = XP_1 * Y_0 - YP_1 * X_0;
4239 : }
4240 :
4241 : // Determine overlap status
4242 157 : if (NV3 < 3) { // Determine overlap status
4243 0 : state.dataSolarShading->OverlapStatus = NoOverlap;
4244 157 : } else if (!INTFLAG) {
4245 12 : state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
4246 : }
4247 157 : }
4248 :
4249 20917 : void CLIPPOLY(EnergyPlusData &state,
4250 : int const NS1, // Figure number of figure 1 (The subject polygon)
4251 : int const NS2, // Figure number of figure 2 (The clipping polygon)
4252 : int const NV1, // Number of vertices of figure 1
4253 : int const NV2, // Number of vertices of figure 2
4254 : int &NV3 // Number of vertices of figure 3
4255 : )
4256 : {
4257 :
4258 : // SUBROUTINE INFORMATION:
4259 : // AUTHOR Tyler Hoyt
4260 : // DATE WRITTEN May 4, 2010
4261 : // MODIFIED na
4262 : // RE-ENGINEERED na
4263 :
4264 : // PURPOSE OF THIS SUBROUTINE:
4265 : // Populate global arrays XTEMP and YTEMP with the vertices
4266 : // of the overlap between NS1 and NS2, and determine relevant
4267 : // overlap status.
4268 :
4269 : // METHODOLOGY EMPLOYED:
4270 : // The Sutherland-Hodgman algorithm for polygon clipping is employed.
4271 :
4272 : using General::SafeDivide;
4273 :
4274 : typedef Array2D<Int64>::size_type size_type;
4275 : bool INTFLAG; // For overlap status
4276 : int S; // Test vertex
4277 : int KK; // Duplicate test index
4278 : int NVOUT; // Current output length for loops
4279 : int NVTEMP;
4280 :
4281 : Real64 W; // Normalization factor
4282 : Real64 HFunct;
4283 :
4284 20917 : auto &s_surf = state.dataSurface;
4285 :
4286 : #ifdef EP_Count_Calls
4287 : ++state.dataTimingsData->NumClipPoly_Calls;
4288 : #endif
4289 : // Tuned Linear indexing
4290 :
4291 20917 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
4292 20917 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
4293 20917 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
4294 20917 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
4295 :
4296 : // Populate the arrays with the original polygon
4297 104901 : for (size_type j = 0, l = state.dataSolarShading->HCX.index(NS1, 1), e = NV1; j < e; ++j, ++l) {
4298 83984 : state.dataSolarShading->XTEMP[j] = state.dataSolarShading->HCX[l]; // [ l ] == ( NS1, j+1 )
4299 83984 : state.dataSolarShading->YTEMP[j] = state.dataSolarShading->HCY[l];
4300 83984 : state.dataSolarShading->ATEMP[j] = state.dataSolarShading->HCA[l];
4301 83984 : state.dataSolarShading->BTEMP[j] = state.dataSolarShading->HCB[l];
4302 83984 : state.dataSolarShading->CTEMP[j] = state.dataSolarShading->HCC[l];
4303 : }
4304 :
4305 20917 : NVOUT = NV1; // First point-loop is the length of the subject polygon.
4306 20917 : INTFLAG = false;
4307 20917 : NVTEMP = 0;
4308 20917 : KK = 0;
4309 :
4310 : // Check if clipping polygon is rectangle
4311 20917 : if (state.dataSysVars->SlaterBarsky) {
4312 422 : int l1 = state.dataSolarShading->HCA.index(NS2, 1);
4313 844 : bool rectFlag = ((NV2 == 4) && (((((state.dataSolarShading->HCX[l1] == state.dataSolarShading->HCX[l1 + 1] &&
4314 157 : state.dataSolarShading->HCY[l1] != state.dataSolarShading->HCY[l1 + 1]) &&
4315 157 : ((state.dataSolarShading->HCY[l1 + 2] == state.dataSolarShading->HCY[l1 + 1] &&
4316 157 : state.dataSolarShading->HCY[l1 + 3] == state.dataSolarShading->HCY[l1]))) &&
4317 157 : state.dataSolarShading->HCX[l1 + 2] == state.dataSolarShading->HCX[l1 + 3]) ||
4318 265 : ((((state.dataSolarShading->HCY[l1] == state.dataSolarShading->HCY[l1 + 1] &&
4319 24 : state.dataSolarShading->HCX[l1] != state.dataSolarShading->HCX[l1 + 1]) &&
4320 24 : (state.dataSolarShading->HCX[l1 + 2] == state.dataSolarShading->HCX[l1 + 1] &&
4321 0 : state.dataSolarShading->HCX[l1 + 3] == state.dataSolarShading->HCX[l1])) &&
4322 0 : (state.dataSolarShading->HCY[l1 + 2] == state.dataSolarShading->HCY[l1 + 3]))))));
4323 422 : if (rectFlag) {
4324 157 : CLIPRECT(state, NS2, NV1, NV3);
4325 157 : return;
4326 : }
4327 : }
4328 :
4329 20760 : int l = state.dataSolarShading->HCA.index(NS2, 1);
4330 88491 : for (int E = 1; E <= NV2; ++E, ++l) { // Loop over edges of the clipping polygon
4331 377790 : for (int P = 1; P <= NVOUT; ++P) {
4332 304257 : state.dataSolarShading->XTEMP1(P) = state.dataSolarShading->XTEMP(P);
4333 304257 : state.dataSolarShading->YTEMP1(P) = state.dataSolarShading->YTEMP(P);
4334 : }
4335 73533 : S = NVOUT;
4336 73533 : Real64 const HCA_E(state.dataSolarShading->HCA[l]);
4337 73533 : Real64 const HCB_E(state.dataSolarShading->HCB[l]);
4338 73533 : Real64 const HCC_E(state.dataSolarShading->HCC[l]);
4339 73533 : Real64 XTEMP1_S(state.dataSolarShading->XTEMP1(S));
4340 73533 : Real64 YTEMP1_S(state.dataSolarShading->YTEMP1(S));
4341 377790 : for (int P = 1; P <= NVOUT; ++P) {
4342 304257 : Real64 const XTEMP1_P(state.dataSolarShading->XTEMP1(P));
4343 304257 : Real64 const YTEMP1_P(state.dataSolarShading->YTEMP1(P));
4344 304257 : HFunct = XTEMP1_P * HCA_E + YTEMP1_P * HCB_E + HCC_E;
4345 : // S is constant within this block
4346 304257 : if (HFunct <= 0.0) { // Vertex is not in the clipping plane
4347 222766 : HFunct = XTEMP1_S * HCA_E + YTEMP1_S * HCB_E + HCC_E;
4348 222766 : if (HFunct > 0.0) { // Test vertex is in the clipping plane
4349 :
4350 : // Find/store the intersection of the clip edge and the line connecting S and P
4351 30580 : KK = NVTEMP;
4352 30580 : ++NVTEMP;
4353 30580 : Real64 const ATEMP_S(state.dataSolarShading->ATEMP(S));
4354 30580 : Real64 const BTEMP_S(state.dataSolarShading->BTEMP(S));
4355 30580 : Real64 const CTEMP_S(state.dataSolarShading->CTEMP(S));
4356 30580 : W = HCB_E * ATEMP_S - HCA_E * BTEMP_S;
4357 30580 : if (W != 0.0) {
4358 30580 : Real64 const W_inv(1.0 / W);
4359 30580 : state.dataSolarShading->XTEMP(NVTEMP) = nint64((HCC_E * BTEMP_S - HCB_E * CTEMP_S) * W_inv);
4360 30580 : state.dataSolarShading->YTEMP(NVTEMP) = nint64((HCA_E * CTEMP_S - HCC_E * ATEMP_S) * W_inv);
4361 : } else {
4362 0 : state.dataSolarShading->XTEMP(NVTEMP) = SafeDivide(HCC_E * BTEMP_S - HCB_E * CTEMP_S, W);
4363 0 : state.dataSolarShading->YTEMP(NVTEMP) = SafeDivide(HCA_E * CTEMP_S - HCC_E * ATEMP_S, W);
4364 : }
4365 30580 : INTFLAG = true;
4366 :
4367 30580 : if (E == NV2) { // Remove near-duplicates on last edge
4368 6024 : if (KK != 0) {
4369 3585 : Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
4370 3585 : Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
4371 8189 : for (int K = 1; K <= KK; ++K) {
4372 4604 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) {
4373 4463 : continue;
4374 : }
4375 141 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) {
4376 141 : continue;
4377 : }
4378 0 : NVTEMP = KK;
4379 0 : break; // K loop
4380 : }
4381 : }
4382 : }
4383 : }
4384 :
4385 222766 : KK = NVTEMP;
4386 222766 : ++NVTEMP;
4387 222766 : if (NVTEMP > state.dataSolarShading->MAXHCArrayBounds) {
4388 0 : int const NewArrayBounds(state.dataSolarShading->MAXHCArrayBounds + state.dataSolarShading->MAXHCArrayIncrement);
4389 0 : state.dataSolarShading->XTEMP.redimension(NewArrayBounds, 0.0);
4390 0 : state.dataSolarShading->YTEMP.redimension(NewArrayBounds, 0.0);
4391 0 : state.dataSolarShading->XTEMP1.redimension(NewArrayBounds, 0.0);
4392 0 : state.dataSolarShading->YTEMP1.redimension(NewArrayBounds, 0.0);
4393 0 : state.dataSolarShading->ATEMP.redimension(NewArrayBounds, 0.0);
4394 0 : state.dataSolarShading->BTEMP.redimension(NewArrayBounds, 0.0);
4395 0 : state.dataSolarShading->CTEMP.redimension(NewArrayBounds, 0.0);
4396 0 : state.dataSolarShading->MAXHCArrayBounds = NewArrayBounds;
4397 : }
4398 :
4399 222766 : state.dataSolarShading->XTEMP(NVTEMP) = XTEMP1_P;
4400 222766 : state.dataSolarShading->YTEMP(NVTEMP) = YTEMP1_P;
4401 :
4402 222766 : if (E == NV2) { // Remove near-duplicates on last edge
4403 50965 : if (KK != 0) {
4404 41120 : Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
4405 41120 : Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
4406 120257 : for (int K = 1; K <= KK; ++K) {
4407 83665 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) {
4408 62637 : continue;
4409 : }
4410 21028 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) {
4411 16500 : continue;
4412 : }
4413 4528 : NVTEMP = KK;
4414 4528 : break; // K loop
4415 : }
4416 : }
4417 : }
4418 :
4419 : } else {
4420 81491 : HFunct = XTEMP1_S * HCA_E + YTEMP1_S * HCB_E + HCC_E;
4421 81491 : if (HFunct <= 0.0) { // Test vertex is not in the clipping plane
4422 30580 : if (NVTEMP < 2 * (s_surf->MaxVerticesPerSurface + 1)) { // avoid assigning to element outside of XTEMP array size
4423 30580 : KK = NVTEMP;
4424 30580 : ++NVTEMP;
4425 30580 : Real64 const ATEMP_S(state.dataSolarShading->ATEMP(S));
4426 30580 : Real64 const BTEMP_S(state.dataSolarShading->BTEMP(S));
4427 30580 : Real64 const CTEMP_S(state.dataSolarShading->CTEMP(S));
4428 30580 : W = HCB_E * ATEMP_S - HCA_E * BTEMP_S;
4429 30580 : if (W != 0.0) {
4430 30580 : Real64 const W_inv(1.0 / W);
4431 30580 : state.dataSolarShading->XTEMP(NVTEMP) = nint64((HCC_E * BTEMP_S - HCB_E * CTEMP_S) * W_inv);
4432 30580 : state.dataSolarShading->YTEMP(NVTEMP) = nint64((HCA_E * CTEMP_S - HCC_E * ATEMP_S) * W_inv);
4433 : } else {
4434 0 : state.dataSolarShading->XTEMP(NVTEMP) = SafeDivide(HCC_E * BTEMP_S - HCB_E * CTEMP_S, W);
4435 0 : state.dataSolarShading->YTEMP(NVTEMP) = SafeDivide(HCA_E * CTEMP_S - HCC_E * ATEMP_S, W);
4436 : }
4437 30580 : INTFLAG = true;
4438 :
4439 30580 : if (E == NV2) { // Remove near-duplicates on last edge
4440 6024 : if (KK != 0) {
4441 3350 : Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
4442 3350 : Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
4443 11212 : for (int K = 1; K <= KK; ++K) {
4444 8062 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) {
4445 6525 : continue;
4446 : }
4447 1537 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) {
4448 1337 : continue;
4449 : }
4450 200 : NVTEMP = KK;
4451 200 : break; // K loop
4452 : }
4453 : }
4454 : }
4455 : }
4456 : }
4457 : }
4458 304257 : S = P;
4459 304257 : XTEMP1_S = XTEMP1_P;
4460 304257 : YTEMP1_S = YTEMP1_P;
4461 : } // end loop over points of subject polygon
4462 :
4463 73533 : NVOUT = NVTEMP;
4464 73533 : if (NVOUT == 0) {
4465 5802 : break; // Added to avoid array bounds violation of XTEMP1 and YTEMP1 and wasted looping
4466 : }
4467 67731 : NVTEMP = 0;
4468 :
4469 67731 : if (E != NV2) {
4470 52773 : if (NVOUT > 2) { // Compute HC values for edges of output polygon
4471 52773 : Real64 const X_1(state.dataSolarShading->XTEMP(1));
4472 52773 : Real64 const Y_1(state.dataSolarShading->YTEMP(1));
4473 52773 : Real64 X_P(X_1), X_P1;
4474 52773 : Real64 Y_P(Y_1), Y_P1;
4475 220913 : for (int P = 1; P < NVOUT; ++P) {
4476 168140 : X_P1 = state.dataSolarShading->XTEMP(P + 1);
4477 168140 : Y_P1 = state.dataSolarShading->YTEMP(P + 1);
4478 168140 : state.dataSolarShading->ATEMP(P) = Y_P - Y_P1;
4479 168140 : state.dataSolarShading->BTEMP(P) = X_P1 - X_P;
4480 168140 : state.dataSolarShading->CTEMP(P) = X_P * Y_P1 - Y_P * X_P1;
4481 168140 : X_P = X_P1;
4482 168140 : Y_P = Y_P1;
4483 : }
4484 52773 : state.dataSolarShading->ATEMP(NVOUT) = Y_P1 - Y_1;
4485 52773 : state.dataSolarShading->BTEMP(NVOUT) = X_1 - X_P1;
4486 52773 : state.dataSolarShading->CTEMP(NVOUT) = X_P1 * Y_1 - Y_P1 * X_1;
4487 : }
4488 : }
4489 :
4490 : } // end loop over edges in NS2
4491 :
4492 20760 : NV3 = NVOUT;
4493 :
4494 20760 : if (NV3 < 3) { // Determine overlap status
4495 6406 : state.dataSolarShading->OverlapStatus = NoOverlap;
4496 14354 : } else if (!INTFLAG) {
4497 1557 : state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
4498 : }
4499 : }
4500 :
4501 5346 : void MULTOL(EnergyPlusData &state,
4502 : int const NNN, // argument
4503 : int const LOC0, // Location in the homogeneous coordinate array
4504 : int const NRFIGS // Number of figures overlapped
4505 : )
4506 : {
4507 :
4508 : // SUBROUTINE INFORMATION:
4509 : // AUTHOR Legacy Code
4510 : // DATE WRITTEN
4511 : // MODIFIED na
4512 : // RE-ENGINEERED Lawrie, Oct 2000
4513 :
4514 : // PURPOSE OF THIS SUBROUTINE:
4515 : // This subroutine determines the overlaps of figure 'NS2' with previous figures
4516 : // 'LOC0+1' through 'LOC0+NRFIGS'. For example, if NS2
4517 : // is a shadow, overlap with previous shadows.
4518 :
4519 : // REFERENCES:
4520 : // BLAST/IBLAST code, original author George Walton
4521 :
4522 : int I; // Loop Control
4523 : int NS1; // Number of the figure being overlapped
4524 : int NS2; // Number of the figure doing overlapping
4525 : int NS3; // Location to place results of overlap
4526 :
4527 5346 : state.dataSolarShading->maxNumberOfFigures = max(state.dataSolarShading->maxNumberOfFigures, NRFIGS);
4528 :
4529 5346 : NS2 = NNN;
4530 12252 : for (I = 1; I <= NRFIGS; ++I) {
4531 6906 : NS1 = LOC0 + I;
4532 6906 : NS3 = state.dataSolarShading->LOCHCA + 1;
4533 :
4534 6906 : DeterminePolygonOverlap(state, NS1, NS2, NS3); // Find overlap of figure NS2 on figure NS1.
4535 :
4536 : // Process overlap cases:
4537 :
4538 6906 : if (state.dataSolarShading->OverlapStatus == NoOverlap) {
4539 1604 : continue;
4540 : }
4541 :
4542 5302 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
4543 0 : break;
4544 : }
4545 :
4546 5302 : state.dataSolarShading->LOCHCA = NS3; // Increment h.c. arrays pointer.
4547 : }
4548 5346 : }
4549 :
4550 0 : void ORDER(EnergyPlusData &state,
4551 : int const NV3, // Number of vertices of figure NS3
4552 : int const NS3 // Location to place results of overlap
4553 : )
4554 : {
4555 :
4556 : // SUBROUTINE INFORMATION:
4557 : // AUTHOR Legacy Code
4558 : // DATE WRITTEN
4559 : // MODIFIED na
4560 : // RE-ENGINEERED Lawrie, Oct 2000
4561 :
4562 : // PURPOSE OF THIS SUBROUTINE:
4563 : // This subroutine sorts the vertices found by inclosure and
4564 : // intercept in to clockwise order so that the overlap polygon
4565 : // may be used in computing subsequent overlaps.
4566 :
4567 : // METHODOLOGY EMPLOYED:
4568 : // The slopes of the lines from the left-most vertex to all
4569 : // others are found. The slopes are sorted into descending
4570 : // sequence. This sequence puts the vertices in clockwise order.
4571 :
4572 : // REFERENCES:
4573 : // BLAST/IBLAST code, original author George Walton
4574 :
4575 : Real64 DELTAX; // Difference between X coordinates of two vertices
4576 : Real64 DELTAY; // Difference between Y coordinates of two vertices
4577 : Real64 SAVES; // Temporary location for exchange of variables
4578 : Real64 SAVEX; // Temporary location for exchange of variables
4579 : Real64 SAVEY; // Temporary location for exchange of variables
4580 : Real64 XMIN; // X coordinate of left-most vertex
4581 : Real64 YXMIN;
4582 : int I; // Sort index
4583 : int IM1; // Sort control
4584 : int J; // Sort index
4585 : int M; // Number of slopes to be sorted
4586 : int N; // Vertex number
4587 : int P; // Location of first slope to be sorted
4588 :
4589 0 : auto &s_surf = state.dataSurface;
4590 :
4591 0 : if (state.dataSolarShading->ORDERFirstTimeFlag) {
4592 0 : state.dataSolarShading->SLOPE.allocate(max(10, s_surf->MaxVerticesPerSurface + 1));
4593 0 : state.dataSolarShading->ORDERFirstTimeFlag = false;
4594 : }
4595 : // Determine left-most vertex.
4596 :
4597 0 : XMIN = state.dataSolarShading->XTEMP(1);
4598 0 : YXMIN = state.dataSolarShading->YTEMP(1);
4599 0 : for (N = 2; N <= NV3; ++N) {
4600 0 : if (state.dataSolarShading->XTEMP(N) >= XMIN) {
4601 0 : continue;
4602 : }
4603 0 : XMIN = state.dataSolarShading->XTEMP(N);
4604 0 : YXMIN = state.dataSolarShading->YTEMP(N);
4605 : }
4606 :
4607 : // Determine slopes from left-most vertex to all others. Identify
4608 : // first and second or last points as they occur.
4609 :
4610 0 : P = 1;
4611 0 : M = 0;
4612 0 : for (N = 1; N <= NV3; ++N) {
4613 :
4614 0 : DELTAX = state.dataSolarShading->XTEMP(N) - XMIN;
4615 0 : DELTAY = state.dataSolarShading->YTEMP(N) - YXMIN;
4616 :
4617 0 : if (std::abs(DELTAX) > 0.5) {
4618 :
4619 0 : ++M;
4620 0 : state.dataSolarShading->SLOPE(M) = DELTAY / DELTAX;
4621 0 : state.dataSolarShading->XTEMP(M) = state.dataSolarShading->XTEMP(N);
4622 0 : state.dataSolarShading->YTEMP(M) = state.dataSolarShading->YTEMP(N);
4623 :
4624 0 : } else if (DELTAY > 0.5) {
4625 :
4626 0 : P = 2;
4627 0 : state.dataSolarShading->HCX(NS3, 2) = nint64(state.dataSolarShading->XTEMP(N));
4628 0 : state.dataSolarShading->HCY(NS3, 2) = nint64(state.dataSolarShading->YTEMP(N));
4629 :
4630 0 : } else if (DELTAY < -0.5) {
4631 :
4632 0 : state.dataSolarShading->HCX(NS3, NV3) = nint64(state.dataSolarShading->XTEMP(N));
4633 0 : state.dataSolarShading->HCY(NS3, NV3) = nint64(state.dataSolarShading->YTEMP(N));
4634 :
4635 : } else {
4636 :
4637 0 : state.dataSolarShading->HCX(NS3, 1) = nint64(XMIN);
4638 0 : state.dataSolarShading->HCY(NS3, 1) = nint64(YXMIN);
4639 : }
4640 : }
4641 :
4642 : // Sequence the temporary arrays in order of decreasing slopes.(bubble sort)
4643 :
4644 0 : if (M != 1) {
4645 :
4646 0 : for (I = 2; I <= M; ++I) {
4647 0 : IM1 = I - 1;
4648 0 : for (J = 1; J <= IM1; ++J) {
4649 0 : if (state.dataSolarShading->SLOPE(I) <= state.dataSolarShading->SLOPE(J)) {
4650 0 : continue;
4651 : }
4652 0 : SAVEX = state.dataSolarShading->XTEMP(I);
4653 0 : SAVEY = state.dataSolarShading->YTEMP(I);
4654 0 : SAVES = state.dataSolarShading->SLOPE(I);
4655 0 : state.dataSolarShading->XTEMP(I) = state.dataSolarShading->XTEMP(J);
4656 0 : state.dataSolarShading->YTEMP(I) = state.dataSolarShading->YTEMP(J);
4657 0 : state.dataSolarShading->SLOPE(I) = state.dataSolarShading->SLOPE(J);
4658 0 : state.dataSolarShading->XTEMP(J) = SAVEX;
4659 0 : state.dataSolarShading->YTEMP(J) = SAVEY;
4660 0 : state.dataSolarShading->SLOPE(J) = SAVES;
4661 : }
4662 : }
4663 : }
4664 :
4665 : // Place sequenced points in the homogeneous coordinate arrays.
4666 :
4667 0 : for (N = 1; N <= M; ++N) {
4668 0 : state.dataSolarShading->HCX(NS3, N + P) = nint64(state.dataSolarShading->XTEMP(N));
4669 0 : state.dataSolarShading->HCY(NS3, N + P) = nint64(state.dataSolarShading->YTEMP(N));
4670 : }
4671 0 : }
4672 :
4673 20917 : void DeterminePolygonOverlap(EnergyPlusData &state,
4674 : int const NS1, // Number of the figure being overlapped
4675 : int const NS2, // Number of the figure doing overlapping
4676 : int const NS3 // Location to place results of overlap
4677 : )
4678 : {
4679 :
4680 : // SUBROUTINE INFORMATION:
4681 : // AUTHOR Legacy Code
4682 : // RE-ENGINEERED Lawrie, Oct 2000
4683 :
4684 : // PURPOSE OF THIS SUBROUTINE:
4685 : // This subroutine computes the possible overlap of two polygons.
4686 : // It uses homogeneous coordinate techniques to determine the overlap area
4687 : // between two convex polygons. Results are stored in the homogeneous coordinate (HC) arrays.
4688 :
4689 : // METHODOLOGY EMPLOYED:
4690 : // The vertices defining the overlap between fig.1 and fig.2
4691 : // consist of: the vertices of fig.1 enclosed by fig.2 (A)
4692 : // plus the vertices of fig.2 enclosed by fig.1 (B)
4693 : // plus the intercepts of fig.1 and fig.2 (C & D)
4694 :
4695 : // +----------------------+
4696 : // ! !
4697 : // ! FIG.2 !
4698 : // ! !
4699 : // +--------------C----------A !
4700 : // ! ! / !
4701 : // ! ! / !
4702 : // ! B-------D--------------+
4703 : // ! FIG.1 /
4704 : // ! /
4705 : // +-------------------+
4706 :
4707 : // REFERENCES:
4708 : // BLAST/IBLAST code, original author George Walton
4709 :
4710 : #ifdef EP_Count_Calls
4711 : ++state.dataTimingsData->NumDetPolyOverlap_Calls;
4712 : #endif
4713 :
4714 : // Check for exceeding array limits.
4715 20917 : if (NS3 > state.dataSolarShading->MaxHCS) {
4716 :
4717 0 : state.dataSolarShading->OverlapStatus = TooManyFigures;
4718 :
4719 0 : if (!state.dataSolarShading->TooManyFiguresMessage && !state.dataGlobal->DisplayExtraWarnings) {
4720 0 : ShowWarningError(state,
4721 0 : format("DeterminePolygonOverlap: Too many figures [>{}] detected in an overlap calculation. Use "
4722 : "Output:Diagnostics,DisplayExtraWarnings; for more details.",
4723 0 : state.dataSolarShading->MaxHCS));
4724 0 : state.dataSolarShading->TooManyFiguresMessage = true;
4725 : }
4726 :
4727 0 : if (state.dataGlobal->DisplayExtraWarnings) {
4728 0 : state.dataSolarShading->TrackTooManyFigures.redimension(++state.dataSolarShading->NumTooManyFigures);
4729 0 : state.dataSolarShading->TrackTooManyFigures(state.dataSolarShading->NumTooManyFigures).SurfIndex1 =
4730 0 : state.dataSolarShading->CurrentShadowingSurface;
4731 0 : state.dataSolarShading->TrackTooManyFigures(state.dataSolarShading->NumTooManyFigures).SurfIndex2 =
4732 0 : state.dataSolarShading->CurrentSurfaceBeingShadowed;
4733 : }
4734 :
4735 0 : return;
4736 : }
4737 :
4738 20917 : state.dataSolarShading->OverlapStatus = PartialOverlap;
4739 20917 : int NV1 = state.dataSolarShading->HCNV(NS1); // Number of vertices of figure NS1
4740 20917 : int NV2 = state.dataSolarShading->HCNV(NS2); // Number of vertices of figure NS2
4741 20917 : int NV3 = 0; // Number of vertices of figure NS3 (the overlap of NS1 and NS2)
4742 20917 : int NIN1 = 0; // Number of vertices of NS1 within NS2
4743 20917 : int NIN2 = 0; // Number of vertices of NS2 within NS1
4744 :
4745 20917 : if (!state.dataSysVars->SutherlandHodgman) {
4746 0 : INCLOS(state, NS1, NV1, NS2, NV2, NV3, NIN1); // Find vertices of NS1 within NS2.
4747 :
4748 0 : if (NIN1 >= NV1) {
4749 :
4750 0 : state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
4751 :
4752 : } else {
4753 :
4754 0 : INCLOS(state, NS2, NV2, NS1, NV1, NV3, NIN2); // Find vertices of NS2 within NS1.
4755 :
4756 0 : if (NIN2 >= NV2) {
4757 :
4758 0 : state.dataSolarShading->OverlapStatus = SecondSurfWithinFirst;
4759 :
4760 : } else {
4761 :
4762 0 : INTCPT(state, NV1, NV2, NV3, NS1, NS2); // Find intercepts of NS1 & NS2.
4763 :
4764 0 : if (NV3 < 3) { // Overlap must have 3 or more vertices
4765 0 : state.dataSolarShading->OverlapStatus = NoOverlap;
4766 0 : return;
4767 : }
4768 : }
4769 : }
4770 :
4771 : } else {
4772 : // simple polygon clipping
4773 20917 : CLIPPOLY(state, NS1, NS2, NV1, NV2, NV3);
4774 : }
4775 :
4776 20917 : if (NV3 < state.dataSolarShading->MaxHCV) {
4777 :
4778 20917 : if (!state.dataSysVars->SutherlandHodgman) {
4779 0 : ORDER(state, NV3, NS3); // Put vertices in clockwise order.
4780 : } else {
4781 20917 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
4782 20917 : int l = state.dataSolarShading->HCX.index(NS3, 1);
4783 79830 : for (int N = 1; N <= NV3; ++N, ++l) {
4784 58913 : state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XTEMP(N)); // [ l ] == ( N, NS3 )
4785 58913 : state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YTEMP(N));
4786 : }
4787 : }
4788 :
4789 20917 : HTRANS0(state, NS3, NV3); // Determine h.c. values of sides.
4790 : // Skip overlaps of negligible area.
4791 :
4792 20917 : if (std::abs(state.dataSolarShading->HCAREA(NS3)) * HCMULT < std::abs(state.dataSolarShading->HCAREA(NS1))) {
4793 6406 : state.dataSolarShading->OverlapStatus = NoOverlap;
4794 : } else {
4795 14511 : if (state.dataSolarShading->HCAREA(NS1) * state.dataSolarShading->HCAREA(NS2) > 0.0) {
4796 2221 : state.dataSolarShading->HCAREA(NS3) = -state.dataSolarShading->HCAREA(NS3); // Determine sign of area of overlap
4797 : }
4798 14511 : Real64 const HCT_1 = state.dataSolarShading->HCT(NS1);
4799 14511 : Real64 const HCT_2 = state.dataSolarShading->HCT(NS2);
4800 14511 : if (HCT_2 == 1.0 || HCT_1 == 1.0) {
4801 13851 : state.dataSolarShading->HCT(NS3) = HCT_1 * HCT_2;
4802 : } else {
4803 : // Determine transmission of overlap which corrects for prior shadows
4804 : // The resulting transmission of overlapping shadows is HCT_1 * HCT_2
4805 : // Shadows with HCT_1 and HCT_2 have already been applied in the overlapping area
4806 : // so the correction is the difference between (HCT_1+HCT_2) and (HCT_1*HCT_2)
4807 660 : state.dataSolarShading->HCT(NS3) = (HCT_1 + HCT_2) - HCT_1 * HCT_2;
4808 : }
4809 : }
4810 :
4811 : } else {
4812 :
4813 0 : state.dataSolarShading->OverlapStatus = TooManyVertices;
4814 :
4815 0 : if (!state.dataSolarShading->TooManyVerticesMessage && !state.dataGlobal->DisplayExtraWarnings) {
4816 0 : ShowWarningError(state,
4817 0 : format("DeterminePolygonOverlap: Too many vertices [>{}] detected in an overlap calculation. Use "
4818 : "Output:Diagnostics,DisplayExtraWarnings; for more details.",
4819 0 : state.dataSolarShading->MaxHCV));
4820 0 : state.dataSolarShading->TooManyVerticesMessage = true;
4821 : }
4822 :
4823 0 : if (state.dataGlobal->DisplayExtraWarnings) {
4824 0 : state.dataSolarShading->TrackTooManyVertices.redimension(++state.dataSolarShading->NumTooManyVertices);
4825 0 : state.dataSolarShading->TrackTooManyVertices(state.dataSolarShading->NumTooManyVertices).SurfIndex1 =
4826 0 : state.dataSolarShading->CurrentShadowingSurface;
4827 0 : state.dataSolarShading->TrackTooManyVertices(state.dataSolarShading->NumTooManyVertices).SurfIndex2 =
4828 0 : state.dataSolarShading->CurrentSurfaceBeingShadowed;
4829 : }
4830 : }
4831 : }
4832 :
4833 1838 : void CalcPerSolarBeam(EnergyPlusData &state,
4834 : Real64 const AvgEqOfTime, // Average value of Equation of Time for period
4835 : Real64 const AvgSinSolarDeclin, // Average value of Sine of Solar Declination for period
4836 : Real64 const AvgCosSolarDeclin // Average value of Cosine of Solar Declination for period
4837 : )
4838 : {
4839 :
4840 : // SUBROUTINE INFORMATION:
4841 : // AUTHOR Legacy Code
4842 : // DATE WRITTEN
4843 : // MODIFIED BG, Nov 2012 - Timestep solar. DetailedSolarTimestepIntegration
4844 : // RE-ENGINEERED Lawrie, Oct 2000
4845 :
4846 : // PURPOSE OF THIS SUBROUTINE:
4847 : // This subroutine manages computation of solar gain multipliers for beam radiation. These
4848 : // are calculated for a period of days depending on the input "Shadowing Calculations".
4849 :
4850 : // REFERENCES:
4851 : // BLAST/IBLAST code, original author George Walton
4852 :
4853 : // Using/Aliasing
4854 :
4855 : using WindowComplexManager::InitComplexWindows;
4856 : using WindowComplexManager::UpdateComplexWindows;
4857 :
4858 : int iHour; // Hour index number
4859 : int TS; // TimeStep Loop Countergit
4860 :
4861 1838 : auto &s_surf = state.dataSurface;
4862 :
4863 1838 : if (state.dataSolarShading->InitComplexOnce) {
4864 106 : InitComplexWindows(state);
4865 : }
4866 1838 : state.dataSolarShading->InitComplexOnce = false;
4867 :
4868 1838 : if (state.dataGlobal->KickOffSizing || state.dataGlobal->KickOffSimulation) {
4869 262 : return; // Skip solar calcs for these Initialization steps.
4870 : }
4871 :
4872 : #ifdef EP_Count_Calls
4873 : ++state.dataTimingsData->NumCalcPerSolBeam_Calls;
4874 : #endif
4875 :
4876 : // Initialize some values for the appropriate period
4877 1576 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4878 549 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
4879 685 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
4880 359 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
4881 359 : int firstSurf = thisSpace.OpaqOrIntMassSurfaceFirst;
4882 359 : int lastSurf = thisSpace.OpaqOrIntMassSurfaceLast;
4883 2252 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4884 1893 : s_surf->SurfOpaqAO(surfNum) = 0.0;
4885 : }
4886 359 : firstSurf = thisSpace.HTSurfaceFirst;
4887 359 : lastSurf = thisSpace.HTSurfaceLast;
4888 2363 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4889 2004 : state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
4890 : }
4891 8975 : for (int hour = 1; hour <= 24; ++hour) {
4892 56712 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4893 48096 : state.dataHeatBal->SurfSunlitFracHR(hour, surfNum) = 0.0;
4894 48096 : state.dataHeatBal->SurfCosIncAngHR(hour, surfNum) = 0.0;
4895 : }
4896 : }
4897 8975 : for (int hour = 1; hour <= 24; ++hour) {
4898 53784 : for (int timestep = 1; timestep <= state.dataGlobal->TimeStepsInHour; ++timestep) {
4899 294648 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4900 249480 : state.dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum) = 0.0;
4901 249480 : state.dataHeatBal->SurfCosIncAng(hour, timestep, surfNum) = 0.0;
4902 249480 : state.dataHeatBal->SurfSunlitFracWithoutReveal(hour, timestep, surfNum) = 0.0;
4903 : }
4904 : }
4905 : }
4906 8975 : for (int hour = 1; hour <= 24; ++hour) {
4907 53784 : for (int timestep = 1; timestep <= state.dataGlobal->TimeStepsInHour; ++timestep) {
4908 948528 : for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
4909 5892960 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4910 4989600 : state.dataHeatBal->SurfWinBackSurfaces(hour, timestep, backSurfNum, surfNum) = 0.0;
4911 4989600 : state.dataHeatBal->SurfWinOverlapAreas(hour, timestep, backSurfNum, surfNum) = 0.0;
4912 : }
4913 : }
4914 : } // for (timestep)
4915 : } // for (hour)
4916 326 : } // for (spaceNum)
4917 : } // for (zoneNum)
4918 :
4919 2270 : for (auto &e : s_surf->SurfaceWindow) {
4920 2047 : std::fill(e.OutProjSLFracMult.begin(), e.OutProjSLFracMult.end(), 1.0);
4921 2047 : std::fill(e.InOutProjSLFracMult.begin(), e.InOutProjSLFracMult.end(), 1.0);
4922 223 : }
4923 : } else {
4924 2705 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
4925 2704 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
4926 1352 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
4927 1352 : int const firstSurf = thisSpace.HTSurfaceFirst;
4928 1352 : int const lastSurf = thisSpace.HTSurfaceLast;
4929 5418 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4930 4066 : state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
4931 4066 : s_surf->SurfOpaqAO(surfNum) = 0.0;
4932 4066 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
4933 4066 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
4934 4066 : state.dataHeatBal->SurfSunlitFracHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
4935 4066 : state.dataHeatBal->SurfCosIncAngHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
4936 4066 : state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
4937 : }
4938 28392 : for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
4939 108360 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4940 81320 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0;
4941 81320 : state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0.0;
4942 : }
4943 : }
4944 1352 : }
4945 : }
4946 :
4947 5434 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
4948 4081 : s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;
4949 4081 : s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;
4950 : }
4951 : }
4952 :
4953 1576 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4954 5575 : for (iHour = 1; iHour <= 24; ++iHour) { // Do for all hours
4955 34560 : for (TS = 1; TS <= state.dataGlobal->TimeStepsInHour; ++TS) {
4956 29208 : FigureSunCosines(state, iHour, TS, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
4957 : }
4958 : }
4959 : } else {
4960 1353 : FigureSunCosines(state, state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
4961 : }
4962 : // Initialize/update the Complex Fenestration geometry and optical properties
4963 1576 : UpdateComplexWindows(state);
4964 1576 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4965 5575 : for (iHour = 1; iHour <= 24; ++iHour) { // Do for all hours.
4966 34560 : for (TS = 1; TS <= state.dataGlobal->TimeStepsInHour; ++TS) {
4967 29208 : FigureSolarBeamAtTimestep(state, iHour, TS);
4968 : } // TimeStep Loop
4969 : } // Hour Loop
4970 : } else {
4971 1353 : FigureSolarBeamAtTimestep(state, state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
4972 : }
4973 : }
4974 :
4975 30561 : void FigureSunCosines(EnergyPlusData &state,
4976 : int const iHour,
4977 : int const iTimeStep,
4978 : Real64 const EqOfTime, // value of Equation of Time for period
4979 : Real64 const SinSolarDeclin, // value of Sine of Solar Declination for period
4980 : Real64 const CosSolarDeclin // value of Cosine of Solar Declination for period
4981 : )
4982 : {
4983 :
4984 : // SUBROUTINE INFORMATION:
4985 : // AUTHOR B. Griffith
4986 : // DATE WRITTEN October 2012
4987 : // MODIFIED na
4988 : // RE-ENGINEERED na
4989 :
4990 : // PURPOSE OF THIS SUBROUTINE:
4991 : // Determine solar position. Default for sun below horizon.
4992 :
4993 : // METHODOLOGY EMPLOYED:
4994 : // Given hour, timestep, equation of time, solar declination sine, and solar declination cosine,
4995 : // determine sun directions for use elsewhere
4996 :
4997 : // Using/Aliasing
4998 :
4999 : Real64 CurrentTime; // Current Time for passing to Solar Position Routine
5000 :
5001 30561 : auto &s_surf = state.dataSurface;
5002 :
5003 30561 : if (state.dataGlobal->TimeStepsInHour != 1) {
5004 30249 : CurrentTime = double(iHour - 1) + double(iTimeStep) * (state.dataGlobal->TimeStepZone);
5005 : } else {
5006 312 : CurrentTime = double(iHour) + state.dataEnvrn->TS1TimeOffset;
5007 : }
5008 30561 : SUN4(state, CurrentTime, EqOfTime, SinSolarDeclin, CosSolarDeclin);
5009 :
5010 : // Save hourly values for use in DaylightingManager
5011 30561 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
5012 29208 : if (iTimeStep == state.dataGlobal->TimeStepsInHour) {
5013 5328 : s_surf->SurfSunCosHourly(iHour) = state.dataSolarShading->SUNCOS;
5014 : }
5015 : } else {
5016 1353 : s_surf->SurfSunCosHourly(iHour) = state.dataSolarShading->SUNCOS;
5017 : }
5018 : // Save timestep values for use in WindowComplexManager
5019 30561 : state.dataBSDFWindow->SUNCOSTS(iTimeStep, iHour) = state.dataSolarShading->SUNCOS;
5020 30561 : }
5021 :
5022 30582 : void FigureSolarBeamAtTimestep(EnergyPlusData &state, int const iHour, int const iTimeStep)
5023 : {
5024 :
5025 : // SUBROUTINE INFORMATION:
5026 : // AUTHOR B.Griffith, derived from CalcPerSolarBeam, Legacy and Lawrie.
5027 : // DATE WRITTEN October 2012
5028 : // MODIFIED na
5029 : // RE-ENGINEERED na
5030 :
5031 : // PURPOSE OF THIS SUBROUTINE:
5032 : // This subroutine computes solar gain multipliers for beam solar
5033 :
5034 : using DataSystemVariables::ShadingMethod;
5035 :
5036 : Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
5037 : Real64 Fac1WoShdg; // Intermediate calculation factor, without shading
5038 : Real64 Fac1WithShdg; // Intermediate calculation factor, with shading
5039 : Real64 FracIlluminated; // Fraction of surface area illuminated by a sky patch
5040 :
5041 30582 : auto &s_surf = state.dataSurface;
5042 :
5043 : // Recover the sun direction from the array stored in previous loop
5044 30582 : state.dataSolarShading->SUNCOS = state.dataBSDFWindow->SUNCOSTS(iTimeStep, iHour);
5045 :
5046 30582 : state.dataSolarShading->SurfSunCosTheta = 0.0;
5047 :
5048 30582 : if (state.dataSolarShading->SUNCOS(3) < DataEnvironment::SunIsUpValue) {
5049 15503 : return;
5050 : }
5051 :
5052 143972 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
5053 257786 : state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
5054 128893 : state.dataSolarShading->SUNCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
5055 128893 : state.dataSolarShading->SUNCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
5056 128893 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
5057 127181 : if (iTimeStep == state.dataGlobal->TimeStepsInHour) {
5058 24518 : state.dataHeatBal->SurfCosIncAngHR(iHour, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
5059 : }
5060 : } else {
5061 1712 : state.dataHeatBal->SurfCosIncAngHR(iHour, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
5062 : }
5063 128893 : state.dataHeatBal->SurfCosIncAng(iHour, iTimeStep, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
5064 : }
5065 :
5066 30157 : if ((state.dataSysVars->shadingMethod == ShadingMethod::Scheduled || state.dataSysVars->shadingMethod == ShadingMethod::Imported) &&
5067 30157 : !state.dataGlobal->DoingSizing && state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather) {
5068 10 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
5069 9 : auto &surf = s_surf->Surface(SurfNum);
5070 9 : if (surf.SurfSchedExternalShadingFrac) {
5071 1 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = surf.surfExternalShadingSched->getHrTsVal(state, iHour, iTimeStep);
5072 : } else {
5073 8 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 1.0;
5074 : }
5075 : }
5076 : } else {
5077 15078 : SHADOW(state, iHour, iTimeStep); // Determine sunlit areas and solar multipliers for all surfaces.
5078 143962 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
5079 128884 : if (s_surf->Surface(SurfNum).Area >= 1.e-10) {
5080 128884 : SurfArea = s_surf->Surface(SurfNum).NetAreaShadowCalc;
5081 128884 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
5082 127172 : if (iTimeStep == state.dataGlobal->TimeStepsInHour) {
5083 24518 : state.dataHeatBal->SurfSunlitFracHR(iHour, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
5084 : }
5085 : } else {
5086 1712 : state.dataHeatBal->SurfSunlitFracHR(iHour, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
5087 : }
5088 128884 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
5089 128884 : if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) < 1.e-5) {
5090 84982 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 0.0;
5091 : }
5092 : }
5093 : // Added check
5094 128884 : if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) > 1.0) {
5095 0 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 1.0;
5096 : }
5097 : }
5098 : }
5099 : // Note -- if not the below, values are set in SkyDifSolarShading routine (constant for simulation)
5100 15096 : if (state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
5101 17 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
5102 148 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
5103 131 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) = 0.;
5104 131 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) = 0.;
5105 131 : state.dataSolarShading->SurfWithShdgHoriz(SurfNum) = 0.;
5106 131 : state.dataSolarShading->SurfWoShdgHoriz(SurfNum) = 0.;
5107 : }
5108 :
5109 119 : for (int IPhi = 0; IPhi < NPhi; ++IPhi) { // Loop over patch altitude values
5110 102 : state.dataSolarShading->SUNCOS(3) = state.dataSolarShading->sin_Phi[IPhi];
5111 :
5112 2550 : for (int ITheta = 0; ITheta < NTheta; ++ITheta) { // Loop over patch azimuth values
5113 2448 : state.dataSolarShading->SUNCOS(1) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->cos_Theta[ITheta];
5114 2448 : state.dataSolarShading->SUNCOS(2) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->sin_Theta[ITheta];
5115 :
5116 21312 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
5117 37728 : state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
5118 18864 : state.dataSolarShading->SUNCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
5119 18864 : state.dataSolarShading->SUNCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
5120 2448 : }
5121 :
5122 2448 : SHADOW(state, iHour, iTimeStep); // Determine sunlit areas and solar multipliers for all surfaces.
5123 :
5124 21312 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
5125 :
5126 18864 : if (state.dataSolarShading->SurfSunCosTheta(SurfNum) < 0.0) {
5127 10338 : continue;
5128 : }
5129 :
5130 8526 : Fac1WoShdg = state.dataSolarShading->cos_Phi[IPhi] * DThetaDPhi * state.dataSolarShading->SurfSunCosTheta(SurfNum);
5131 8526 : SurfArea = s_surf->Surface(SurfNum).NetAreaShadowCalc;
5132 8526 : if (SurfArea > Eps) {
5133 8526 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
5134 : } else {
5135 0 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / (SurfArea + Eps);
5136 : }
5137 8526 : Fac1WithShdg = Fac1WoShdg * FracIlluminated;
5138 8526 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) += Fac1WithShdg;
5139 8526 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) += Fac1WoShdg;
5140 :
5141 : // Horizon region
5142 8526 : if (IPhi == 0) {
5143 1421 : state.dataSolarShading->SurfWithShdgHoriz(SurfNum) += Fac1WithShdg;
5144 1421 : state.dataSolarShading->SurfWoShdgHoriz(SurfNum) += Fac1WoShdg;
5145 : }
5146 2448 : } // End of surface loop
5147 : } // End of Theta loop
5148 : } // End of Phi loop
5149 :
5150 148 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
5151 : // Original conditions:
5152 : // if (!s_surf->Surface(SurfNum).IsShadowing &&
5153 : // (!s_surf->Surface(SurfNum).HeatTransSurf || !s_surf->Surface(SurfNum).ExtSolar))
5154 : // continue;
5155 :
5156 131 : if (std::abs(state.dataSolarShading->SurfWoShdgIsoSky(SurfNum)) > Eps) {
5157 95 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(iTimeStep, iHour, SurfNum) =
5158 95 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum));
5159 : } else {
5160 36 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(iTimeStep, iHour, SurfNum) =
5161 36 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) + Eps);
5162 : }
5163 131 : if (std::abs(state.dataSolarShading->SurfWoShdgHoriz(SurfNum)) > Eps) {
5164 95 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS(iTimeStep, iHour, SurfNum) =
5165 95 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum));
5166 : } else {
5167 36 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS(iTimeStep, iHour, SurfNum) =
5168 36 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum) + Eps);
5169 : }
5170 17 : }
5171 :
5172 : // ! Get IR view factors. An exterior surface can receive IR radiation from
5173 : // ! sky, ground or shadowing surfaces. Assume shadowing surfaces have same
5174 : // ! temperature as outside air (and therefore same temperature as ground),
5175 : // ! so that the view factor to these shadowing surfaces can be included in
5176 : // ! the ground view factor. Sky IR is assumed to be isotropic and shadowing
5177 : // ! surfaces are assumed to be opaque to IR so they totally "shade" IR from
5178 : // ! sky or ground.
5179 :
5180 : // DO SurfNum = 1,TotSurfaces
5181 : // Surface(SurfNum)%ViewFactorSkyIR = Surface(SurfNum)%ViewFactorSkyIR * DifShdgRatioIsoSky(SurfNum,IHOUR,TS)
5182 : // Surface(SurfNum)%ViewFactorGroundIR = 1.0 - Surface(SurfNum)%ViewFactorSkyIR
5183 : // END DO
5184 :
5185 : } // test for shading surfaces
5186 :
5187 15102 : for (int SurfNum : s_surf->AllExtSolWinWithFrameSurfaceList) {
5188 : // For exterior windows with frame/divider that are partially or fully sunlit,
5189 : // correct SunlitFrac due to shadowing of frame and divider projections onto window glass.
5190 : // Note: if SunlitFrac = 0.0 the window is either completely shaded or the sun is in back
5191 : // of the window; in either case, frame/divider shadowing doesn't have to be done.
5192 :
5193 23 : if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) > 0.0) {
5194 17 : CalcFrameDividerShadow(state, SurfNum, s_surf->Surface(SurfNum).FrameDivider, iHour);
5195 : }
5196 15079 : }
5197 : }
5198 :
5199 133 : void DetermineShadowingCombinations(EnergyPlusData &state)
5200 : {
5201 :
5202 : // SUBROUTINE INFORMATION:
5203 : // AUTHOR From Legacy Code
5204 : // DATE WRITTEN
5205 : // MODIFIED LKL; March 2002 -- another missing translation from BLAST's routine
5206 : // FCW; Jan 2003 -- removed line that prevented beam solar through interior windows
5207 : // RE-ENGINEERED Rick Strand; 1998
5208 : // Linda Lawrie; Oct 2000
5209 :
5210 : // PURPOSE OF THIS SUBROUTINE:
5211 : // This routine prepares a list of heat transfer surfaces and
5212 : // their possible shadowers which is used to direct the hourly
5213 : // calculation of shadows and sunlit areas.
5214 :
5215 : // METHODOLOGY EMPLOYED:
5216 : // As appropriate surfaces are identified, they are placed into the
5217 : // ShadowComb data structure (module level) with the accompanying lists
5218 : // of other surface numbers.
5219 :
5220 : // REFERENCES:
5221 : // BLAST/IBLAST code, original author George Walton
5222 :
5223 : // Using/Aliasing
5224 : using namespace DataErrorTracking;
5225 :
5226 133 : Array1D_int GSS; // List of shadowing surfaces numbers for a receiving surface
5227 133 : Array1D_int BKS; // List of back surface numbers for a receiving surface
5228 133 : Array1D_int SBS; // List of subsurfaces for a receiving surface
5229 : bool CannotShade; // TRUE if subsurface cannot shade receiving surface
5230 : bool HasWindow; // TRUE if a window is present on receiving surface
5231 : Real64 ZMIN; // Lowest point on the receiving surface
5232 : int BackSurfaceNumber; // Back surface number
5233 : int HTS; // Heat transfer surface number for a receiving surface
5234 : int GRSNR; // Receiving surface number
5235 : int GSSNR; // Shadowing surface number
5236 : int SBSNR; // Subsurface number
5237 : int NBKS; // Number of back surfaces for a receiving surface
5238 : int NGSS; // Number of shadowing surfaces for a receiving surface
5239 : int NSBS; // Number of subsurfaces for a receiving surface
5240 : bool ShadowingSurf; // True if a receiving surface is a shadowing surface
5241 133 : Array1D_bool CastingSurface; // tracking during setup of ShadowComb
5242 :
5243 133 : auto &s_surf = state.dataSurface;
5244 :
5245 : #ifdef EP_Count_Calls
5246 : ++state.dataTimingsData->NumDetShadowCombs_Calls;
5247 : #endif
5248 :
5249 133 : state.dataShadowComb->ShadowComb.dimension(s_surf->TotSurfaces, ShadowingCombinations{}); // Set all elements to default constructed state
5250 :
5251 133 : CastingSurface.dimension(s_surf->TotSurfaces, false);
5252 :
5253 133 : state.dataSolarShading->HCA.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5254 133 : state.dataSolarShading->HCB.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5255 133 : state.dataSolarShading->HCC.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5256 133 : state.dataSolarShading->HCX.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5257 133 : state.dataSolarShading->HCY.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5258 133 : state.dataSolarShading->HCAREA.dimension(2 * state.dataSolarShading->MaxHCS, 0.0);
5259 133 : state.dataSolarShading->HCNS.dimension(2 * state.dataSolarShading->MaxHCS, 0);
5260 133 : state.dataSolarShading->HCNV.dimension(2 * state.dataSolarShading->MaxHCS, 0);
5261 133 : state.dataSolarShading->HCT.dimension(2 * state.dataSolarShading->MaxHCS, 0.0);
5262 :
5263 133 : GSS.dimension(state.dataSolarShading->MaxGSS, 0);
5264 133 : BKS.dimension(state.dataSolarShading->MaxGSS, 0);
5265 133 : SBS.dimension(state.dataSolarShading->MaxGSS, 0);
5266 :
5267 133 : state.dataSolarShading->penumbraIDs.clear();
5268 :
5269 133 : HTS = 0;
5270 :
5271 : // Check every surface as a possible shadow receiving surface ("RS" = receiving surface).
5272 133 : if (state.dataEnvrn->IgnoreSolarRadiation) {
5273 0 : return;
5274 : }
5275 :
5276 1108 : for (GRSNR = 1; GRSNR <= s_surf->TotSurfaces; ++GRSNR) { // Loop through all surfaces (looking for potential receiving surfaces)...
5277 :
5278 975 : ShadowingSurf = s_surf->Surface(GRSNR).IsShadowing;
5279 975 : NGSS = 0;
5280 975 : NSBS = 0;
5281 975 : NBKS = 0;
5282 :
5283 975 : if (!ShadowingSurf && !s_surf->Surface(GRSNR).HeatTransSurf) {
5284 2 : continue;
5285 : }
5286 973 : HTS = GRSNR;
5287 :
5288 : #ifndef EP_NO_OPENGL
5289 973 : if (state.dataSolarShading->penumbra) {
5290 0 : bool skipSurface = s_surf->Surface(GRSNR).MirroredSurf;
5291 : // Penumbra doesn't need mirrored surfaces TODO: Don't bother creating them in the first place?
5292 :
5293 : // Skip interior surfaces if the other side has already been added to penumbra
5294 0 : if (s_surf->Surface(GRSNR).ExtBoundCond > 0) {
5295 0 : if (s_surf->SurfPenumbraID(s_surf->Surface(GRSNR).ExtBoundCond) >= 0) {
5296 0 : s_surf->SurfPenumbraID(GRSNR) = s_surf->SurfPenumbraID(s_surf->Surface(GRSNR).ExtBoundCond);
5297 0 : skipSurface = true;
5298 : }
5299 : }
5300 :
5301 0 : if (!skipSurface) {
5302 : // Add surfaces to penumbra...
5303 0 : Penumbra::Polygon poly;
5304 :
5305 0 : if (s_surf->Surface(GRSNR).Reveal > 0.0) {
5306 0 : Real64 R = s_surf->Surface(GRSNR).Reveal;
5307 0 : auto &norm = s_surf->Surface(GRSNR).NewellSurfaceNormalVector;
5308 0 : auto &v = s_surf->Surface(GRSNR).Vertex;
5309 0 : for (unsigned i = 0; i < v.size(); ++i) {
5310 0 : poly.push_back(v[i].x);
5311 0 : poly.push_back(v[i].y);
5312 0 : poly.push_back(v[i].z);
5313 :
5314 0 : Vector vPrev;
5315 0 : if (i == 0) {
5316 0 : vPrev = v[v.size() - 1];
5317 : } else {
5318 0 : vPrev = v[i - 1];
5319 : }
5320 :
5321 0 : Penumbra::Polygon rPoly; // Reveal surface
5322 0 : rPoly.push_back(v[i].x);
5323 0 : rPoly.push_back(v[i].y);
5324 0 : rPoly.push_back(v[i].z);
5325 :
5326 0 : rPoly.push_back(v[i].x + norm.x * R);
5327 0 : rPoly.push_back(v[i].y + norm.y * R);
5328 0 : rPoly.push_back(v[i].z + norm.z * R);
5329 :
5330 0 : rPoly.push_back(vPrev.x + norm.x * R);
5331 0 : rPoly.push_back(vPrev.y + norm.y * R);
5332 0 : rPoly.push_back(vPrev.z + norm.z * R);
5333 :
5334 0 : rPoly.push_back(vPrev.x);
5335 0 : rPoly.push_back(vPrev.y);
5336 0 : rPoly.push_back(vPrev.z);
5337 :
5338 0 : Penumbra::Surface rSurf(rPoly, fmt::format("{} reveal {}", s_surf->Surface(GRSNR).Name, i));
5339 0 : state.dataSolarShading->penumbra->add_surface(rSurf);
5340 0 : }
5341 : } else {
5342 0 : for (auto const &v : s_surf->Surface(GRSNR).Vertex) {
5343 0 : poly.push_back(v.x);
5344 0 : poly.push_back(v.y);
5345 0 : poly.push_back(v.z);
5346 : }
5347 : }
5348 0 : Penumbra::Surface pSurf(poly, s_surf->Surface(GRSNR).Name);
5349 :
5350 : // Punch holes for subsurfaces
5351 0 : if (s_surf->Surface(GRSNR).BaseSurf == GRSNR) { // Only look for subsurfaces on base surfaces
5352 0 : for (int subSurface = 1; subSurface <= s_surf->TotSurfaces; ++subSurface) {
5353 0 : if (s_surf->Surface(subSurface).BaseSurf != GRSNR) {
5354 0 : continue; // Ignore subsurfaces of other surfaces
5355 : }
5356 0 : if (!s_surf->Surface(subSurface).HeatTransSurf) {
5357 0 : continue; // Skip non heat transfer subsurfaces
5358 : }
5359 0 : if (subSurface == GRSNR) {
5360 0 : continue; // Surface itself cannot be its own subsurface
5361 : }
5362 :
5363 0 : Penumbra::Polygon subPoly;
5364 0 : if (s_surf->Surface(subSurface).Reveal > 0.0) {
5365 0 : Real64 R = s_surf->Surface(subSurface).Reveal;
5366 0 : auto &norm = s_surf->Surface(subSurface).NewellSurfaceNormalVector;
5367 0 : for (auto const &v : s_surf->Surface(subSurface).Vertex) {
5368 0 : subPoly.push_back(v.x + norm.x * R);
5369 0 : subPoly.push_back(v.y + norm.y * R);
5370 0 : subPoly.push_back(v.z + norm.z * R);
5371 : }
5372 : } else {
5373 0 : for (auto const &v : s_surf->Surface(subSurface).Vertex) {
5374 0 : subPoly.push_back(v.x);
5375 0 : subPoly.push_back(v.y);
5376 0 : subPoly.push_back(v.z);
5377 : }
5378 : }
5379 :
5380 0 : pSurf.add_hole(subPoly);
5381 0 : }
5382 : }
5383 0 : s_surf->SurfPenumbraID(GRSNR) = state.dataSolarShading->penumbra->add_surface(pSurf);
5384 0 : state.dataSolarShading->penumbraIDs.push_back(s_surf->SurfPenumbraID(GRSNR));
5385 0 : }
5386 : }
5387 : #endif
5388 :
5389 973 : if (!ShadowingSurf && !s_surf->Surface(GRSNR).ExtSolar) {
5390 302 : continue; // Skip surfaces with no external solar
5391 : }
5392 :
5393 671 : if (!ShadowingSurf && s_surf->Surface(GRSNR).BaseSurf != GRSNR) { // Skip subsurfaces (SBS)
5394 70 : continue;
5395 : }
5396 :
5397 : // Get the lowest point of receiving surface
5398 601 : ZMIN = minval(s_surf->Surface(GRSNR).Vertex, &Vector::z);
5399 :
5400 : // Check every surface as a possible shadow casting surface ("SS" = shadow sending)
5401 601 : NGSS = 0;
5402 601 : if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) { // Except when doing simplified exterior shadowing.
5403 :
5404 5485 : for (GSSNR = 1; GSSNR <= s_surf->TotSurfaces; ++GSSNR) { // Loop through all surfaces, looking for ones that could shade GRSNR
5405 :
5406 5090 : if (GSSNR == GRSNR) {
5407 395 : continue; // Receiving surface cannot shade itself
5408 : }
5409 4695 : if ((s_surf->Surface(GSSNR).HeatTransSurf) && (s_surf->Surface(GSSNR).BaseSurf == GRSNR)) {
5410 63 : continue; // A heat transfer subsurface of a receiving surface
5411 : }
5412 : // cannot shade the receiving surface
5413 4632 : if (ShadowingSurf) {
5414 : // If receiving surf is a shadowing surface exclude matching shadow surface as sending surface
5415 : // IF((GSSNR == GRSNR+1 .AND. Surface(GSSNR)%Name(1:3) == 'Mir').OR. &
5416 : // (GSSNR == GRSNR-1 .AND. Surface(GRSNR)%Name(1:3) == 'Mir')) CYCLE
5417 1817 : if (((GSSNR == GRSNR + 1) && s_surf->Surface(GSSNR).MirroredSurf) ||
5418 893 : ((GSSNR == GRSNR - 1) && s_surf->Surface(GRSNR).MirroredSurf)) {
5419 62 : continue;
5420 : }
5421 : }
5422 :
5423 4570 : if (s_surf->Surface(GSSNR).BaseSurf == GRSNR) { // Shadowing subsurface of receiving surface
5424 :
5425 0 : ++NGSS;
5426 0 : if (NGSS > state.dataSolarShading->MaxGSS) {
5427 0 : GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
5428 : }
5429 0 : GSS(NGSS) = GSSNR;
5430 :
5431 8712 : } else if ((s_surf->Surface(GSSNR).BaseSurf == 0) ||
5432 4142 : ((s_surf->Surface(GSSNR).BaseSurf == GSSNR) &&
5433 3610 : ((s_surf->Surface(GSSNR).ExtBoundCond == ExternalEnvironment) ||
5434 1472 : s_surf->Surface(GSSNR).ExtBoundCond ==
5435 : OtherSideCondModeledExt))) { // Detached shadowing surface or | any other base surface
5436 : // exposed to outside environment
5437 :
5438 2566 : CHKGSS(state, GRSNR, GSSNR, ZMIN, CannotShade); // Check to see if this can shade the receiving surface
5439 2566 : if (!CannotShade) { // Update the shadowing surface data if shading is possible
5440 126 : ++NGSS;
5441 126 : if (NGSS > state.dataSolarShading->MaxGSS) {
5442 0 : GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
5443 : }
5444 126 : GSS(NGSS) = GSSNR;
5445 : }
5446 : }
5447 :
5448 : } // ...end of surfaces DO loop (GSSNR)
5449 : } else { // Simplified Distribution -- still check for Shading Subsurfaces
5450 :
5451 1483 : for (GSSNR = 1; GSSNR <= s_surf->TotSurfaces; ++GSSNR) { // Loop through all surfaces (looking for surfaces which could shade GRSNR) ...
5452 :
5453 1277 : if (GSSNR == GRSNR) {
5454 206 : continue; // Receiving surface cannot shade itself
5455 : }
5456 1071 : if ((s_surf->Surface(GSSNR).HeatTransSurf) && (s_surf->Surface(GSSNR).BaseSurf == GRSNR)) {
5457 7 : continue; // Skip heat transfer subsurfaces of receiving surface
5458 : }
5459 1064 : if (s_surf->Surface(GSSNR).BaseSurf == GRSNR) { // Shadowing subsurface of receiving surface
5460 0 : ++NGSS;
5461 0 : if (NGSS > state.dataSolarShading->MaxGSS) {
5462 0 : GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
5463 : }
5464 0 : GSS(NGSS) = GSSNR;
5465 : }
5466 : }
5467 :
5468 : } // ...end of check for simplified solar distribution
5469 :
5470 : // Check every surface as a receiving subsurface of the receiving surface
5471 601 : NSBS = 0;
5472 601 : HasWindow = false;
5473 : // legacy: IF (OSENV(HTS) > 10) WINDOW=.TRUE. -->Note: WINDOW was set true for roof ponds, solar walls, or other zones
5474 6968 : for (SBSNR = 1; SBSNR <= s_surf->TotSurfaces; ++SBSNR) { // Loop through the surfaces yet again (looking for subsurfaces of GRSNR)...
5475 :
5476 6367 : if (!s_surf->Surface(SBSNR).HeatTransSurf) {
5477 552 : continue; // Skip non heat transfer subsurfaces
5478 : }
5479 5815 : if (SBSNR == GRSNR) {
5480 539 : continue; // Surface itself cannot be its own subsurface
5481 : }
5482 5276 : if (s_surf->Surface(SBSNR).BaseSurf != GRSNR) {
5483 5206 : continue; // Ignore subsurfaces of other surfaces and other surfaces
5484 : }
5485 :
5486 70 : if (state.dataConstruction->Construct(s_surf->Surface(SBSNR).Construction).TransDiff > 0.0) {
5487 45 : HasWindow = true; // Check for window
5488 : }
5489 70 : CHKSBS(state, HTS, GRSNR, SBSNR); // Check that the receiving surface completely encloses the subsurface;
5490 : // severe error if not
5491 70 : ++NSBS;
5492 70 : if (NSBS > state.dataSolarShading->MaxSBS) {
5493 0 : SBS.redimension(state.dataSolarShading->MaxSBS *= 2, 0);
5494 : }
5495 70 : SBS(NSBS) = SBSNR;
5496 :
5497 : } // ...end of surfaces DO loop (SBSNR)
5498 :
5499 : // Check every surface as a back surface
5500 601 : NBKS = 0;
5501 : // Except for simplified
5502 : // interior solar distribution,
5503 601 : if ((state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) &&
5504 : (HasWindow)) { // For full interior solar distribution | and a window present on base surface (GRSNR)
5505 :
5506 76 : for (BackSurfaceNumber = 1; BackSurfaceNumber <= s_surf->TotSurfaces;
5507 : ++BackSurfaceNumber) { // Loop through surfaces yet again, looking for back surfaces to GRSNR
5508 :
5509 69 : if (!s_surf->Surface(BackSurfaceNumber).HeatTransSurf) {
5510 0 : continue; // Skip non-heat transfer surfaces
5511 : }
5512 69 : if (s_surf->Surface(BackSurfaceNumber).BaseSurf == GRSNR) {
5513 14 : continue; // Skip subsurfaces of this GRSNR
5514 : }
5515 55 : if (BackSurfaceNumber == GRSNR) {
5516 0 : continue; // A back surface cannot be GRSNR itself
5517 : }
5518 55 : if (s_surf->Surface(BackSurfaceNumber).SolarEnclIndex != s_surf->Surface(GRSNR).SolarEnclIndex) {
5519 14 : continue; // Skip if back surface not in same solar enclosure
5520 : }
5521 :
5522 41 : if (s_surf->Surface(BackSurfaceNumber).Class == SurfaceClass::IntMass) {
5523 0 : continue;
5524 : }
5525 :
5526 : // Following line removed 1/27/03 by FCW. Was in original code that didn't do beam solar transmitted through
5527 : // interior windows. Was removed to allow such beam solar but then somehow was put back in.
5528 : // IF (Surface(BackSurfaceNumber)%BaseSurf /= BackSurfaceNumber) CYCLE ! Not for subsurfaces of Back Surface
5529 :
5530 41 : if (!state.dataSolarShading->penumbra) {
5531 41 : CHKBKS(state, BackSurfaceNumber, GRSNR); // CHECK FOR CONVEX ZONE; severe error if not
5532 : }
5533 41 : ++NBKS;
5534 41 : if (NBKS > state.dataSolarShading->MaxBKS) {
5535 0 : BKS.redimension(state.dataSolarShading->MaxBKS *= 2, 0);
5536 : }
5537 41 : BKS(NBKS) = BackSurfaceNumber;
5538 :
5539 : } // ...end of surfaces DO loop (BackSurfaceNumber)
5540 : }
5541 :
5542 : // Put this into the ShadowComb data structure
5543 601 : state.dataShadowComb->ShadowComb(GRSNR).UseThisSurf = true;
5544 601 : state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf = NGSS;
5545 601 : state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf = NBKS;
5546 601 : state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf = NSBS;
5547 601 : state.dataSolarShading->MaxDim = max(state.dataSolarShading->MaxDim, NGSS, NBKS, NSBS);
5548 :
5549 601 : state.dataShadowComb->ShadowComb(GRSNR).GenSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf});
5550 601 : state.dataShadowComb->ShadowComb(GRSNR).GenSurf(0) = 0;
5551 601 : if (state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf > 0) {
5552 89 : state.dataShadowComb->ShadowComb(GRSNR).GenSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf}) = GSS({1, NGSS});
5553 : }
5554 :
5555 601 : state.dataShadowComb->ShadowComb(GRSNR).BackSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf});
5556 601 : state.dataShadowComb->ShadowComb(GRSNR).BackSurf(0) = 0;
5557 601 : if (state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf > 0) {
5558 7 : state.dataShadowComb->ShadowComb(GRSNR).BackSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf}) = BKS({1, NBKS});
5559 : }
5560 :
5561 601 : state.dataShadowComb->ShadowComb(GRSNR).SubSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf});
5562 601 : state.dataShadowComb->ShadowComb(GRSNR).SubSurf(0) = 0;
5563 601 : if (state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf > 0) {
5564 65 : state.dataShadowComb->ShadowComb(GRSNR).SubSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf}) = SBS({1, NSBS});
5565 : }
5566 :
5567 : } // ...end of surfaces (GRSNR) DO loop
5568 :
5569 133 : GSS.deallocate();
5570 133 : SBS.deallocate();
5571 133 : BKS.deallocate();
5572 :
5573 133 : if (!state.dataSolarShading->penumbra) {
5574 133 : if (state.dataSolarShading->shd_stream) {
5575 114 : *state.dataSolarShading->shd_stream << "Shadowing Combinations\n";
5576 114 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
5577 41 : *state.dataSolarShading->shd_stream
5578 41 : << "..Solar Distribution=Minimal Shadowing, Detached Shading will not be used in shadowing calculations\n";
5579 73 : } else if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullExterior) {
5580 63 : if (s_surf->CalcSolRefl) {
5581 0 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullExteriorWithReflectionsFromExteriorSurfaces\n";
5582 : } else {
5583 63 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullExterior\n";
5584 : }
5585 10 : } else if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
5586 10 : if (s_surf->CalcSolRefl) {
5587 0 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullInteriorAndExteriorWithReflectionsFromExteriorSurfaces\n";
5588 : } else {
5589 10 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullInteriorAndExterior\n";
5590 : }
5591 : } else {
5592 : }
5593 :
5594 114 : *state.dataSolarShading->shd_stream << "..In the following, only the first 10 reference surfaces will be shown.\n";
5595 114 : *state.dataSolarShading->shd_stream << "..But all surfaces are used in the calculations.\n";
5596 :
5597 941 : for (int HTSnum : s_surf->AllSurfaceListReportOrder) {
5598 827 : *state.dataSolarShading->shd_stream << "==================================\n";
5599 827 : if (state.dataShadowComb->ShadowComb(HTSnum).UseThisSurf) {
5600 484 : if (s_surf->Surface(HTSnum).IsConvex) {
5601 960 : *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
5602 960 : << " is used as Receiving Surface in calculations and is convex.\n";
5603 : } else {
5604 8 : *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
5605 8 : << " is used as Receiving Surface in calculations and is non-convex.\n";
5606 4 : if (state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf > 0) {
5607 2 : if (state.dataGlobal->DisplayExtraWarnings) {
5608 0 : ShowWarningError(state,
5609 0 : format("DetermineShadowingCombinations: Surface=\"{}\" is a receiving surface and is non-convex.",
5610 0 : s_surf->Surface(HTSnum).Name));
5611 0 : ShowContinueError(state,
5612 : "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5613 : } else {
5614 2 : ++state.dataErrTracking->TotalReceivingNonConvexSurfaces;
5615 : }
5616 : }
5617 : }
5618 : } else {
5619 686 : *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
5620 686 : << " is not used as Receiving Surface in calculations.\n";
5621 : }
5622 827 : *state.dataSolarShading->shd_stream << "Number of general casting surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf
5623 827 : << '\n';
5624 904 : for (NGSS = 1; NGSS <= state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf; ++NGSS) {
5625 77 : if (NGSS <= 10) {
5626 77 : *state.dataSolarShading->shd_stream
5627 77 : << "..Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).GenSurf(NGSS)).Name << '\n';
5628 : }
5629 77 : CastingSurface(state.dataShadowComb->ShadowComb(HTSnum).GenSurf(NGSS)) = true;
5630 : }
5631 827 : *state.dataSolarShading->shd_stream << "Number of back surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumBackSurf << '\n';
5632 861 : for (NGSS = 1; NGSS <= min(10, state.dataShadowComb->ShadowComb(HTSnum).NumBackSurf); ++NGSS) {
5633 34 : *state.dataSolarShading->shd_stream
5634 34 : << "...Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).BackSurf(NGSS)).Name << '\n';
5635 : }
5636 827 : *state.dataSolarShading->shd_stream << "Number of receiving sub surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumSubSurf
5637 827 : << '\n';
5638 884 : for (NGSS = 1; NGSS <= min(10, state.dataShadowComb->ShadowComb(HTSnum).NumSubSurf); ++NGSS) {
5639 57 : *state.dataSolarShading->shd_stream
5640 57 : << "....Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).SubSurf(NGSS)).Name << '\n';
5641 : }
5642 114 : }
5643 : }
5644 :
5645 1108 : for (HTS = 1; HTS <= s_surf->TotSurfaces; ++HTS) {
5646 975 : if (CastingSurface(HTS) && !s_surf->Surface(HTS).IsConvex) {
5647 2 : if (state.dataGlobal->DisplayExtraWarnings) {
5648 0 : ShowSevereError(
5649 : state,
5650 0 : format("DetermineShadowingCombinations: Surface=\"{}\" is a casting surface and is non-convex.", s_surf->Surface(HTS).Name));
5651 0 : ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5652 : } else {
5653 2 : ++state.dataErrTracking->TotalCastingNonConvexSurfaces;
5654 : }
5655 : }
5656 : }
5657 :
5658 133 : if (state.dataErrTracking->TotalReceivingNonConvexSurfaces > 0) {
5659 6 : ShowWarningMessage(state,
5660 6 : format("DetermineShadowingCombinations: There are {} surfaces which are receiving surfaces and are non-convex.",
5661 3 : state.dataErrTracking->TotalReceivingNonConvexSurfaces));
5662 6 : ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5663 6 : ShowContinueError(state, "...Add Output:Diagnostics,DisplayExtraWarnings; to see individual warnings for each surface.");
5664 3 : state.dataErrTracking->TotalWarningErrors += state.dataErrTracking->TotalReceivingNonConvexSurfaces;
5665 : }
5666 :
5667 133 : if (state.dataErrTracking->TotalCastingNonConvexSurfaces > 0) {
5668 6 : ShowSevereMessage(state,
5669 6 : format("DetermineShadowingCombinations: There are {} surfaces which are casting surfaces and are non-convex.",
5670 3 : state.dataErrTracking->TotalCastingNonConvexSurfaces));
5671 6 : ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5672 6 : ShowContinueError(state, "...Add Output:Diagnostics,DisplayExtraWarnings; to see individual severes for each surface.");
5673 3 : state.dataErrTracking->TotalSevereErrors += state.dataErrTracking->TotalCastingNonConvexSurfaces;
5674 : }
5675 : }
5676 :
5677 133 : CastingSurface.deallocate();
5678 :
5679 : #ifndef EP_NO_OPENGL
5680 133 : if (state.dataSolarShading->penumbra && state.dataSolarShading->penumbra->get_number_of_surfaces() > 0) {
5681 0 : state.dataSolarShading->penumbra->set_model();
5682 : }
5683 : #endif
5684 133 : }
5685 :
5686 33798 : void SHADOW(EnergyPlusData &state,
5687 : int const iHour, // Hour index
5688 : int const TS // Time Step
5689 : )
5690 : {
5691 :
5692 : // SUBROUTINE INFORMATION:
5693 : // AUTHOR Legacy Code
5694 : // DATE WRITTEN
5695 : // MODIFIED Nov 2003, FCW: modify to do shadowing on shadowing surfaces
5696 : // RE-ENGINEERED Lawrie, Oct 2000
5697 :
5698 : // PURPOSE OF THIS SUBROUTINE:
5699 : // This subroutine is a driving routine for calculations of shadows
5700 : // and sunlit areas used in computing the solar beam flux multipliers.
5701 :
5702 : // REFERENCES:
5703 : // BLAST/IBLAST code, original author George Walton
5704 :
5705 : Real64 XS; // Intermediate result
5706 : Real64 YS; // Intermediate result
5707 : Real64 ZS; // Intermediate result
5708 : int N; // Vertex number
5709 : int NGRS; // Coordinate transformation index
5710 : int NVT;
5711 : int HTS; // Heat transfer surface number of the general receiving surface
5712 : int GRSNR; // Surface number of general receiving surface
5713 : int NBKS; // Number of back surfaces
5714 : int NGSS; // Number of general shadowing surfaces
5715 : int NSBS; // Number of subsurfaces (windows and doors)
5716 : Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
5717 : // For windows, includes divider area
5718 :
5719 33798 : auto &s_surf = state.dataSurface;
5720 :
5721 33798 : if (state.dataSolarShading->ShadowOneTimeFlag) {
5722 112 : state.dataSolarShading->XVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
5723 112 : state.dataSolarShading->YVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
5724 112 : state.dataSolarShading->ZVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
5725 112 : state.dataSolarShading->XVrt = 0.0;
5726 112 : state.dataSolarShading->YVrt = 0.0;
5727 112 : state.dataSolarShading->ZVrt = 0.0;
5728 112 : state.dataSolarShading->ShadowOneTimeFlag = false;
5729 : }
5730 :
5731 : #ifdef EP_Count_Calls
5732 : if (iHour == 0) {
5733 : ++state.dataTimingsData->NumShadow_Calls;
5734 : } else {
5735 : ++state.dataTimingsData->NumShadowAtTS_Calls;
5736 : }
5737 : #endif
5738 :
5739 33798 : state.dataSolarShading->SurfSunlitArea = 0.0;
5740 :
5741 : #ifndef EP_NO_OPENGL
5742 33798 : if (state.dataSolarShading->penumbra) {
5743 0 : Real64 ElevSun = Constant::PiOvr2 - std::acos(state.dataSolarShading->SUNCOS(3));
5744 0 : Real64 AzimSun = std::atan2(state.dataSolarShading->SUNCOS(1), state.dataSolarShading->SUNCOS(2));
5745 0 : state.dataSolarShading->penumbra->set_sun_position(AzimSun, ElevSun);
5746 0 : state.dataSolarShading->penumbra->submit_pssa();
5747 : }
5748 : #endif
5749 :
5750 301066 : for (GRSNR = 1; GRSNR <= s_surf->TotSurfaces; ++GRSNR) {
5751 :
5752 267268 : if (!state.dataShadowComb->ShadowComb(GRSNR).UseThisSurf) {
5753 109386 : continue;
5754 : }
5755 :
5756 157882 : state.dataSolarShading->SurfSunlitArea(GRSNR) = 0.0;
5757 :
5758 157882 : NGSS = state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf;
5759 157882 : state.dataSolarShading->NGSSHC = 0;
5760 157882 : NBKS = state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf;
5761 157882 : state.dataSolarShading->NBKSHC = 0;
5762 157882 : NSBS = state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf;
5763 157882 : state.dataSolarShading->NRVLHC = 0;
5764 157882 : state.dataSolarShading->NSBSHC = 0;
5765 157882 : state.dataSolarShading->LOCHCA = 1;
5766 : // Temporarily determine the old heat transfer surface number (HTS)
5767 157882 : HTS = GRSNR;
5768 :
5769 157882 : if (state.dataSolarShading->SurfSunCosTheta(GRSNR) < DataEnvironment::SunIsUpValue) { //.001) THEN ! Receiving surface is not in the sun
5770 :
5771 74481 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
5772 74481 : SHDSBS(state, iHour, GRSNR, NBKS, NSBS, HTS, TS);
5773 :
5774 83401 : } else if ((NGSS <= 0) && (NSBS <= 0)) { // Simple surface--no shaders or subsurfaces
5775 :
5776 67614 : state.dataSolarShading->SurfSunlitArea(HTS) = s_surf->Surface(GRSNR).NetAreaShadowCalc;
5777 : } else { // Surface in sun and either shading surfaces or subsurfaces present (or both)
5778 :
5779 : #ifndef EP_NO_OPENGL
5780 15787 : int id = s_surf->SurfPenumbraID(HTS);
5781 15787 : if (state.dataSolarShading->penumbra && id >= 0) {
5782 : // SurfSunlitArea(HTS) = buildingPSSF.at(id) / SurfSunCosTheta(HTS);
5783 0 : state.dataSolarShading->SurfSunlitArea(HTS) =
5784 0 : state.dataSolarShading->penumbra->retrieve_pssa(id) / state.dataSolarShading->SurfSunCosTheta(HTS);
5785 : // SurfSunlitArea(HTS) = penumbra->fetchPSSA(Surface(HTS).PenumbraID)/SurfSunCosTheta(HTS);
5786 0 : for (int SS = 1; SS <= NSBS; ++SS) {
5787 0 : int HTSS = state.dataShadowComb->ShadowComb(HTS).SubSurf(SS);
5788 0 : id = s_surf->SurfPenumbraID(HTSS);
5789 0 : if (id >= 0) {
5790 : // SurfSunlitArea(HTSS) = buildingPSSF.at(id) / SurfSunCosTheta(HTSS);
5791 0 : state.dataSolarShading->SurfSunlitArea(HTSS) =
5792 0 : state.dataSolarShading->penumbra->retrieve_pssa(id) / state.dataSolarShading->SurfSunCosTheta(HTSS);
5793 : // SurfSunlitArea(HTSS) = penumbra->fetchPSSA(Surface(HTSS).PenumbraID)/SurfSunCosTheta(HTSS);
5794 0 : if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
5795 0 : if (iHour > 0 && TS > 0) {
5796 0 : state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
5797 0 : state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).Area;
5798 : }
5799 : }
5800 : }
5801 : }
5802 15787 : } else if (!state.dataSolarShading->penumbra) {
5803 : #else
5804 : {
5805 : #endif
5806 15787 : NGRS = s_surf->Surface(GRSNR).BaseSurf;
5807 15787 : if (s_surf->Surface(GRSNR).IsShadowing) {
5808 7210 : NGRS = GRSNR;
5809 : }
5810 :
5811 : // Compute the X and Y displacements of a shadow.
5812 15787 : XS = s_surf->Surface(NGRS).lcsx.x * state.dataSolarShading->SUNCOS(1) +
5813 15787 : s_surf->Surface(NGRS).lcsx.y * state.dataSolarShading->SUNCOS(2) +
5814 15787 : s_surf->Surface(NGRS).lcsx.z * state.dataSolarShading->SUNCOS(3);
5815 15787 : YS = s_surf->Surface(NGRS).lcsy.x * state.dataSolarShading->SUNCOS(1) +
5816 15787 : s_surf->Surface(NGRS).lcsy.y * state.dataSolarShading->SUNCOS(2) +
5817 15787 : s_surf->Surface(NGRS).lcsy.z * state.dataSolarShading->SUNCOS(3);
5818 15787 : ZS = s_surf->Surface(NGRS).lcsz.x * state.dataSolarShading->SUNCOS(1) +
5819 15787 : s_surf->Surface(NGRS).lcsz.y * state.dataSolarShading->SUNCOS(2) +
5820 15787 : s_surf->Surface(NGRS).lcsz.z * state.dataSolarShading->SUNCOS(3);
5821 :
5822 15787 : if (std::abs(ZS) > Constant::SmallDistance) {
5823 15787 : state.dataSolarShading->XShadowProjection = XS / ZS;
5824 15787 : state.dataSolarShading->YShadowProjection = YS / ZS;
5825 15787 : if (std::abs(state.dataSolarShading->XShadowProjection) < 1.e-8) {
5826 900 : state.dataSolarShading->XShadowProjection = 0.0;
5827 : }
5828 15787 : if (std::abs(state.dataSolarShading->YShadowProjection) < 1.e-8) {
5829 384 : state.dataSolarShading->YShadowProjection = 0.0;
5830 : }
5831 : } else {
5832 0 : state.dataSolarShading->XShadowProjection = 0.0;
5833 0 : state.dataSolarShading->YShadowProjection = 0.0;
5834 : }
5835 :
5836 15787 : CTRANS(state,
5837 : GRSNR,
5838 : NGRS,
5839 : NVT,
5840 15787 : state.dataSolarShading->XVrt,
5841 15787 : state.dataSolarShading->YVrt,
5842 15787 : state.dataSolarShading->ZVrt); // Transform coordinates of the receiving surface to 2-D form
5843 :
5844 : // Re-order its vertices to clockwise sequential.
5845 78935 : for (N = 1; N <= NVT; ++N) {
5846 63148 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVrt(NVT + 1 - N);
5847 63148 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVrt(NVT + 1 - N);
5848 : }
5849 :
5850 15787 : HTRANS1(state, 1, NVT); // Transform to homogeneous coordinates.
5851 :
5852 15787 : state.dataSolarShading->HCAREA(1) = -state.dataSolarShading->HCAREA(1); // Compute (+) gross surface area.
5853 15787 : state.dataSolarShading->HCT(1) = 1.0;
5854 :
5855 15787 : SHDGSS(state, NGRS, iHour, TS, GRSNR, NGSS, HTS); // Determine shadowing on surface.
5856 :
5857 15787 : if (!state.dataSolarShading->CalcSkyDifShading) {
5858 9865 : SHDBKS(state, s_surf->Surface(GRSNR).BaseSurf, GRSNR, NBKS, HTS); // Determine possible back surfaces.
5859 : }
5860 : }
5861 :
5862 15787 : SHDSBS(state, iHour, GRSNR, NBKS, NSBS, HTS, TS); // Subtract subsurf areas from total
5863 :
5864 : // Error checking: require that 0 <= SurfSunlitArea <= AREA. + or - .01*AREA added for round-off errors
5865 15787 : SurfArea = s_surf->Surface(GRSNR).NetAreaShadowCalc;
5866 15787 : state.dataSolarShading->SurfSunlitArea(HTS) = max(0.0, state.dataSolarShading->SurfSunlitArea(HTS));
5867 :
5868 15787 : state.dataSolarShading->SurfSunlitArea(HTS) = min(state.dataSolarShading->SurfSunlitArea(HTS), SurfArea);
5869 : } // ...end of surface in sun/surface with shaders and/or subsurfaces IF-THEN block
5870 :
5871 : // NOTE:
5872 : // There used to be a call to legacy subroutine SHDCVR here when the
5873 : // zone type was not a standard zone.
5874 : }
5875 33798 : }
5876 :
5877 9865 : void SHDBKS(EnergyPlusData &state,
5878 : int const NGRS, // Number of the general receiving surface
5879 : int const CurSurf,
5880 : int const NBKS, // Number of back surfaces
5881 : int const HTS // Heat transfer surface number of the general receiving surf
5882 : )
5883 : {
5884 :
5885 : // SUBROUTINE INFORMATION:
5886 : // AUTHOR Legacy Code
5887 : // DATE WRITTEN
5888 : // MODIFIED na
5889 : // RE-ENGINEERED Lawrie, Oct 2000
5890 :
5891 : // PURPOSE OF THIS SUBROUTINE:
5892 : // This is the driving subroutine for computing
5893 : // the sunlit areas for back surfaces.
5894 :
5895 : // REFERENCES:
5896 : // BLAST/IBLAST code, original author George Walton
5897 :
5898 : typedef Array2D<Int64>::size_type size_type;
5899 : int I;
5900 : int M;
5901 : int N;
5902 : int NVR;
5903 : int NVT; // Number of vertices of back surface
5904 : int BackSurfaceNumber;
5905 : int NS1; // Number of the figure being overlapped
5906 : int NS2; // Number of the figure doing overlapping
5907 : int NS3; // Location to place results of overlap
5908 :
5909 9865 : auto &s_surf = state.dataSurface;
5910 :
5911 : // Tuned Linear indexing
5912 :
5913 9865 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
5914 9865 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
5915 :
5916 9865 : if (state.dataSolarShading->SHDBKSOneTimeFlag) {
5917 27 : state.dataSolarShading->XVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
5918 27 : state.dataSolarShading->YVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
5919 27 : state.dataSolarShading->ZVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
5920 27 : state.dataSolarShading->XVrtx = 0.0;
5921 27 : state.dataSolarShading->YVrtx = 0.0;
5922 27 : state.dataSolarShading->ZVrtx = 0.0;
5923 27 : state.dataSolarShading->SHDBKSOneTimeFlag = false;
5924 : }
5925 :
5926 10570 : if ((NBKS <= 0) || (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0) || (state.dataSolarShading->OverlapStatus == TooManyVertices) ||
5927 705 : (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
5928 9160 : return;
5929 : }
5930 :
5931 705 : state.dataSolarShading->FBKSHC = state.dataSolarShading->LOCHCA + 1;
5932 :
5933 4230 : for (I = 1; I <= NBKS; ++I) { // Loop through all back surfaces associated with the receiving surface
5934 :
5935 3525 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(CurSurf).BackSurf(I);
5936 :
5937 3525 : if (state.dataSolarShading->SurfSunCosTheta(BackSurfaceNumber) > -DataEnvironment::SunIsUpValue) {
5938 1410 : continue; //-0.001) CYCLE ! go to next back surface since inside of this surface
5939 : }
5940 : // cannot be in sun if the outside can be
5941 :
5942 : // Transform coordinates of back surface from general system to the
5943 : // plane of the receiving surface
5944 :
5945 2115 : CTRANS(state, BackSurfaceNumber, NGRS, NVT, state.dataSolarShading->XVrtx, state.dataSolarShading->YVrtx, state.dataSolarShading->ZVrtx);
5946 :
5947 : // Project "shadow" from back surface along sun's rays to receiving surface. Back surface vertices
5948 : // become clockwise sequential.
5949 :
5950 10575 : for (N = 1; N <= NVT; ++N) {
5951 8460 : state.dataSolarShading->XVS(N) =
5952 8460 : state.dataSolarShading->XVrtx(N) - state.dataSolarShading->XShadowProjection * state.dataSolarShading->ZVrtx(N);
5953 8460 : state.dataSolarShading->YVS(N) =
5954 8460 : state.dataSolarShading->YVrtx(N) - state.dataSolarShading->YShadowProjection * state.dataSolarShading->ZVrtx(N);
5955 : }
5956 :
5957 : // Transform to the homogeneous coordinate system.
5958 :
5959 2115 : NS3 = state.dataSolarShading->LOCHCA + 1;
5960 2115 : state.dataSolarShading->HCT(NS3) = 0.0;
5961 2115 : HTRANS1(state, NS3, NVT);
5962 :
5963 : // Adjust near-duplicate points.
5964 :
5965 2115 : NVR = state.dataSolarShading->HCNV(1);
5966 2115 : int l3 = state.dataSolarShading->HCX.index(NS3, 1);
5967 10575 : for (N = 1; N <= NVT; ++N, ++l3) {
5968 8460 : Real64 const x3 = state.dataSolarShading->HCX[l3]; // [ l3 ] == ( NS3, N )
5969 8460 : Real64 const y3 = state.dataSolarShading->HCY[l3];
5970 8460 : size_type l1 = 0;
5971 35240 : for (M = 1; M <= NVR; ++M, ++l1) {
5972 29600 : if (std::abs(state.dataSolarShading->HCX[l1] - x3) > 6) {
5973 25370 : continue; // [ l1 ] == ( 1, M )
5974 : }
5975 4230 : if (std::abs(state.dataSolarShading->HCY[l1] - y3) > 6) {
5976 1410 : continue;
5977 : }
5978 2820 : state.dataSolarShading->HCX[l3] = state.dataSolarShading->HCX[l1];
5979 2820 : state.dataSolarShading->HCY[l3] = state.dataSolarShading->HCY[l1];
5980 2820 : break;
5981 : }
5982 : }
5983 :
5984 2115 : HTRANS0(state, NS3, NVT);
5985 :
5986 : // Determine area of overlap of projected back surface and receiving surface.
5987 :
5988 2115 : NS1 = 1;
5989 2115 : NS2 = NS3;
5990 2115 : state.dataSolarShading->HCT(NS3) = 1.0;
5991 2115 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
5992 :
5993 2115 : if (state.dataSolarShading->OverlapStatus == NoOverlap) {
5994 669 : continue; // to next back surface
5995 : }
5996 1446 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
5997 0 : break; // back surfaces DO loop
5998 : }
5999 :
6000 : // Increment back surface count.
6001 :
6002 1446 : state.dataSolarShading->LOCHCA = NS3;
6003 1446 : state.dataSolarShading->HCNS(state.dataSolarShading->LOCHCA) = BackSurfaceNumber;
6004 1446 : state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
6005 1446 : state.dataSolarShading->NBKSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FBKSHC + 1;
6006 : }
6007 : }
6008 :
6009 15787 : void SHDGSS(EnergyPlusData &state,
6010 : int const NGRS,
6011 : int const iHour, // Hour Counter
6012 : int const TS, // TimeStep
6013 : int const CurSurf, // Current Surface
6014 : int const NGSS, // Number of general shadowing surfaces
6015 : int const HTS // Heat transfer surface number of the general receiving surf
6016 : )
6017 : {
6018 :
6019 : // SUBROUTINE INFORMATION:
6020 : // AUTHOR Legacy Code
6021 : // DATE WRITTEN
6022 : // MODIFIED na
6023 : // RE-ENGINEERED Lawrie, Oct 2000
6024 :
6025 : // PURPOSE OF THIS SUBROUTINE:
6026 : // This subroutine determines the shadows on a general receiving surface.
6027 :
6028 : // REFERENCES:
6029 : // BLAST/IBLAST code, original author George Walton
6030 :
6031 : typedef Array2D<Int64>::size_type size_type;
6032 : int GSSNR; // General shadowing surface number
6033 : int MainOverlapStatus; // Overlap status of the main overlap calculation not the check for
6034 : // multiple overlaps (unless there was an error)
6035 : int NS1; // Number of the figure being overlapped
6036 : int NS2; // Number of the figure doing overlapping
6037 : int NS3; // Location to place results of overlap
6038 : Real64 SchValue; // Value for Schedule of shading transmittance
6039 :
6040 15787 : auto &s_surf = state.dataSurface;
6041 :
6042 15787 : if (state.dataSolarShading->SHDGSSOneTimeFlag) {
6043 29 : state.dataSolarShading->XVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
6044 29 : state.dataSolarShading->YVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
6045 29 : state.dataSolarShading->ZVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
6046 29 : state.dataSolarShading->SHDGSSOneTimeFlag = false;
6047 : }
6048 :
6049 15787 : state.dataSolarShading->FGSSHC = state.dataSolarShading->LOCHCA + 1;
6050 15787 : MainOverlapStatus = NoOverlap; // Set to ensure that the value from the last surface is not saved
6051 15787 : state.dataSolarShading->OverlapStatus = NoOverlap;
6052 :
6053 15787 : if (NGSS <= 0) { // IF NO S.S., receiving surface FULLY SUNLIT.
6054 :
6055 4958 : state.dataSolarShading->SurfSunlitArea(HTS) = state.dataSolarShading->HCAREA(1); // Surface fully sunlit
6056 :
6057 : } else {
6058 :
6059 10829 : int ExitLoopStatus = -1;
6060 10829 : auto const &GenSurf = state.dataShadowComb->ShadowComb(CurSurf).GenSurf;
6061 10829 : int const sunIsUp = DataEnvironment::SunIsUpValue;
6062 27796 : for (int I = 1; I <= NGSS; ++I) { // Loop through all shadowing surfaces...
6063 :
6064 17924 : GSSNR = GenSurf(I);
6065 :
6066 17924 : if (state.dataSolarShading->SurfSunCosTheta(GSSNR) > sunIsUp) {
6067 5001 : continue; //.001) CYCLE ! NO SHADOW IF GSS IN SUNLIGHT.
6068 : }
6069 :
6070 12923 : auto const &surface = s_surf->Surface(GSSNR);
6071 12923 : bool const notHeatTransSurf = !surface.HeatTransSurf;
6072 :
6073 : // This used to check to see if the shadowing surface was not opaque (within the scheduled dates of
6074 : // transmittance value. Perhaps it ignored it if it were outside the range. (if so, was an error)
6075 : // The proper action seems to be delete this statement all together, but there would also be no shading if
6076 : // the shading surface were transparent...
6077 : //---former stmt IF ((.NOT.Surface(GSSNR)%HeatTransSurf) .AND. &
6078 : //---former stmt GetCurrentScheduleValue(state, Surface(GSSNR)%SchedShadowSurfIndex,IHOUR) == 0.0) CYCLE
6079 :
6080 12923 : if (notHeatTransSurf) {
6081 8315 : if (surface.IsTransparent) {
6082 0 : continue; // No shadow if shading surface is transparent
6083 : }
6084 8315 : if (surface.shadowSurfSched != nullptr) {
6085 6819 : if (surface.shadowSurfSched->getHrTsVal(state, iHour) == 1.0) {
6086 1097 : continue;
6087 : }
6088 5722 : if (!state.dataSolarShading->CalcSkyDifShading) {
6089 3619 : if (surface.shadowSurfSched->getHrTsVal(state, iHour, TS) == 1.0) {
6090 0 : continue;
6091 : }
6092 : }
6093 : }
6094 : }
6095 : // Eliminate shadowing surfaces that is supposed to be disabled.
6096 11826 : if (state.dataSysVars->DisableAllSelfShading) {
6097 0 : if (surface.Zone != 0) {
6098 0 : continue; // Disable all shadowing surfaces in all zones. Attached shading surfaces are not part of a zone, zone value is 0.
6099 : }
6100 11826 : } else if (state.dataSysVars->DisableGroupSelfShading) {
6101 0 : std::vector<int> DisabledZones = s_surf->SurfShadowDisabledZoneList(CurSurf);
6102 0 : bool isDisabledShadowSurf = false;
6103 0 : for (int i : DisabledZones) {
6104 0 : if (surface.Zone == i) {
6105 0 : isDisabledShadowSurf = true;
6106 0 : break;
6107 : }
6108 0 : }
6109 0 : if (isDisabledShadowSurf) {
6110 0 : continue; // Disable all shadowing surfaces in all disabled zones.
6111 : }
6112 0 : }
6113 :
6114 : // IF ((.NOT.Surface(GSSNR)%HeatTransSurf) .AND. &
6115 : // GetCurrentScheduleValue(state, Surface(GSSNR)%SchedShadowSurfIndex) == 1.0) CYCLE
6116 :
6117 : // Transform shadow casting surface from cartesian to homogeneous coordinates according to surface type.
6118 :
6119 11826 : if ((notHeatTransSurf) && (surface.BaseSurf != 0)) {
6120 :
6121 : // For shadowing subsurface coordinates of shadow casting surface are relative to the receiving surface
6122 : // project shadow to the receiving surface
6123 :
6124 0 : state.dataSolarShading->NVS = surface.Sides;
6125 0 : auto const &XV = s_surf->ShadeV(GSSNR).XV;
6126 0 : auto const &YV = s_surf->ShadeV(GSSNR).YV;
6127 0 : auto const &ZV = s_surf->ShadeV(GSSNR).ZV;
6128 0 : for (int N = 1; N <= state.dataSolarShading->NVS; ++N) {
6129 0 : state.dataSolarShading->XVS(N) = XV(N) - state.dataSolarShading->XShadowProjection * ZV(N);
6130 0 : state.dataSolarShading->YVS(N) = YV(N) - state.dataSolarShading->YShadowProjection * ZV(N);
6131 : }
6132 :
6133 0 : } else {
6134 : // Transform coordinates of shadow casting surface from general system to the system relative to the receiving surface
6135 : int NVT;
6136 11826 : CTRANS(state, GSSNR, NGRS, NVT, state.dataSolarShading->XVert, state.dataSolarShading->YVert, state.dataSolarShading->ZVert);
6137 11826 : CLIP(state,
6138 : NVT,
6139 11826 : state.dataSolarShading->XVert,
6140 11826 : state.dataSolarShading->YVert,
6141 11826 : state.dataSolarShading->ZVert); // Clip portions of the shadow casting surface which are behind the receiving surface
6142 :
6143 11826 : if (state.dataSolarShading->NumVertInShadowOrClippedSurface <= 2) {
6144 0 : continue;
6145 : }
6146 :
6147 : // Project shadow from shadow casting surface along sun's rays to receiving surface Shadow vertices
6148 : // become clockwise sequential
6149 :
6150 59098 : for (int N = 1; N <= state.dataSolarShading->NumVertInShadowOrClippedSurface; ++N) {
6151 47272 : state.dataSolarShading->XVS(N) =
6152 47272 : state.dataSolarShading->XVC(N) - state.dataSolarShading->XShadowProjection * state.dataSolarShading->ZVC(N);
6153 47272 : state.dataSolarShading->YVS(N) =
6154 47272 : state.dataSolarShading->YVC(N) - state.dataSolarShading->YShadowProjection * state.dataSolarShading->ZVC(N);
6155 : }
6156 : }
6157 :
6158 : // Transform to the homogeneous coordinate system.
6159 :
6160 11826 : NS3 = state.dataSolarShading->LOCHCA + 1;
6161 11826 : HTRANS1(state, NS3, state.dataSolarShading->NVS);
6162 :
6163 : // Adjust near-duplicate points.
6164 :
6165 11826 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
6166 11826 : assert(state.dataSolarShading->HCX.index(1, 1) == 0u);
6167 11826 : size_type j(state.dataSolarShading->HCX.index(NS3, 1));
6168 11826 : size_type NVR(state.dataSolarShading->HCNV(1));
6169 59098 : for (int N = 1; N <= state.dataSolarShading->NumVertInShadowOrClippedSurface;
6170 47272 : ++N, ++j) { // Tuned Logic change: break after 1st "close" point found
6171 47272 : Int64 const HCX_N(state.dataSolarShading->HCX[j]); // [ j ] == ( NS3, N )
6172 47272 : Int64 const HCY_N(state.dataSolarShading->HCY[j]);
6173 234767 : for (size_type l = 0; l < NVR; ++l) { // [ l ] == ( 1, l+1 )
6174 188150 : Real64 const delX = std::abs(state.dataSolarShading->HCX[l] - HCX_N);
6175 188150 : if (delX > 6) {
6176 184714 : continue;
6177 : }
6178 3436 : Real64 const delY = std::abs(state.dataSolarShading->HCY[l] - HCY_N);
6179 3436 : if (delY > 6) {
6180 2781 : continue;
6181 : }
6182 655 : if (delX > 0) {
6183 0 : state.dataSolarShading->HCX[j] = state.dataSolarShading->HCX[l]; // [ j ] == ( NS3, N )
6184 : }
6185 655 : if (delY > 0) {
6186 0 : state.dataSolarShading->HCY[j] = state.dataSolarShading->HCY[l];
6187 : }
6188 655 : break;
6189 : }
6190 : }
6191 11826 : HTRANS0(state, NS3, state.dataSolarShading->NumVertInShadowOrClippedSurface);
6192 11826 : if (!state.dataSolarShading->CalcSkyDifShading && surface.shadowSurfSched != nullptr) {
6193 3619 : if (iHour != 0) {
6194 3619 : SchValue = surface.shadowSurfSched->getHrTsVal(state, iHour, TS);
6195 : } else {
6196 0 : SchValue = surface.SchedMinValue;
6197 : }
6198 : } else {
6199 8207 : SchValue = surface.SchedMinValue;
6200 : }
6201 :
6202 11826 : state.dataSolarShading->HCT(NS3) = SchValue;
6203 :
6204 : // Determine overlap of shadow with receiving surface
6205 :
6206 11826 : state.dataSolarShading->CurrentShadowingSurface = I;
6207 11826 : state.dataSolarShading->CurrentSurfaceBeingShadowed = GSSNR;
6208 11826 : NS1 = 1;
6209 11826 : NS2 = NS3;
6210 11826 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
6211 : // Next statement is special to deal with transmitting shading devices
6212 11826 : if (state.dataSolarShading->OverlapStatus == FirstSurfWithinSecond && SchValue > 0.0) {
6213 67 : state.dataSolarShading->OverlapStatus = PartialOverlap;
6214 : }
6215 11826 : MainOverlapStatus = state.dataSolarShading->OverlapStatus;
6216 11826 : ExitLoopStatus = MainOverlapStatus;
6217 :
6218 11826 : if (MainOverlapStatus == NoOverlap) { // No overlap of general surface shadow and receiving surface
6219 : // Continue
6220 7693 : } else if ((MainOverlapStatus == FirstSurfWithinSecond) || (MainOverlapStatus == TooManyVertices) ||
6221 : (MainOverlapStatus == TooManyFigures)) {
6222 957 : goto ShadowingSurfaces_exit;
6223 6736 : } else if ((MainOverlapStatus == SecondSurfWithinFirst) || (MainOverlapStatus == PartialOverlap)) {
6224 : // Determine overlaps with previous shadows.
6225 6736 : state.dataSolarShading->LOCHCA = NS3;
6226 6736 : state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
6227 7863 : if (state.dataSolarShading->NGSSHC > 1) {
6228 1127 : MULTOL(state,
6229 1127 : state.dataSolarShading->LOCHCA,
6230 1127 : state.dataSolarShading->FGSSHC - 1,
6231 1127 : state.dataSolarShading->NGSSHC - 1); // HOYT - Remove this call
6232 : }
6233 : } else {
6234 0 : goto ShadowingSurfaces_exit;
6235 : }
6236 :
6237 10869 : ExitLoopStatus = -1;
6238 : }
6239 9872 : ShadowingSurfaces_exit:;
6240 :
6241 : // Compute sunlit area of surface (excluding effects of subsurfs).
6242 :
6243 10829 : if (ExitLoopStatus == FirstSurfWithinSecond) { // Surface fully shaded
6244 957 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
6245 957 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FGSSHC;
6246 :
6247 9872 : } else if ((ExitLoopStatus == TooManyVertices) || (ExitLoopStatus == TooManyFigures)) { // Array limits exceeded, estimate
6248 0 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.25 * state.dataSolarShading->HCAREA(1);
6249 :
6250 : } else {
6251 :
6252 : // Compute the sunlit area here.
6253 : // Call UnionShadow(FGSSHC,LOCHCA)
6254 :
6255 9872 : state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
6256 9872 : if (state.dataSolarShading->NGSSHC <= 0) {
6257 4263 : state.dataSolarShading->SurfSunlitArea(HTS) = state.dataSolarShading->HCAREA(1); // Surface fully sunlit
6258 : } else {
6259 5609 : Real64 A(state.dataSolarShading->HCAREA(1)); // Area
6260 12935 : for (int i = state.dataSolarShading->FGSSHC, e = state.dataSolarShading->FGSSHC + state.dataSolarShading->NGSSHC - 1; i <= e; ++i) {
6261 7326 : A += state.dataSolarShading->HCAREA(i) * (1.0 - state.dataSolarShading->HCT(i));
6262 : }
6263 5609 : state.dataSolarShading->SurfSunlitArea(HTS) = A;
6264 5609 : if (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0) { // Surface fully shaded
6265 25 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
6266 25 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FGSSHC;
6267 : }
6268 : }
6269 : }
6270 : }
6271 15787 : state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
6272 15787 : }
6273 :
6274 6982 : void CalcInteriorSolarOverlaps(EnergyPlusData &state,
6275 : int const iHour, // Hour Index
6276 : int const NBKS, // Number of back surfaces associated with this GRSNR (in general, only
6277 : int const HTSS, // Surface number of the subsurface (exterior window)
6278 : int const GRSNR, // General receiving surface number (base surface of the exterior window)
6279 : int const TS // Time step Index
6280 : )
6281 : {
6282 :
6283 : // SUBROUTINE INFORMATION:
6284 : // AUTHOR Fred Winkelmann
6285 : // DATE WRITTEN January 1999
6286 : // MODIFIED Nov 2001, FW: include beam radiation overlaps with
6287 : // back windows and doors; previously these subsurfaces ignored.
6288 : // May 2002, FW: fix problem where reveal was not being considered
6289 : // in calculating overlap areas if window is shaded only by reveal.
6290 : // June 2002, FW: fix problem that gave incorrect calculation when
6291 : // window is not shaded only by reveal
6292 : // June 2002, FW: remove incorrect multiplication of overlap areas
6293 : // by sunlit fraction when window is shaded only by reveal
6294 :
6295 : // PURPOSE OF THIS SUBROUTINE:
6296 : // For an exterior window with surface number HTSS, determines (1) the surface numbers of back
6297 : // surfaces receiving beam radiation from the window and (2) for each such back surface, the area
6298 : // of the portion of the window sending beam radiation to the back surface; this is called the
6299 : // "overlap area."
6300 :
6301 : // REFERENCES:
6302 : // BLAST/IBLAST code, original author George Walton
6303 :
6304 : // SUBROUTINE ARGUMENT DEFINITIONS:
6305 : // some of these will receive beam radiation from HTSS this hour)
6306 :
6307 : // SUBROUTINE PARAMETER DEFINITIONS:
6308 6982 : int constexpr WindowShadedOnlyByReveal(2); // for use with RevealStatus
6309 :
6310 : typedef Array2D<Int64>::size_type size_type;
6311 : int JBKS; // Counter of back surfaces with non-zero overlap with HTSS
6312 : int BackSurfNum; // Back surface number
6313 :
6314 : bool UseSimpleDistribution; // TRUE means simple interior solar distribution
6315 : // (all incoming beam assumed to strike floor),
6316 : // FALSE means exact interior solar distribution
6317 : // (track which back surfaces beam illuminates)
6318 :
6319 6982 : auto &s_surf = state.dataSurface;
6320 :
6321 : // Tuned Linear indexing
6322 :
6323 6982 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
6324 6982 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
6325 6982 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
6326 6982 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
6327 :
6328 6982 : if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
6329 :
6330 3822 : UseSimpleDistribution = false;
6331 :
6332 3822 : if ((NBKS <= 0) || (s_surf->Surface(GRSNR).ExtBoundCond > 0)) {
6333 :
6334 3117 : UseSimpleDistribution = true;
6335 :
6336 : } else {
6337 : // Using 'exact' distribution, replace subsurface HC entries with reveal HC entries
6338 : // so that the reveal HC is used in calculating interior solar overlap areas
6339 :
6340 : // Adding the following line fixes a problem where, if the window was shaded only
6341 : // by reveal, then the reveal was not considered in calculating interior solar
6342 : // overlap areas (FCW 5/3/02).
6343 : // IF(Surface(HTSS)%Reveal > 0.0) NRVLHC = 1
6344 : // Changing the line to the following avoids incorrect calculation when window is not shaded
6345 : // only by reveal (FCW 6/28/02).
6346 705 : if (state.dataSolarShading->SurfWinRevealStatus(iHour, TS, HTSS) == WindowShadedOnlyByReveal) {
6347 0 : state.dataSolarShading->NRVLHC = 1;
6348 : }
6349 705 : if (state.dataSolarShading->NRVLHC > 0) {
6350 0 : for (int I = 1; I <= state.dataSolarShading->NRVLHC; ++I) {
6351 0 : int const iS(state.dataSolarShading->FSBSHC - 1 + I);
6352 0 : int const iR(state.dataSolarShading->FRVLHC - 1 + I);
6353 0 : state.dataSolarShading->HCT(iS) = state.dataSolarShading->HCT(iR);
6354 0 : state.dataSolarShading->HCNV(iS) = state.dataSolarShading->HCNV(iR);
6355 0 : state.dataSolarShading->HCAREA(iS) = state.dataSolarShading->HCAREA(iR);
6356 0 : size_type lS(state.dataSolarShading->HCX.index(iS, 1));
6357 0 : size_type lR(state.dataSolarShading->HCX.index(iR, 1));
6358 0 : for (int J = 1; J <= state.dataSolarShading->MaxHCV; ++J, ++lS, ++lR) { // [ lS ] == ( iS, J ), [ lR ] == ( iR, J )
6359 0 : state.dataSolarShading->HCX[lS] = state.dataSolarShading->HCX[lR];
6360 0 : state.dataSolarShading->HCY[lS] = state.dataSolarShading->HCY[lR];
6361 0 : state.dataSolarShading->HCA[lS] = state.dataSolarShading->HCA[lR];
6362 0 : state.dataSolarShading->HCB[lS] = state.dataSolarShading->HCB[lR];
6363 0 : state.dataSolarShading->HCC[lS] = state.dataSolarShading->HCC[lR];
6364 : }
6365 : }
6366 0 : state.dataSolarShading->NSBSHC = state.dataSolarShading->NRVLHC;
6367 : }
6368 : }
6369 :
6370 : // Check for array space.
6371 3822 : if (state.dataSolarShading->FSBSHC + state.dataSolarShading->NBKSHC > state.dataSolarShading->MaxHCS) {
6372 0 : UseSimpleDistribution = true;
6373 : }
6374 :
6375 3822 : if (!UseSimpleDistribution) { // Compute overlaps
6376 :
6377 705 : std::unordered_map<unsigned, float> pssas;
6378 :
6379 : #ifndef EP_NO_OPENGL
6380 705 : if (state.dataSolarShading->penumbra) {
6381 : // Add back surfaces to array
6382 0 : std::vector<unsigned> pbBackSurfaces;
6383 0 : for (int bkSurfNum : state.dataShadowComb->ShadowComb(GRSNR).BackSurf) {
6384 0 : if (bkSurfNum == 0) {
6385 0 : continue;
6386 : }
6387 0 : if (state.dataSolarShading->SurfSunCosTheta(bkSurfNum) < DataEnvironment::SunIsUpValue) {
6388 0 : pbBackSurfaces.push_back(s_surf->SurfPenumbraID(bkSurfNum));
6389 : }
6390 : }
6391 0 : pssas = state.dataSolarShading->penumbra->calculate_interior_pssas({(unsigned)s_surf->SurfPenumbraID(HTSS)}, pbBackSurfaces);
6392 : // penumbra->render_interior_scene({(unsigned)Surface(HTSS).PenumbraID}, pbBackSurfaces);
6393 :
6394 0 : JBKS = 0;
6395 0 : for (int bkSurfNum : state.dataShadowComb->ShadowComb(GRSNR).BackSurf) {
6396 0 : if (bkSurfNum == 0) {
6397 0 : continue;
6398 : }
6399 0 : if (pssas[s_surf->SurfPenumbraID(bkSurfNum)] > 0) {
6400 0 : ++JBKS;
6401 0 : state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, JBKS, HTSS) = bkSurfNum;
6402 0 : Real64 OverlapArea = pssas[s_surf->SurfPenumbraID(bkSurfNum)] / state.dataSolarShading->SurfSunCosTheta(HTSS);
6403 0 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS) = OverlapArea * s_surf->SurfaceWindow(HTSS).glazedFrac;
6404 : }
6405 : }
6406 0 : }
6407 : #endif
6408 :
6409 705 : if (!state.dataSolarShading->penumbra) {
6410 :
6411 705 : state.dataSolarShading->FINSHC = state.dataSolarShading->FSBSHC + state.dataSolarShading->NSBSHC;
6412 :
6413 705 : JBKS = 0;
6414 :
6415 2151 : for (int IBKS = 1; IBKS <= state.dataSolarShading->NBKSHC;
6416 : ++IBKS) { // Loop over back surfaces to GRSNR this hour. NBKSHC is the number of
6417 : // back surfaces that would receive beam radiation from the base surface, GRSNR,
6418 : // if the base surface was transparent. In general, some (at least one) or all of these
6419 : // will receive beam radiation from the exterior window subsurface, HTSS, of GRSNR,
6420 : // depending on the size of HTSS and its location on GRSNR
6421 :
6422 1446 : BackSurfNum = state.dataSolarShading->HCNS(state.dataSolarShading->FBKSHC - 1 + IBKS);
6423 :
6424 : // Determine if this back surface number can receive beam radiation from the
6425 : // exterior window, HTSS, this hour, i.e., overlap area is positive
6426 :
6427 1446 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FINSHC - 1;
6428 :
6429 1446 : MULTOL(state, state.dataSolarShading->FBKSHC - 1 + IBKS, state.dataSolarShading->FSBSHC - 1, state.dataSolarShading->NSBSHC);
6430 :
6431 : // Compute overlap area for this back surface
6432 :
6433 1446 : state.dataSolarShading->NINSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FINSHC + 1;
6434 1446 : if (state.dataSolarShading->NINSHC <= 0) {
6435 224 : continue;
6436 : }
6437 1222 : Real64 OverlapArea = state.dataSolarShading->HCAREA(state.dataSolarShading->FINSHC);
6438 1222 : for (int J = 2; J <= state.dataSolarShading->NINSHC; ++J) {
6439 0 : OverlapArea += state.dataSolarShading->HCAREA(state.dataSolarShading->FINSHC - 1 + J) *
6440 0 : (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FINSHC - 1 + J));
6441 : }
6442 :
6443 1222 : if (OverlapArea > 0.001) {
6444 1222 : ++JBKS;
6445 1222 : if (JBKS <= state.dataBSDFWindow->MaxBkSurf) {
6446 1222 : state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, JBKS, HTSS) = BackSurfNum;
6447 1222 : int baseSurfaceNum = s_surf->Surface(BackSurfNum).BaseSurf;
6448 1222 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS) = OverlapArea * s_surf->SurfaceWindow(HTSS).glazedFrac;
6449 : // If this is a subsurface, subtract its overlap area from its base surface
6450 1222 : if (baseSurfaceNum != BackSurfNum) {
6451 0 : for (int iBaseBKS = 1; iBaseBKS <= JBKS; ++iBaseBKS) {
6452 0 : if (baseSurfaceNum == state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, iBaseBKS, HTSS)) {
6453 0 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, iBaseBKS, HTSS) =
6454 0 : max(0.0,
6455 0 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, iBaseBKS, HTSS) -
6456 0 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS));
6457 0 : break;
6458 : }
6459 : }
6460 : }
6461 : }
6462 : }
6463 : } // End of loop over back surfaces
6464 : }
6465 705 : }
6466 : } // End of check that sunlit area > 0.
6467 6982 : }
6468 :
6469 71220 : void CalcInteriorSolarDistribution(EnergyPlusData &state)
6470 : {
6471 :
6472 : // SUBROUTINE INFORMATION:
6473 : // AUTHOR Fred Winkelmann
6474 : // DATE WRITTEN January 1999
6475 : // MODIFIED Nov 1999, FW, for Window5 calculation method
6476 : // Oct 2000, FW: add transmitted solar variables for reporting
6477 : // Mar 2001, FW: add new calc of solar absorbed by window shades
6478 : // May 2001, FW: add calc of solar transmitted and absorbed by window blinds
6479 : // Oct 2001, LL: remove interpolation, solar now at time step
6480 : // Oct 2001, FW: add solar transmitted through interior windows
6481 : // Mar 24, 2001, FW: remove incorrect multiplication of Boverlap by sunlit fraction
6482 : // since effect of shadowing is already included in Aoverlap
6483 : // Apr 2001, FW: add effects of beam solar reflection from outside and inside reveals
6484 : // Jan 2003, FW: add between-glass shades and blinds
6485 : // Dec 2003, FW: report beam incident on inside of surface
6486 : // Jan 2004, FW: for blinds with horizontal slats, allow different diffuse/diffuse
6487 : // transmittance for ground and sky solar
6488 : // Apr 2004, FW: allow diffusing glazing
6489 : // May 2006, RR: allow external window screen
6490 : // Jan 2010, TH: add calculating and reporting of WinBmBmSolar, WinBmDifSolar,
6491 : // WinBmBmSolarEnergy, and WinBmDifSolarEnergy
6492 : // Jun 2013, SV: scheduled surface gains for walls and windows
6493 :
6494 : // PURPOSE OF THIS SUBROUTINE:
6495 : // For a time step, calculates solar radiation absorbed by exterior
6496 : // surfaces and interior solar radiation distribution
6497 :
6498 : using Dayltg::TransTDD;
6499 : using namespace DataWindowEquivalentLayer;
6500 :
6501 71220 : Array1D<Real64> CFBoverlap; // Sum of boverlap for each back surface
6502 71220 : Array2D<Real64> CFDirBoverlap; // Directional boverlap (Direction, IBack)
6503 :
6504 71220 : auto &s_mat = state.dataMaterial;
6505 71220 : auto &s_surf = state.dataSurface;
6506 :
6507 : #ifdef EP_Count_Calls
6508 : ++state.dataTimingsData->NumIntSolarDist_Calls;
6509 : #endif
6510 :
6511 170529 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
6512 211324 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
6513 112015 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
6514 112015 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
6515 112015 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
6516 143129 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
6517 248912 : for (int lay = 1; lay <= CFSMAXNL + 1; ++lay) {
6518 217798 : s_surf->SurfWinA(SurfNum, lay) = 0.0;
6519 : }
6520 31114 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfNum) = 0.0;
6521 31114 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = 0.0;
6522 : }
6523 112015 : int const firstSurfOpaque = thisSpace.OpaqOrIntMassSurfaceFirst;
6524 112015 : int const lastSurfOpaque = thisSpace.OpaqOrIntMassSurfaceLast;
6525 692595 : for (int SurfNum = firstSurfOpaque; SurfNum <= lastSurfOpaque; ++SurfNum) {
6526 580580 : s_surf->SurfOpaqAI(SurfNum) = 0.0;
6527 580580 : s_surf->SurfOpaqAO(SurfNum) = 0.0;
6528 : }
6529 99309 : }
6530 : }
6531 :
6532 71220 : if ((int)state.dataDaylightingDevicesData->TDDPipe.size() > 0) {
6533 0 : for (auto &e : state.dataDaylightingDevicesData->TDDPipe) {
6534 0 : int SurfDome = e.Dome;
6535 0 : for (int lay = 1; lay <= CFSMAXNL + 1; ++lay) {
6536 0 : s_surf->SurfWinA(SurfDome, lay) = 0.0;
6537 : }
6538 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfDome) = 0.0;
6539 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfDome) = 0.0;
6540 : }
6541 : }
6542 :
6543 176530 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
6544 : // Solar entering a zone as beam or diffuse radiation, originating as beam solar incident on exterior windows)/(Beam normal solar) [W/(W/m2)]
6545 105310 : Real64 BTOTZone = 0.0;
6546 : // Beam radiation from exterior windows absorbed in a zone or transmitted through
6547 105310 : Real64 BABSZone = 0.0;
6548 105310 : state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
6549 105310 : state.dataHeatBal->EnclSolDBSSG(enclosureNum) = 0.0;
6550 105310 : state.dataHeatBal->EnclSolDBIntWin(enclosureNum) = 0.0;
6551 : // Loop over exterior surfaces in this zone
6552 105310 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
6553 : // delete values from previous timestep
6554 105310 : if (state.dataHeatBal->AnyBSDF) {
6555 0 : s_surf->SurfWinACFOverlap = 0.0;
6556 : }
6557 :
6558 : //-------------------------------------------------------------------------
6559 : // EXTERIOR BEAM SOLAR RADIATION ABSORBED ON THE OUTSIDE OF OPAQUE SURFACES
6560 : //-------------------------------------------------------------------------
6561 : // TODO: use opaq and window loop after airboundary is sorted
6562 : // TODO: It may be useful to sort SurfacePtr to group windows and domes together to reduce if conditions
6563 716999 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
6564 611689 : if (s_surf->Surface(SurfNum).Class != SurfaceClass::Window && s_surf->Surface(SurfNum).Class != SurfaceClass::TDD_Dome) {
6565 580573 : if (!s_surf->Surface(SurfNum).HeatTransSurf) {
6566 0 : continue;
6567 : }
6568 580573 : if (!s_surf->Surface(SurfNum).ExtSolar) {
6569 232447 : continue;
6570 : }
6571 348126 : int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
6572 348126 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
6573 348126 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
6574 348126 : s_surf->SurfOpaqAO(SurfNum) = state.dataConstruction->Construct(ConstrNum).OutsideAbsorpSolar * CosInc * SunLitFract;
6575 : }
6576 : }
6577 :
6578 : //--------------------------------------------------------------------------------------------------------
6579 : // EXTERIOR WINDOWS OR TDD DOMES
6580 : //--------------------------------------------------------------------------------------------------------
6581 716999 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
6582 611689 : auto &surf = s_surf->Surface(SurfNum);
6583 611689 : if (surf.Class != SurfaceClass::Window && surf.Class != SurfaceClass::TDD_Dome) {
6584 580573 : continue;
6585 : }
6586 31116 : if (!surf.ExtSolar && surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
6587 0 : continue;
6588 : }
6589 :
6590 31116 : auto &surfWin = s_surf->SurfaceWindow(SurfNum);
6591 31116 : int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
6592 31116 : int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(SurfNum);
6593 31116 : auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
6594 31116 : int ScNum = surfWin.screenNum;
6595 31116 : WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum); // Set in subr. WindowShadingManager
6596 :
6597 31116 : auto &surfShade = s_surf->surfShades(SurfNum);
6598 :
6599 31116 : Real64 ProfAng = 0.0; // Window solar profile angle (radians)
6600 :
6601 31116 : Real64 SlatAng = surfShade.blind.slatAng;
6602 31116 : int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
6603 31116 : int SurfNum2 = SurfNum;
6604 31116 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
6605 0 : SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
6606 : }
6607 31116 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
6608 31116 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
6609 :
6610 : //-----------------------------------------
6611 : // BLOCK 1
6612 : // EXTERIOR BEAM AND DIFFUSE SOLAR RADIATION ABSORBED IN THE GLASS LAYERS OF (SurfWinA)
6613 : // EXTERIOR BEAM ABSORBED BY SHADING DEVICE (SurfWinExtBeamAbsByShadFac)
6614 : //-----------------------------------------
6615 : // Somewhat of a kludge
6616 31116 : if (surf.Class == SurfaceClass::TDD_Dome || surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
6617 0 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) =
6618 : SunLitFract; // Frames/dividers not allow
6619 : }
6620 31116 : int FenSolAbsPtr = 0;
6621 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
6622 0 : FenSolAbsPtr = WindowScheduledSolarAbs(state, SurfNum, ConstrNum);
6623 : }
6624 : bool SunlitFracWithoutReveal =
6625 31116 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) > 0;
6626 :
6627 : // Calculate interpolated blind properties
6628 : Real64 FrontDiffDiffTrans; // Bare-blind front diffuse-diffuse solar transmittance
6629 : Real64 FrontDiffDiffRefl;
6630 : Real64 FrontDiffAbs; // Bare-blind front diffuse solar reflectance
6631 : Real64 BackDiffDiffTrans; // Bare-blind back diffuse-diffuse solar transmittance
6632 : Real64 BackDiffDiffRefl;
6633 : Real64 BackDiffAbs; // Bare-blind back diffuse solar reflectance
6634 :
6635 : Real64 FrontBeamDiffTrans; // Blind ProfileAnglesolar front beam-diffuse transmittance
6636 : Real64 BackBeamDiffTrans; // Blind solar back beam-diffuse transmittance
6637 : Real64 FrontBeamDiffRefl; // Blind solar front beam-diffuse reflectance
6638 : Real64 BackBeamDiffRefl; // Blind solar back beam-diffuse reflectance
6639 : Real64 FrontBeamAbs; // Blind solar front beam absorptance
6640 : Real64 BackBeamAbs; // Blind solar back beam absorptance
6641 :
6642 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL && ANY_BLIND(ShadeFlag)) {
6643 0 : auto const &surfShade = s_surf->surfShades(SurfNum);
6644 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
6645 0 : assert(matBlind != nullptr);
6646 :
6647 0 : int profIdxLo = surfShade.blind.profAngIdxLo;
6648 0 : int profIdxHi = surfShade.blind.profAngIdxHi;
6649 0 : Real64 profInterpFac = surfShade.blind.profAngInterpFac;
6650 :
6651 0 : FrontDiffDiffTrans = surfShade.blind.TAR.Sol.Ft.Df.Tra;
6652 :
6653 0 : if (SunLitFract > 0.0 || SunlitFracWithoutReveal) {
6654 0 : auto const &btar1 = surfShade.blind.TAR;
6655 0 : auto const &btarFront1Lo = btar1.Sol.Ft.Bm[profIdxLo];
6656 0 : auto const &btarFront1Hi = btar1.Sol.Ft.Bm[profIdxHi];
6657 :
6658 0 : FrontBeamAbs = Interp(btarFront1Lo.Abs, btarFront1Hi.Abs, profInterpFac);
6659 0 : FrontBeamDiffTrans = Interp(btarFront1Lo.DfTra, btarFront1Hi.DfTra, profInterpFac);
6660 0 : if (ShadeFlag != WinShadingType::ExtBlind) { // FRONT: interior or bg blinds
6661 0 : FrontDiffDiffRefl = btar1.Sol.Ft.Df.Ref;
6662 0 : FrontDiffAbs = btar1.Sol.Ft.Df.Abs;
6663 0 : FrontBeamDiffRefl = Interp(btarFront1Lo.DfRef, btarFront1Hi.DfRef, profInterpFac);
6664 : }
6665 :
6666 0 : if (ShadeFlag != WinShadingType::IntBlind) { // BACK: exterior or bg blinds{
6667 0 : BackDiffDiffTrans = btar1.Sol.Bk.Df.Tra;
6668 0 : BackDiffDiffRefl = btar1.Sol.Bk.Df.Ref;
6669 0 : BackDiffAbs = btar1.Sol.Bk.Df.Abs;
6670 :
6671 0 : auto const &btarBack1Lo = btar1.Sol.Bk.Bm[profIdxLo];
6672 0 : auto const &btarBack1Hi = btar1.Sol.Bk.Bm[profIdxHi];
6673 :
6674 0 : BackBeamDiffTrans = Interp(btarBack1Lo.DfTra, btarBack1Hi.DfTra, profInterpFac);
6675 0 : BackBeamDiffRefl = Interp(btarBack1Lo.DfRef, btarBack1Hi.DfRef, profInterpFac);
6676 0 : BackBeamAbs = Interp(btarBack1Lo.Abs, btarBack1Hi.Abs, profInterpFac);
6677 : }
6678 : } // if (SunLitFrac > 0.0)
6679 : } // if (ANY_BLIND)
6680 :
6681 31116 : if (SunlitFracWithoutReveal) {
6682 :
6683 16090 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
6684 :
6685 : // For bare glazing or switchable glazing, the following includes the effects of
6686 : // (1) diffuse solar produced by beam solar incident on the outside and inside reveal
6687 : // surfaces, and (2) absorption of beam solar by outside and inside reveal surfaces.
6688 : // If there is an exterior shade/blind both of these effects are ignored. If there
6689 : // is an interior or between-glass shade/blind the effects of beam incident on
6690 : // inside reveal surfaces is ignored.
6691 15305 : int NGlass = thisConstruct.TotGlassLayers;
6692 15305 : Array1D<Real64> AbWin(NGlass); // Factor for front beam radiation absorbed in window glass layer
6693 33750 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6694 36890 : AbWin(Lay) = Window::POLYF(CosInc, thisConstruct.AbsBeamCoef(Lay)) * CosInc * SunLitFract *
6695 18445 : s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
6696 : }
6697 15305 : if (!IS_SHADED_NO_GLARE_CTRL(ShadeFlag)) {
6698 : // (ShadeFlag <= 0 || ShadeFlag >= 10) - Bare window (ShadeFlag = -1 or 0 or shading device of off)
6699 33750 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6700 : // Add contribution of beam reflected from outside and inside reveal
6701 36890 : s_surf->SurfWinA(SurfNum, Lay) = AbWin(Lay) +
6702 18445 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstruct.AbsDiff(Lay) +
6703 18445 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) * thisConstruct.AbsDiffBack(Lay);
6704 : }
6705 : } else {
6706 : // Shade, screen, blind or switchable glazing on (ShadeFlag > 0)
6707 : Real64 FracSunLit =
6708 0 : SunLitFract * s_surf->SurfaceWindow(SurfNum)
6709 0 : .OutProjSLFracMult[state.dataGlobal->HourOfDay]; // Effective fraction of window that is sunlit;
6710 0 : Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
6711 0 : Array1D<Real64> AbWinSh(NGlass); // Like AbWin, but for shaded window
6712 0 : Array1D<Real64> ADiffWinSh(NGlass); // Diffuse solar absorptance of glass layer, window with shading device
6713 0 : if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
6714 0 : FracSunLit = SunLitFract;
6715 : }
6716 :
6717 0 : if (ANY_SHADE(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
6718 0 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
6719 : // Shade or switchable glazing on
6720 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6721 0 : AbWinSh(Lay) = Window::POLYF(CosInc, thisConstructSh.AbsBeamCoef(Lay)) * CosInc * FracSunLit;
6722 0 : ADiffWinSh(Lay) = thisConstructSh.AbsDiff(Lay);
6723 : }
6724 0 : if (ShadeFlag == WinShadingType::IntShade) { // Exterior beam absorbed by INTERIOR SHADE
6725 : // Note that AbsBeamShadeCoef includes effect of shade/glazing inter-reflection
6726 0 : Real64 AbsShade = Window::POLYF(CosInc,
6727 0 : thisConstructSh.AbsBeamShadeCoef); // Interior shade or blind beam solar absorptance
6728 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6729 0 : (AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
6730 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstructSh.AbsDiffShade) *
6731 0 : surfWin.glazedFrac;
6732 : // In the above, GlazedFrac corrects for shadowing of divider onto interior shade
6733 0 : } else if (ShadeFlag == WinShadingType::ExtShade) { // Exterior beam absorbed by EXTERIOR SHADE
6734 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = thisConstructSh.AbsDiffShade * CosInc * SunLitFract;
6735 0 : } else if (ShadeFlag == WinShadingType::BGShade) { // Exterior beam absorbed by BETWEEN-GLASS SHADE
6736 0 : Real64 AbsShade = Window::POLYF(CosInc, thisConstructSh.AbsBeamShadeCoef);
6737 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6738 0 : AbsShade * CosInc * SunLitFract +
6739 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstructSh.AbsDiffShade;
6740 : }
6741 :
6742 : } else {
6743 : // Blind or screen on
6744 0 : ProfAng = surfShade.blind.profAng;
6745 0 : if (ShadeFlag == WinShadingType::IntBlind) {
6746 : // Interior blind on
6747 0 : Real64 TBmBm = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef);
6748 0 : Real64 RGlDiffBack = thisConstruct.ReflectSolDiffBack; // Glazing system back diffuse solar reflectance
6749 0 : Real64 RhoBlFront = FrontBeamDiffRefl; // Blind solar front beam reflectance
6750 0 : Real64 RhoBlDiffFront = FrontDiffDiffRefl; // Blind solar front diffuse reflectance
6751 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6752 0 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6753 0 : Real64 AGlDiffBack = thisConstruct.AbsDiffBack(Lay); // Glass layer back diffuse solar absorptance
6754 0 : AbWinSh(Lay) =
6755 0 : AbWin(Lay) + (TBmBm * AGlDiffBack * RhoBlFront / (1.0 - RhoBlFront * RGlDiffBack)) * CosInc * FracSunLit;
6756 0 : ADiffWinSh(Lay) =
6757 0 : ADiffWin + thisConstruct.TransDiff * AGlDiffBack * RhoBlDiffFront / (1.0 - RhoBlDiffFront * RGlDiffBack);
6758 : }
6759 : // Exterior beam absorbed by INTERIOR BLIND
6760 :
6761 0 : Real64 AbsBlFront = FrontBeamAbs; // Blind solar front beam absorptance
6762 0 : Real64 AbsBlDiffFront = FrontDiffAbs; // Blind solar front diffuse absorptance
6763 0 : Real64 AbsShade =
6764 0 : TBmBm * (AbsBlFront + RhoBlFront * RGlDiffBack * AbsBlDiffFront / (1.0 - RhoBlDiffFront * RGlDiffBack));
6765 0 : Real64 AbsShadeDiff =
6766 0 : thisConstruct.TransDiff *
6767 0 : (AbsBlDiffFront + RhoBlDiffFront * RGlDiffBack * AbsBlDiffFront /
6768 0 : (1.0 - RhoBlDiffFront * RGlDiffBack)); // Interior shade or blind diffuse solar absorptance
6769 :
6770 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6771 0 : (AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
6772 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * AbsShadeDiff) *
6773 0 : surfWin.glazedFrac;
6774 :
6775 : // In the above, GlazedFrac corrects for shadowing of divider onto interior blind
6776 0 : } else if (ShadeFlag == WinShadingType::ExtBlind) {
6777 : // Exterior blind on
6778 0 : Real64 TBlBmBm = surfShade.blind.bmBmTrans; // Blind solar front beam-beam transmittance
6779 0 : Real64 TBlDifDif = FrontDiffDiffTrans; // Diffuse-diffuse solar transmittance of blind
6780 0 : Real64 TBlBmDiff = FrontBeamDiffTrans; // Blind solar front beam-diffuse transmittance
6781 0 : Real64 RhoBlBack = BackBeamDiffRefl; // Blind solar back beam-diffuse reflectance
6782 0 : Real64 RhoBlDiffBack = BackDiffDiffRefl; // Blind solar back diffuse reflectance
6783 : Real64 RGlFront =
6784 0 : Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
6785 0 : Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
6786 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6787 0 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6788 0 : Real64 AGlDiffFront = thisConstruct.AbsDiff(Lay); // Glass layer front diffuse solar absorptance
6789 0 : AbWinSh(Lay) = TBlBmBm * AbWin(Lay) + ((TBlBmBm * RGlFront * RhoBlBack + TBlBmDiff) * AGlDiffFront /
6790 0 : (1 - RGlDiffFront * RhoBlDiffBack)) *
6791 0 : CosInc * FracSunLit;
6792 : // ADiffWinSh = 0.0 ! Assumes no contribution from reveal reflection when exterior blind in place
6793 : // Replaced above line with (FCW, 2/10/03):
6794 0 : ADiffWinSh(Lay) = ADiffWin * TBlDifDif / (1.0 - RGlDiffFront * RhoBlDiffBack);
6795 : }
6796 : // Exterior beam absorbed by EXTERIOR BLIND
6797 0 : Real64 AbsBlFront = FrontBeamAbs;
6798 0 : Real64 AbsBlBack = BackBeamAbs; // Blind solar back beam absorptance
6799 0 : Real64 AbsBlDiffBack = BackDiffAbs; // Blind solar back diffuse absorptance
6800 0 : Real64 AbsShade = AbsBlFront + AbsBlBack * RGlFront * TBlBmBm +
6801 0 : (AbsBlDiffBack * RGlDiffFront / (1.0 - RhoBlDiffBack * RGlDiffFront)) *
6802 0 : (RGlFront * TBlBmBm * RhoBlBack + TBlBmDiff);
6803 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsShade * CosInc * SunLitFract * InOutProjSLFracMult;
6804 0 : } else if (ShadeFlag == WinShadingType::ExtScreen) {
6805 : // Exterior screen on
6806 0 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
6807 0 : assert(screen != nullptr);
6808 :
6809 0 : auto &surf = s_surf->Surface(SurfNum);
6810 :
6811 0 : Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
6812 0 : Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
6813 0 : Real64 winPhi = surf.Tilt * Constant::DegToRad;
6814 0 : Real64 winTheta = surf.Azimuth * Constant::DegToRad;
6815 0 : Real64 phi = std::abs(solPhi - winPhi);
6816 0 : Real64 theta = std::abs(solTheta - winTheta);
6817 0 : Material::NormalizePhiTheta(phi, theta);
6818 : #ifdef PRECALC_INTERP_SCREEN
6819 : int ip1, ip2, it1, it2;
6820 : BilinearInterpCoeffs coeffs;
6821 0 : Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
6822 0 : GetBilinearInterpCoeffs(
6823 0 : phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
6824 0 : auto const &b11 = screen->btars[ip1][it1];
6825 0 : auto const &b12 = screen->btars[ip1][it2];
6826 0 : auto const &b21 = screen->btars[ip2][it1];
6827 0 : auto const &b22 = screen->btars[ip2][it2];
6828 :
6829 0 : Real64 TScDifDif = screen->DfTrans;
6830 0 : Real64 TScBmDif = BilinearInterp(b11.DfTrans, b12.DfTrans, b21.DfTrans, b22.DfTrans, coeffs);
6831 0 : Real64 TScBmBm = BilinearInterp(b11.BmTrans, b12.BmTrans, b21.BmTrans, b22.BmTrans, coeffs);
6832 0 : Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
6833 0 : Real64 RScDifBack = screen->DfRef;
6834 :
6835 : Real64 RGlFront =
6836 0 : Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
6837 0 : Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
6838 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
6839 : // Reduce the bare window absorbed beam by the screen beam transmittance and then account for
6840 : // interreflections
6841 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6842 0 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6843 0 : AbWinSh(Lay) = TScBmBm * AbWin(Lay) + (TScBmBm * RGlFront * RScBack + TScBmDif) * thisConstruct.AbsDiff(Lay) /
6844 0 : (1.0 - RGlDiffFront * RScDifBack) * CosInc * FracSunLit;
6845 0 : ADiffWinSh(Lay) = ADiffWin * TScDifDif / (1.0 - RGlDifFr * RScDifBack);
6846 : }
6847 : // Exterior beam absorbed by EXTERIOR SCREEN
6848 0 : Real64 AbsScBeam = BilinearInterp(b11.AbsSolFront, b12.AbsSolFront, b21.AbsSolFront, b22.AbsSolFront, coeffs);
6849 0 : Real64 AbsScDiffBack = screen->DfAbs;
6850 0 : Real64 AbsScreen = AbsScBeam * (1.0 + TScBmBm * RGlFront) +
6851 0 : (AbsScDiffBack * TScBmBm * RGlFront * RGlDiffFront * RScBack /
6852 0 : (1.0 - RScDifBack * RGlDiffFront)); // Exterior screen beam solar absorptance
6853 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsScreen * CosInc * SunLitFract * InOutProjSLFracMult;
6854 : #else // !PRECALC_INTERP_SCREEN
6855 : Material::ScreenBmTransAbsRef btar;
6856 : CalcScreenTransmittance(state, screen, phi, theta, btar);
6857 :
6858 : Real64 TScDifDif = screen->DfTrans;
6859 : Real64 TScBmDif = btar.DfTrans;
6860 : Real64 TScBmBm = btar.BmTrans;
6861 : Real64 RScBack = btar.RefSolFront;
6862 : Real64 RScDifBack = screen->DfRef;
6863 :
6864 : Real64 RGlFront =
6865 : Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
6866 : Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
6867 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
6868 : // Reduce the bare window absorbed beam by the screen beam transmittance and then account for
6869 : // interreflections
6870 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6871 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6872 : AbWinSh(Lay) = TScBmBm * AbWin(Lay) + (TScBmBm * RGlFront * RScBack + TScBmDif) * thisConstruct.AbsDiff(Lay) /
6873 : (1.0 - RGlDiffFront * RScDifBack) * CosInc * FracSunLit;
6874 : ADiffWinSh(Lay) = ADiffWin * TScDifDif / (1.0 - RGlDifFr * RScDifBack);
6875 : }
6876 : // Exterior beam absorbed by EXTERIOR SCREEN
6877 : Real64 AbsScBeam = btar.AbsSolFront;
6878 : Real64 AbsScDiffBack = screen->DfAbs;
6879 : Real64 AbsScreen = AbsScBeam * (1.0 + TScBmBm * RGlFront) +
6880 : (AbsScDiffBack * TScBmBm * RGlFront * RGlDiffFront * RScBack /
6881 : (1.0 - RScDifBack * RGlDiffFront)); // Exterior screen beam solar absorptance
6882 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsScreen * CosInc * SunLitFract * InOutProjSLFracMult;
6883 : #endif // PRECALC_INTERP_SCREEN
6884 0 : } else if (ShadeFlag == WinShadingType::BGBlind) {
6885 : // Between-glass blind o
6886 : // Isolated glass and blind properties at current incidence angle, profile angle and slat angle
6887 0 : Real64 t1 = Window::POLYF(CosInc,
6888 0 : thisConstruct.tBareSolCoef(1)); // Bare-glass beam solar trans for glass layers 1,2 and 3
6889 0 : Real64 t2 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(2));
6890 : Real64 af1 =
6891 0 : Window::POLYF(CosInc,
6892 0 : thisConstruct.afBareSolCoef(1)); // Bare-glass beam solar front abs for glass layers 1,2 and 3
6893 0 : Real64 af2 = Window::POLYF(CosInc, thisConstruct.afBareSolCoef(2));
6894 0 : Real64 ab1 = Window::POLYF(
6895 : CosInc,
6896 0 : thisConstruct.abBareSolCoef(1)); // Bare-glass beam solar back absorptance for glass layers 1,2 and 3
6897 0 : Real64 ab2 = Window::POLYF(CosInc, thisConstruct.abBareSolCoef(2));
6898 0 : Real64 rf2 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(2));
6899 0 : Real64 td1 = thisConstruct.tBareSolDiff(1); // Bare-glass diffuse solar transmittance for glass layers 1,2 and 3
6900 0 : Real64 td2 = thisConstruct.tBareSolDiff(2);
6901 0 : Real64 afd1 = thisConstruct.afBareSolDiff(1); // Bare-glass diffuse solar front absorptance for glass layers 1,2 and 3
6902 0 : Real64 afd2 = thisConstruct.afBareSolDiff(2);
6903 0 : Real64 abd1 = thisConstruct.abBareSolDiff(1); // Bare-glass diffuse solar back absorptance for glass layers 1,2 and 3
6904 0 : Real64 abd2 = thisConstruct.abBareSolDiff(2);
6905 0 : Real64 rfd2 = thisConstruct.rfBareSolDiff(2);
6906 0 : Real64 rbd1 = thisConstruct.rbBareSolDiff(1); // Bare-glass diffuse solar back reflectance for glass layers 1,2 and 3
6907 0 : Real64 rbd2 = thisConstruct.rbBareSolDiff(2);
6908 0 : Real64 tfshBB = surfShade.blind.bmBmTrans; // Bare-blind front and back beam-beam solar transmittance
6909 :
6910 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
6911 0 : assert(matBlind != nullptr);
6912 0 : Real64 tbshBB = matBlind->BeamBeamTrans(ProfAng, Constant::Pi - SlatAng);
6913 0 : Real64 tfshBd = FrontBeamDiffTrans; // Bare-blind front and back beam-diffuse solar transmittance
6914 0 : Real64 tbshBd = BackBeamDiffTrans;
6915 0 : Real64 rfshB = FrontBeamDiffRefl; // Bare-blind front and back beam solar reflectance
6916 0 : Real64 rbshB = BackBeamDiffRefl;
6917 0 : Real64 afshB = FrontBeamAbs;
6918 0 : Real64 abshB = BackBeamAbs;
6919 :
6920 0 : Real64 tfshd = FrontDiffDiffTrans; // Bare-blind front and back diffuse-diffuse solar transmittance
6921 0 : Real64 tbshd = BackDiffDiffTrans;
6922 0 : Real64 rfshd = FrontDiffDiffRefl; // Bare-blind front and back diffuse solar reflectance
6923 0 : Real64 rbshd = BackDiffDiffRefl;
6924 0 : Real64 afshd = FrontDiffAbs;
6925 0 : Real64 abshd = BackDiffAbs;
6926 :
6927 0 : Real64 AbsShade = 0.0;
6928 0 : Real64 AbsShadeDiff = 0.0;
6929 0 : if (NGlass == 2) {
6930 0 : AbWinSh(1) = CosInc * FracSunLit *
6931 0 : (af1 + t1 * tfshBB * rf2 * tbshBB * ab1 +
6932 0 : t1 * (rfshB + rfshB * rbd1 * rfshd + tfshBB * rf2 * tbshBd + tfshBd * rfd2 * tbshd) * abd1);
6933 0 : ADiffWinSh(1) = afd1 + td1 * (rfshd + rfshd * rbd1 * rfshd + tfshd * rfd2 * tbshd) * abd1;
6934 0 : AbWinSh(2) =
6935 0 : CosInc * FracSunLit *
6936 0 : (t1 * rfshB * af2 + t1 * (rfshB * rf2 * rbshd + tfshBd * (1 + rfd2 * rbshd) + rfshB * rbd1 * tfshd) * afd2);
6937 0 : ADiffWinSh(2) = td1 * (tfshd * (1 + rfd2 * rbshd) + rfshd * rbd1 * tfshd) * afd2;
6938 0 : AbsShade = t1 * (afshB + tfshBB * rf2 * abshB + tfshBd * rfd2 * abshd + rfshB * rbd1 * afshd);
6939 0 : AbsShadeDiff = td1 * (afshd * (1 + rfshd * rbd1) + tfshd * rfd2 * abshd);
6940 0 : } else if (NGlass == 3) {
6941 0 : Real64 t1t2 = t1 * t2; // t1*t2
6942 0 : Real64 td1td2 = td1 * td2;
6943 0 : Real64 af3 = Window::POLYF(CosInc, thisConstruct.afBareSolCoef(3));
6944 0 : Real64 rf3 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(3));
6945 0 : Real64 afd3 = thisConstruct.afBareSolDiff(3);
6946 0 : Real64 rfd3 = thisConstruct.rfBareSolDiff(3);
6947 0 : Real64 td2 = thisConstruct.tBareSolDiff(2);
6948 0 : AbWinSh(1) = CosInc * FracSunLit *
6949 0 : (af1 + t1 * rf2 * ab1 + t1t2 * tfshBB * rf3 * tbshBB * t2 * ab1 +
6950 0 : t1t2 * (rfshB * td2 + rfshB * rbd2 * rfshd * td2 + tfshBd * rfd3 * tbshd * td2) * abd1);
6951 0 : ADiffWinSh(1) = afd1 + td1 * rbd2 * abd1 +
6952 0 : td1td2 *
6953 0 : (rfshd * (1 + rbd2 * rfshd + td2 * rbd1 * td2 * rfshd) +
6954 0 : tfshd * (rfd3 * tbshd + rfd3 * rbshd * rfd3 * tbshd)) *
6955 0 : td2 * abd1;
6956 0 : AbWinSh(2) = CosInc * FracSunLit *
6957 0 : (t1 * af2 + t1t2 * (tfshBB * rf3 * tbshBB * ab2 + rfshB * td2 * rbd1 * afd2) +
6958 0 : t1t2 * (rfshB * (1 + rbd2 * rfshd) + tfshBB * rf3 * tbshBd + tfshBd * rfd3 * tbshd) * abd2);
6959 0 : ADiffWinSh(2) = td1 * afd2 + td1td2 * rfshd * td2 * rbd1 * afd2 +
6960 0 : td1td2 * (rfshd * (1 + rbd2 * rfshd) + tfshd * rfd3 * tbshd) * abd2;
6961 0 : AbWinSh(3) = CosInc * FracSunLit *
6962 0 : (t1t2 * tfshBB * af3 + t1t2 *
6963 0 : (tfshBB * rf3 * rbshB + tfshBd * (1 + rfd3 * rbshd) +
6964 0 : rfshB * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) *
6965 : afd3);
6966 0 : ADiffWinSh(3) = td1td2 * (tfshd * (1 + rfd3 * rbshd) + rfshd * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) * afd3;
6967 0 : AbsShade = t1t2 * (afshB * (1 + tfshBB * rf3) + afshd * (tfshBd * rfd3 + rfshB * (rbd2 + td2 * rbd1 * td2)));
6968 0 : AbsShadeDiff = td1td2 * (afshd + tfshd * rfd3 * abshd + rfshd * (rfd2 + td2 * rbd2 * td2) * afshd);
6969 : } // End of check if NGlass
6970 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6971 0 : AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
6972 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * AbsShadeDiff;
6973 : } // End of check if blind is interior, exterior or between-glass
6974 : } // End of check if a blind is on
6975 :
6976 0 : if (ShadeFlag != WinShadingType::SwitchableGlazing) {
6977 : // Interior or between glass shade or blind on
6978 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6979 0 : s_surf->SurfWinA(SurfNum, Lay) = AbWinSh(Lay);
6980 : // Add contribution of diffuse from beam on outside reveal
6981 0 : if (ANY_INTERIOR_SHADE_BLIND(ShadeFlag) || ANY_BETWEENGLASS_SHADE_BLIND(ShadeFlag)) {
6982 0 : s_surf->SurfWinA(SurfNum, Lay) += ADiffWinSh(Lay) * s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum);
6983 : }
6984 : }
6985 : } else {
6986 0 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
6987 : // Switchable glazing
6988 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6989 0 : Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum);
6990 0 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay);
6991 0 : s_surf->SurfWinA(SurfNum, Lay) = Window::InterpSw(SwitchFac, AbWin(Lay), AbWinSh(Lay));
6992 : // Add contribution of diffuse from beam on outside and inside reveal
6993 0 : s_surf->SurfWinA(SurfNum, Lay) +=
6994 0 : Window::InterpSw(SwitchFac, ADiffWin, ADiffWinSh(Lay)) * s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) +
6995 0 : Window::InterpSw(SwitchFac, thisConstruct.AbsDiffBack(Lay), thisConstructSh.AbsDiffBack(Lay)) *
6996 0 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum);
6997 : }
6998 : }
6999 0 : }
7000 :
7001 16090 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
7002 : // Do not read from schedule file here since this will be called only if direct beam is hitting the window and schedule
7003 : // will not be loaded in that case even if diffuse part of solar radiation is entering through the window
7004 0 : if (FenSolAbsPtr == 0) {
7005 : // Put in the equivalent layer absorptions
7006 : // Simon: This should not be multiplied with CosInc since Abs coefficient already includes angular
7007 : // factor
7008 0 : for (int Lay = 1;
7009 0 : Lay <= s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).NLayers;
7010 : ++Lay) {
7011 0 : Real64 absBeamWin = s_surf->SurfaceWindow(SurfNum)
7012 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
7013 0 : .WinBmFtAbs(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, Lay);
7014 : Real64 AbWin =
7015 0 : absBeamWin * CosInc * SunLitFract * s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
7016 :
7017 : // Add contribution of beam reflected from outside and inside reveal
7018 0 : s_surf->SurfWinA(SurfNum, Lay) = AbWin +
7019 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) *
7020 0 : s_surf->SurfaceWindow(SurfNum)
7021 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
7022 0 : .WinFtHemAbs(Lay) +
7023 0 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) *
7024 0 : s_surf->SurfaceWindow(SurfNum)
7025 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
7026 0 : .WinBkHemAbs(Lay);
7027 : }
7028 : }
7029 :
7030 785 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
7031 : // call the ASHWAT fenestration model for optical properties
7032 : // determine the beam radiation absorptance and transmittance of the
7033 : // the equivalent layer window model
7034 785 : WindowEquivalentLayer::CalcEQLOpticalProperty(state, SurfNum, SolarArrays::BEAM, state.dataSolarShading->SurfWinAbsSolBeamEQL);
7035 785 : auto &CFS = state.dataWindowEquivLayer->CFS;
7036 : // recalculate the diffuse absorptance and transmittance of the
7037 : // the equivalent layer window model if there is shade control
7038 785 : int EQLNum = state.dataConstruction->Construct(surf.Construction).EQLConsPtr; // equivalent layer fenestration index
7039 785 : if (CFS(EQLNum).ISControlled) {
7040 320 : WindowEquivalentLayer::CalcEQLOpticalProperty(
7041 320 : state, SurfNum, SolarArrays::DIFF, state.dataSolarShading->SurfWinAbsSolDiffEQL);
7042 : } else {
7043 930 : state.dataSolarShading->SurfWinAbsSolDiffEQL(_, {1, CFS(EQLNum).NL + 1}) =
7044 1395 : state.dataWindowEquivalentLayer->CFSDiffAbsTrans(_, {1, CFS(EQLNum).NL + 1}, EQLNum);
7045 : }
7046 785 : thisConstruct.TransDiff = state.dataSolarShading->SurfWinAbsSolDiffEQL(1, CFS(EQLNum).NL + 1);
7047 :
7048 3628 : for (int Lay = 1; Lay <= CFS(EQLNum).NL + 1; ++Lay) {
7049 : // Factor for front beam radiation absorbed for equivalent layer window model
7050 2843 : Real64 AbWinEQL = state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay) * CosInc * SunLitFract *
7051 2843 : s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
7052 : ;
7053 2843 : if (CFS(EQLNum).L(1).LTYPE != LayerType::GLAZE) {
7054 : // if the first layer is not glazing (or it is a shade) do not
7055 0 : s_surf->SurfWinA(SurfNum, Lay) = AbWinEQL;
7056 : } else {
7057 : // the first layer is a glazing, include the outside reveal reflection
7058 : // and the inside reveal reflection until indoor shade layer is encountered.
7059 2843 : if (CFS(EQLNum).L(Lay).LTYPE == LayerType::GLAZE) {
7060 1570 : s_surf->SurfWinA(SurfNum, Lay) =
7061 1570 : AbWinEQL +
7062 1570 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay) +
7063 1570 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) * state.dataSolarShading->SurfWinAbsSolDiffEQL(2, Lay);
7064 : } else {
7065 2546 : s_surf->SurfWinA(SurfNum, Lay) = AbWinEQL + s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) *
7066 1273 : state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay);
7067 : }
7068 : }
7069 : }
7070 : }
7071 : } // End of SunlitFrac check
7072 :
7073 : //-----------------------------------------------------------------
7074 : // BLOCK 2
7075 : // SKY AND GROUND DIFFUSE SOLAR GAIN INTO ZONE FROM EXTERIOR WINDOW
7076 : //-----------------------------------------------------------------
7077 :
7078 : Real64 SkySolarInc =
7079 31116 : s_surf->SurfSkySolarInc(SurfNum); // Incident solar radiation on a window: sky diffuse plus beam reflected from obstruction (W/m2)
7080 31116 : Real64 DiffTrans = 0.0; // Glazing diffuse solar transmittance (including shade/blind/switching, if present)
7081 : Real64 DiffTransGnd; // Ground diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
7082 : Real64 DiffTransBmGnd; // Complex fen: diffuse solar transmittance for ground-reflected beam radiation
7083 : Real64 DiffTransSky; // Sky diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
7084 31116 : Real64 NomDiffTrans = 0.0;
7085 :
7086 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // complex fenestration
7087 0 : if (FenSolAbsPtr == 0) {
7088 : // Sky diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
7089 0 : DiffTransSky =
7090 0 : s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinSkyTrans;
7091 : // Ground diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
7092 0 : DiffTransGnd =
7093 0 : s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinSkyGndTrans;
7094 : // Complex fen: diffuse solar transmittance for ground-reflected beam radiation
7095 0 : DiffTransBmGnd = s_surf->SurfaceWindow(SurfNum)
7096 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
7097 0 : .WinBmGndTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
7098 : // Define the effective transmittance for total sky and ground radiation
7099 0 : if ((SkySolarInc + s_surf->SurfWinBmGndSolarInc(SurfNum) + s_surf->SurfWinSkyGndSolarInc(SurfNum)) != 0.0) {
7100 0 : DiffTrans = (SkySolarInc * DiffTransSky + s_surf->SurfWinBmGndSolarInc(SurfNum) * DiffTransBmGnd +
7101 0 : s_surf->SurfWinSkyGndSolarInc(SurfNum) * DiffTransGnd) /
7102 0 : (SkySolarInc + s_surf->SurfWinBmGndSolarInc(SurfNum) + s_surf->SurfWinSkyGndSolarInc(SurfNum));
7103 : }
7104 : // Also update the nominal diffuse transmittance
7105 0 : NomDiffTrans =
7106 0 : s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinDiffTrans;
7107 : // Do not store in TransDiff because it is not used by BSDF and rest of the code uses it as flag for opaque
7108 : // surface incorrectly assuming wall heat transfer routines for windows.
7109 : // Construct( Surface( SurfNum ).Construction ).TransDiff = NomDiffTrans;
7110 : }
7111 31116 : } else if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
7112 0 : DiffTrans = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso);
7113 : } else {
7114 31116 : DiffTrans = thisConstruct.TransDiff;
7115 : }
7116 :
7117 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
7118 29742 : if (IS_SHADED_NO_GLARE_CTRL(s_surf->SurfWinShadingFlag(SurfNum))) {
7119 0 : auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
7120 0 : if (ShadeFlag != WinShadingType::SwitchableGlazing) {
7121 : // Shade or blind
7122 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
7123 : // Shade or screen
7124 0 : DiffTrans = constrSh.TransDiff;
7125 : } else {
7126 : // Blind
7127 0 : int slatIdxLo = surfShade.blind.slatAngIdxLo;
7128 0 : int slatIdxHi = surfShade.blind.slatAngIdxHi;
7129 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
7130 :
7131 0 : auto const &btarLo = constrSh.blindTARs[slatIdxLo];
7132 0 : auto const &btarHi = constrSh.blindTARs[slatIdxHi];
7133 :
7134 0 : DiffTrans = Interp(btarLo.Sol.Ft.Df.Tra, btarHi.Sol.Ft.Df.Tra, slatInterpFac);
7135 :
7136 : // For blinds with horizontal slats, allow different diffuse/diffuse transmittance for
7137 : // ground and sky solar
7138 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
7139 0 : assert(matBlind != nullptr);
7140 0 : if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
7141 0 : DiffTransGnd = Interp(btarLo.Sol.Ft.Df.TraGnd, btarHi.Sol.Ft.Df.TraGnd, slatInterpFac);
7142 0 : DiffTransSky = Interp(btarLo.Sol.Ft.Df.TraSky, btarHi.Sol.Ft.Df.TraSky, slatInterpFac);
7143 : }
7144 : }
7145 :
7146 : } else { // Switchable glazing
7147 :
7148 0 : Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum); // Switching factor for a window
7149 0 : DiffTrans = Window::InterpSw(SwitchFac, thisConstruct.TransDiff, constrSh.TransDiff);
7150 : }
7151 : }
7152 : }
7153 :
7154 : // Reporting variables
7155 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
7156 29742 : s_surf->SurfWinBlGlSysTsolDifDif(SurfNum) = DiffTrans;
7157 29742 : s_surf->SurfWinScGlSysTsolDifDif(SurfNum) = DiffTrans;
7158 29742 : if (ANY_BLIND(ShadeFlag) || ShadeFlag == WinShadingType::ExtScreen) {
7159 0 : s_surf->SurfWinBlGlSysTsolDifDif(SurfNum) = DiffTrans;
7160 0 : s_surf->SurfWinScGlSysTsolDifDif(SurfNum) = DiffTrans;
7161 0 : if (ShadeFlag == WinShadingType::ExtScreen) {
7162 0 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
7163 0 : assert(screen != nullptr);
7164 0 : s_surf->SurfWinScTsolDifDif(SurfNum) = screen->DfTrans;
7165 : } else {
7166 0 : s_surf->SurfWinBlTsolDifDif(SurfNum) = FrontDiffDiffTrans;
7167 : }
7168 : }
7169 : }
7170 :
7171 : //-----------------------------------------------------------------
7172 : // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
7173 : //-----------------------------------------------------------------
7174 31116 : Real64 TBmBm = 0.0; // Beam-beam solar transmittance for bare window or window with switchable glazing
7175 31116 : Real64 TBmDif = 0.0; // Beam-diffuse solar transmittance for bare window with diffusing glass
7176 31116 : Real64 TBmAllShBlSc = 0.0; // Beam-beam + beam-diffuse transmittance for window with shade, blind, screen, or switchable glazing
7177 31116 : Real64 TBmBmShBlSc = 0.0; // Beam-beam transmittance for window with shade, blind, screen, or switchable glazing
7178 31116 : Real64 TBmDifShBlSc = 0.0; // Beam-diffuse transmittance for window with shade, blind, screen, or switchable glazing
7179 : Real64 TBmBmBl; // Beam-beam transmittance for window with blind
7180 : Real64 TBmBmSc; // Beam-beam transmittance for window with screen
7181 : Real64 TDifBare; // Bare diffuse transmittance of exterior window
7182 : // Beam-beam transmittance for bare exterior window
7183 31116 : if (SunLitFract > 0.0) {
7184 16092 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
7185 0 : TBmDif = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarBeam);
7186 0 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolBeam = TBmDif; // Report variable
7187 16092 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) { // Regular window
7188 15307 : if (!s_surf->SurfWinSolarDiffusing(SurfNum)) { // Clear glazing
7189 15307 : TBmBm = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef); //[-]
7190 : } else { // Diffusing glazing
7191 0 : TBmDif = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef); //[-]
7192 : }
7193 785 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
7194 : // Need to check what effect, if any, defining these here has
7195 0 : TBmBm = s_surf->SurfaceWindow(SurfNum)
7196 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
7197 0 : .WinDirSpecTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
7198 0 : TBmDif = s_surf->SurfaceWindow(SurfNum)
7199 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
7200 0 : .WinDirHemiTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep) -
7201 : TBmBm;
7202 785 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
7203 : // get ASHWAT fenestration model beam-beam and beam-diffuse properties
7204 785 : int EQLNum = state.dataConstruction->Construct(surf.Construction).EQLConsPtr; // equivalent layer fenestration index
7205 785 : Real64 TBmBmEQL = state.dataSolarShading->SurfWinAbsSolBeamEQL(1, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1);
7206 : // Beam-diffuse transmittance
7207 785 : Real64 TBmDiffEQL = max(0.0, state.dataSolarShading->SurfWinAbsSolBeamEQL(2, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1));
7208 : // Beam-beam transmittance: difference between beam-total and beam-diffuse transmittance
7209 785 : TBmBmEQL = max(0.0, (TBmBmEQL - TBmDiffEQL));
7210 785 : TBmBm = TBmBmEQL;
7211 785 : TBmDif = TBmDiffEQL;
7212 : }
7213 : }
7214 : // Diffuse-diffuse transmittance for bare exterior window
7215 31116 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
7216 0 : TDifBare = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso);
7217 : } else {
7218 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
7219 : // Complex Fenestration: use hemispherical ave of directional-hemispherical transmittance
7220 : // Note: this is not quite the same as the effective transmittance for total of sky and ground radiation
7221 0 : TDifBare = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinDiffTrans;
7222 : } else { // Regular window
7223 31116 : TDifBare = thisConstruct.TransDiff;
7224 : }
7225 : }
7226 :
7227 : //-----------------------------------------------------------------
7228 : // BLOCK 3 - SCREEN, BLINDS AND GLAZING SYSTEM BEAM SOLAR TRANSMITTANCE
7229 : //-----------------------------------------------------------------
7230 31116 : if (ConstrNumSh != 0 && SunLitFract > 0.0) {
7231 6440 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
7232 6440 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
7233 6440 : if (IS_SHADED_NO_GLARE_CTRL(ShadeFlag)) {
7234 : // Shade or screen or blind on, or switchable glazing
7235 : // (note in the following that diffusing glass is not oallowed in a window with shade, blind or switchable glazing)
7236 0 : if (ANY_SHADE(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
7237 : // Shade on or switchable glazing
7238 0 : TBmAllShBlSc = Window::POLYF(CosInc, thisConstructSh.TransSolBeamCoef);
7239 : } else {
7240 : // Blind or Screen on
7241 : Real64 TScBmDif; // Beam-diffuse solar transmittance of screen
7242 : Real64 TBlBmDif; // Beam-diffuse solar transmittance of blind
7243 : Real64 TBlDifDif; // Diffuse-diffuse solar transmittance of blind
7244 : Real64 TScBmBm;
7245 : Real64 TBlBmBm;
7246 0 : if (ShadeFlag == WinShadingType::ExtScreen) { // Exterior screen
7247 0 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
7248 0 : assert(screen != nullptr);
7249 :
7250 0 : auto &surf = s_surf->Surface(SurfNum);
7251 0 : Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
7252 0 : Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
7253 0 : Real64 winPhi = surf.Tilt * Constant::DegToRad;
7254 0 : Real64 winTheta = surf.Azimuth * Constant::DegToRad;
7255 0 : Real64 phi = std::abs(solPhi - winPhi);
7256 0 : Real64 theta = std::abs(solTheta - winTheta);
7257 0 : Material::NormalizePhiTheta(phi, theta);
7258 : #ifdef PRECALC_INTERP_SCREEN
7259 : int ip1, ip2, it1, it2;
7260 : BilinearInterpCoeffs coeffs;
7261 0 : Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
7262 0 : GetBilinearInterpCoeffs(
7263 0 : phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
7264 0 : auto const &b11 = screen->btars[ip1][it1];
7265 0 : auto const &b12 = screen->btars[ip1][it2];
7266 0 : auto const &b21 = screen->btars[ip2][it1];
7267 0 : auto const &b22 = screen->btars[ip2][it2];
7268 :
7269 0 : Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
7270 0 : Real64 RScDifBack = screen->DfRef;
7271 :
7272 0 : Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Beam front reflectance of glass
7273 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
7274 : // beam transmittance (written in subroutine CalcScreenTransmittance each time step)
7275 0 : TScBmBm = BilinearInterp(b11.BmTrans, b12.BmTrans, b21.BmTrans, b22.BmTrans, coeffs);
7276 0 : TBmBmSc = TBmBm * TScBmBm;
7277 0 : TScBmDif = BilinearInterp(b11.DfTrans, b12.DfTrans, b21.DfTrans, b22.DfTrans, coeffs);
7278 : // beam-beam and diffuse transmittance of exterior beam
7279 0 : TBmAllShBlSc = TScBmBm * (TBmBm + RGlBmFr * RScBack * TDifBare / (1 - RGlDifFr * RScDifBack)) +
7280 0 : TScBmDif * TDifBare / (1 - RGlDifFr * RScDifBack);
7281 0 : TBmBmShBlSc = TBmBmSc;
7282 0 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7283 : // Report variable for Beam-to-Diffuse transmittance (scattered transmittance)
7284 0 : s_surf->SurfWinScGlSysTsolBmBm(SurfNum) = TBmBmSc;
7285 0 : s_surf->SurfWinScTsolBmBm(SurfNum) = TScBmBm;
7286 0 : s_surf->SurfWinScTsolBmDif(SurfNum) = TScBmDif;
7287 : #else // !PRECALC_INTERP_SCREEN
7288 : Material::ScreenBmTransAbsRef btar;
7289 : CalcScreenTransmittance(state, screen, phi, theta, btar);
7290 :
7291 : Real64 RScBack = btar.RefSolFront;
7292 : Real64 RScDifBack = screen->DfRef;
7293 :
7294 : Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Beam front reflectance of glass
7295 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
7296 : // beam transmittance (written in subroutine CalcScreenTransmittance each time step)
7297 : TScBmBm = btar.BmTrans;
7298 : TBmBmSc = TBmBm * TScBmBm;
7299 : TScBmDif = btar.DfTrans;
7300 : // beam-beam and diffuse transmittance of exterior beam
7301 : TBmAllShBlSc = TScBmBm * (TBmBm + RGlBmFr * RScBack * TDifBare / (1 - RGlDifFr * RScDifBack)) +
7302 : TScBmDif * TDifBare / (1 - RGlDifFr * RScDifBack);
7303 : TBmBmShBlSc = TBmBmSc;
7304 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7305 : // Report variable for Beam-to-Diffuse transmittance (scattered transmittance)
7306 : s_surf->SurfWinScGlSysTsolBmBm(SurfNum) = TBmBmSc;
7307 : s_surf->SurfWinScTsolBmBm(SurfNum) = TScBmBm;
7308 : s_surf->SurfWinScTsolBmDif(SurfNum) = TScBmDif;
7309 : #endif // PRECALC_INTERP_SCREEN
7310 : } else {
7311 0 : TBlBmBm = surfShade.blind.bmBmTrans;
7312 0 : TBlBmDif = FrontBeamDiffTrans;
7313 0 : if (ShadeFlag == WinShadingType::IntBlind) {
7314 0 : Real64 RhoBlBmDifFr = FrontBeamDiffRefl; // Beam-diffuse front reflectance of blind
7315 0 : Real64 RGlDifBk = thisConstruct.ReflectSolDiffBack; // Diffuse front reflectance of glass
7316 0 : Real64 RhoBlDifDifFr = FrontDiffDiffRefl; // Diffuse-diffuse front reflectance of blind
7317 : // beam-beam and diffuse transmittance of exterior beam
7318 0 : TBmBmBl = TBmBm * TBlBmBm;
7319 0 : TBlDifDif = FrontDiffDiffTrans;
7320 0 : TBmAllShBlSc =
7321 0 : TBmBm * (TBlBmBm + TBlBmDif + TBlDifDif * RhoBlBmDifFr * RGlDifBk / (1 - RhoBlDifDifFr * RGlDifBk));
7322 0 : TBmBmShBlSc = TBmBmBl; // TBmBm * TBlBmBm
7323 0 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7324 0 : if (TBmDifShBlSc < 0.0) {
7325 0 : TBmDifShBlSc = 0.0;
7326 : }
7327 0 : } else if (ShadeFlag == WinShadingType::ExtBlind) {
7328 0 : Real64 RhoBlBmDifBk = BackBeamDiffRefl; // Beam-diffuse back reflectance of blind
7329 0 : Real64 RhoBlDifDifBk = BackDiffDiffRefl; // Diffuse-diffuse back reflectance of blind
7330 0 : Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef);
7331 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
7332 : // beam-beam and diffuse transmittance of exterior beam
7333 0 : TBmBmBl = TBmBm * TBlBmBm;
7334 0 : TBmAllShBlSc = TBlBmBm * (TBmBm + TDifBare * RGlBmFr * RhoBlBmDifBk / (1 - RGlDifFr * RhoBlDifDifBk)) +
7335 0 : TBlBmDif * TDifBare / (1 - RGlDifFr * RhoBlDifDifBk);
7336 0 : TBmBmShBlSc = TBmBmBl; // TBmBm * TBlBmBm
7337 0 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7338 : } else {
7339 : // Between-glass blind on
7340 0 : int NGlass = thisConstruct.TotGlassLayers;
7341 0 : Real64 td2 = thisConstruct.tBareSolDiff(2);
7342 0 : Real64 rbd1 = thisConstruct.rbBareSolDiff(1);
7343 0 : Real64 rbshB = BackBeamDiffRefl;
7344 0 : Real64 rfshd = FrontDiffDiffRefl;
7345 0 : Real64 rbshd = BackDiffDiffRefl;
7346 0 : Real64 tfshBd = FrontBeamDiffTrans;
7347 0 : Real64 t1 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(1));
7348 0 : Real64 t2 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(2));
7349 0 : Real64 tfshBB = surfShade.blind.bmBmTrans;
7350 0 : if (NGlass == 2) {
7351 0 : Real64 rf2 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(2));
7352 0 : Real64 rfshB = FrontBeamDiffRefl;
7353 0 : Real64 rfd2 = thisConstruct.rfBareSolDiff(2);
7354 0 : TBmBmBl = t1 * tfshBB * t2;
7355 0 : TBmAllShBlSc = t1 * tfshBB * t2 +
7356 0 : t1 * (tfshBB * rf2 * rbshB + tfshBd * (1.0 + rfd2 * rbshd) + rfshB * rbd1 * rfshd) * td2;
7357 : } else { // NGlass = 3
7358 0 : Real64 t1t2 = t1 * t2;
7359 0 : Real64 t3 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(3));
7360 0 : Real64 td3 = thisConstruct.tBareSolDiff(3);
7361 0 : Real64 rf3 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(3));
7362 0 : Real64 rbd2 = thisConstruct.rbBareSolDiff(2);
7363 0 : Real64 rfd3 = thisConstruct.rfBareSolDiff(3);
7364 0 : Real64 tfshd = FrontDiffDiffTrans;
7365 0 : TBmBmBl = t1 * t2 * tfshBB * t3;
7366 0 : TBmAllShBlSc = t1t2 * tfshBB * t3 + t1t2 *
7367 0 : (tfshBB * rf3 * rbshB + tfshBd * (1.0 + rfd3 * rbshd) +
7368 0 : rbshB * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) *
7369 : td3;
7370 : }
7371 : // added TH 12/9/2009
7372 0 : TBmBmShBlSc = TBmBmBl;
7373 0 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7374 : }
7375 0 : s_surf->SurfWinBlTsolBmBm(SurfNum) = TBlBmBm;
7376 0 : s_surf->SurfWinBlTsolBmDif(SurfNum) = TBlBmDif;
7377 0 : s_surf->SurfWinBlGlSysTsolBmBm(SurfNum) = TBmBmBl;
7378 : }
7379 : }
7380 : } // End of check if ShadeFlag > 0 and ShadeFlag < 10
7381 : } // end of checking if not eql window model
7382 : } // end of checking if sunlitfract > 0
7383 :
7384 31116 : if (ShadeFlag == WinShadingType::SwitchableGlazing) {
7385 : // Switchable glazing
7386 0 : Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum);
7387 0 : if (!s_surf->SurfWinSolarDiffusing(SurfNum)) {
7388 0 : TBmBm = Window::InterpSw(SwitchFac, TBmBm, TBmAllShBlSc);
7389 : } else {
7390 0 : TBmDif = Window::InterpSw(SwitchFac, TBmDif, TBmAllShBlSc);
7391 : }
7392 : }
7393 : // Report variables
7394 31116 : s_surf->SurfWinGlTsolBmBm(SurfNum) = TBmBm;
7395 31116 : s_surf->SurfWinGlTsolBmDif(SurfNum) = TBmDif;
7396 31116 : s_surf->SurfWinGlTsolDifDif(SurfNum) = TDifBare;
7397 :
7398 : //-----------------------------------------------------------------
7399 : // BLOCK 4 - REPORT WINDOW TRANSMITTANCE
7400 : //-----------------------------------------------------------------
7401 :
7402 : // The following SurfWinTransBmSolar and SurfWinTransDifSolar will be combined later to give
7403 : // WinTransSolar for reporting
7404 31116 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = 0.0;
7405 31116 : state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = 0.0;
7406 31116 : state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = 0.0;
7407 31116 : state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = 0.0;
7408 31116 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) =
7409 : 0.0; // Factor for exterior beam to beam solar transmitted through window, or window plus shade, into zone at current time (m2)
7410 31116 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) =
7411 : 0.0; // Factor for exterior beam to diffuse solar transmitted through window, or window plus shade, into zone at current time (m2)
7412 :
7413 31116 : Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
7414 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
7415 29742 : state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = DiffTrans * surf.Area;
7416 29742 : if (ANY_BLIND(ShadeFlag)) {
7417 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
7418 0 : assert(matBlind != nullptr);
7419 0 : if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
7420 0 : state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = DiffTransGnd * surf.Area;
7421 0 : state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = DiffTransSky * surf.Area;
7422 : }
7423 : }
7424 : } else {
7425 : // In equivalent layer window model system diffuse transmittance is based on unit
7426 : // diffuse radiation flux, and hence doesn't distinguish between sky and
7427 : // ground reflected diffuse radiations
7428 1374 : state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = DiffTrans * surf.Area;
7429 1374 : state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = DiffTrans * surf.Area;
7430 1374 : state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = DiffTrans * surf.Area;
7431 : }
7432 :
7433 31116 : if (!IS_SHADED_NO_GLARE_CTRL(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
7434 : // Unshaded or switchable glazing
7435 : // Note: with previous defs of TBmBm & TBmDif, these come out right for Complex Fenestration
7436 : // SurfWinTransBmSolar uses the directional-hemispherical transmittance
7437 31116 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = (TBmBm + TBmDif) * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7438 31116 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBm * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7439 31116 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDif * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7440 :
7441 : } else {
7442 0 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = TBmAllShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7443 0 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBmShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7444 0 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDifShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7445 : }
7446 :
7447 : // Add diffuse transmitted by window from beam reflected from outside reveal
7448 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // Complex Fenestration
7449 0 : if (FenSolAbsPtr == 0) {
7450 0 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = (TBmBm + TBmDif) * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7451 0 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBm * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7452 0 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDif * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7453 0 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) +=
7454 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
7455 0 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) +=
7456 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
7457 : } else {
7458 0 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = 0.0;
7459 0 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = 0.0;
7460 : }
7461 : } else { // Regular window
7462 : // this is also valid for equivalent layer window
7463 31116 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) += s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
7464 31116 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) += s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
7465 : }
7466 :
7467 : //-----------------------------------------------------------------
7468 : // BLOCK 5 - UPDATE SOLAR ENTERING A ZONE AS BEAM OR DIFFUSE RADIATION
7469 : //-----------------------------------------------------------------
7470 : // Increment factor for total exterior beam solar entering zone through window as beam or diffuse
7471 31116 : if (SunLitFract > 0.0 && surf.Class != SurfaceClass::TDD_Dome) {
7472 : // Window is schedule surface gained. Do not make addition to what enters into zone since that information is not available
7473 16092 : if (FenSolAbsPtr == 0) {
7474 : Real64 TBmAll; // Window beam-to-(beam+diffuse) transmittance
7475 16092 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::BSDF && (ANY_BLIND(ShadeFlag) || ANY_SHADE_SCREEN(ShadeFlag))) {
7476 0 : TBmAll = TBmAllShBlSc;
7477 : } else {
7478 16092 : TBmAll = TBmBm + TBmDif;
7479 : }
7480 16092 : BTOTZone += surf.IncSolMultiplier * TBmAll * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // [m2]
7481 : }
7482 : }
7483 :
7484 : // Correct for effect of (1) beam absorbed by inside reveal, (2) diffuse entering zone from beam
7485 : // reflected by inside reveal and (3) diffuse transmitted by window from beam reflected from outside reveal.
7486 31116 : if (CosInc > 0.0) {
7487 : // The BTOTZone is the solar into zone assuming no inside or outside reveals
7488 : // The inside reveals receive solar (reflected part + absorbed part) from the window, this amount should be deducted from the
7489 : // BTOTZone, then adds the InsRevealDiffIntoZone
7490 16820 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // Complex Fenestration
7491 : // Do not add total into zone from scheduled surface gains. That will be added later
7492 0 : if (SurfaceScheduledSolarInc(state, SurfNum, ConstrNum) == 0) {
7493 0 : BTOTZone = BTOTZone - s_surf->SurfWinBmSolRefldInsReveal(SurfNum) - s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +
7494 0 : s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) +
7495 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
7496 : }
7497 : } else { // Regular window
7498 16820 : BTOTZone = BTOTZone - s_surf->SurfWinBmSolRefldInsReveal(SurfNum) - s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +
7499 16820 : s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) +
7500 16820 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
7501 : }
7502 : // Add beam solar absorbed by outside reveal to outside of window's base surface. Add beam solar absorbed by inside reveal to inside
7503 : // of window's base surface. This ignores 2-D heat transfer effects.
7504 16820 : int BaseSurfNum = surf.BaseSurf;
7505 16820 : s_surf->SurfOpaqAI(BaseSurfNum) += s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / s_surf->Surface(BaseSurfNum).Area;
7506 16820 : s_surf->SurfOpaqAO(BaseSurfNum) += s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) / s_surf->Surface(BaseSurfNum).Area;
7507 : }
7508 :
7509 : //-----------------------------------------------------------------
7510 : // BLOCK 6 - INTERIOR BEAM FROM EXTERIOR WINDOW THAT IS ABSORBED/TRANSMITTED BY BACK SURFACES
7511 : //-----------------------------------------------------------------
7512 :
7513 : // If shade is in place or there is a diffusing glass layer there is no interior beam
7514 : // from this exterior window since the beam-beam transmittance of shades and diffusing glass
7515 : // is assumed to be zero. The beam-beam transmittance of tubular daylighting devices is also
7516 : // assumed to be zero.
7517 31116 : if (SunLitFract > 0.0) {
7518 16092 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::BSDF) {
7519 32184 : if (ANY_SHADE(ShadeFlag) || s_surf->SurfWinSolarDiffusing(SurfNum) || surf.OriginalClass == SurfaceClass::TDD_Diffuser ||
7520 16092 : surf.Class == SurfaceClass::TDD_Dome) {
7521 0 : continue;
7522 : }
7523 : }
7524 :
7525 : // Find interior beam radiation that is:
7526 : // (1) absorbed by opaque back surfaces;
7527 : // (2) absorbed by glass layers of back surfaces that are interior or exterior windows;
7528 : // (3) absorbed by interior, exterior or between-glass shades or blinds of back surfaces
7529 : // that are exterior windows; and
7530 : // (4) transmitted through back surfaces that are interior or exterior windows.
7531 : // Beam-beam transmittance of exterior window
7532 : Real64 TBm; // Window beam-beam transmittance
7533 : Real64 TBmDenom; // TBmDenominator
7534 16092 : Real64 TBmBmSc = s_surf->SurfWinScGlSysTsolBmBm(SurfNum);
7535 16092 : Real64 TBmBmBl = s_surf->SurfWinBlGlSysTsolBmBm(SurfNum);
7536 16092 : Real64 TBmBm = s_surf->SurfWinGlTsolBmBm(SurfNum);
7537 :
7538 16092 : Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
7539 16092 : int InShelfSurf = 0; // Inside daylighting shelf surface number
7540 16092 : int ShelfNum = s_surf->SurfDaylightingShelfInd(SurfNum);
7541 16092 : if (ShelfNum > 0) { // Daylighting shelf
7542 0 : InShelfSurf = state.dataDaylightingDevicesData->Shelf(ShelfNum).InSurf;
7543 : }
7544 16092 : if (ANY_BLIND(ShadeFlag)) {
7545 0 : TBm = TBmBmBl; // Interior, exterior or between-glass blind on
7546 16092 : } else if (ShadeFlag == WinShadingType::ExtScreen) {
7547 0 : TBm = TBmBmSc; // Exterior screen on
7548 : } else {
7549 16092 : TBm = TBmBm; // Bare glass or switchable glazing
7550 : // Correction for beam absorbed by inside reveal
7551 16092 : TBmDenom = (SunLitFract * CosInc * surf.Area * InOutProjSLFracMult);
7552 16092 : if (TBmDenom != 0.0) { // when =0.0, no correction
7553 16081 : TBm -= s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / TBmDenom;
7554 : }
7555 16092 : TBm = max(0.0, TBm);
7556 : // this multiplier doesn't work with other shading, so no need to apply in other branches
7557 16092 : TBm *= surf.IncSolMultiplier;
7558 : }
7559 :
7560 16092 : if (TBm == 0.0) {
7561 309 : continue;
7562 : }
7563 15783 : if (InShelfSurf > 0) { // Inside daylighting shelf
7564 : // Inside daylighting shelves assume that no beam will pass the end of the shelf.
7565 : // Since all beam is absorbed on the shelf, this might cause them to get unrealistically hot at times.
7566 : // BTOTWinZone - Transmitted beam solar factor for a window [m2]
7567 0 : Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * InOutProjSLFracMult;
7568 : // Shelf surface area is divided by 2 because only one side sees beam (Area was multiplied by 2 during init)
7569 0 : s_surf->SurfOpaqAI(InShelfSurf) += BTOTWinZone / (0.5 * s_surf->Surface(InShelfSurf).Area); //[-]
7570 0 : BABSZone += BTOTWinZone; //[m2]
7571 0 : continue;
7572 0 : }
7573 :
7574 15783 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) { // Full interior solar distribution
7575 2997 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
7576 : // Loop over back surfaces irradiated by beam from this exterior window
7577 8220 : for (int IBack = 1; IBack <= state.dataBSDFWindow->MaxBkSurf; ++IBack) {
7578 : int BackSurfNum =
7579 8220 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
7580 8220 : if (BackSurfNum == 0) {
7581 2997 : break; // No more irradiated back surfaces for this exterior window
7582 : }
7583 :
7584 5223 : auto &surfShadeBack = s_surf->surfShades(BackSurfNum);
7585 5223 : int ConstrNumBack = s_surf->SurfActiveConstruction(BackSurfNum);
7586 5223 : auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
7587 :
7588 5223 : int NBackGlass = constrBack.TotGlassLayers;
7589 : // Irradiated (overlap) area for this back surface, projected onto window plane
7590 : // (includes effect of shadowing on exterior window)
7591 : Real64 AOverlap =
7592 5223 : state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
7593 : // Back surface area irradiated by beam solar from an exterior window, projected onto window plane
7594 5223 : Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
7595 : // AOverlap multiplied by exterior window beam transmittance and cosine of incidence angle
7596 5223 : if (constrBack.TransDiff <= 0.0) {
7597 :
7598 : // Back surface is opaque interior or exterior wall
7599 : // Interior solar absorptance of opaque surface
7600 5222 : Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
7601 5222 : s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
7602 5222 : BABSZone += BOverlap * AbsIntSurf; //[m2]
7603 :
7604 : } else {
7605 :
7606 : // Back surface is an interior or exterior window
7607 : // Note that exterior back windows can have a shading device but interior back windows
7608 : // are assumed to be bare, i.e., they have no shading device and are non-switchable.
7609 : // The layer order for interior windows is "outside" to "inside," where "outside" refers to
7610 : // the adjacent zone and "inside" refers to the current zone.
7611 1 : WinShadingType ShadeFlagBack = s_surf->SurfWinShadingFlag(BackSurfNum);
7612 1 : Real64 slatAngBack = surfShadeBack.blind.slatAng;
7613 : Real64 CosIncBack =
7614 1 : std::abs(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, BackSurfNum));
7615 1 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
7616 : // Transmitting window is complex fen, change the incident angle to one for ray joining
7617 : // transmitting and back window centers
7618 0 : CosIncBack = std::abs(state.dataBSDFWindow->ComplexWind(SurfNum).sdotN(IBack));
7619 : }
7620 1 : int ConstrNumBackShRaw = s_surf->SurfWinActiveShadedConstruction(BackSurfNum);
7621 1 : int const ConstrNumBackSh = ConstrNumBackShRaw == 0 ? ConstrNumBack : ConstrNumBackShRaw;
7622 1 : state.dataSolarShading->SurfWinAbsBeam.dimension(state.dataHeatBal->MaxSolidWinLayers, 0.0);
7623 1 : Real64 TransBeamWin = 0.0; // Beam solar transmittance of a window
7624 1 : Real64 AbsBeamTotWin = 0.0; // Sum of window glass layer beam solar absorptances
7625 1 : Real64 backSurfBeamSolInTrans = 0.0; // Fraction of BeamSolarRad transmitted out through window inside face [W]
7626 :
7627 : // Interior beam absorptance of glass layers and beam transmittance of back exterior &
7628 : // or interior window WITHOUT SHADING this timestep
7629 1 : if (NOT_SHADED(ShadeFlagBack)) {
7630 3 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7631 2 : state.dataSolarShading->SurfWinAbsBeam(Lay) = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
7632 : }
7633 1 : TransBeamWin = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
7634 : }
7635 :
7636 : // Interior beam absorptance of glass layers and beam transmittance
7637 : // of back exterior window with SHADE
7638 1 : if (ANY_SHADE(ShadeFlagBack)) {
7639 0 : for (int Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNumBackSh).TotGlassLayers; ++Lay) {
7640 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7641 0 : Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).AbsBeamBackCoef(Lay));
7642 : }
7643 0 : TransBeamWin = Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).TransSolBeamCoef);
7644 : }
7645 :
7646 : // Interior beam absorbed by INTERIOR SHADE of back exterior window
7647 1 : if (ShadeFlagBack == WinShadingType::IntShade) {
7648 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7649 0 : BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade /
7650 0 : (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7651 0 : BABSZone += BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade;
7652 0 : backSurfBeamSolInTrans += BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade;
7653 :
7654 : // Interior beam absorbed by EXTERIOR SHADE of back exterior window
7655 1 : } else if (ShadeFlagBack == WinShadingType::ExtShade) {
7656 0 : Real64 RGlFront = constrBack.ReflectSolDiffFront;
7657 0 : auto const *matSh = s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(1));
7658 0 : auto const *matFenSh = dynamic_cast<Material::MaterialFen const *>(matSh);
7659 0 : assert(matFenSh != nullptr);
7660 :
7661 0 : Real64 AbsSh = matFenSh->AbsorpSolar;
7662 0 : Real64 RhoSh = 1.0 - AbsSh - matFenSh->Trans;
7663 0 : Real64 AShBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef) * AbsSh / (1.0 - RGlFront * RhoSh);
7664 0 : BABSZone += BOverlap * AShBack;
7665 0 : backSurfBeamSolInTrans += BOverlap * AShBack;
7666 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7667 0 : BOverlap * AShBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7668 :
7669 : // Interior beam absorbed by BETWEEN-GLASS SHADE of back exterior window
7670 1 : } else if (ShadeFlagBack == WinShadingType::BGShade) {
7671 0 : Real64 rbd1k = constrBack.rbBareSolDiff(1);
7672 0 : Real64 rfd2k = constrBack.rfBareSolDiff(2);
7673 : Real64 AShBack; // System shade absorptance for interior beam solar
7674 0 : if (NBackGlass == 2) {
7675 0 : Real64 t2k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(2));
7676 0 : auto const *matShade = dynamic_cast<Material::MaterialShade const *>(
7677 0 : s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(3)));
7678 0 : assert(matShade != nullptr);
7679 0 : Real64 TrSh = matShade->Trans; // Shade material solar transmittance
7680 0 : Real64 RhoSh = matShade->ReflectShade; // Shade material solar absorptance
7681 0 : Real64 AbsSh = min(1.0, max(0.0, 1 - TrSh - RhoSh)); // Shade material solar absorptance
7682 0 : AShBack = t2k * (1 + RhoSh * rfd2k + TrSh * rbd1k) * AbsSh;
7683 : } else { // NBackGlass = 3
7684 0 : Real64 t3k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(3));
7685 0 : Real64 td2k = constrBack.tBareSolDiff(2);
7686 0 : Real64 rbd2k = constrBack.rbBareSolDiff(2);
7687 0 : Real64 rfd3k = constrBack.rfBareSolDiff(3);
7688 0 : auto const *matShade = dynamic_cast<Material::MaterialShade const *>(
7689 0 : s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(5)));
7690 0 : assert(matShade != nullptr);
7691 0 : Real64 TrSh = matShade->Trans;
7692 0 : Real64 RhoSh = matShade->ReflectShade;
7693 0 : Real64 AbsSh = min(1.0, max(0.0, 1 - TrSh - RhoSh));
7694 0 : AShBack = t3k * (1 + RhoSh * rfd3k + TrSh * (rbd2k + td2k * rbd1k * td2k)) * AbsSh;
7695 : }
7696 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7697 0 : BOverlap * AShBack / s_surf->Surface(BackSurfNum).Area;
7698 0 : BABSZone += BOverlap * AShBack;
7699 0 : backSurfBeamSolInTrans += BOverlap * AShBack;
7700 : }
7701 :
7702 : // Interior beam absorptance of glass layers and beam absorbed in blind
7703 : // of back exterior window with BLIND
7704 1 : if (ANY_BLIND(ShadeFlagBack)) {
7705 0 : auto const &btarBack = surfShadeBack.blind.TAR;
7706 : auto const *matBlindBack =
7707 0 : dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShadeBack.blind.matNum));
7708 0 : assert(matBlindBack != nullptr);
7709 :
7710 0 : auto const &btar = surfShade.blind.TAR;
7711 0 : Real64 profAngBack = surfShadeBack.blind.profAng;
7712 :
7713 0 : int profIdxLoBack = surfShadeBack.blind.profAngIdxLo;
7714 0 : int profIdxHiBack = surfShadeBack.blind.profAngIdxHi;
7715 0 : Real64 profInterpFacBack = surfShadeBack.blind.profAngInterpFac;
7716 :
7717 0 : Real64 TGlBmBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
7718 0 : Real64 TBlBmBmBack = matBlindBack->BeamBeamTrans(profAngBack, Constant::Pi - slatAngBack);
7719 :
7720 : // Blind solar back beam-diffuse transmittance
7721 : // Is this supposed to be blindBack?
7722 : Real64 TBlBmDiffBack =
7723 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfTra, btar.Sol.Bk.Bm[profIdxLoBack].DfTra, profInterpFacBack);
7724 :
7725 0 : if (ShadeFlagBack == WinShadingType::IntBlind) {
7726 : // Interior beam absorptance of GLASS LAYERS of exterior back window with INTERIOR BLIND
7727 0 : FrontDiffDiffRefl = btarBack.Sol.Ft.Df.Ref; // Blind solar front beam reflectance
7728 0 : FrontDiffAbs = btarBack.Sol.Ft.Df.Abs;
7729 : Real64 RhoBlFront =
7730 0 : Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfRef, btar.Sol.Ft.Bm[profIdxHiBack].DfRef, profInterpFacBack);
7731 : Real64 AbsBlFront =
7732 0 : Interp(btar.Sol.Ft.Bm[profIdxLoBack].Abs, btar.Sol.Ft.Bm[profIdxHiBack].Abs, profInterpFacBack);
7733 : Real64 AbsBlBack =
7734 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
7735 :
7736 0 : Real64 RhoBlDiffFront = FrontDiffDiffRefl; // Glazing system solar back beam-beam reflectance
7737 0 : Real64 RGlBack = Window::POLYF(
7738 0 : CosIncBack, constrBack.ReflSolBeamBackCoef); // Glazing system back diffuse solar reflectance
7739 0 : Real64 RGlDiffBack = constrBack.ReflectSolDiffBack;
7740 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7741 0 : Real64 AbWinBack = Window::POLYF(
7742 : CosIncBack,
7743 : constrBack.AbsBeamBackCoef(Lay)); // Factor for back beam radiation absorbed in window glass layer
7744 0 : Real64 AGlDiffBack = constrBack.AbsDiffBack(Lay); // Glass layer back diffuse solar absorptance
7745 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7746 0 : TBlBmBmBack * AbWinBack + ((TBlBmBmBack * RGlBack * RhoBlFront + TBlBmDiffBack) * AGlDiffBack /
7747 0 : (1.0 - RGlDiffBack * RhoBlDiffFront));
7748 : }
7749 :
7750 : // Interior beam transmitted by exterior back window with INTERIOR BLIND
7751 0 : Real64 TGlDif = constrBack.TransDiff; // Bare diffuse transmittance of back window
7752 0 : TransBeamWin =
7753 0 : TBlBmBmBack * (TGlBmBack + TGlDif * RGlBack * RhoBlFront / (1.0 - RGlDiffBack * RhoBlDiffFront)) +
7754 0 : TBlBmDiffBack * TGlDif / (1.0 - RGlDiffBack * RhoBlDiffFront);
7755 :
7756 : // Interior beam absorbed by BLIND on exterior back window with INTERIOR BLIND
7757 :
7758 0 : Real64 AbsBlDiffFront = FrontDiffAbs; // Blind solar front diffuse absorptance
7759 0 : Real64 ABlBack = AbsBlBack + TBlBmBmBack * RGlBack * AbsBlFront +
7760 0 : (AbsBlDiffFront * RGlDiffBack / (1 - RhoBlDiffFront * RGlDiffBack)) *
7761 0 : (RGlBack * TBlBmBmBack * RhoBlFront +
7762 : TBlBmDiffBack); // Blind solar back absorptance for interior solar
7763 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7764 0 : BOverlap * ABlBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7765 0 : BABSZone += BOverlap * ABlBack;
7766 0 : backSurfBeamSolInTrans += BOverlap * ABlBack;
7767 :
7768 0 : } else if (ShadeFlagBack == WinShadingType::ExtBlind) {
7769 :
7770 : // Interior beam absorptance of GLASS LAYERS of exterior back window with EXTERIOR BLIND
7771 :
7772 0 : Real64 RGlDiffFront = state.dataConstruction->Construct(ConstrNumBack)
7773 0 : .ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
7774 :
7775 : // Is this supposed to be beam-beam reflection?
7776 : Real64 RhoBlBack =
7777 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
7778 : Real64 RhoBlBmDifBk =
7779 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
7780 : Real64 AbsBlBack =
7781 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
7782 :
7783 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7784 0 : Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
7785 0 : Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
7786 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7787 0 : AbWinBack + (TGlBmBack * AGlDiffFront * RhoBlBack / (1.0 - RhoBlBack * RGlDiffFront));
7788 : }
7789 :
7790 : // Interior beam transmitted by exterior back window with EXTERIOR BLIND
7791 0 : Real64 TBlDifDif = BackDiffDiffTrans;
7792 0 : Real64 RhoBlDifDifBk = BackDiffDiffRefl;
7793 0 : Real64 AbsBlDiffBack = BackDiffAbs;
7794 0 : Real64 ABlBack =
7795 0 : TGlBmBack * (AbsBlBack + RhoBlBack * RGlDiffFront * AbsBlDiffBack / (1 - RhoBlDifDifBk * RGlDiffFront));
7796 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
7797 0 : TransBeamWin = TGlBmBack * (TBlBmBmBack + TBlBmDiffBack +
7798 0 : TBlDifDif * RhoBlBmDifBk * RGlDifFr / (1.0 - RhoBlDifDifBk * RGlDifFr));
7799 : // Interior beam absorbed by EXTERIOR BLIND on exterior back window
7800 0 : BABSZone += BOverlap * ABlBack;
7801 0 : backSurfBeamSolInTrans += BOverlap * ABlBack;
7802 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7803 0 : BOverlap * ABlBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7804 :
7805 : } else {
7806 : // ShadeFlagBack == BGBlindOn
7807 0 : Real64 t1k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(1));
7808 0 : Real64 t2k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(2));
7809 0 : Real64 af2k = Window::POLYF(CosIncBack, constrBack.afBareSolCoef(2));
7810 0 : Real64 ab1k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(1));
7811 0 : Real64 ab2k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(2));
7812 0 : Real64 rb1k = Window::POLYF(CosIncBack, constrBack.rbBareSolCoef(1));
7813 0 : Real64 rb2k = Window::POLYF(CosIncBack, constrBack.rbBareSolCoef(2));
7814 0 : Real64 td1k = constrBack.tBareSolDiff(1);
7815 0 : Real64 td2k = constrBack.tBareSolDiff(2);
7816 0 : Real64 afd2k = constrBack.afBareSolDiff(2);
7817 0 : Real64 abd1k = constrBack.abBareSolDiff(1);
7818 0 : Real64 abd2k = constrBack.abBareSolDiff(2);
7819 0 : Real64 rfd2k = constrBack.rfBareSolDiff(2);
7820 0 : Real64 rbd1k = constrBack.rbBareSolDiff(1);
7821 0 : Real64 rbd2k = constrBack.rbBareSolDiff(2);
7822 0 : Real64 tfshBBk = matBlindBack->BeamBeamTrans(profAngBack, slatAngBack);
7823 0 : Real64 tbshBBk = matBlindBack->BeamBeamTrans(profAngBack, Constant::Pi - slatAngBack);
7824 :
7825 : Real64 tfshBdk =
7826 0 : Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfTra, btar.Sol.Ft.Bm[profIdxHiBack].DfTra, profInterpFacBack);
7827 : Real64 tbshBdk =
7828 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfTra, btar.Sol.Bk.Bm[profIdxHiBack].DfTra, profInterpFacBack);
7829 : Real64 rfshBk =
7830 0 : Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfRef, btar.Sol.Ft.Bm[profIdxHiBack].DfRef, profInterpFacBack);
7831 : Real64 rbshBk =
7832 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
7833 : Real64 afshBk =
7834 0 : Interp(btar.Sol.Ft.Bm[profIdxLoBack].Abs, btar.Sol.Ft.Bm[profIdxHiBack].Abs, profInterpFacBack);
7835 : Real64 abshBk =
7836 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
7837 0 : Real64 tfshdk = btarBack.Sol.Ft.Df.Tra;
7838 0 : Real64 rfshdk = btarBack.Sol.Ft.Df.Ref;
7839 0 : Real64 afshdk = btarBack.Sol.Ft.Df.Abs;
7840 0 : Real64 tbshdk = btarBack.Sol.Bk.Df.Tra;
7841 0 : Real64 rbshdk = btarBack.Sol.Bk.Df.Ref;
7842 0 : Real64 abshdk = btarBack.Sol.Bk.Df.Abs;
7843 : Real64 ABlBack;
7844 :
7845 0 : if (NBackGlass == 2) {
7846 : // Interior beam absorptance of GLASS LAYERS of exterior back window with BETWEEN-GLASS BLIND
7847 0 : state.dataSolarShading->SurfWinAbsBeam(2) =
7848 0 : ab2k + t2k * tbshBBk * rb1k * tfshBBk * af2k +
7849 0 : t2k * (tbshBBk * rb1k * tfshBdk + tbshBdk * rbd1k * tfshdk + rbshBk * (1.0 + rfd2k * rbshdk)) * afd2k;
7850 0 : state.dataSolarShading->SurfWinAbsBeam(1) =
7851 0 : t2k * tbshBBk * ab1k + t2k * (rbshBk * rfd2k * tbshdk + tbshBdk * (1.0 + rbd1k * rfshdk)) * abd1k;
7852 : // Interior beam transmitted by exterior back window with BETWEEN-GLASS BLIND
7853 0 : TransBeamWin =
7854 0 : t2k * tbshBBk * t1k +
7855 0 : t2k * (tbshBBk * rb1k * rfshBk + rbshBk * rfd2k * tbshdk + tbshBdk * (1.0 + rbd1k * rfshdk)) * td1k;
7856 : // Interior beam absorbed by BLIND on exterior back window with BETWEEN-GLASS BLIND
7857 0 : ABlBack = t2k * (abshBk + tbshBBk * rb1k * afshBk + rbshBk * rfd2k * abshdk + tbshBdk * rbd1k * afshdk);
7858 : } else { // NBackGlass = 3
7859 0 : Real64 t3k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(3));
7860 0 : Real64 af3k = Window::POLYF(CosIncBack, constrBack.afBareSolCoef(3));
7861 0 : Real64 ab3k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(3));
7862 0 : Real64 afd3k = constrBack.afBareSolDiff(3);
7863 0 : Real64 rfd3k = constrBack.rfBareSolDiff(3);
7864 0 : state.dataSolarShading->SurfWinAbsBeam(3) =
7865 0 : ab3k + t3k * tbshBBk * (rb2k + t2k * rb1k * t2k) * tfshBBk * af3k +
7866 0 : t3k *
7867 0 : (tbshBdk * rbd2k * tfshdk + tbshBdk * td2k * rbd1k * td2k * tfshdk +
7868 0 : rbshBk * (1.0 + rfd3k * rbshdk)) *
7869 : afd3k;
7870 0 : state.dataSolarShading->SurfWinAbsBeam(2) =
7871 0 : t3k * tbshBBk * (ab2k + t2k * rb1k * (af2k + t2k * rfshBk * abd2k)) +
7872 0 : t3k * (tbshBdk + tbshBdk * (rbd2k + td2k * rbd1k * td2k) * rfshdk + rbshBk * rfd3k * tbshdk) * abd2k +
7873 0 : t3k * tbshBdk * td2k * rbd1k * afd2k;
7874 0 : state.dataSolarShading->SurfWinAbsBeam(1) =
7875 0 : t3k * tbshBBk * (t2k * ab1k + (rb2k + t2k * rb1k * t2k) * rfshBk * td2k * abd1k) +
7876 0 : t3k * (rbshBk * rfd3k * tbshdk + tbshBdk * (1.0 + rbd2k * rfshdk + td2k * rbd2k * td2k * rfshdk)) *
7877 0 : td2k * abd1k;
7878 0 : TransBeamWin = t3k * tbshBBk * t2k * t1k +
7879 0 : t3k *
7880 0 : (tbshBBk * (rb2k * rfshBk + t2k * rb1k * t2k * rfshBk) + rbshBk * rfd3k * tbshdk +
7881 0 : tbshBdk * (1.0 + rbd2k * rfshdk + td2k * rbd1k * td2k * rfshdk)) *
7882 0 : td2k * td1k;
7883 0 : ABlBack = t3k * abshBk + t3k * tbshBBk * (rb2k + t2k * rb1k * t2k) * afshBk +
7884 0 : t3k * rbshBk * rfd3k * abshdk + t3k * tbshBdk * (rbd2k + td2k * rbd1k * td2k) * afshdk;
7885 : }
7886 :
7887 0 : BABSZone += BOverlap * ABlBack;
7888 0 : backSurfBeamSolInTrans += BOverlap * ABlBack;
7889 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7890 0 : BOverlap * ABlBack / s_surf->Surface(BackSurfNum).Area;
7891 :
7892 : } // End of check if between-glass blind is on back window
7893 1 : } else if (ShadeFlagBack == WinShadingType::ExtScreen) {
7894 :
7895 : // Interior beam absorptance of GLASS LAYERS of exterior back window with EXTERIOR SCREEN
7896 0 : Real64 TGlBmBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
7897 0 : Real64 RGlDiffFront = constrBack.ReflectSolDiffFront;
7898 :
7899 0 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
7900 0 : assert(screen != nullptr);
7901 :
7902 0 : auto &surf = s_surf->Surface(SurfNum);
7903 0 : Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
7904 0 : Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
7905 0 : Real64 winPhi = surf.Tilt * Constant::DegToRad;
7906 0 : Real64 winTheta = surf.Azimuth * Constant::DegToRad;
7907 0 : Real64 phi = std::abs(solPhi - winPhi);
7908 0 : Real64 theta = std::abs(solTheta - winTheta);
7909 0 : Material::NormalizePhiTheta(phi, theta);
7910 : #ifdef PRECALC_INTERP_SCREEN
7911 : int ip1, ip2, it1, it2;
7912 : BilinearInterpCoeffs coeffs;
7913 0 : Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
7914 0 : GetBilinearInterpCoeffs(
7915 0 : phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
7916 0 : auto const &b11 = screen->btars[ip1][it1];
7917 0 : auto const &b12 = screen->btars[ip1][it2];
7918 0 : auto const &b21 = screen->btars[ip2][it1];
7919 0 : auto const &b22 = screen->btars[ip2][it2];
7920 :
7921 0 : Real64 TScBmBmBack = BilinearInterp(b11.BmTransBack, b12.BmTransBack, b21.BmTransBack, b22.BmTransBack, coeffs);
7922 0 : Real64 TScBmDiffBack = BilinearInterp(b11.DfTransBack, b12.DfTransBack, b21.DfTransBack, b22.DfTransBack, coeffs);
7923 0 : Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
7924 0 : Real64 RScDifBack = screen->DfRef;
7925 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7926 0 : Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
7927 0 : Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
7928 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7929 0 : AbWinBack + (TGlBmBack * AGlDiffFront * RScBack / (1.0 - RScDifBack * RGlDiffFront));
7930 : }
7931 :
7932 : // Interior beam transmitted by exterior back window with EXTERIOR SCREEN
7933 0 : Real64 TScDifDif = screen->DfTrans;
7934 0 : Real64 RScBmDifBk = BilinearInterp(b11.RefSolBack, b12.RefSolBack, b21.RefSolBack, b22.RefSolBack, coeffs);
7935 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
7936 0 : Real64 RScDifDifBk = screen->DfRef;
7937 0 : TransBeamWin = TGlBmBack *
7938 0 : (TScBmBmBack + TScBmDiffBack + TScDifDif * RScBmDifBk * RGlDifFr / (1.0 - RScDifDifBk * RGlDifFr));
7939 :
7940 : // Interior beam absorbed by EXTERIOR SCREEN on exterior back window
7941 0 : Real64 AbsScBack = BilinearInterp(b11.AbsSolBack, b12.AbsSolBack, b21.AbsSolBack, b22.AbsSolBack, coeffs);
7942 0 : Real64 AbsScDiffBack = screen->DfAbs;
7943 0 : Real64 RScDiffBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
7944 : // Screen solar back absorptance for interior solar
7945 0 : Real64 AScBack =
7946 0 : TGlBmBack * (AbsScBack + RScBack * RGlDiffFront * AbsScDiffBack / (1.0 - RScDiffBack * RGlDiffFront));
7947 :
7948 0 : BABSZone += BOverlap * AScBack;
7949 0 : backSurfBeamSolInTrans += BOverlap * AScBack;
7950 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7951 0 : BOverlap * AScBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7952 : #else // !PRECALC_INTERP_SCREEN
7953 : Material::ScreenBmTransAbsRef btar;
7954 : Material::CalcScreenTransmittance(state, screen, phi, theta, btar);
7955 :
7956 : Real64 TScBmBmBack = btar.BmTransBack;
7957 : Real64 TScBmDiffBack = btar.DfTransBack;
7958 : Real64 RScBack = btar.RefSolFront;
7959 : Real64 RScDifBack = screen->DfRef;
7960 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7961 : Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
7962 : Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
7963 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7964 : AbWinBack + (TGlBmBack * AGlDiffFront * RScBack / (1.0 - RScDifBack * RGlDiffFront));
7965 : }
7966 :
7967 : // Interior beam transmitted by exterior back window with EXTERIOR SCREEN
7968 : Real64 TScDifDif = screen->DfTrans;
7969 : Real64 RScBmDifBk = btar.RefSolBack;
7970 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
7971 : Real64 RScDifDifBk = screen->DfRef;
7972 : TransBeamWin = TGlBmBack *
7973 : (TScBmBmBack + TScBmDiffBack + TScDifDif * RScBmDifBk * RGlDifFr / (1.0 - RScDifDifBk * RGlDifFr));
7974 :
7975 : // Interior beam absorbed by EXTERIOR SCREEN on exterior back window
7976 : Real64 AbsScBack = btar.AbsSolBack;
7977 : Real64 AbsScDiffBack = screen->DfAbs;
7978 : Real64 RScDiffBack = btar.RefSolFront;
7979 : // Screen solar back absorptance for interior solar
7980 : Real64 AScBack =
7981 : TGlBmBack * (AbsScBack + RScBack * RGlDiffFront * AbsScDiffBack / (1.0 - RScDiffBack * RGlDiffFront));
7982 :
7983 : BABSZone += BOverlap * AScBack;
7984 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7985 : BOverlap * AScBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7986 : #endif // PRECALC_INTERP_SCREEN
7987 :
7988 : } // End of check if exterior screen on back window
7989 :
7990 : // Interior beam absorptance of glass layers of back exterior window with SWITCHABLE GLAZING
7991 1 : if (ShadeFlagBack == WinShadingType::SwitchableGlazing && s_surf->Surface(BackSurfNum).ExtBoundCond == 0) {
7992 0 : Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum); // Switching factor for a window
7993 : Real64 AbsBeamWinSh; // Glass layer beam solar absorptance of a shaded window
7994 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7995 : AbsBeamWinSh =
7996 0 : Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).AbsBeamBackCoef(Lay));
7997 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7998 0 : Window::InterpSw(SwitchFac, state.dataSolarShading->SurfWinAbsBeam(Lay), AbsBeamWinSh);
7999 : }
8000 : // Beam solar transmittance of a shaded window
8001 : Real64 TransBeamWinSh =
8002 0 : Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).TransSolBeamCoef);
8003 0 : TransBeamWin = Window::InterpSw(SwitchFac, TransBeamWin, TransBeamWinSh);
8004 : }
8005 :
8006 : // Sum of interior beam absorbed by all glass layers of back window
8007 1 : AbsBeamTotWin = 0.0;
8008 3 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
8009 2 : AbsBeamTotWin += state.dataSolarShading->SurfWinAbsBeam(Lay);
8010 2 : s_surf->SurfWinA(BackSurfNum, Lay) +=
8011 2 : BOverlap * state.dataSolarShading->SurfWinAbsBeam(Lay) /
8012 2 : (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum)); //[-]
8013 : }
8014 :
8015 : // To BABSZon, add interior beam glass absorption and overall beam transmission for this back window
8016 1 : BABSZone += BOverlap * (AbsBeamTotWin + TransBeamWin);
8017 1 : backSurfBeamSolInTrans += BOverlap * (AbsBeamTotWin + TransBeamWin);
8018 1 : state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfNum) +=
8019 1 : backSurfBeamSolInTrans * state.dataEnvrn->BeamSolarRad; //[W]
8020 : // Interior beam transmitted to adjacent zone through an interior back window (assumed unshaded);
8021 : // this beam radiation is categorized as diffuse radiation in the adjacent zone.
8022 1 : int AdjSurfNum = s_surf->Surface(BackSurfNum).ExtBoundCond;
8023 1 : if (AdjSurfNum > 0) {
8024 0 : int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
8025 0 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BOverlap * TransBeamWin; //[m2]
8026 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) +=
8027 0 : BOverlap * TransBeamWin * state.dataEnvrn->BeamSolarRad; //[W]
8028 0 : s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfNum) =
8029 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
8030 : }
8031 : } // End of check if back surface is opaque or window
8032 5223 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) += BOverlap;
8033 5223 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(BackSurfNum) =
8034 5223 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
8035 : } // End of loop over back surfaces
8036 0 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
8037 : // For complex window calculation goes over outgoing basis directions for current state
8038 0 : int CurCplxFenState = s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState; // Current state for complex fenestration
8039 : // Get construction number which keeps transmittance properties
8040 0 : int IConst = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(CurCplxFenState).Konst; // Current surface construction number
8041 : // (it depends of state too)
8042 : // Solar radiation from this window will be calculated only in case when this window is not scheduled surface gained
8043 0 : if (WindowScheduledSolarAbs(state, SurfNum, IConst) == 0) {
8044 : // Current incoming direction number (Sun direction)
8045 0 : int IBm = state.dataBSDFWindow->ComplexWind(SurfNum)
8046 0 : .Geom(CurCplxFenState)
8047 0 : .SolBmIndex(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
8048 : // Report variables for complex fenestration here
8049 0 : state.dataHeatBal->SurfWinBSDFBeamDirectionRep(SurfNum) = IBm;
8050 0 : state.dataHeatBal->SurfWinBSDFBeamThetaRep(SurfNum) =
8051 0 : state.dataBSDFWindow->ComplexWind(SurfNum)
8052 0 : .Geom(CurCplxFenState)
8053 0 : .ThetaBm(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
8054 0 : state.dataHeatBal->SurfWinBSDFBeamPhiRep(SurfNum) = state.dataBSDFWindow->ComplexWind(SurfNum)
8055 0 : .Geom(CurCplxFenState)
8056 0 : .PhiBm(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
8057 :
8058 0 : int BaseSurf = surf.BaseSurf; // Base surface number for current complex window
8059 : // Get total number of back surfaces for current window (surface)
8060 : // Note that it is organized by base surface
8061 0 : int NBkSurf = state.dataShadowComb->ShadowComb(BaseSurf).NumBackSurf;
8062 0 : if (!allocated(CFBoverlap)) {
8063 0 : CFBoverlap.allocate(NBkSurf);
8064 : }
8065 0 : if (!allocated(CFDirBoverlap)) {
8066 0 : CFDirBoverlap.allocate(NBkSurf, state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis);
8067 : }
8068 :
8069 0 : CFBoverlap = 0.0;
8070 : // Calculate effects on all back surfaces for each of basis directions. Each of basis directions from the back of the
8071 : // window has to be considered as beam and therefore calculate CFBoverlap for each of them
8072 0 : for (int CurTrnDir = 1; CurTrnDir <= state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis;
8073 : ++CurTrnDir) {
8074 0 : Real64 CurLambda = state.dataBSDFWindow->ComplexWind(SurfNum)
8075 0 : .Geom(CurCplxFenState)
8076 0 : .Trn.Lamda(CurTrnDir); // Current lambda value in BSDF outgoing directions
8077 0 : Real64 DirTrans = state.dataConstruction->Construct(IConst).BSDFInput.SolFrtTrans(
8078 0 : IBm, CurTrnDir); // Current BSDF directional transmittance
8079 : // Now calculate effect of this direction on all back surfaces
8080 0 : for (int IBack = 1; IBack <= NBkSurf; ++IBack) {
8081 0 : CFDirBoverlap(IBack, CurTrnDir) =
8082 0 : state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).AOverlap(IBack, CurTrnDir) * DirTrans *
8083 0 : CurLambda * CosInc;
8084 0 : CFBoverlap(IBack) += CFDirBoverlap(IBack, CurTrnDir);
8085 : } // DO IBack = 1,MaxBkSurf
8086 : }
8087 :
8088 : // Summarizing results
8089 0 : for (int IBack = 1; IBack <= NBkSurf; ++IBack) {
8090 0 : int BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(IBack);
8091 0 : int ConstrNumBack = s_surf->Surface(BackSurfaceNumber).Construction;
8092 0 : auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
8093 : // Do not perform any calculation if surface is scheduled for incoming solar radiation
8094 0 : int SurfSolIncPtr = SurfaceScheduledSolarInc(state, BackSurfaceNumber, ConstrNumBack);
8095 :
8096 0 : if (SurfSolIncPtr == 0) {
8097 : // Surface hit is another complex fenestration
8098 0 : if (s_surf->SurfWinWindowModelType(BackSurfaceNumber) == WindowModel::BSDF) {
8099 : int CurBackState =
8100 0 : s_surf->SurfaceWindow(BackSurfaceNumber)
8101 0 : .ComplexFen.CurrentState; // Current state for back surface if that surface is complex fenestration
8102 : // Do not take into account this window if it is scheduled for surface gains
8103 0 : if (WindowScheduledSolarAbs(state, BackSurfaceNumber, ConstrNumBack) == 0) {
8104 : // Calculate energy loss per each outgoing orientation
8105 0 : for (int CurTrnDir = 1;
8106 0 : CurTrnDir <= state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis;
8107 : ++CurTrnDir) {
8108 : Real64 bestDot; // complex fenestration hits other complex fenestration, it is important to find
8109 : // matching beam directions. Beam leaving one window will have certain number for it's basis
8110 : // while same beam reaching back surface will have different beam number. This value is used
8111 : // to keep best matching dot product for those directions
8112 : Real64 curDot; // temporary variable for current dot product
8113 : int bestBackTrn; // Direction corresponding best dot product for back surface window
8114 0 : for (int CurBackDir = 1;
8115 0 : CurBackDir <= state.dataBSDFWindow->ComplexWind(BackSurfaceNumber).Geom(CurBackState).Trn.NBasis;
8116 : ++CurBackDir) {
8117 : // Purpose of this part is to find best match for outgoing beam number of window back surface
8118 : // and incoming beam number of complex fenestration which this beam will hit on (back surface
8119 : // again)
8120 : curDot =
8121 0 : dot(state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).sTrn(CurTrnDir),
8122 0 : state.dataBSDFWindow->ComplexWind(BackSurfaceNumber).Geom(CurBackState).sTrn(CurBackDir));
8123 0 : if (CurBackDir == 1) {
8124 0 : bestDot = curDot;
8125 0 : bestBackTrn = CurBackDir;
8126 : } else {
8127 0 : if (curDot < bestDot) {
8128 0 : bestDot = curDot;
8129 0 : bestBackTrn = CurBackDir;
8130 : }
8131 : }
8132 : }
8133 : // CurLambda = ComplexWind(BackSurfaceNumber)%Geom(CurBackState)%Trn%Lamda(CurTrnDir)
8134 : // Add influence of this exact direction to what stays in the zone. It is important to note that
8135 : // this needs to be done for each outgoing direction
8136 0 : Real64 babs = CFDirBoverlap(IBack, CurTrnDir) * (1 - s_surf->SurfaceWindow(BackSurfaceNumber)
8137 0 : .ComplexFen.State(CurBackState)
8138 0 : .IntegratedBkRefl(bestBackTrn));
8139 0 : BABSZone += babs;
8140 0 : state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfaceNumber) +=
8141 0 : babs * state.dataEnvrn->BeamSolarRad; //[W]
8142 :
8143 : // Absorptance from current back direction
8144 0 : int TotSolidLay = constrBack.TotSolidLayers;
8145 0 : for (int Lay = 1; Lay <= TotSolidLay; ++Lay) {
8146 : // IF (ALLOCATED(Construct(ConstrNumBack)%BSDFInput)) THEN
8147 : // CFDirBoverlap is energy transmitted for current basis beam. It is important to note that
8148 : // AWinOverlap array needs to contain flux and not absorbed energy because later in the code
8149 : // this will be multiplied with window area
8150 0 : s_surf->SurfWinACFOverlap(BackSurfaceNumber, Lay) +=
8151 0 : constrBack.BSDFInput.Layer(Lay).BkAbs(bestBackTrn, 1) * CFDirBoverlap(IBack, CurTrnDir) /
8152 0 : s_surf->Surface(BackSurfaceNumber).Area;
8153 : // END IF
8154 : }
8155 :
8156 : // Interior beam transmitted to adjacent zone through an interior back window;
8157 : // This beam radiation is categorized as diffuse radiation in the adjacent zone.
8158 : // Note that this is done for each outgoing direction of exterior window
8159 0 : int AdjSurfNum = s_surf->Surface(BackSurfaceNumber).ExtBoundCond;
8160 0 : if (AdjSurfNum > 0) {
8161 0 : int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
8162 0 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) +=
8163 0 : CFDirBoverlap(IBack, CurTrnDir) * s_surf->SurfaceWindow(BackSurfaceNumber)
8164 0 : .ComplexFen.State(CurBackState)
8165 0 : .IntegratedBkTrans(bestBackTrn);
8166 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfaceNumber) +=
8167 0 : CFDirBoverlap(IBack, CurTrnDir) *
8168 0 : s_surf->SurfaceWindow(BackSurfaceNumber)
8169 0 : .ComplexFen.State(CurBackState)
8170 0 : .IntegratedBkTrans(bestBackTrn) *
8171 0 : state.dataEnvrn->BeamSolarRad; //[W]
8172 0 : s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfaceNumber) =
8173 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfaceNumber) * state.dataGlobal->TimeStepZoneSec;
8174 : }
8175 : }
8176 : }
8177 : } else {
8178 0 : if (constrBack.TransDiff <= 0.0) {
8179 : // Do not take into account this window if it is scheduled for surface gains
8180 0 : Real64 AbsIntSurf = constrBack.InsideAbsorpSolar;
8181 0 : s_surf->SurfOpaqAI(BackSurfaceNumber) +=
8182 0 : CFBoverlap(IBack) * AbsIntSurf / s_surf->Surface(BackSurfaceNumber).Area;
8183 0 : BABSZone += CFBoverlap(IBack) * AbsIntSurf;
8184 : } else {
8185 : // Code for mixed windows goes here. It is same as above code for "ordinary" windows.
8186 : // Try to do something which will not produce duplicate code.
8187 : }
8188 : }
8189 : }
8190 : }
8191 :
8192 0 : if (allocated(CFBoverlap)) {
8193 0 : CFBoverlap.deallocate();
8194 : }
8195 0 : if (allocated(CFDirBoverlap)) {
8196 0 : CFDirBoverlap.deallocate();
8197 : }
8198 : }
8199 :
8200 0 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
8201 :
8202 0 : for (int IBack = 1; IBack <= state.dataBSDFWindow->MaxBkSurf; ++IBack) {
8203 : int BackSurfNum =
8204 0 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
8205 0 : if (BackSurfNum == 0) {
8206 0 : break; // No more irradiated back surfaces for this exterior window
8207 : }
8208 0 : if (s_surf->SurfWinWindowModelType(IBack) != WindowModel::EQL) {
8209 0 : continue; // only EQL back window is allowed
8210 : }
8211 :
8212 0 : int ConstrNumBack = s_surf->Surface(BackSurfNum).Construction;
8213 0 : auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
8214 0 : int NBackGlass = constrBack.TotGlassLayers;
8215 : // Irradiated (overlap) area for this back surface, projected onto window plane
8216 : // (includes effect of shadowing on exterior window)
8217 :
8218 : Real64 AOverlap =
8219 0 : state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
8220 0 : Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
8221 :
8222 0 : if (constrBack.TransDiff <= 0.0) {
8223 :
8224 : // Back surface is opaque interior or exterior wall
8225 0 : Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
8226 0 : s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
8227 0 : BABSZone += BOverlap * AbsIntSurf; //[m2]
8228 :
8229 : } else {
8230 :
8231 : // Back surface is an interior or exterior window
8232 : // Note that exterior back windows with and without shades are treated as defined.
8233 : // Equivalent Layer window model has no distinction when treating windows with and
8234 : // without shades (interior, inbetween and exterior shades)
8235 : // Note in equivalent layer window model if storm window exists it is defined as part of
8236 : // window construction, hence it does not require a separate treatment
8237 0 : state.dataSolarShading->SurfWinAbsBeamEQL = 0.0;
8238 0 : Real64 TransBeamWin = 0.0; // Beam solar transmittance of a window
8239 0 : Real64 backSurfBeamSolInTrans = 0.0; // Fraction of BeamSolarRad transmitted out through window inside face [W]
8240 :
8241 : // Interior beam absorptance of glass layers and beam transmittance of back exterior &
8242 : // or interior window (treats windows with/without shades as defined) for this timestep
8243 :
8244 : // call the ASHWAT fenestration model for beam radiation here
8245 0 : WindowEquivalentLayer::CalcEQLOpticalProperty(
8246 0 : state, BackSurfNum, SolarArrays::BEAM, state.dataSolarShading->SurfWinAbsSolBeamBackEQL);
8247 0 : auto &CFS = state.dataWindowEquivLayer->CFS;
8248 0 : int EQLNum = constrBack.EQLConsPtr;
8249 0 : state.dataSolarShading->SurfWinAbsBeamEQL({1, CFS(EQLNum).NL}) =
8250 0 : state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, {1, CFS(EQLNum).NL});
8251 : // get the interior beam transmitted through back exterior or interior EQL window
8252 0 : TransBeamWin = state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL + 1);
8253 : // Absorbed by the interior shade layer of back exterior window
8254 0 : if (CFS(EQLNum).L(CFS(EQLNum).NL).LTYPE != LayerType::GLAZE) {
8255 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
8256 0 : BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL) /
8257 0 : (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
8258 0 : BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL);
8259 0 : backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL);
8260 : }
8261 : // Absorbed by the exterior shade layer of back exterior window
8262 0 : if (CFS(EQLNum).L(1).LTYPE != LayerType::GLAZE) {
8263 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
8264 0 : BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1) /
8265 0 : (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
8266 0 : BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1);
8267 0 : backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1);
8268 : }
8269 :
8270 : // determine the number of glass layers
8271 0 : NBackGlass = 0;
8272 0 : for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
8273 0 : if (CFS(EQLNum).L(Lay).LTYPE != LayerType::GLAZE) {
8274 0 : continue;
8275 : }
8276 0 : ++NBackGlass;
8277 : }
8278 0 : if (NBackGlass >= 2) {
8279 : // If the number of glass is greater than 2, in between glass shade can be present
8280 0 : for (int Lay = 2; Lay <= CFS(EQLNum).NL - 1; ++Lay) {
8281 0 : if (CFS(EQLNum).L(CFS(EQLNum).NL).LTYPE != LayerType::GLAZE) {
8282 : // if there is in between shade glass determine the shade absorptance
8283 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) +=
8284 0 : BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay) /
8285 0 : s_surf->Surface(BackSurfNum).Area;
8286 0 : BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay);
8287 0 : backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay);
8288 : }
8289 : }
8290 : }
8291 : // Sum of interior beam absorbed by all glass layers of back window
8292 0 : Real64 AbsBeamTotWin = 0.0; // Glass layer beam solar absorptance of a shaded window
8293 0 : for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
8294 0 : AbsBeamTotWin += state.dataSolarShading->SurfWinAbsBeamEQL(Lay);
8295 0 : s_surf->SurfWinA(BackSurfNum, Lay) +=
8296 0 : BOverlap * state.dataSolarShading->SurfWinAbsBeamEQL(Lay) /
8297 0 : (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum)); //[-]
8298 : }
8299 :
8300 : // To BABSZon, add interior beam glass absorption and overall beam transmission for this back window
8301 :
8302 0 : BABSZone += BOverlap * (AbsBeamTotWin + TransBeamWin);
8303 0 : backSurfBeamSolInTrans += BOverlap * (AbsBeamTotWin + TransBeamWin);
8304 0 : state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfNum) +=
8305 0 : backSurfBeamSolInTrans * state.dataEnvrn->BeamSolarRad; //[W]
8306 :
8307 : // Interior beam transmitted to adjacent zone through an interior back window (assumed unshaded);
8308 : // this beam radiation is categorized as diffuse radiation in the adjacent zone.
8309 :
8310 0 : int AdjSurfNum = s_surf->Surface(BackSurfNum).ExtBoundCond;
8311 0 : if (AdjSurfNum > 0) {
8312 0 : int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
8313 0 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BOverlap * TransBeamWin; //[m2]
8314 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) +=
8315 0 : BOverlap * TransBeamWin * state.dataEnvrn->BeamSolarRad; //[W]
8316 0 : s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfNum) =
8317 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
8318 : }
8319 : } // End of check if back surface is opaque or window
8320 0 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) += BOverlap;
8321 0 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(BackSurfNum) =
8322 0 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
8323 : } // End of loop over back surfaces
8324 :
8325 : // *****************************
8326 :
8327 : } // IF (SurfaceWindow(SurfNum)%WindowModelType /= WindowModel:: BSDF) THEN
8328 : } else { // Simple interior solar distribution. All beam from exterior windows falls on floor;
8329 : // some of this is absorbed/transmitted, rest is reflected to other surfaces.
8330 :
8331 187294 : for (int const FloorNum : thisEnclosure.SurfacePtr) {
8332 : // In following, ISABSF is zero except for nominal floor surfaces
8333 174508 : if (state.dataSolarShading->SurfIntAbsFac(FloorNum) <= 0.0 || FloorNum == SurfNum) {
8334 155283 : continue; // Keep only floor surfaces
8335 : }
8336 19225 : int const FlConstrNum = s_surf->SurfActiveConstruction(FloorNum);
8337 :
8338 19225 : Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * InOutProjSLFracMult; //[m2]
8339 19225 : Real64 AbsBeamTotWin = 0.0;
8340 :
8341 19225 : if (state.dataConstruction->Construct(FlConstrNum).TransDiff <= 0.0) {
8342 : // Opaque surface
8343 19224 : s_surf->SurfOpaqAI(FloorNum) +=
8344 19224 : BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) / s_surf->Surface(FloorNum).Area; //[-]
8345 : } else {
8346 : // Window
8347 :
8348 : // Note that diffuse solar absorptance is used here for floor windows even though we're
8349 : // dealing with incident beam radiation. This is because, for this simple interior distribution,
8350 : // the beam radiation from exterior windows is assumed to be uniformly distributed over the
8351 : // floor and so it makes no sense to use directional absorptances. Note also that floor windows
8352 : // are assumed to not have blinds or shades in this calculation.
8353 : // For the case of the floor window a complex fenestration (strange situation) the correct back
8354 : // diffuse layer absorptions have already been put into the construction
8355 :
8356 3 : for (int Lay = 1; Lay <= state.dataConstruction->Construct(FlConstrNum).TotGlassLayers; ++Lay) {
8357 2 : AbsBeamTotWin += state.dataConstruction->Construct(FlConstrNum).AbsDiffBack(Lay);
8358 : }
8359 : // In the following we have to multiply by the AbsDiffBack(Lay)/AbsBeamTotWin ratio to get the
8360 : // layer by layer absorbed beam since ISABSF(FloorNum) is proportional to AbsBeamTotWin
8361 : // (see ComputeIntSolarAbsorpFactors).
8362 :
8363 3 : for (int Lay = 1; Lay <= state.dataConstruction->Construct(FlConstrNum).TotGlassLayers; ++Lay) {
8364 4 : s_surf->SurfWinA(FloorNum, Lay) += state.dataConstruction->Construct(FlConstrNum).AbsDiffBack(Lay) / AbsBeamTotWin *
8365 2 : BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) /
8366 2 : s_surf->Surface(FloorNum).Area; //[-]
8367 : }
8368 : }
8369 :
8370 19225 : BABSZone += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum); //[m2]
8371 :
8372 19225 : int AdjSurfNum = s_surf->Surface(FloorNum).ExtBoundCond;
8373 19225 : if (state.dataConstruction->Construct(FlConstrNum).TransDiff > 0.0 && AdjSurfNum > 0) {
8374 :
8375 : // Window in an interior floor
8376 :
8377 0 : int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
8378 :
8379 : // Contribution (assumed diffuse) to adjacent zone of beam radiation passing
8380 : // through this window
8381 0 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) *
8382 0 : state.dataConstruction->Construct(FlConstrNum).TransDiff /
8383 : AbsBeamTotWin;
8384 :
8385 0 : BABSZone += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) *
8386 0 : state.dataConstruction->Construct(FlConstrNum).TransDiff / AbsBeamTotWin;
8387 : }
8388 :
8389 : } // End of loop over floor sections
8390 : } // End of check on complex vs. simple interior solar distribution
8391 :
8392 : } // End of sunlit fraction > 0 test
8393 : } // End of first loop over surfaces in zone
8394 :
8395 105310 : Real64 BABSZoneSSG = 0.0; // Beam radiation from exterior windows absorbed in a zone (only for scheduled surface gains)
8396 105310 : Real64 BTOTZoneSSG = 0.0; // Solar entering a zone in case of scheduled surface gains
8397 105310 : for (int iSSG = 1; iSSG <= s_surf->TotSurfIncSolSSG; ++iSSG) {
8398 0 : int SurfNum = s_surf->SurfIncSolSSG(iSSG).SurfPtr;
8399 0 : auto &surf = s_surf->Surface(SurfNum);
8400 : // do calculation only if construction number match.
8401 0 : if (s_surf->SurfIncSolSSG(iSSG).ConstrPtr == surf.Construction) {
8402 0 : if (surf.SolarEnclIndex == enclosureNum) {
8403 0 : Real64 AbsIntSurf = state.dataConstruction->Construct(surf.Construction).InsideAbsorpSolar;
8404 : // SolarIntoZone = GetCurrentScheduleValue(SurfIncSolSSG(iSSG)%SchedPtr) * Surface(SurfNum)%Area
8405 0 : Real64 SolarIntoZone = s_surf->SurfIncSolSSG(iSSG).sched->getCurrentVal(); // Solar radiation into zone to current surface
8406 0 : s_surf->SurfOpaqAI(SurfNum) = SolarIntoZone * AbsIntSurf;
8407 0 : BABSZoneSSG += s_surf->SurfOpaqAI(SurfNum) * surf.Area;
8408 0 : BTOTZoneSSG += SolarIntoZone * surf.Area;
8409 : }
8410 : }
8411 : }
8412 105310 : state.dataHeatBal->EnclSolDBSSG(enclosureNum) = BTOTZoneSSG - BABSZoneSSG;
8413 105310 : state.dataHeatBal->EnclSolDB(enclosureNum) = BTOTZone - BABSZone;
8414 :
8415 105310 : if (state.dataHeatBal->EnclSolDB(enclosureNum) < 0.0) {
8416 0 : state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
8417 : }
8418 :
8419 : // Variables for reporting
8420 716999 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
8421 611689 : auto &surf = s_surf->Surface(SurfNum);
8422 :
8423 611689 : Real64 SurfIncSolarMultiplier = surf.IncSolMultiplier;
8424 611689 : Real64 currBeamSolarRad = state.dataEnvrn->BeamSolarRad * SurfIncSolarMultiplier;
8425 611689 : Real64 currDifSolarRad = state.dataEnvrn->DifSolarRad * SurfIncSolarMultiplier;
8426 611689 : Real64 currGndSolarRad = state.dataEnvrn->GndSolarRad * SurfIncSolarMultiplier;
8427 611689 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
8428 78961 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) *= currBeamSolarRad;
8429 78961 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) =
8430 78961 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8431 78961 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) =
8432 78961 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) / (surf.Area + s_surf->SurfWinDividerArea(SurfNum));
8433 : } else { // Simple interior solar distribution. All beam falls on floor.
8434 532728 : if (state.dataSolarShading->SurfIntAbsFac(SurfNum) > 0.0 && surf.HeatTransSurf) {
8435 104432 : if (thisEnclosure.FloorArea > 0.0) {
8436 : // spread onto all floor surfaces, these may or may not be called "floor"
8437 104432 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = currBeamSolarRad * BTOTZone / thisEnclosure.FloorArea;
8438 0 : } else if (thisEnclosure.TotalSurfArea > 0.0) {
8439 : // spread onto all interior surfaces
8440 0 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = currBeamSolarRad * BTOTZone / thisEnclosure.TotalSurfArea;
8441 : } else { // divide be zero otherwise
8442 0 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = 0.0;
8443 : }
8444 : }
8445 532728 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) = surf.Area * state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum);
8446 532728 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) =
8447 532728 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8448 : }
8449 611689 : if (surf.Class == SurfaceClass::Window || surf.Class == SurfaceClass::TDD_Dome) {
8450 :
8451 31116 : s_surf->SurfWinIntBeamAbsByShade(SurfNum) = state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfNum);
8452 31116 : s_surf->SurfWinExtBeamAbsByShade(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum);
8453 :
8454 31116 : if ((surf.ExtBoundCond == ExternalEnvironment) || (surf.ExtBoundCond == OtherSideCondModeledExt)) {
8455 :
8456 31116 : WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum);
8457 31116 : int ShelfNum = s_surf->SurfDaylightingShelfInd(SurfNum);
8458 31116 : int OutShelfSurf = 0;
8459 31116 : if (ShelfNum > 0) { // Outside daylighting shelf
8460 0 : OutShelfSurf = state.dataDaylightingDevicesData->Shelf(ShelfNum).OutSurf;
8461 : }
8462 :
8463 : // This lookup may be avoid if this 2nd surf loop can be combined with the 1st
8464 31116 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
8465 0 : int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
8466 0 : int SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
8467 0 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8468 : // Exterior diffuse solar incident on window (W/m2)
8469 0 : Real64 DifSolarInc = currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(SurfNum2) +
8470 0 : currGndSolarRad * s_surf->Surface(SurfNum2).ViewFactorGround;
8471 : // Exterior diffuse sky solar transmitted by TDD (W/m2)
8472 0 : Real64 SkySolarTrans = currDifSolarRad * TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso) *
8473 0 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum2);
8474 : // Exterior diffuse ground solar transmitted by TDD (W/m2)
8475 0 : Real64 GndSolarTrans = currGndSolarRad * state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolIso *
8476 0 : s_surf->Surface(SurfNum2).ViewFactorGround;
8477 :
8478 0 : s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
8479 0 : s_surf->SurfWinDifSolar(SurfNum) = SkySolarTrans * surf.Area + GndSolarTrans * surf.Area;
8480 0 : s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8481 0 : s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8482 :
8483 0 : s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
8484 0 : s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8485 :
8486 0 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransmittedSolar = s_surf->SurfWinTransSolar(SurfNum);
8487 : // TDDPipe(PipeNum)%TransSolBeam = TBmBm ! Reported above
8488 0 : if (DifSolarInc > 0) {
8489 0 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolDiff = (SkySolarTrans + GndSolarTrans) / DifSolarInc;
8490 : } else {
8491 0 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolDiff = 0.0;
8492 : }
8493 :
8494 31116 : } else if (OutShelfSurf > 0) { // Outside daylighting shelf
8495 : Real64 ShelfSolarRad =
8496 0 : (currBeamSolarRad *
8497 0 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, OutShelfSurf) *
8498 0 : state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, OutShelfSurf) +
8499 0 : currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(OutShelfSurf)) *
8500 0 : state.dataDaylightingDevicesData->Shelf(ShelfNum).OutReflectSol;
8501 :
8502 0 : Real64 DifSolarInc = currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(SurfNum) +
8503 0 : currGndSolarRad * surf.ViewFactorGround +
8504 0 : ShelfSolarRad * state.dataDaylightingDevicesData->Shelf(ShelfNum).ViewFactor;
8505 :
8506 0 : s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
8507 0 : s_surf->SurfWinDifSolar(SurfNum) = DifSolarInc * state.dataSolarShading->SurfWinTransDifSolar(SurfNum);
8508 0 : s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8509 0 : s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8510 :
8511 0 : s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
8512 0 : s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8513 :
8514 : } else { // Regular window
8515 31116 : Real64 SkySolarInc = s_surf->SurfSkySolarInc(SurfNum);
8516 31116 : Real64 GndSolarInc = s_surf->SurfGndSolarInc(SurfNum);
8517 31116 : Real64 DifSolarInc = SkySolarInc + GndSolarInc;
8518 31116 : s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
8519 : // Note: for complex fenestration, SurfWinTransDifSolar has previously been defined using the effective
8520 : // transmittance for sky and ground diffuse radiation (including beam radiation reflected from the ground)
8521 : // so these calculations should be correct
8522 31116 : s_surf->SurfWinDifSolar(SurfNum) = DifSolarInc * state.dataSolarShading->SurfWinTransDifSolar(SurfNum);
8523 31116 : s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8524 31116 : s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8525 31116 : if (ANY_BLIND(ShadeFlag)) {
8526 0 : auto const &surfShade = s_surf->surfShades(SurfNum);
8527 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
8528 0 : assert(matBlind != nullptr);
8529 0 : if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
8530 0 : s_surf->SurfWinDifSolar(SurfNum) = SkySolarInc * state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) +
8531 0 : GndSolarInc * state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum);
8532 0 : s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8533 : }
8534 : }
8535 :
8536 31116 : s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
8537 31116 : s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8538 : }
8539 :
8540 : // added TH 12/9/2009, CR 7907 & 7809
8541 31116 : s_surf->SurfWinBmBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum);
8542 :
8543 31116 : s_surf->SurfWinBmDifSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum);
8544 31116 : s_surf->SurfWinBmBmSolarEnergy(SurfNum) = s_surf->SurfWinBmBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8545 31116 : s_surf->SurfWinBmDifSolarEnergy(SurfNum) = s_surf->SurfWinBmDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8546 :
8547 : // Solar not added by TDD:DOME; added to zone via TDD:DIFFUSER
8548 31116 : if (surf.Class != SurfaceClass::TDD_Dome) {
8549 31116 : state.dataHeatBal->ZoneTransSolar(enclosureNum) += s_surf->SurfWinTransSolar(SurfNum); //[W]
8550 31116 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) =
8551 31116 : state.dataHeatBal->ZoneTransSolar(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8552 31116 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinBmSolar(SurfNum);
8553 31116 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinDifSolar(SurfNum);
8554 31116 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) =
8555 31116 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8556 31116 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) =
8557 31116 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8558 : }
8559 : }
8560 : }
8561 : } // End of second loop over surfaces in zone
8562 :
8563 : } // End of first zone loop
8564 :
8565 : // Add interior window contribution to EnclSolDB
8566 :
8567 176530 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
8568 105310 : state.dataHeatBal->EnclSolDB(enclosureNum) += state.dataHeatBal->EnclSolDBIntWin(enclosureNum);
8569 105310 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum) = state.dataHeatBal->EnclSolDBIntWin(enclosureNum) * state.dataEnvrn->BeamSolarRad;
8570 105310 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclosureNum) =
8571 105310 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8572 : }
8573 :
8574 : // RJH - Calculate initial distribution of diffuse solar transmitted by exterior windows into each zone
8575 : // to all interior surfaces in the zone
8576 : // Includes subsequent transmittance of diffuse solar to adjacent zones through interior windows
8577 71220 : CalcWinTransDifSolInitialDistribution(state);
8578 71220 : }
8579 0 : void CalcAbsorbedOnExteriorOpaqueSurfaces(EnergyPlusData &state)
8580 : {
8581 : // SUBROUTINE INFORMATION:
8582 : // AUTHOR Simon Vidanovic
8583 : // DATE WRITTEN May 2017
8584 : // MODIFIED na
8585 : // RE-ENGINEERED na
8586 :
8587 : // PURPOSE OF THIS SUBROUTINE:
8588 : // Calculates solar energy absorbed on exterior opaque surfaces
8589 :
8590 0 : auto &s_surf = state.dataSurface;
8591 :
8592 0 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
8593 0 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
8594 0 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
8595 0 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
8596 0 : auto &surf = s_surf->Surface(SurfNum);
8597 : // TH added 3/24/2010 while debugging CR 7872
8598 0 : if (!surf.ExtSolar && surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
8599 0 : continue;
8600 : }
8601 0 : int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
8602 0 : int SurfNum2 = SurfNum;
8603 0 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
8604 0 : int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
8605 0 : SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
8606 : }
8607 0 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8608 0 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8609 :
8610 : //-------------------------------------------------------------------------
8611 : // EXTERIOR BEAM SOLAR RADIATION ABSORBED ON THE OUTSIDE OF OPAQUE SURFACES
8612 : //-------------------------------------------------------------------------
8613 :
8614 0 : if (SunLitFract > 0.0 && state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) {
8615 0 : s_surf->SurfOpaqAO(SurfNum) = state.dataConstruction->Construct(ConstrNum).OutsideAbsorpSolar * CosInc * SunLitFract;
8616 :
8617 : // Note: movable insulation, if present, is accounted for in subr. InitIntSolarDistribution,
8618 : // where SurfQRadSWOutMvIns is calculated from SurfOpaqQRadSWOutAbs and insulation solar absorptance
8619 : }
8620 : }
8621 0 : }
8622 : }
8623 0 : }
8624 :
8625 0 : void CalcInteriorSolarDistributionWCESimple(EnergyPlusData &state)
8626 : {
8627 :
8628 : // SUBROUTINE INFORMATION:
8629 : // AUTHOR Simon Vidanovic
8630 : // DATE WRITTEN May 2017
8631 :
8632 : // PURPOSE OF THIS SUBROUTINE:
8633 : // For a time step, calculates solar radiation absorbed by window layers, sky and diffuse solar
8634 : // gain into zone from exterior window, beam solar on exterior window transmitted as beam and/or diffuse
8635 : // and interior beam from exterior window that is absorbed/transmitted by back surfaces
8636 :
8637 : using namespace MultiLayerOptics;
8638 :
8639 0 : auto &s_surf = state.dataSurface;
8640 :
8641 0 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
8642 0 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
8643 0 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
8644 0 : int const firstSurf = thisSpace.HTSurfaceFirst;
8645 0 : int const lastSurf = thisSpace.HTSurfaceLast;
8646 0 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
8647 0 : s_surf->SurfOpaqAI(surfNum) = 0.0;
8648 0 : s_surf->SurfOpaqAO(surfNum) = 0.0;
8649 : }
8650 0 : }
8651 : }
8652 :
8653 0 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
8654 :
8655 0 : Real64 BABSZone = 0;
8656 0 : Real64 BTOTZone = 0;
8657 0 : state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
8658 0 : state.dataHeatBal->EnclSolDBIntWin(enclosureNum) = 0.0;
8659 0 : state.dataHeatBal->ZoneTransSolar(enclosureNum) = 0;
8660 0 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) = 0;
8661 0 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) = 0;
8662 0 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) = 0;
8663 0 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) = 0;
8664 0 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) = 0;
8665 0 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
8666 :
8667 0 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
8668 0 : auto &surf = s_surf->Surface(SurfNum);
8669 0 : if (surf.Class != SurfaceClass::Window) {
8670 0 : continue;
8671 : }
8672 0 : int SurfNum2 = 0;
8673 0 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
8674 0 : int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
8675 0 : SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
8676 : } else {
8677 0 : SurfNum2 = SurfNum;
8678 : }
8679 0 : auto &window = s_surf->SurfaceWindow(SurfNum2);
8680 0 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2); // Note: surfnum 2
8681 0 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8682 :
8683 0 : std::pair<Real64, Real64> incomingAngle = getSunWCEAngles(state, SurfNum2, BSDFDirection::Incoming);
8684 0 : Real64 Theta = incomingAngle.first;
8685 0 : Real64 Phi = incomingAngle.second;
8686 :
8687 0 : int ConstrNum = s_surf->Surface(SurfNum2).Construction;
8688 0 : if (s_surf->Surface(SurfNum2).activeShadedConstruction > 0) {
8689 0 : ConstrNum = s_surf->Surface(SurfNum2).activeShadedConstruction;
8690 : }
8691 : auto aLayer = // (AUTO_OK_OBJ)
8692 0 : CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, WavelengthRange::Solar, ConstrNum);
8693 :
8694 : ///////////////////////////////////////////////
8695 : // Solar absorbed in window layers
8696 : ///////////////////////////////////////////////
8697 0 : if (state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2) > 0.0) {
8698 0 : size_t numOfLayers = aLayer->getNumOfLayers();
8699 0 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
8700 0 : int CurrentState = s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState;
8701 0 : auto &cplxState = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(CurrentState);
8702 0 : for (size_t Lay = 1; Lay <= numOfLayers; ++Lay) {
8703 : // Simon: Important note about this equation is to use BeamSolarRad and not SurfQRadSWOutIncident
8704 : // is because BeamSolarRad is direct normal radiation (looking at the Sun) while SurfRadSWOutIncident
8705 : // is normal to window incidence. Since BSDF coefficients are taking into account angle of incidence,
8706 : // BeamSolarRad should be used in this case
8707 0 : state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) =
8708 0 : cplxState.WinSkyFtAbs(Lay) * s_surf->SurfSkySolarInc(SurfNum2) +
8709 0 : cplxState.WinSkyGndAbs(Lay) * s_surf->SurfGndSolarInc(SurfNum2) +
8710 0 : s_surf->SurfWinA(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad +
8711 0 : s_surf->SurfWinACFOverlap(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad;
8712 0 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfNum, Lay) = state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) * surf.Area;
8713 0 : s_surf->SurfWinADiffFront(SurfNum, Lay) = cplxState.WinSkyGndAbs(Lay);
8714 : }
8715 : } else {
8716 0 : for (size_t Lay = 1; Lay <= numOfLayers; ++Lay) {
8717 0 : Real64 AbWinBeam = aLayer->getAbsorptanceLayer(Lay, Side::Front, ScatteringSimple::Direct, Theta, Phi) *
8718 0 : window.OutProjSLFracMult[state.dataGlobal->HourOfDay];
8719 0 : Real64 AbWinDiffFront = aLayer->getAbsorptanceLayer(Lay, Side::Front, ScatteringSimple::Diffuse, Theta, Phi);
8720 : // Real64 AbWinDiffBack = aLayer->getAbsorptanceLayer(Lay, Side::Back, ScatteringSimple::Diffuse,
8721 : // Theta, Phi);
8722 :
8723 : // Simon: This should not be multiplied with cosine of incident angle. This however gives same
8724 : // results as BSDF and Winkelmann models.
8725 0 : s_surf->SurfWinA(SurfNum, Lay) =
8726 0 : AbWinBeam * CosInc * SunLitFract * s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
8727 0 : s_surf->SurfWinADiffFront(SurfNum, Lay) = AbWinDiffFront;
8728 :
8729 : // Simon: Same not as for BSDF. Normal solar radiation should be taken here because angle of
8730 : // incidence is already taken into account
8731 0 : Real64 absBeam = s_surf->SurfWinA(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad;
8732 : Real64 absDiff =
8733 0 : s_surf->SurfWinADiffFront(SurfNum, Lay) * (s_surf->SurfSkySolarInc(SurfNum2) + s_surf->SurfGndSolarInc(SurfNum2));
8734 0 : state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) = (absBeam + absDiff);
8735 0 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfNum, Lay) = state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) * surf.Area;
8736 : }
8737 : }
8738 : }
8739 :
8740 : ////////////////////////////////////////////////////////////////////
8741 : // SKY AND GROUND DIFFUSE SOLAR GAIN INTO ZONE FROM EXTERIOR WINDOW
8742 : ////////////////////////////////////////////////////////////////////
8743 0 : constexpr Real64 minLambda{0.3};
8744 0 : constexpr Real64 maxLambda{2.5};
8745 : const Real64 Tdiff =
8746 0 : aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DiffuseDiffuse, Theta, Phi);
8747 0 : state.dataConstruction->Construct(ConstrNum).TransDiff = Tdiff;
8748 0 : Real64 EnclSolDSWin = s_surf->SurfSkySolarInc(SurfNum2) * Tdiff * s_surf->Surface(SurfNum2).Area;
8749 0 : if ((state.dataEnvrn->DifSolarRad != 0)) {
8750 0 : EnclSolDSWin /= state.dataEnvrn->DifSolarRad;
8751 : } else {
8752 0 : EnclSolDSWin /= 1e-8;
8753 : }
8754 :
8755 0 : Real64 EnclSolDGWin = s_surf->SurfGndSolarInc(SurfNum2) * Tdiff * s_surf->Surface(SurfNum2).Area;
8756 0 : (state.dataEnvrn->GndSolarRad != 0) ? EnclSolDGWin /= state.dataEnvrn->GndSolarRad : EnclSolDGWin /= 1e-8;
8757 :
8758 : ////////////////////////////////////////////////////////////////////
8759 : // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
8760 : ////////////////////////////////////////////////////////////////////
8761 0 : Real64 TBmBm = aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DirectDirect, Theta, Phi);
8762 0 : Real64 TBmDif = aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DirectDiffuse, Theta, Phi);
8763 0 : Real64 SurfWinTransBmBmSolar = TBmBm * SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
8764 0 : Real64 SurfWinTransBmDifSolar = TBmDif * SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
8765 0 : BTOTZone += SurfWinTransBmBmSolar + SurfWinTransBmDifSolar;
8766 :
8767 0 : Real64 DifSolarRadiation = s_surf->SurfSkySolarInc(SurfNum2) + s_surf->SurfGndSolarInc(SurfNum2);
8768 0 : s_surf->SurfWinBmSolar(SurfNum) = state.dataEnvrn->BeamSolarRad * (TBmBm + TBmDif) * surf.Area * CosInc;
8769 0 : s_surf->SurfWinDifSolar(SurfNum) = DifSolarRadiation * Tdiff * surf.Area;
8770 0 : s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8771 0 : s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8772 0 : s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum);
8773 0 : s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8774 :
8775 : // Add beam solar absorbed by outside reveal to outside of window's base surface.
8776 : // Add beam solar absorbed by inside reveal to inside of window's base surface.
8777 : // This ignores 2-D heat transfer effects.
8778 0 : int BaseSurfNum = surf.BaseSurf;
8779 0 : s_surf->SurfOpaqAI(BaseSurfNum) = s_surf->SurfWinBmSolAbsdInsReveal(SurfNum2) / s_surf->Surface(BaseSurfNum).Area;
8780 0 : s_surf->SurfOpaqAO(BaseSurfNum) = s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum2) / s_surf->Surface(BaseSurfNum).Area;
8781 :
8782 : ////////////////////////////////////////////////////////////////////
8783 : // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
8784 : ////////////////////////////////////////////////////////////////////
8785 0 : Real64 TBm = TBmBm;
8786 : // Correction for beam absorbed by inside reveal
8787 0 : Real64 TBmDenom = SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
8788 0 : if (TBmDenom != 0.0) { // when =0.0, no correction
8789 0 : TBm -= s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / TBmDenom;
8790 : }
8791 :
8792 0 : TBm = max(0.0, TBm);
8793 0 : TBm *= surf.IncSolMultiplier;
8794 :
8795 0 : int NumOfBackSurf = state.dataShadowComb->ShadowComb(BaseSurfNum).NumBackSurf;
8796 :
8797 0 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
8798 0 : for (int IBack = 1; IBack <= NumOfBackSurf; ++IBack) {
8799 :
8800 : int const BackSurfNum =
8801 0 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
8802 :
8803 0 : if (BackSurfNum == 0) {
8804 0 : break; // No more irradiated back surfaces for this exterior window
8805 : }
8806 0 : int ConstrNumBack = s_surf->Surface(BackSurfNum).Construction;
8807 0 : auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
8808 : // NBackGlass = Construct( ConstrNumBack ).TotGlassLayers;
8809 : // Irradiated (overlap) area for this back surface, projected onto window plane
8810 : // (includes effect of shadowing on exterior window)
8811 0 : Real64 AOverlap = state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
8812 0 : Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
8813 :
8814 0 : if (constrBack.TransDiff <= 0.0) {
8815 : // Back surface is opaque interior or exterior wall
8816 :
8817 0 : Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
8818 0 : s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
8819 0 : BABSZone += BOverlap * AbsIntSurf; //[m2]
8820 : }
8821 : }
8822 : } else {
8823 0 : for (int const FloorNum : thisEnclosure.SurfacePtr) {
8824 : // In following, ISABSF is zero except for nominal floor surfaces
8825 0 : if (!s_surf->Surface(FloorNum).HeatTransSurf) {
8826 0 : continue;
8827 : }
8828 0 : if (state.dataSolarShading->SurfIntAbsFac(FloorNum) <= 0.0 || FloorNum == SurfNum) {
8829 0 : continue; // Keep only floor surfaces
8830 : }
8831 :
8832 0 : Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay]; //[m2]
8833 :
8834 0 : if (state.dataConstruction->Construct(s_surf->Surface(FloorNum).Construction).TransDiff <= 0.0) {
8835 : // Opaque surface
8836 0 : s_surf->SurfOpaqAI(FloorNum) +=
8837 0 : BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) / s_surf->Surface(FloorNum).Area; //[-]
8838 : }
8839 : }
8840 : }
8841 0 : state.dataHeatBal->ZoneTransSolar(enclosureNum) += s_surf->SurfWinTransSolar(SurfNum); //[W]
8842 0 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) =
8843 0 : state.dataHeatBal->ZoneTransSolar(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8844 0 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinBmSolar(SurfNum);
8845 0 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinDifSolar(SurfNum);
8846 0 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) =
8847 0 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8848 0 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) =
8849 0 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8850 0 : }
8851 0 : state.dataHeatBal->EnclSolDB(enclosureNum) = BTOTZone - BABSZone;
8852 : }
8853 0 : }
8854 :
8855 0 : int WindowScheduledSolarAbs(EnergyPlusData &state,
8856 : int const SurfNum, // Surface number
8857 : int const ConstNum // Construction number
8858 : )
8859 : {
8860 : // SUBROUTINE INFORMATION:
8861 : // AUTHOR Simon Vidanovic
8862 : // DATE WRITTEN June 2013
8863 :
8864 : // PURPOSE OF THIS SUBROUTINE:
8865 : // Returns scheduled surface gain object for given surface-construction combination
8866 0 : auto &s_surf = state.dataSurface;
8867 :
8868 0 : for (int i = 1; i <= s_surf->TotFenLayAbsSSG; ++i) {
8869 0 : if ((s_surf->FenLayAbsSSG(i).SurfPtr == SurfNum) && (s_surf->FenLayAbsSSG(i).ConstrPtr == ConstNum)) {
8870 0 : return i;
8871 : }
8872 : }
8873 :
8874 0 : return 0;
8875 : }
8876 :
8877 580565 : int SurfaceScheduledSolarInc(EnergyPlusData &state,
8878 : int const SurfNum, // Surface number
8879 : int const ConstNum // Construction number
8880 : )
8881 : {
8882 : // SUBROUTINE INFORMATION:
8883 : // AUTHOR Simon Vidanovic
8884 : // DATE WRITTEN June 2013
8885 :
8886 : // PURPOSE OF THIS SUBROUTINE:
8887 : // Returns scheduled surface gain pointer for given surface-construction combination
8888 :
8889 580565 : auto &s_surf = state.dataSurface;
8890 :
8891 580577 : for (int i = 1; i <= s_surf->TotSurfIncSolSSG; ++i) {
8892 15 : if ((s_surf->SurfIncSolSSG(i).SurfPtr == SurfNum) && (s_surf->SurfIncSolSSG(i).ConstrPtr == ConstNum)) {
8893 3 : return i;
8894 : }
8895 : }
8896 :
8897 580562 : return 0;
8898 : }
8899 :
8900 3643 : void PerformSolarCalculations(EnergyPlusData &state)
8901 : {
8902 :
8903 : // SUBROUTINE INFORMATION:
8904 : // AUTHOR Linda K. Lawrie
8905 : // DATE WRITTEN July 1999
8906 : // MODIFIED Sept 2003, FCW: add calls to CalcBeamSolDiffuseReflFactors and
8907 : // CalcBeamSolSpecularReflFactors
8908 : // Jan 2004, FCW: call CalcDayltgCoefficients if storm window status on
8909 : // any window has changed
8910 : // RE-ENGINEERED na
8911 :
8912 : // PURPOSE OF THIS SUBROUTINE:
8913 : // This subroutine determines if new solar/shading calculations need
8914 : // to be performed and calls the proper routines to do the job.
8915 :
8916 : // METHODOLOGY EMPLOYED:
8917 : // Users are allowed to enter a value for number of days in each period that
8918 : // will be used for calculating solar. (Later, this could be more complicated as
8919 : // in allowing a number of days in a month or something). Using this value or the
8920 : // default (20 days) if nothing is entered by the user, the routine will use the
8921 : // number of days left to determine if a new set of calculations should be done.
8922 : // The calculations use the average of "equation of time" and "solar declination"
8923 : // to perform the calculations.
8924 :
8925 : // REFERENCES:
8926 : // na
8927 :
8928 : // Using/Aliasing
8929 : using Dayltg::CalcDayltgCoefficients;
8930 : // Locals
8931 : // SUBROUTINE ARGUMENT DEFINITIONS:
8932 : // na
8933 :
8934 : // SUBROUTINE PARAMETER DEFINITIONS:
8935 : // na
8936 :
8937 : // INTERFACE BLOCK SPECIFICATIONS
8938 : // na
8939 :
8940 : // DERIVED TYPE DEFINITIONS
8941 : // na
8942 :
8943 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
8944 : Real64 SumDec;
8945 : Real64 SumET;
8946 : Real64 AvgEqOfTime;
8947 : Real64 AvgSinSolarDeclin;
8948 : Real64 AvgCosSolarDeclin;
8949 : int PerDayOfYear;
8950 : int Count;
8951 : Real64 SinDec;
8952 : Real64 EqTime;
8953 : // not used INTEGER SurfNum
8954 :
8955 3643 : auto &s_surf = state.dataSurface;
8956 : // Calculate sky diffuse shading
8957 :
8958 3643 : if (state.dataGlobal->BeginSimFlag) {
8959 104 : state.dataSolarShading->CalcSkyDifShading = true;
8960 104 : SkyDifSolarShading(state); // Calculate factors for shading of sky diffuse solar
8961 104 : state.dataSolarShading->CalcSkyDifShading = false;
8962 : }
8963 :
8964 3643 : if (state.dataGlobal->BeginEnvrnFlag) {
8965 481 : state.dataSolarShading->ShadowingDaysLeft = 0;
8966 : }
8967 :
8968 3643 : if (state.dataSolarShading->ShadowingDaysLeft <= 0 || state.dataSysVars->DetailedSolarTimestepIntegration) {
8969 :
8970 1836 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
8971 : // Perform calculations.
8972 478 : state.dataSolarShading->ShadowingDaysLeft = state.dataSolarShading->ShadowingCalcFrequency;
8973 478 : if (state.dataGlobal->DayOfSim + state.dataSolarShading->ShadowingDaysLeft > state.dataGlobal->NumOfDayInEnvrn) {
8974 458 : state.dataSolarShading->ShadowingDaysLeft = state.dataGlobal->NumOfDayInEnvrn - state.dataGlobal->DayOfSim + 1;
8975 : }
8976 :
8977 : // Calculate average Equation of Time, Declination Angle for this period
8978 :
8979 478 : if (!state.dataGlobal->WarmupFlag) {
8980 1 : if (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather) {
8981 1 : DisplayString(state, "Updating Shadowing Calculations, Start Date=" + state.dataEnvrn->CurMnDyYr);
8982 : } else {
8983 0 : DisplayString(state, "Updating Shadowing Calculations, Start Date=" + state.dataEnvrn->CurMnDy);
8984 : }
8985 1 : state.dataReportFlag->DisplayPerfSimulationFlag = true;
8986 : }
8987 :
8988 478 : PerDayOfYear = state.dataEnvrn->DayOfYear;
8989 478 : SumDec = 0.0;
8990 478 : SumET = 0.0;
8991 1336 : for (Count = 1; Count <= state.dataSolarShading->ShadowingDaysLeft; ++Count) {
8992 858 : SUN3(PerDayOfYear, SinDec, EqTime);
8993 858 : SumDec += SinDec;
8994 858 : SumET += EqTime;
8995 858 : ++PerDayOfYear;
8996 : }
8997 :
8998 : // Compute Period Values
8999 478 : AvgSinSolarDeclin = SumDec / double(state.dataSolarShading->ShadowingDaysLeft);
9000 478 : AvgCosSolarDeclin = std::sqrt(1.0 - pow_2(AvgSinSolarDeclin));
9001 478 : AvgEqOfTime = SumET / double(state.dataSolarShading->ShadowingDaysLeft);
9002 : } else {
9003 1358 : SUN3(state.dataEnvrn->DayOfYear, AvgSinSolarDeclin, AvgEqOfTime);
9004 1358 : AvgCosSolarDeclin = std::sqrt(1.0 - pow_2(AvgSinSolarDeclin));
9005 : // trigger display of progress in the simulation every two weeks
9006 1358 : if (!state.dataGlobal->WarmupFlag && state.dataGlobal->BeginDayFlag && (state.dataGlobal->DayOfSim % 14 == 0)) {
9007 0 : state.dataReportFlag->DisplayPerfSimulationFlag = true;
9008 : }
9009 : }
9010 :
9011 1836 : CalcPerSolarBeam(state, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
9012 :
9013 : // Calculate factors for solar reflection
9014 1836 : if (s_surf->CalcSolRefl) {
9015 0 : CalcBeamSolDiffuseReflFactors(state);
9016 0 : CalcBeamSolSpecularReflFactors(state);
9017 0 : if (state.dataGlobal->BeginSimFlag) {
9018 0 : CalcSkySolDiffuseReflFactors(state);
9019 : }
9020 : }
9021 : // Calculate daylighting coefficients
9022 1836 : CalcDayltgCoefficients(state);
9023 : }
9024 :
9025 3643 : if (!state.dataGlobal->WarmupFlag) {
9026 417 : --state.dataSolarShading->ShadowingDaysLeft;
9027 : }
9028 :
9029 : // Recalculate daylighting coefficients if storm window has been added
9030 : // or removed from one or more windows at beginning of day
9031 5005 : if (state.dataDayltg->TotWindowsWithDayl > 0 && !state.dataGlobal->BeginSimFlag && !state.dataGlobal->BeginEnvrnFlag &&
9032 5005 : !state.dataGlobal->WarmupFlag && s_surf->TotStormWin > 0 && state.dataHeatBal->StormWinChangeThisDay) {
9033 0 : CalcDayltgCoefficients(state);
9034 : }
9035 3643 : }
9036 :
9037 8010 : void SHDRVL(EnergyPlusData &state,
9038 : int const HTSS, // Heat transfer surface number of the subsurface
9039 : int const SBSNR, // Subsurface number
9040 : int const Hour,
9041 : int const TS)
9042 : {
9043 :
9044 : // SUBROUTINE INFORMATION:
9045 : // AUTHOR Legacy Code
9046 : // DATE WRITTEN
9047 : // MODIFIED May 2002 (FCW): allow triangular windows to have reveal.
9048 : // RE-ENGINEERED Lawrie, Oct 2000
9049 :
9050 : // PURPOSE OF THIS SUBROUTINE:
9051 : // This subroutine computes the shadowing from a reveal onto a subsurface.
9052 :
9053 : // REFERENCES:
9054 : // BLAST/IBLAST code, original author George Walton
9055 :
9056 : int NVS; // Number of vertices
9057 :
9058 8010 : int constexpr None(0); // for use with RevealStatus
9059 8010 : int constexpr EntireWindowShadedByReveal(1); // for use with RevealStatus
9060 8010 : int constexpr WindowShadedOnlyByReveal(2); // for use with RevealStatus
9061 :
9062 : Real64 A; // Area
9063 : Real64 R; // Depth of the reveal (m)
9064 : int I; // Loop control
9065 : int N; // Vertex number
9066 : int NS1; // Locations in homogeneous coordinate array
9067 : int NS2;
9068 : // note, below dimensions not changed because subsurface still max 4
9069 8010 : Array1D<Real64> XVT(5); // Projected X coordinates of vertices
9070 8010 : Array1D<Real64> YVT(5); // Projected Y coordinates of vertices
9071 : bool RevealStatusSet; // Used to control flow through this subroutine.
9072 : // Certain operations performed only if reveal status not yet set.
9073 : int RevealStatus; // Status of the reveal, takes the parameter values above
9074 :
9075 8010 : auto &s_surf = state.dataSurface;
9076 :
9077 8010 : RevealStatus = None;
9078 8010 : RevealStatusSet = false;
9079 :
9080 8010 : if (!state.dataSolarShading->CalcSkyDifShading) {
9081 4994 : state.dataSolarShading->SurfWinRevealStatus(Hour, TS, SBSNR) = None;
9082 : }
9083 :
9084 8010 : R = s_surf->Surface(SBSNR).Reveal;
9085 8010 : if (R <= 0.0) {
9086 8010 : RevealStatus = None;
9087 8010 : RevealStatusSet = true;
9088 : }
9089 :
9090 8010 : if (!RevealStatusSet) {
9091 :
9092 0 : state.dataSolarShading->FRVLHC = state.dataSolarShading->LOCHCA + 1;
9093 0 : ++state.dataSolarShading->LOCHCA;
9094 0 : NVS = s_surf->Surface(SBSNR).Sides;
9095 :
9096 : // Currently (06May02) windows are either rectangles (NVS=4) or triangles (NVS=3)
9097 :
9098 0 : if (NVS == 4) { // Rectangular subsurface
9099 :
9100 : // Determine vertices of reveal.
9101 : // Project the subsurface up to the plane of the wall.
9102 :
9103 0 : XVT(1) = s_surf->ShadeV(SBSNR).XV(1) + R * max(state.dataSolarShading->XShadowProjection, 0.0);
9104 0 : XVT(2) = s_surf->ShadeV(SBSNR).XV(2) + R * max(state.dataSolarShading->XShadowProjection, 0.0);
9105 0 : XVT(3) = s_surf->ShadeV(SBSNR).XV(3) + R * min(state.dataSolarShading->XShadowProjection, 0.0);
9106 0 : XVT(4) = s_surf->ShadeV(SBSNR).XV(4) + R * min(state.dataSolarShading->XShadowProjection, 0.0);
9107 0 : YVT(1) = s_surf->ShadeV(SBSNR).YV(1) + R * min(state.dataSolarShading->YShadowProjection, 0.0);
9108 0 : YVT(2) = s_surf->ShadeV(SBSNR).YV(2) + R * max(state.dataSolarShading->YShadowProjection, 0.0);
9109 0 : YVT(3) = s_surf->ShadeV(SBSNR).YV(3) + R * max(state.dataSolarShading->YShadowProjection, 0.0);
9110 0 : YVT(4) = s_surf->ShadeV(SBSNR).YV(4) + R * min(state.dataSolarShading->YShadowProjection, 0.0);
9111 :
9112 : // Check for complete shadowing.
9113 :
9114 0 : if ((XVT(2) >= XVT(3)) || (YVT(2) >= YVT(1))) {
9115 :
9116 0 : RevealStatus = EntireWindowShadedByReveal;
9117 0 : RevealStatusSet = true;
9118 :
9119 : } else {
9120 : // Re-order vertices to clockwise.
9121 :
9122 0 : for (N = 1; N <= NVS; ++N) {
9123 0 : state.dataSolarShading->XVS(N) = XVT(NVS + 1 - N);
9124 0 : state.dataSolarShading->YVS(N) = YVT(NVS + 1 - N);
9125 : }
9126 :
9127 : // Transform to homogeneous coordinates
9128 :
9129 0 : HTRANS1(state, state.dataSolarShading->FRVLHC, NVS);
9130 0 : state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC) = -state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC);
9131 0 : state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC) = 1.0;
9132 :
9133 0 : if (state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC) <= 0.0) {
9134 0 : RevealStatus = EntireWindowShadedByReveal;
9135 0 : RevealStatusSet = true;
9136 : }
9137 : }
9138 :
9139 0 : } else if (NVS == 3) { // Triangular window
9140 :
9141 : // Project window to outside plane of parent surface
9142 :
9143 0 : for (N = 1; N <= 3; ++N) {
9144 0 : XVT(N) = s_surf->ShadeV(SBSNR).XV(N) + R * state.dataSolarShading->XShadowProjection;
9145 0 : YVT(N) = s_surf->ShadeV(SBSNR).YV(N) + R * state.dataSolarShading->YShadowProjection;
9146 : }
9147 :
9148 : // Find the overlap between the original window and the projected window
9149 : // Put XVT,YVT in clockwise order
9150 :
9151 0 : for (N = 1; N <= NVS; ++N) {
9152 0 : state.dataSolarShading->XVS(N) = XVT(NVS + 1 - N);
9153 0 : state.dataSolarShading->YVS(N) = YVT(NVS + 1 - N);
9154 : }
9155 :
9156 : // Transform to homogeneous coordinates
9157 :
9158 0 : NS1 = state.dataSolarShading->LOCHCA + 1;
9159 0 : state.dataSolarShading->LOCHCA = NS1;
9160 0 : HTRANS1(state, NS1, NVS);
9161 :
9162 : // Put XV,YV in clockwise order
9163 :
9164 0 : for (N = 1; N <= NVS; ++N) {
9165 0 : state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(NVS + 1 - N);
9166 0 : state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(NVS + 1 - N);
9167 : }
9168 :
9169 : // Transform to homogeneous coordinates
9170 :
9171 0 : NS2 = state.dataSolarShading->LOCHCA + 1;
9172 0 : state.dataSolarShading->LOCHCA = NS2;
9173 0 : HTRANS1(state, NS2, NVS);
9174 0 : state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC) = 1.0;
9175 :
9176 : // Find overlap
9177 :
9178 0 : DeterminePolygonOverlap(state, NS1, NS2, state.dataSolarShading->FRVLHC);
9179 0 : if (state.dataSolarShading->OverlapStatus == NoOverlap) {
9180 0 : RevealStatus = EntireWindowShadedByReveal;
9181 0 : RevealStatusSet = true;
9182 : }
9183 : }
9184 : }
9185 :
9186 8010 : if (!RevealStatusSet) {
9187 :
9188 : // Check for no shadows on window.
9189 :
9190 0 : if (state.dataSolarShading->NSBSHC <= 1) {
9191 0 : RevealStatus = WindowShadedOnlyByReveal;
9192 0 : RevealStatusSet = true;
9193 : } else {
9194 : // Reduce all previous shadows to size of reveal opening.
9195 0 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FRVLHC;
9196 0 : MULTOL(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->FSBSHC, state.dataSolarShading->NSBSHC - 1);
9197 0 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
9198 0 : RevealStatus = None;
9199 0 : RevealStatusSet = true;
9200 : } else {
9201 0 : state.dataSolarShading->NRVLHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FRVLHC + 1;
9202 0 : if (state.dataSolarShading->NRVLHC <= 1) {
9203 0 : RevealStatus = WindowShadedOnlyByReveal;
9204 0 : RevealStatusSet = true;
9205 : }
9206 : }
9207 : }
9208 : }
9209 :
9210 8010 : if (!RevealStatusSet) {
9211 : // Compute sunlit area.
9212 0 : A = state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC);
9213 0 : for (I = 2; I <= state.dataSolarShading->NRVLHC; ++I) {
9214 0 : A += state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC - 1 + I) *
9215 0 : (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC - 1 + I));
9216 : }
9217 0 : state.dataSolarShading->SurfSunlitArea(HTSS) = A;
9218 : }
9219 :
9220 8010 : if ((RevealStatus == EntireWindowShadedByReveal) || (state.dataSolarShading->SurfSunlitArea(HTSS) < 0.0)) {
9221 0 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0; // Window entirely shaded by reveal.
9222 8010 : } else if (RevealStatus == WindowShadedOnlyByReveal) {
9223 0 : state.dataSolarShading->SurfSunlitArea(HTSS) =
9224 0 : state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC); // Window shaded only by reveal.
9225 : }
9226 :
9227 8010 : if (!state.dataSolarShading->CalcSkyDifShading) {
9228 4994 : state.dataSolarShading->SurfWinRevealStatus(Hour, TS, SBSNR) = RevealStatus;
9229 : }
9230 8010 : }
9231 :
9232 90268 : void SHDSBS(EnergyPlusData &state,
9233 : int const iHour, // Hour Index
9234 : int const CurSurf,
9235 : int const NBKS, // Number of back surfaces
9236 : int const NSBS, // Number of subsurfaces
9237 : int const HTS, // Heat transfer surface number of the general receiving surf
9238 : int const TS // Time step Index
9239 : )
9240 : {
9241 :
9242 : // SUBROUTINE INFORMATION:
9243 : // AUTHOR Legacy Code
9244 : // DATE WRITTEN
9245 : // MODIFIED FCW, Oct 2002: Surface%Area --> Surface%Area + SurfaceWindow%DividerArea
9246 : // in calculation of SunlitFracWithoutReveal (i.e., use full window area, not
9247 : // just glass area.
9248 : // TH, May 2009: Bug fixed to address part of CR 7596 - inside reveals
9249 : // causing high cooling loads
9250 : // RE-ENGINEERED Lawrie, Oct 2000
9251 :
9252 : // PURPOSE OF THIS SUBROUTINE:
9253 : // This subroutine determines the shadowing on subsurfaces and
9254 : // revises the base surface area accordingly. It also computes
9255 : // the effect of transparent subsurfaces.
9256 :
9257 : // REFERENCES:
9258 : // BLAST/IBLAST code, original author George Walton
9259 :
9260 : Real64 A; // Area
9261 : int I; // Loop control
9262 : int J; // Loop control
9263 : int K; // Window construction number
9264 : int N; // Vertex number
9265 : Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
9266 : // For windows, includes divider area
9267 : // REAL(r64) FrameAreaAdd ! Additional frame area sunlit
9268 : // REAL(r64) DividerAreaAdd ! Additional frame area sunlit
9269 : int HTSS; // Heat transfer surface number of the subsurface
9270 : int SBSNR; // Subsurface number
9271 :
9272 90268 : auto &s_surf = state.dataSurface;
9273 :
9274 90268 : if (NSBS > 0) { // Action taken only if subsurfaces present
9275 :
9276 15470 : state.dataSolarShading->FSBSHC = state.dataSolarShading->LOCHCA + 1;
9277 :
9278 32628 : for (I = 1; I <= NSBS; ++I) { // Do for all subsurfaces (sbs).
9279 :
9280 17158 : SBSNR = state.dataShadowComb->ShadowComb(CurSurf).SubSurf(I);
9281 :
9282 17158 : HTSS = SBSNR;
9283 :
9284 17158 : K = s_surf->Surface(SBSNR).Construction;
9285 :
9286 17158 : if (!state.dataSolarShading->penumbra) {
9287 34316 : if ((state.dataSolarShading->OverlapStatus != TooManyVertices) && (state.dataSolarShading->OverlapStatus != TooManyFigures) &&
9288 17158 : (state.dataSolarShading->SurfSunlitArea(HTS) > 0.0)) {
9289 :
9290 : // Re-order vertices to clockwise sequential; compute homogeneous coordinates.
9291 8329 : state.dataSolarShading->NVS = s_surf->Surface(SBSNR).Sides;
9292 41645 : for (N = 1; N <= state.dataSolarShading->NVS; ++N) {
9293 33316 : state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(state.dataSolarShading->NVS + 1 - N);
9294 33316 : state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(state.dataSolarShading->NVS + 1 - N);
9295 : }
9296 8329 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FSBSHC;
9297 8329 : HTRANS1(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->NVS);
9298 8329 : state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
9299 8329 : state.dataSolarShading->HCT(state.dataSolarShading->LOCHCA) = 1.0;
9300 8329 : state.dataSolarShading->NSBSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FSBSHC + 1;
9301 :
9302 : // Determine sunlit area of subsurface due to shadows on general receiving surface.
9303 8329 : if (state.dataSolarShading->NGSSHC > 0) {
9304 2773 : MULTOL(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->FGSSHC - 1, state.dataSolarShading->NGSSHC);
9305 2773 : if ((state.dataSolarShading->OverlapStatus != TooManyVertices) && (state.dataSolarShading->OverlapStatus != TooManyFigures)) {
9306 2773 : state.dataSolarShading->NSBSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FSBSHC + 1;
9307 : }
9308 : }
9309 : }
9310 :
9311 34316 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures) ||
9312 17158 : (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0)) { // General receiving surface totally shaded.
9313 :
9314 8829 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9315 :
9316 8829 : if (iHour > 0 && TS > 0) {
9317 4649 : state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) = 0.0;
9318 : }
9319 :
9320 8329 : } else if ((state.dataSolarShading->NGSSHC <= 0) || (state.dataSolarShading->NSBSHC == 1)) { // No shadows.
9321 :
9322 5608 : state.dataSolarShading->SurfSunlitArea(HTSS) = state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC);
9323 5608 : state.dataSolarShading->SurfSunlitArea(HTS) -=
9324 5608 : state.dataSolarShading->SurfSunlitArea(HTSS); // Revise sunlit area of general receiving surface.
9325 :
9326 : // TH. This is a bug. SunLitFracWithoutReveal should be a ratio of area
9327 : // IF(IHour > 0 .AND. TS > 0) SunLitFracWithoutReveal(HTSS,IHour,TS) = &
9328 : // Surface(HTSS)%NetAreaShadowCalc
9329 :
9330 : // new code fixed part of CR 7596. TH 5/29/2009
9331 5608 : if (iHour > 0 && TS > 0) {
9332 3452 : state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
9333 3452 : state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).NetAreaShadowCalc;
9334 : }
9335 :
9336 5608 : SHDRVL(state, HTSS, SBSNR, iHour, TS); // Determine shadowing from reveal.
9337 :
9338 5608 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
9339 0 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9340 : }
9341 :
9342 : } else { // Compute area.
9343 :
9344 2721 : A = state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC);
9345 6211 : for (J = 2; J <= state.dataSolarShading->NSBSHC; ++J) {
9346 3490 : A += state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC - 1 + J) *
9347 3490 : (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FSBSHC - 1 + J));
9348 : }
9349 2721 : state.dataSolarShading->SurfSunlitArea(HTSS) = A;
9350 2721 : if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
9351 :
9352 2402 : state.dataSolarShading->SurfSunlitArea(HTS) -=
9353 2402 : state.dataSolarShading->SurfSunlitArea(HTSS); // Revise sunlit area of general receiving surface.
9354 :
9355 2402 : if (iHour > 0 && TS > 0) {
9356 1542 : state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
9357 1542 : state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).Area;
9358 : }
9359 :
9360 2402 : SHDRVL(state, HTSS, SBSNR, iHour, TS); // Determine shadowing from reveal.
9361 :
9362 2402 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
9363 0 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9364 : }
9365 :
9366 : } else { // General receiving surface totally shaded.
9367 :
9368 319 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9369 : }
9370 : }
9371 : }
9372 :
9373 : // Determine transmittance and absorptances of sunlit window.
9374 17158 : if (state.dataConstruction->Construct(K).TransDiff > 0.0) {
9375 :
9376 11878 : if (!state.dataSolarShading->CalcSkyDifShading) { // Overlaps calculation is only done for beam solar
9377 : // shading, not for sky diffuse solar shading
9378 :
9379 6982 : CalcInteriorSolarOverlaps(state, iHour, NBKS, HTSS, CurSurf, TS);
9380 : }
9381 : }
9382 :
9383 : // Error checking.
9384 17158 : SurfArea = s_surf->Surface(SBSNR).NetAreaShadowCalc;
9385 17158 : state.dataSolarShading->SurfSunlitArea(HTSS) = max(0.0, state.dataSolarShading->SurfSunlitArea(HTSS));
9386 :
9387 17158 : state.dataSolarShading->SurfSunlitArea(HTSS) = min(state.dataSolarShading->SurfSunlitArea(HTSS), SurfArea);
9388 :
9389 : } // End of subsurface loop
9390 : }
9391 90268 : }
9392 :
9393 2216 : void SUN3(int const JulianDayOfYear, // Julian Day Of Year
9394 : Real64 &SineOfSolarDeclination, // Sine of Solar Declination
9395 : Real64 &EquationOfTime // Equation of Time (Degrees)
9396 : )
9397 : {
9398 :
9399 : // SUBROUTINE INFORMATION:
9400 : // AUTHOR Legacy Code
9401 : // DATE WRITTEN
9402 : // MODIFIED na
9403 : // RE-ENGINEERED Linda K. Lawrie
9404 :
9405 : // PURPOSE OF THIS SUBROUTINE:
9406 : // This subroutine computes the coefficients for determining
9407 : // the solar position.
9408 :
9409 : // METHODOLOGY EMPLOYED:
9410 : // The expressions are based on least-squares fits of data on p.316 of 'Thermal
9411 : // Environmental Engineering' by Threlkeld and on p.387 of the ASHRAE Handbook
9412 : // of Fundamentals (need date of ASHRAE HOF).
9413 :
9414 : // REFERENCES:
9415 : // BLAST/IBLAST code, original author George Walton
9416 :
9417 : // Fitted coefficients of Fourier series | Sine of declination coefficients
9418 : static constexpr std::array<Real64, 9> SineSolDeclCoef = {
9419 : 0.00561800, 0.0657911, -0.392779, 0.00064440, -0.00618495, -0.00010101, -0.00007951, -0.00011691, 0.00002096};
9420 : // Fitted coefficients of Fourier Series | Equation of Time coefficients
9421 : static constexpr std::array<Real64, 9> EqOfTimeCoef = {
9422 : 0.00021971, -0.122649, 0.00762856, -0.156308, -0.0530028, -0.00388702, -0.00123978, -0.00270502, -0.00167992};
9423 :
9424 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
9425 : Real64 X; // Day of Year in Radians (Computed from Input JulianDayOfYear)
9426 : Real64 CosX; // COS(X)
9427 : Real64 SineX; // SIN(X)
9428 :
9429 2216 : X = 0.017167 * JulianDayOfYear; // Convert julian date to angle X
9430 :
9431 : // Calculate sines and cosines of X
9432 2216 : SineX = std::sin(X);
9433 2216 : CosX = std::cos(X);
9434 :
9435 2216 : SineOfSolarDeclination = SineSolDeclCoef[0] + SineSolDeclCoef[1] * SineX + SineSolDeclCoef[2] * CosX + SineSolDeclCoef[3] * (SineX * CosX * 2.0) +
9436 2216 : SineSolDeclCoef[4] * (pow_2(CosX) - pow_2(SineX)) +
9437 2216 : SineSolDeclCoef[5] * (SineX * (pow_2(CosX) - pow_2(SineX)) + CosX * (SineX * CosX * 2.0)) +
9438 2216 : SineSolDeclCoef[6] * (CosX * (pow_2(CosX) - pow_2(SineX)) - SineX * (SineX * CosX * 2.0)) +
9439 2216 : SineSolDeclCoef[7] * (2.0 * (SineX * CosX * 2.0) * (pow_2(CosX) - pow_2(SineX))) +
9440 2216 : SineSolDeclCoef[8] * (pow_2(pow_2(CosX) - pow_2(SineX)) - pow_2(SineX * CosX * 2.0));
9441 :
9442 2216 : EquationOfTime = EqOfTimeCoef[0] + EqOfTimeCoef[1] * SineX + EqOfTimeCoef[2] * CosX + EqOfTimeCoef[3] * (SineX * CosX * 2.0) +
9443 2216 : EqOfTimeCoef[4] * (pow_2(CosX) - pow_2(SineX)) +
9444 2216 : EqOfTimeCoef[5] * (SineX * (pow_2(CosX) - pow_2(SineX)) + CosX * (SineX * CosX * 2.0)) +
9445 2216 : EqOfTimeCoef[6] * (CosX * (pow_2(CosX) - pow_2(SineX)) - SineX * (SineX * CosX * 2.0)) +
9446 2216 : EqOfTimeCoef[7] * (2.0 * (SineX * CosX * 2.0) * (pow_2(CosX) - pow_2(SineX))) +
9447 2216 : EqOfTimeCoef[8] * (pow_2(pow_2(CosX) - pow_2(SineX)) - pow_2(SineX * CosX * 2.0));
9448 2216 : }
9449 :
9450 30561 : void SUN4(EnergyPlusData &state,
9451 : Real64 const CurrentTime, // Time to use in shadowing calculations
9452 : Real64 const EqOfTime, // Equation of time for current day
9453 : Real64 const SinSolarDeclin, // Sine of the Solar declination (current day)
9454 : Real64 const CosSolarDeclin // Cosine of the Solar declination (current day)
9455 : )
9456 : {
9457 :
9458 : // SUBROUTINE INFORMATION:
9459 : // AUTHOR Legacy Code
9460 : // DATE WRITTEN
9461 : // MODIFIED na
9462 : // RE-ENGINEERED Lawrie, Oct 2000
9463 :
9464 : // PURPOSE OF THIS SUBROUTINE:
9465 : // This subroutine computes solar direction cosines for a given hour. These
9466 : // cosines are used in the shadowing calculations.
9467 : // REFERENCES:
9468 : // BLAST/IBLAST code, original author George Walton
9469 :
9470 : Real64 H; // Hour angle (before noon = +) (in radians)
9471 : Real64 HrAngle; // Basic hour angle
9472 :
9473 : // Compute the hour angle
9474 30561 : HrAngle = (15.0 * (12.0 - (CurrentTime + EqOfTime)) + (state.dataEnvrn->TimeZoneMeridian - state.dataEnvrn->Longitude));
9475 30561 : H = HrAngle * Constant::DegToRad;
9476 :
9477 : // Compute the cosine of the solar zenith angle.
9478 30561 : state.dataSolarShading->SUNCOS(3) = SinSolarDeclin * state.dataEnvrn->SinLatitude + CosSolarDeclin * state.dataEnvrn->CosLatitude * std::cos(H);
9479 30561 : state.dataSolarShading->SUNCOS(2) = 0.0;
9480 30561 : state.dataSolarShading->SUNCOS(1) = 0.0;
9481 :
9482 30561 : if (state.dataSolarShading->SUNCOS(3) < DataEnvironment::SunIsUpValue) {
9483 15503 : return; // Return if sun not above horizon.
9484 : }
9485 :
9486 : // Compute other direction cosines.
9487 15058 : state.dataSolarShading->SUNCOS(2) = SinSolarDeclin * state.dataEnvrn->CosLatitude - CosSolarDeclin * state.dataEnvrn->SinLatitude * std::cos(H);
9488 15058 : state.dataSolarShading->SUNCOS(1) = CosSolarDeclin * std::sin(H);
9489 : }
9490 :
9491 249958 : void WindowShadingManager(EnergyPlusData &state)
9492 : {
9493 :
9494 : // SUBROUTINE INFORMATION:
9495 : // AUTHOR Fred Winkelmann
9496 : // DATE WRITTEN December 1998
9497 : // MODIFIED November 1999 (FW)
9498 : // Aug 2001 (FW): change shading control names, change approach
9499 : // to scheduling and glare control, add movable
9500 : // insulation controls (mainly for heating reduction)
9501 : // Dec 2001 (FW): add slat angle control for blinds
9502 : // Aug 2002 (FW): add four new control types:
9503 : // OnIfHighOutsideAirTempAndHighSolarOnWindow
9504 : // OnIfHighOutsideAirTempAndHighHorizontalSolar
9505 : // OnIfHighZoneAirTempAndHighSolarOnWindow
9506 : // OnIfHighZoneAirTempAndHighHorizontalSolar
9507 : // Dec 2002 (FW): add between-glass shade/blind
9508 : // Mar 2003 (FW): allow GlareControlIsActive = .TRUE. only for daylit zones
9509 : // Apr 2003 (FW): use SNLoadCoolRate or SNLoadHeatRate only if not first time step
9510 : // (fixes problem when used first time thru and not allocated)
9511 : // May 2006 (RR): add exterior window screen
9512 : // May 2009 (BG): add EMS actuator override for shade flag and slat angle
9513 : // RE-ENGINEERED na
9514 :
9515 : // PURPOSE OF THIS SUBROUTINE:
9516 : // For windows with shading, selects the shaded construction
9517 : // that is used in the heat balance calculation, and sets
9518 : // the window shading flag, which is:
9519 : // -1: if window has no shading device
9520 : // 0: if shading device is off
9521 : // 1: if interior shade is on
9522 : // 2: if glazing is switched to darker state
9523 : // 3: if exterior shade is on
9524 : // 6: if interior blind is on
9525 : // 7: if exterior blind is on
9526 : // 8: if between-glass shade is on
9527 : // 9: if between-glass blind is on
9528 : // 10: window has interior shade that is off but may be triggered on later
9529 : // to control daylight glare
9530 : // 20: window has switchable glazing that is unswitched but may be switched later
9531 : // to control daylight glare or daylight illuminance
9532 : // 30: window has exterior shade that is off but may be triggered on later
9533 : // to control daylight glare or daylight illuminance
9534 : // 60: window has interior blind that is off but may be triggered on later
9535 : // to control daylight glare or daylight illuminance
9536 : // 70: window has exterior blind that is off but may be triggered on later
9537 : // to control daylight glare or daylight illuminance
9538 : // 80: window has between-glass shade that is off but may be triggered on later
9539 : // to control daylight glare or daylight illuminance
9540 : // 90: window has between-glass blind that is off but may be triggered on later
9541 : // to control daylight glare or daylight illuminance
9542 : // A "shading device" may be an exterior, interior or between-glass shade or blind,
9543 : // or the lower-transmitting (dark) state of switchable glazing (e.g., electrochromic).
9544 : // In all cases, the unshaded condition is represented
9545 : // by the construction given by window's Surface()%Construction and
9546 : // the shaded condition is represented by the construction given by
9547 : // the window's Surface()%ShadedConstruction
9548 : // REFERENCES:
9549 : // na
9550 :
9551 : int IConst; // Construction
9552 :
9553 249958 : auto &s_mat = state.dataMaterial;
9554 249958 : auto &s_surf = state.dataSurface;
9555 :
9556 586610 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
9557 706907 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
9558 370255 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
9559 370255 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
9560 370255 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
9561 458823 : for (int ISurf = firstSurfWin; ISurf <= lastSurfWin; ++ISurf) {
9562 88568 : auto &surfWin = s_surf->SurfaceWindow(ISurf);
9563 88568 : s_surf->SurfWinExtIntShadePrevTS(ISurf) = s_surf->SurfWinShadingFlag(ISurf);
9564 :
9565 88568 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::NoShade;
9566 88568 : s_surf->SurfWinFracTimeShadingDeviceOn(ISurf) = 0.0;
9567 88568 : if (s_surf->SurfWinWindowModelType(ISurf) == WindowModel::EQL) {
9568 2369 : int EQLNum = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction).EQLConsPtr;
9569 2369 : if (state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr > 0) {
9570 1473 : auto &surfShade = s_surf->surfShades(ISurf);
9571 1473 : if (state.dataWindowEquivLayer->CFS(EQLNum).L(state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr).CNTRL ==
9572 1473 : state.dataWindowEquivalentLayer->lscNONE) {
9573 507 : surfShade.blind.slatAngDeg =
9574 507 : state.dataWindowEquivLayer->CFS(EQLNum).L(state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr).PHI_DEG;
9575 : } else {
9576 966 : surfShade.blind.slatAngDeg = 0.0;
9577 : }
9578 : }
9579 : }
9580 :
9581 : // Initialization of complex fenestration shading device
9582 88568 : if (s_surf->SurfWinWindowModelType(ISurf) == WindowModel::BSDF) {
9583 0 : auto &construction = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction);
9584 0 : int TotLayers = construction.TotLayers;
9585 0 : for (int Lay = 1; Lay <= TotLayers; ++Lay) {
9586 0 : const int LayPtr = construction.LayerPoint(Lay);
9587 0 : auto const *material = s_mat->materials(LayPtr);
9588 0 : const bool isShading = material->group == Material::Group::ComplexShade;
9589 0 : if (isShading && Lay == 1) {
9590 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtShade;
9591 : }
9592 0 : if (isShading && Lay == TotLayers) {
9593 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntShade;
9594 : }
9595 : }
9596 :
9597 0 : if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::IntShade) {
9598 0 : auto &surfShade = s_surf->surfShades(ISurf);
9599 0 : auto &construction = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction);
9600 0 : const int TotLay = construction.TotLayers;
9601 0 : int ShadingLayerPtr = construction.LayerPoint(TotLay);
9602 :
9603 0 : auto const *matComplexShade = dynamic_cast<Material::MaterialComplexShade *>(s_mat->materials(ShadingLayerPtr));
9604 0 : Real64 TauShadeIR = matComplexShade->TransThermal;
9605 0 : Real64 EpsShadeIR = matComplexShade->BackEmissivity;
9606 0 : Real64 RhoShadeIR = max(0.0, 1.0 - TauShadeIR - EpsShadeIR);
9607 : // Get properties of glass next to inside shading layer
9608 0 : int GlassLayPtr = construction.LayerPoint(TotLay - 2);
9609 0 : Real64 EpsGlassIR = s_mat->materials(GlassLayPtr)->AbsorpThermalBack;
9610 0 : Real64 RhoGlassIR = 1 - EpsGlassIR;
9611 :
9612 0 : surfShade.effShadeEmi = EpsShadeIR * (1.0 + RhoGlassIR * TauShadeIR / (1.0 - RhoGlassIR * RhoShadeIR));
9613 0 : surfShade.effGlassEmi = EpsGlassIR * TauShadeIR / (1.0 - RhoGlassIR * RhoShadeIR);
9614 : }
9615 : }
9616 :
9617 88568 : if (s_surf->Surface(ISurf).ExtBoundCond != ExternalEnvironment) {
9618 0 : continue;
9619 : }
9620 88568 : if (!s_surf->Surface(ISurf).HasShadeControl) {
9621 56212 : continue;
9622 : } else {
9623 : //
9624 : }
9625 :
9626 : // Initialize switching factor (applicable only to switchable glazing) to unswitched
9627 32356 : s_surf->SurfWinSwitchingFactor(ISurf) = 0.0;
9628 :
9629 32356 : IConst = s_surf->Surface(ISurf).Construction;
9630 : // Vis trans at normal incidence of unswitched glass. Counting the GlazedFrac
9631 32356 : if (IConst > 0) {
9632 32352 : s_surf->SurfWinVisTransSelected(ISurf) =
9633 32352 : Window::POLYF(1.0, state.dataConstruction->Construct(IConst).TransVisBeamCoef) * surfWin.glazedFrac;
9634 : }
9635 :
9636 : // Window has shading control
9637 : // select the active window shading control and corresponding constructions
9638 32356 : size_t indexWindowShadingControl = selectActiveWindowShadingControlIndex(state, ISurf);
9639 64712 : if (!s_surf->Surface(ISurf).windowShadingControlList.empty() &&
9640 32356 : indexWindowShadingControl <= s_surf->Surface(ISurf).windowShadingControlList.size() - 1) {
9641 32356 : s_surf->Surface(ISurf).activeWindowShadingControl = s_surf->Surface(ISurf).windowShadingControlList[indexWindowShadingControl];
9642 : }
9643 32356 : s_surf->Surface(ISurf).activeShadedConstructionPrev = s_surf->Surface(ISurf).activeShadedConstruction;
9644 64708 : if (!s_surf->Surface(ISurf).shadedConstructionList.empty() &&
9645 32352 : indexWindowShadingControl <= s_surf->Surface(ISurf).shadedConstructionList.size() - 1) {
9646 32352 : s_surf->Surface(ISurf).activeShadedConstruction = s_surf->Surface(ISurf).shadedConstructionList[indexWindowShadingControl];
9647 : }
9648 32356 : s_surf->SurfWinActiveShadedConstruction(ISurf) = s_surf->Surface(ISurf).activeShadedConstruction;
9649 32356 : if (!s_surf->Surface(ISurf).shadedStormWinConstructionList.empty() &&
9650 0 : indexWindowShadingControl <= s_surf->Surface(ISurf).shadedStormWinConstructionList.size() - 1) {
9651 0 : if (s_surf->SurfWinStormWinFlag(ISurf) == 1) {
9652 0 : s_surf->SurfWinActiveShadedConstruction(ISurf) =
9653 0 : s_surf->Surface(ISurf).shadedStormWinConstructionList[indexWindowShadingControl];
9654 : }
9655 : }
9656 :
9657 32356 : int IShadingCtrl = s_surf->Surface(ISurf).activeWindowShadingControl;
9658 32356 : int IZone = s_surf->Surface(ISurf).Zone;
9659 : // Setpoint for shading
9660 32356 : Real64 SetPoint = s_surf->WindowShadingControl(IShadingCtrl).SetPoint; // Control setpoint
9661 32356 : Real64 SetPoint2 = s_surf->WindowShadingControl(IShadingCtrl).SetPoint2; // Second control setpoint
9662 :
9663 32356 : bool SchedAllowsControl = true; // True if control schedule is not specified or is specified and schedule value = 1
9664 32356 : auto const *sched = s_surf->WindowShadingControl(IShadingCtrl).sched;
9665 32356 : if (sched != nullptr) {
9666 32352 : if (s_surf->WindowShadingControl(IShadingCtrl).ShadingControlIsScheduled && sched->getCurrentVal() <= 0.0) {
9667 32352 : SchedAllowsControl = false;
9668 : }
9669 : }
9670 :
9671 32356 : Real64 GlareControlIsActive = (state.dataDayltg->ZoneDaylight(IZone).totRefPts > 0 && state.dataEnvrn->SunIsUp &&
9672 0 : s_surf->WindowShadingControl(IShadingCtrl).GlareControlIsActive); // True if glare control is active
9673 :
9674 32356 : Real64 SolarOnWindow = 0.0; // Direct plus diffuse solar intensity on window (W/m2)
9675 32356 : Real64 BeamSolarOnWindow = 0.0; // Direct solar intensity on window (W/m2)
9676 32356 : Real64 HorizSolar = 0.0; // Horizontal direct plus diffuse solar intensity
9677 32356 : if (state.dataEnvrn->SunIsUp) {
9678 16354 : Real64 SkySolarOnWindow = state.dataSolarShading->SurfAnisoSkyMult(ISurf) *
9679 16354 : state.dataEnvrn->DifSolarRad; // Sky diffuse solar intensity on window (W/m2)
9680 16354 : BeamSolarOnWindow = state.dataEnvrn->BeamSolarRad *
9681 16354 : state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, ISurf) *
9682 16354 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, ISurf);
9683 16354 : SolarOnWindow = BeamSolarOnWindow + SkySolarOnWindow + state.dataEnvrn->GndSolarRad * s_surf->Surface(ISurf).ViewFactorGround;
9684 16354 : HorizSolar = state.dataEnvrn->BeamSolarRad * state.dataEnvrn->SOLCOS(3) + state.dataEnvrn->DifSolarRad;
9685 : }
9686 :
9687 : // Determine whether to deploy shading depending on type of control
9688 32356 : auto &thisIZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(IZone);
9689 :
9690 32356 : bool shadingOn = false;
9691 32356 : bool shadingOffButGlareControlOn = false;
9692 32356 : switch (s_surf->WindowShadingControl(IShadingCtrl).shadingControlType) {
9693 0 : case WindowShadingControlType::AlwaysOn: // 'ALWAYSON'
9694 0 : shadingOn = true;
9695 0 : break;
9696 0 : case WindowShadingControlType::AlwaysOff: // 'ALWAYSOFF'
9697 0 : break;
9698 32352 : case WindowShadingControlType::OnIfScheduled: // 'ONIFSCHEDULEALLOWS'
9699 32352 : if (SchedAllowsControl) {
9700 0 : shadingOn = true;
9701 : }
9702 32352 : break;
9703 0 : case WindowShadingControlType::HiSolar: // 'ONIFHIGHSOLARONWINDOW'
9704 : // ! Direct plus diffuse solar intensity on window
9705 0 : if (state.dataEnvrn->SunIsUp) {
9706 0 : if (SolarOnWindow > SetPoint && SchedAllowsControl) {
9707 0 : shadingOn = true;
9708 0 : } else if (GlareControlIsActive) {
9709 0 : shadingOffButGlareControlOn = true;
9710 : }
9711 : }
9712 0 : break;
9713 :
9714 0 : case WindowShadingControlType::HiHorzSolar: // 'ONIFHIGHHORIZONTALSOLAR' ! Direct plus diffuse exterior horizontal solar intensity
9715 0 : if (state.dataEnvrn->SunIsUp) {
9716 0 : if (HorizSolar > SetPoint && SchedAllowsControl) {
9717 0 : shadingOn = true;
9718 0 : } else if (GlareControlIsActive) {
9719 0 : shadingOffButGlareControlOn = true;
9720 : }
9721 : }
9722 0 : break;
9723 :
9724 0 : case WindowShadingControlType::HiOutAirTemp: // 'OnIfHighOutdoorAirTemperature'
9725 0 : if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && SchedAllowsControl) {
9726 0 : shadingOn = true;
9727 0 : } else if (GlareControlIsActive) {
9728 0 : shadingOffButGlareControlOn = true;
9729 : }
9730 0 : break;
9731 :
9732 0 : case WindowShadingControlType::HiZoneAirTemp: // 'OnIfHighZoneAirTemperature' ! Previous time step zone air temperature
9733 0 : if (thisIZoneHB.MAT > SetPoint && SchedAllowsControl) {
9734 0 : shadingOn = true;
9735 0 : } else if (GlareControlIsActive) {
9736 0 : shadingOffButGlareControlOn = true;
9737 : }
9738 0 : break;
9739 :
9740 0 : case WindowShadingControlType::OnHiOutTemp_HiSolarWindow: // 'OnIfHighOutdoorAirTempAndHighSolarOnWindow' ! Outside air temp and
9741 : // solar on window
9742 0 : if (state.dataEnvrn->SunIsUp) {
9743 0 : if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && SolarOnWindow > SetPoint2 && SchedAllowsControl) {
9744 0 : shadingOn = true;
9745 0 : } else if (GlareControlIsActive) {
9746 0 : shadingOffButGlareControlOn = true;
9747 : }
9748 : }
9749 0 : break;
9750 :
9751 0 : case WindowShadingControlType::OnHiOutTemp_HiHorzSolar: // 'OnIfHighOutdoorAirTempAndHighHorizontalSolar' ! Outside air temp and
9752 : // horizontal solar
9753 0 : if (state.dataEnvrn->SunIsUp) {
9754 0 : if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && HorizSolar > SetPoint2 && SchedAllowsControl) {
9755 0 : shadingOn = true;
9756 0 : } else if (GlareControlIsActive) {
9757 0 : shadingOffButGlareControlOn = true;
9758 : }
9759 : }
9760 0 : break;
9761 :
9762 0 : case WindowShadingControlType::OnHiZoneTemp_HiSolarWindow: // 'ONIFHIGHZONEAIRTEMPANDHIGHSOLARONWINDOW' ! Zone air temp and solar on
9763 : // window
9764 0 : if (state.dataEnvrn->SunIsUp) {
9765 0 : if (thisIZoneHB.MAT > SetPoint && SolarOnWindow > SetPoint2 && SchedAllowsControl) {
9766 0 : shadingOn = true;
9767 0 : } else if (GlareControlIsActive) {
9768 0 : shadingOffButGlareControlOn = true;
9769 : }
9770 : }
9771 0 : break;
9772 :
9773 0 : case WindowShadingControlType::OnHiZoneTemp_HiHorzSolar: // 'ONIFHIGHZONEAIRTEMPANDHIGHHORIZONTALSOLAR' ! Zone air temp and
9774 : // horizontal solar
9775 0 : if (state.dataEnvrn->SunIsUp) {
9776 0 : if (thisIZoneHB.MAT > SetPoint && HorizSolar > SetPoint2 && SchedAllowsControl) {
9777 0 : shadingOn = true;
9778 0 : } else if (GlareControlIsActive) {
9779 0 : shadingOffButGlareControlOn = true;
9780 : }
9781 : }
9782 0 : break;
9783 :
9784 0 : case WindowShadingControlType::HiZoneCooling:
9785 : // 'ONIFHIGHZONECOOLING' ! Previous time step zone sensible cooling rate [W]
9786 : // In the following, the check on BeginSimFlag is needed since SNLoadCoolRate (and SNLoadHeatRate,
9787 : // used in other CASEs) are not allocated at this point for the first time step of the simulation.
9788 0 : if (!state.dataGlobal->BeginSimFlag) {
9789 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > SetPoint && SchedAllowsControl) {
9790 0 : shadingOn = true;
9791 0 : } else if (GlareControlIsActive) {
9792 0 : shadingOffButGlareControlOn = true;
9793 : }
9794 : }
9795 0 : break;
9796 :
9797 0 : case WindowShadingControlType::HiGlare:
9798 : // 'ONIFHIGHGLARE' ! Daylight glare index at first reference point in the zone.
9799 : // This type of shading control is done in DayltgInteriorIllum. Glare control is not affected
9800 : // by control schedule.
9801 0 : if (state.dataEnvrn->SunIsUp) {
9802 0 : shadingOffButGlareControlOn = true;
9803 : }
9804 0 : break;
9805 :
9806 0 : case WindowShadingControlType::MeetDaylIlumSetp:
9807 : // 'MEETDAYLIGHTILLUMINANCESETPOINT') ! Daylight illuminance test is done in DayltgInteriorIllum
9808 : // Only switchable glazing does daylight illuminance control
9809 0 : if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9810 0 : shadingOffButGlareControlOn = true;
9811 : }
9812 0 : break;
9813 :
9814 1 : case WindowShadingControlType::HiSolar_HiLumin_OffMidNight:
9815 : // 'OnIfHighSolarOrHighLuminanceTillMidnight'
9816 : // if shade is already on, then keep it on until midnight, otherwise check thresholds
9817 1 : if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
9818 0 : shadingOn = true;
9819 1 : } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9820 1 : if (SolarOnWindow > SetPoint) {
9821 0 : shadingOn = true;
9822 : } else {
9823 : // pass to DayltgInteriorIllum to check for luminance
9824 1 : shadingOn = false;
9825 1 : shadingOffButGlareControlOn = true;
9826 : }
9827 : }
9828 : // if it is the beginning of the day, then shades off
9829 1 : if (state.dataGlobal->BeginDayFlag) {
9830 0 : shadingOn = false;
9831 0 : shadingOffButGlareControlOn = false;
9832 : }
9833 1 : break;
9834 :
9835 0 : case WindowShadingControlType::HiSolar_HiLumin_OffSunset:
9836 : // 'OnIfHighSolarOrHighLuminanceTillSunset'
9837 : // if shade is already on, then keep it on until sunset, otherwise check thresholds
9838 0 : if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
9839 0 : shadingOn = true;
9840 0 : } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9841 0 : if (SolarOnWindow > SetPoint) {
9842 0 : shadingOn = true;
9843 : } else {
9844 : // pass to DayltgInteriorIllum to check for luminance
9845 0 : shadingOn = false;
9846 0 : shadingOffButGlareControlOn = true;
9847 : }
9848 : }
9849 : // if sunset, then shades off
9850 0 : if (!state.dataEnvrn->SunIsUp) {
9851 0 : shadingOn = false;
9852 0 : shadingOffButGlareControlOn = false;
9853 : }
9854 0 : break;
9855 :
9856 1 : case WindowShadingControlType::HiSolar_HiLumin_OffNextMorning:
9857 : // 'OnIfHighSolarOrHighLuminanceTillNextMorning'
9858 : // if shade is already on, then keep it on until next day when sun is up, otherwise check thresholds
9859 1 : if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
9860 0 : shadingOn = true;
9861 1 : } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9862 1 : if (SolarOnWindow > SetPoint) {
9863 1 : shadingOn = true;
9864 : } else {
9865 : // pass to DayltgInteriorIllum to check for luminance
9866 0 : shadingOn = false;
9867 0 : shadingOffButGlareControlOn = true;
9868 : }
9869 : }
9870 : // if next morning (identified by sun is not up in previous time step and is up now), then shades off
9871 1 : if (!state.dataEnvrn->SunIsUpPrevTS && state.dataEnvrn->SunIsUp) {
9872 0 : shadingOn = false;
9873 0 : shadingOffButGlareControlOn = false;
9874 : }
9875 1 : break;
9876 :
9877 0 : case WindowShadingControlType::OnNightLoOutTemp_OffDay: // 'OnNightIfLowOutdoorTempAndOffDay'
9878 0 : if (!state.dataEnvrn->SunIsUp && s_surf->SurfOutDryBulbTemp(ISurf) < SetPoint && SchedAllowsControl) {
9879 0 : shadingOn = true;
9880 0 : } else if (GlareControlIsActive) {
9881 0 : shadingOffButGlareControlOn = true;
9882 : }
9883 0 : break;
9884 :
9885 0 : case WindowShadingControlType::OnNightLoInTemp_OffDay: // 'OnNightIfLowInsideTempAndOffDay')
9886 0 : if (!state.dataEnvrn->SunIsUp && thisIZoneHB.MAT < SetPoint && SchedAllowsControl) {
9887 0 : shadingOn = true;
9888 0 : } else if (GlareControlIsActive) {
9889 0 : shadingOffButGlareControlOn = true;
9890 : }
9891 0 : break;
9892 :
9893 0 : case WindowShadingControlType::OnNightIfHeating_OffDay: // 'OnNightIfHeatingAndOffDay'
9894 0 : if (!state.dataGlobal->BeginSimFlag) {
9895 0 : if (!state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysHeatRate > SetPoint &&
9896 : SchedAllowsControl) {
9897 0 : shadingOn = true;
9898 0 : } else if (GlareControlIsActive) {
9899 0 : shadingOffButGlareControlOn = true;
9900 : }
9901 : }
9902 0 : break;
9903 :
9904 0 : case WindowShadingControlType::OnNightLoOutTemp_OnDayCooling: // 'OnNightIfLowOutdoorTempAndOnDayIfCooling'
9905 0 : if (!state.dataGlobal->BeginSimFlag) {
9906 0 : if (!state.dataEnvrn->SunIsUp) { // Night
9907 0 : if (s_surf->SurfOutDryBulbTemp(ISurf) < SetPoint && SchedAllowsControl) {
9908 0 : shadingOn = true;
9909 : }
9910 : } else { // Day
9911 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 && SchedAllowsControl) {
9912 0 : shadingOn = true;
9913 0 : } else if (GlareControlIsActive) {
9914 0 : shadingOffButGlareControlOn = true;
9915 : }
9916 : }
9917 : }
9918 0 : break;
9919 :
9920 0 : case WindowShadingControlType::OnNightIfHeating_OnDayCooling: // 'OnNightIfHeatingAndOnDayIfCooling'
9921 0 : if (!state.dataGlobal->BeginSimFlag) {
9922 0 : if (!state.dataEnvrn->SunIsUp) { // Night
9923 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysHeatRate > SetPoint && SchedAllowsControl) {
9924 0 : shadingOn = true;
9925 : }
9926 : } else { // Day
9927 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 && SchedAllowsControl) {
9928 0 : shadingOn = true;
9929 0 : } else if (GlareControlIsActive) {
9930 0 : shadingOffButGlareControlOn = true;
9931 : }
9932 : }
9933 : }
9934 0 : break;
9935 :
9936 0 : case WindowShadingControlType::OffNight_OnDay_HiSolarWindow: // 'OffNightAndOnDayIfCoolingAndHighSolarOnWindow'
9937 0 : if (!state.dataGlobal->BeginSimFlag) {
9938 0 : if (state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 &&
9939 : SchedAllowsControl) {
9940 0 : if (SolarOnWindow > SetPoint) {
9941 0 : shadingOn = true;
9942 : }
9943 0 : } else if (GlareControlIsActive) {
9944 0 : shadingOffButGlareControlOn = true;
9945 : }
9946 : }
9947 0 : break;
9948 :
9949 0 : case WindowShadingControlType::OnNight_OnDay_HiSolarWindow: // 'OnNightAndOnDayIfCoolingAndHighSolarOnWindow'
9950 0 : if (!state.dataGlobal->BeginSimFlag) {
9951 0 : if (state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 &&
9952 : SchedAllowsControl) {
9953 0 : if (SolarOnWindow > SetPoint) {
9954 0 : shadingOn = true;
9955 : }
9956 0 : } else if (!state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9957 0 : shadingOn = true;
9958 0 : } else if (GlareControlIsActive) {
9959 0 : shadingOffButGlareControlOn = true;
9960 : }
9961 : }
9962 0 : break;
9963 2 : default:
9964 2 : ShowWarningError(state, format("Invalid Selection of Window Shading Control Type for Surface {}", s_surf->Surface(ISurf).Name));
9965 : }
9966 :
9967 32356 : WinShadingType ShType = s_surf->WindowShadingControl(IShadingCtrl).ShadingType;
9968 :
9969 32356 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ShadeOff; // Initialize shading flag to off
9970 :
9971 32356 : if (IS_SHADED(ShType)) {
9972 32355 : if (shadingOn) {
9973 1 : s_surf->SurfWinShadingFlag(ISurf) = ShType;
9974 32354 : } else if (shadingOffButGlareControlOn) {
9975 1 : if (ShType == WinShadingType::SwitchableGlazing) {
9976 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::GlassConditionallyLightened;
9977 1 : } else if (ShType == WinShadingType::IntShade) {
9978 1 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntShadeConditionallyOff;
9979 0 : } else if (ShType == WinShadingType::ExtShade) {
9980 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtShadeConditionallyOff;
9981 0 : } else if (ShType == WinShadingType::IntBlind) {
9982 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntBlindConditionallyOff;
9983 0 : } else if (ShType == WinShadingType::ExtBlind) {
9984 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtBlindConditionallyOff;
9985 0 : } else if (ShType == WinShadingType::BGShade) {
9986 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::BGShadeConditionallyOff;
9987 0 : } else if (ShType == WinShadingType::BGBlind) {
9988 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::BGBlindConditionallyOff;
9989 : }
9990 : }
9991 : }
9992 :
9993 : // Set switching factor to fully switched if ShadingFlag = 2
9994 32356 : if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::SwitchableGlazing) {
9995 0 : s_surf->SurfWinSwitchingFactor(ISurf) = 1.0;
9996 :
9997 : // Added TH 1/20/2010
9998 : // Vis trans at normal incidence of fully switched glass
9999 0 : IConst = s_surf->Surface(ISurf).activeShadedConstruction;
10000 0 : s_surf->SurfWinVisTransSelected(ISurf) =
10001 0 : Window::POLYF(1.0, state.dataConstruction->Construct(IConst).TransVisBeamCoef) * surfWin.glazedFrac;
10002 : }
10003 :
10004 : // Slat angle control for blinds
10005 32356 : auto &surfShade = s_surf->surfShades(ISurf);
10006 32356 : surfShade.blind.slatAng = 0.0;
10007 32356 : surfShade.blind.slatAngDeg = 0.0;
10008 32356 : surfShade.blind.slatBlockBeam = false;
10009 64712 : if (ANY_BLIND(s_surf->SurfWinShadingFlag(ISurf)) || s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::IntBlindConditionallyOff ||
10010 97068 : s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::ExtBlindConditionallyOff ||
10011 32356 : s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::BGBlindConditionallyOff) {
10012 : // Blind in place or may be in place due to glare control
10013 0 : if (surfShade.blind.matNum > 0) {
10014 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
10015 0 : assert(matBlind != nullptr);
10016 0 : Real64 InputSlatAngle = matBlind->SlatAngle * Constant::DegToRad; // Slat angle of associated Material:WindowBlind (rad)
10017 : Real64 ThetaBase; // Intermediate slat angle variable (rad)
10018 : Real64 ThetaBlock1; // Slat angles that just block beam solar (rad)
10019 : Real64 ThetaBlock2;
10020 :
10021 0 : Real64 ProfAng = surfShade.blind.profAng =
10022 0 : Dayltg::ProfileAngle(state, ISurf, state.dataEnvrn->SOLCOS, matBlind->SlatOrientation);
10023 :
10024 0 : if (ProfAng > Constant::PiOvr2 || ProfAng < -Constant::PiOvr2) {
10025 0 : ProfAng = min(max(ProfAng, -Constant::PiOvr2), Constant::PiOvr2);
10026 : }
10027 0 : surfShade.blind.profAngIdxLo = int((ProfAng + Constant::PiOvr2) / Material::dProfAng) + 1;
10028 0 : surfShade.blind.profAngIdxHi = std::min(Material::MaxProfAngs, surfShade.blind.profAngIdxLo + 1);
10029 :
10030 0 : surfShade.blind.profAngInterpFac =
10031 0 : (ProfAng + Constant::PiOvr2 - (surfShade.blind.profAngIdxLo - 1) * Material::dProfAng) / Material::dProfAng;
10032 :
10033 0 : if (matBlind->SlatWidth > matBlind->SlatSeparation && BeamSolarOnWindow > 0.0) {
10034 0 : ProfAng = surfShade.blind.profAng;
10035 0 : Real64 ThetaBase = std::acos(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth);
10036 : // There are two solutions for the slat angle that just blocks beam radiation
10037 0 : ThetaBlock1 = ProfAng + ThetaBase;
10038 0 : ThetaBlock2 = ProfAng + Constant::Pi - ThetaBase;
10039 0 : state.dataSolarShading->ThetaSmall = min(ThetaBlock1, ThetaBlock2);
10040 0 : state.dataSolarShading->ThetaBig = max(ThetaBlock1, ThetaBlock2);
10041 0 : state.dataSolarShading->ThetaMin = matBlind->MinSlatAngle * Constant::DegToRad;
10042 0 : state.dataSolarShading->ThetaMax = matBlind->MaxSlatAngle * Constant::DegToRad;
10043 : }
10044 :
10045 : // TH 5/20/2010, CR 8064: Slat Width <= Slat Separation
10046 0 : if (matBlind->SlatWidth <= matBlind->SlatSeparation && BeamSolarOnWindow > 0.0) {
10047 0 : if (s_surf->WindowShadingControl(IShadingCtrl).slatAngleControl == SlatAngleControl::BlockBeamSolar) {
10048 0 : ProfAng = surfShade.blind.profAng;
10049 0 : if (std::abs(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth) <= 1.0) {
10050 : // set to block 100% of beam solar, not necessarily to block maximum solar (beam + diffuse)
10051 0 : ThetaBase = std::acos(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth);
10052 0 : surfShade.blind.slatBlockBeam = true;
10053 : } else {
10054 : // cannot block 100% of beam solar, turn slats to be perpendicular to sun beam to block maximal beam solar
10055 0 : ThetaBase = 0.0;
10056 : }
10057 :
10058 : // There are two solutions for the slat angle that just blocks beam radiation
10059 0 : ThetaBlock1 = ProfAng + ThetaBase;
10060 0 : ThetaBlock2 = ProfAng - ThetaBase + Constant::Pi;
10061 :
10062 0 : state.dataSolarShading->ThetaSmall = min(ThetaBlock1, ThetaBlock2);
10063 0 : state.dataSolarShading->ThetaBig = max(ThetaBlock1, ThetaBlock2);
10064 0 : state.dataSolarShading->ThetaMin = matBlind->MinSlatAngle * Constant::DegToRad;
10065 0 : state.dataSolarShading->ThetaMax = matBlind->MaxSlatAngle * Constant::DegToRad;
10066 : }
10067 : }
10068 :
10069 : //
10070 0 : Real64 slatAng = 0.0;
10071 0 : bool slatBlockBeam = false;
10072 0 : switch (s_surf->WindowShadingControl(IShadingCtrl).slatAngleControl) {
10073 :
10074 0 : case SlatAngleControl::Fixed: { // 'FIXEDSLATANGLE'
10075 0 : slatAng = InputSlatAngle;
10076 :
10077 0 : if ((slatAng <= state.dataSolarShading->ThetaSmall || slatAng >= state.dataSolarShading->ThetaBig) &&
10078 0 : (matBlind->SlatWidth > matBlind->SlatSeparation) && (BeamSolarOnWindow > 0.0)) {
10079 0 : slatBlockBeam = true;
10080 : }
10081 0 : } break;
10082 :
10083 0 : case SlatAngleControl::Scheduled: { // 'SCHEDULEDSLATANGLE'
10084 0 : slatAng = s_surf->WindowShadingControl(IShadingCtrl).slatAngleSched->getCurrentVal();
10085 0 : slatAng = max(matBlind->MinSlatAngle, min(slatAng, matBlind->MaxSlatAngle)) * Constant::DegToRad;
10086 :
10087 0 : if ((slatAng <= state.dataSolarShading->ThetaSmall || slatAng >= state.dataSolarShading->ThetaBig) &&
10088 0 : (matBlind->SlatWidth > matBlind->SlatSeparation) && (BeamSolarOnWindow > 0.0)) {
10089 0 : slatBlockBeam = true;
10090 : }
10091 0 : } break;
10092 :
10093 0 : case SlatAngleControl::BlockBeamSolar: { // 'BLOCKBEAMSOLAR'
10094 0 : if (BeamSolarOnWindow > 0.0) {
10095 0 : if (matBlind->SlatSeparation >= matBlind->SlatWidth) {
10096 : // TH 5/20/2010. CR 8064.
10097 : // The following line of code assumes slats are always vertical/closed to minimize solar penetration
10098 : // The slat angle can however change if the only goal is to block maximum amount of direct beam solar
10099 : // SurfaceWindow(ISurf)%SlatAngThisTS = 0.0 ! Allows beam penetration but minimizes it
10100 :
10101 0 : if (state.dataSolarShading->ThetaSmall >= state.dataSolarShading->ThetaMin &&
10102 0 : state.dataSolarShading->ThetaSmall <= state.dataSolarShading->ThetaMax) {
10103 0 : slatAng = state.dataSolarShading->ThetaSmall;
10104 0 : } else if (state.dataSolarShading->ThetaBig >= state.dataSolarShading->ThetaMin &&
10105 0 : state.dataSolarShading->ThetaBig <= state.dataSolarShading->ThetaMax) {
10106 0 : slatAng = state.dataSolarShading->ThetaBig;
10107 0 : } else if (state.dataSolarShading->ThetaSmall < state.dataSolarShading->ThetaMin &&
10108 0 : state.dataSolarShading->ThetaBig < state.dataSolarShading->ThetaMin) {
10109 0 : slatAng = state.dataSolarShading->ThetaMin;
10110 0 : } else if (state.dataSolarShading->ThetaSmall > state.dataSolarShading->ThetaMax &&
10111 0 : state.dataSolarShading->ThetaBig > state.dataSolarShading->ThetaMax) {
10112 0 : slatAng = state.dataSolarShading->ThetaMax;
10113 : } else { // ThetaBig > ThetaMax and ThetaSmall < ThetaMin (no-block condition)
10114 0 : slatAng = state.dataSolarShading->ThetaMin;
10115 : }
10116 :
10117 : } else { // Usual case -- slat width greater than slat separation
10118 0 : if (state.dataSolarShading->ThetaSmall >= state.dataSolarShading->ThetaMin &&
10119 0 : state.dataSolarShading->ThetaSmall <= state.dataSolarShading->ThetaMax) {
10120 0 : slatAng = state.dataSolarShading->ThetaSmall;
10121 0 : slatBlockBeam = true;
10122 0 : } else if (state.dataSolarShading->ThetaBig >= state.dataSolarShading->ThetaMin &&
10123 0 : state.dataSolarShading->ThetaBig <= state.dataSolarShading->ThetaMax) {
10124 0 : slatAng = state.dataSolarShading->ThetaBig;
10125 0 : slatBlockBeam = true;
10126 0 : } else if (state.dataSolarShading->ThetaSmall < state.dataSolarShading->ThetaMin &&
10127 0 : state.dataSolarShading->ThetaBig < state.dataSolarShading->ThetaMin) {
10128 0 : slatAng = state.dataSolarShading->ThetaMin;
10129 0 : slatBlockBeam = true;
10130 0 : } else if (state.dataSolarShading->ThetaSmall > state.dataSolarShading->ThetaMax &&
10131 0 : state.dataSolarShading->ThetaBig > state.dataSolarShading->ThetaMax) {
10132 0 : slatAng = state.dataSolarShading->ThetaMax;
10133 0 : slatBlockBeam = true;
10134 : } else { // ThetaBig > ThetaMax and ThetaSmall < ThetaMin (no-block condition)
10135 0 : slatAng = state.dataSolarShading->ThetaMin;
10136 : }
10137 : }
10138 : } else {
10139 0 : slatAng = InputSlatAngle;
10140 : }
10141 0 : } break;
10142 0 : default:
10143 0 : break;
10144 : } // switch (slatAngControl)
10145 :
10146 0 : if (surfShade.blind.slatAngDegEMSon) {
10147 0 : slatAng = Constant::DegToRad * surfShade.blind.slatAngDegEMSValue;
10148 : }
10149 :
10150 : // Slat angle is changing, need to recalculate stored values
10151 0 : if (slatAng != surfShade.blind.slatAng) {
10152 0 : surfShade.blind.slatAng = slatAng;
10153 0 : surfShade.blind.slatAngDeg = surfShade.blind.slatAng * Constant::RadToDeg;
10154 :
10155 0 : Material::GetSlatIndicesInterpFac(surfShade.blind.slatAng,
10156 0 : surfShade.blind.slatAngIdxLo,
10157 0 : surfShade.blind.slatAngIdxHi,
10158 0 : surfShade.blind.slatAngInterpFac);
10159 0 : surfShade.blind.TAR.interpSlatAng(matBlind->TARs[surfShade.blind.slatAngIdxLo],
10160 0 : matBlind->TARs[surfShade.blind.slatAngIdxHi],
10161 : surfShade.blind.slatAngInterpFac);
10162 :
10163 0 : Real64 TauShIR = surfShade.blind.TAR.IR.Ft.Tra;
10164 0 : Real64 EpsShIR = surfShade.blind.TAR.IR.Bk.Emi;
10165 0 : Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
10166 :
10167 0 : surfShade.effShadeEmi = EpsShIR * (1.0 + surfShade.glass.rhoIR * TauShIR / (1.0 - surfShade.glass.rhoIR * RhoShIR));
10168 0 : surfShade.effGlassEmi = surfShade.glass.epsIR * TauShIR / (1.0 - surfShade.glass.rhoIR * RhoShIR);
10169 : }
10170 :
10171 0 : surfShade.blind.slatBlockBeam = slatBlockBeam;
10172 :
10173 : // Air flow permeability for calculation of convective air flow between blind and glass
10174 0 : Real64 PermeabilityA = std::sin(surfShade.blind.slatAng) - matBlind->SlatThickness / matBlind->SlatSeparation;
10175 0 : Real64 PermeabilityB = 1.0 - (std::abs(matBlind->SlatWidth * std::cos(surfShade.blind.slatAng)) +
10176 0 : matBlind->SlatThickness * std::sin(surfShade.blind.slatAng)) /
10177 0 : matBlind->SlatSeparation;
10178 0 : surfShade.blind.airFlowPermeability = min(1.0, max(0.0, PermeabilityA, PermeabilityB));
10179 0 : surfShade.blind.bmBmTrans = matBlind->BeamBeamTrans(surfShade.blind.profAng, surfShade.blind.slatAng);
10180 : }
10181 : } // End of check if interior or exterior or between glass blind in place
10182 :
10183 : // AR: don't need to do this anymore I don't think
10184 : // CALL CalcScreenTransmittance to initialized all screens prior to HB calc's
10185 : // if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::ExtScreen && state.dataEnvrn->SunIsUp) {
10186 : // CalcScreenTransmittance(state, ISurf);
10187 : // }
10188 :
10189 : // EMS Actuator Point: override setting if ems flag on
10190 32356 : if (s_surf->SurfWinShadingFlagEMSOn(ISurf)) {
10191 1 : WinShadingType SurfWinShadingFlagEMS = findValueInEnumeration(s_surf->SurfWinShadingFlagEMSValue(ISurf));
10192 1 : if (SurfWinShadingFlagEMS != WinShadingType::Invalid) {
10193 1 : s_surf->SurfWinShadingFlag(ISurf) = SurfWinShadingFlagEMS;
10194 : } else {
10195 0 : ShowWarningError(state,
10196 0 : format("Invalid EMS value of Window Shading Control Type for Surface {}", s_surf->Surface(ISurf).Name));
10197 : }
10198 : }
10199 : } // End of surface loop
10200 336652 : }
10201 : }
10202 249958 : }
10203 :
10204 249956 : void CheckGlazingShadingStatusChange(EnergyPlusData &state)
10205 : {
10206 249956 : auto &s_surf = state.dataSurface;
10207 249956 : if (state.dataGlobal->BeginSimFlag) {
10208 112 : if (state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() && state.dataWindowManager->winOpticalModel->isSimplifiedModel()) {
10209 0 : state.dataHeatBal->EnclRadAlwaysReCalc = true;
10210 : } else {
10211 244 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
10212 281 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
10213 149 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
10214 934 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
10215 791 : auto &surf = s_surf->Surface(SurfNum);
10216 1582 : if (state.dataConstruction->Construct(surf.Construction).isTCWindow ||
10217 791 : state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
10218 6 : state.dataHeatBal->EnclRadAlwaysReCalc = true;
10219 6 : break;
10220 : }
10221 : }
10222 132 : }
10223 : }
10224 : }
10225 112 : if (state.dataHeatBal->EnclRadAlwaysReCalc) {
10226 12 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
10227 6 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
10228 : }
10229 12 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
10230 6 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
10231 : }
10232 : }
10233 : }
10234 249956 : if (state.dataHeatBal->EnclRadAlwaysReCalc) {
10235 2368 : return;
10236 : }
10237 :
10238 247588 : if (state.dataGlobal->BeginEnvrnFlag || state.dataGlobal->AnyConstrOverridesInModel || state.dataGlobal->AnySurfPropOverridesInModel) {
10239 15397 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
10240 7818 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
10241 : }
10242 15397 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
10243 7818 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
10244 : }
10245 7579 : return;
10246 : }
10247 582697 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
10248 342688 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = false;
10249 : }
10250 582697 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
10251 342688 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = false;
10252 : }
10253 240009 : if (!state.dataGlobal->AndShadingControlInModel) {
10254 235973 : return;
10255 : }
10256 16144 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
10257 153368 : for (int const SurfNum : state.dataViewFactor->EnclRadInfo(enclosureNum).SurfacePtr) {
10258 141260 : auto &surf = s_surf->Surface(SurfNum);
10259 141260 : auto &surfShade = s_surf->surfShades(SurfNum);
10260 141260 : bool surfShadingStatusChange = s_surf->SurfWinExtIntShadePrevTS(SurfNum) != s_surf->SurfWinShadingFlag(SurfNum) ||
10261 141260 : surf.activeShadedConstruction != surf.activeShadedConstructionPrev || surfShade.blind.movableSlats;
10262 141260 : if (surfShadingStatusChange) {
10263 0 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
10264 0 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
10265 0 : break;
10266 : }
10267 : }
10268 : }
10269 : }
10270 :
10271 1 : DataSurfaces::WinShadingType findValueInEnumeration(Real64 controlValue)
10272 : {
10273 : // This is a workaround to translate EMS Shading control numerical values
10274 : // EMS control of window shading devices involves setting the control values for shading control actuators with
10275 : // one of these values. The variable names can be used or replaced, it is the whole number values that trigger
10276 : // changes in the modeling.
10277 : // Shades and Blinds are either fully on or fully off, partial positions require multiple windows.
10278 : // the window shading control flag values follow
10279 : // -1: if window has no shading device
10280 : // 0: if shading device is off
10281 : // 1: if interior shade is on
10282 : // 2: if glazing is switched to darker state
10283 : // 3: if exterior shade is on
10284 : // 4: if exterior screen is on
10285 : // 6: if interior blind is on
10286 : // 7: if exterior blind is on
10287 : // 8: if between-glass shade is on
10288 : // 9: if between-glass blind is on
10289 : // 10: window has interior shade that is off but may be triggered on later to control daylight glare
10290 : // 20: window has switchable glazing that is unswitched but may be switched later to control daylight glare or
10291 : // daylight illuminance 30: window has exterior shade that is off but may be triggered on later to control
10292 : // daylight glare or daylight illuminance 60: window has interior blind that is off but may be triggered on later
10293 : // to control daylight glare or daylight illuminance 70: window has exterior blind that is off but may be
10294 : // triggered on later to control daylight glare or daylight illuminance 80: window has between-glass shade that is
10295 : // off but may be triggered on later to control daylight glare or daylight illuminance 90: window has
10296 : // between-glass blind that is off but may be triggered on later to control daylight glare or daylight illuminance
10297 1 : if (controlValue == -1.0) {
10298 0 : return WinShadingType::NoShade;
10299 : }
10300 1 : if (controlValue == 0.0) {
10301 0 : return WinShadingType::ShadeOff;
10302 : }
10303 1 : if (controlValue == 1.0) {
10304 1 : return WinShadingType::IntShade;
10305 : }
10306 0 : if (controlValue == 2.0) {
10307 0 : return WinShadingType::SwitchableGlazing;
10308 : }
10309 0 : if (controlValue == 3.0) {
10310 0 : return WinShadingType::ExtShade;
10311 : }
10312 0 : if (controlValue == 4.0) {
10313 0 : return WinShadingType::ExtScreen;
10314 : }
10315 0 : if (controlValue == 6.0) {
10316 0 : return WinShadingType::IntBlind;
10317 : }
10318 0 : if (controlValue == 7.0) {
10319 0 : return WinShadingType::ExtBlind;
10320 : }
10321 0 : if (controlValue == 8.0) {
10322 0 : return WinShadingType::BGShade;
10323 : }
10324 0 : if (controlValue == 9.0) {
10325 0 : return WinShadingType::BGBlind;
10326 : }
10327 0 : if (controlValue == 10.0) {
10328 0 : return WinShadingType::IntShadeConditionallyOff;
10329 : }
10330 0 : if (controlValue == 20.0) {
10331 0 : return WinShadingType::GlassConditionallyLightened;
10332 : }
10333 0 : if (controlValue == 30.0) {
10334 0 : return WinShadingType::ExtShadeConditionallyOff;
10335 : }
10336 0 : if (controlValue == 60.0) {
10337 0 : return WinShadingType::IntBlindConditionallyOff;
10338 : }
10339 0 : if (controlValue == 70.0) {
10340 0 : return WinShadingType::ExtBlindConditionallyOff;
10341 : }
10342 0 : if (controlValue == 80.0) {
10343 0 : return WinShadingType::BGShadeConditionallyOff;
10344 : }
10345 0 : if (controlValue == 90.0) {
10346 0 : return WinShadingType::BGBlindConditionallyOff;
10347 : }
10348 0 : return WinShadingType::Invalid;
10349 : }
10350 :
10351 32364 : int selectActiveWindowShadingControlIndex(EnergyPlusData &state, int curSurface)
10352 : {
10353 32364 : auto &s_surf = state.dataSurface;
10354 : // For a given surface, determine based on the schedules which index to the window shading control list vector
10355 : // should be active
10356 : // presume it is the first shading control - even if it is not active it needs to be some
10357 : // shading control which is then turned off in the WindowShadingManager
10358 32364 : if (s_surf->Surface(curSurface).windowShadingControlList.size() > 1) {
10359 6 : for (std::size_t listIndex = 0; listIndex < s_surf->Surface(curSurface).windowShadingControlList.size(); ++listIndex) {
10360 6 : int wsc = s_surf->Surface(curSurface).windowShadingControlList[listIndex];
10361 : // pick the first WindowShadingControl that has a non-zero schedule value
10362 6 : if (s_surf->WindowShadingControl(wsc).sched->getCurrentVal() > 0.0) {
10363 3 : return listIndex;
10364 : }
10365 : }
10366 : }
10367 32361 : return 0;
10368 : }
10369 :
10370 0 : void WindowGapAirflowControl(EnergyPlusData &state)
10371 : {
10372 :
10373 : // SUBROUTINE INFORMATION:
10374 : // AUTHOR Fred Winkelmann
10375 : // DATE WRITTEN February 2003
10376 : // MODIFIED June 2003, FCW: add fatal error for illegal schedule value
10377 : // RE-ENGINEERED na
10378 :
10379 : // PURPOSE OF THIS SUBROUTINE:
10380 : // For airflow windows, determines the airflow in the gap of
10381 : // double glazing and in the inner gap of triple glazing.
10382 :
10383 : // REFERENCES:
10384 : // na
10385 :
10386 0 : auto &s_surf = state.dataSurface;
10387 0 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
10388 0 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
10389 0 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
10390 0 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
10391 0 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
10392 0 : for (int ISurf = firstSurfWin; ISurf <= lastSurfWin; ++ISurf) {
10393 :
10394 0 : s_surf->SurfWinAirflowThisTS(ISurf) = 0.0;
10395 0 : if (s_surf->SurfWinMaxAirflow(ISurf) == 0.0) {
10396 0 : continue;
10397 : }
10398 0 : if (s_surf->Surface(ISurf).ExtBoundCond != ExternalEnvironment) {
10399 0 : continue;
10400 : }
10401 0 : switch (s_surf->SurfWinAirflowControlType(ISurf)) {
10402 0 : case WindowAirFlowControlType::MaxFlow: {
10403 0 : s_surf->SurfWinAirflowThisTS(ISurf) = s_surf->SurfWinMaxAirflow(ISurf);
10404 0 : } break;
10405 0 : case WindowAirFlowControlType::AlwaysOff: {
10406 0 : s_surf->SurfWinAirflowThisTS(ISurf) = 0.0;
10407 0 : } break;
10408 0 : case WindowAirFlowControlType::Schedule: {
10409 0 : if (s_surf->SurfWinAirflowHasSchedule(ISurf)) {
10410 0 : auto const *sched = s_surf->SurfWinAirflowScheds(ISurf);
10411 0 : Real64 ScheduleMult = sched->getCurrentVal(); // Multiplier value from schedule
10412 0 : if (ScheduleMult < 0.0 || ScheduleMult > 1.0) {
10413 0 : ShowFatalError(
10414 : state,
10415 0 : format("Airflow schedule has a value outside the range 0.0 to 1.0 for window={}", s_surf->Surface(ISurf).Name));
10416 : }
10417 0 : s_surf->SurfWinAirflowThisTS(ISurf) = ScheduleMult * s_surf->SurfWinMaxAirflow(ISurf);
10418 : }
10419 0 : } break;
10420 0 : default:
10421 0 : break;
10422 : }
10423 : } // End of surface loop
10424 0 : } // End of space loop
10425 : } // End of zone loop
10426 0 : }
10427 :
10428 113 : void SkyDifSolarShading(EnergyPlusData &state)
10429 : {
10430 :
10431 : // SUBROUTINE INFORMATION:
10432 : // AUTHOR Fred Winkelmann
10433 : // DATE WRITTEN May 1999
10434 : // MODIFIED Sep 2000, FCW: add IR view factor calc
10435 : // Sep 2002, FCW: correct error in expression for ground IR view factor.
10436 : // Affects only non-vertical surfaces that are shadowed. For these surfaces
10437 : // error caused underestimate of IR from ground and shadowing surfaces.
10438 : // Dec 2002; LKL: Sky Radiance Distribution now only anisotropic
10439 : // Nov 2003: FCW: modify to do sky solar shading of shadowing surfaces
10440 : // RE-ENGINEERED na
10441 :
10442 : // PURPOSE OF THIS SUBROUTINE:
10443 : // Calculates factors that account for shading of sky diffuse
10444 : // solar radiation by shadowing surfaces such as overhangs and detached
10445 : // shades.
10446 : // Called by PerformSolarCalculations
10447 : // For each exterior heat transfer surface calculates the following
10448 : // ratio (called DifShdgRatioIsoSky in this subroutine):
10449 : // R1 = (Diffuse solar from sky dome on surface, with shading)/
10450 : // (Diffuse solar from sky dome on surface, without shading)
10451 : // To calculate the incident diffuse radiation on a surface the sky
10452 : // hemisphere is divided into source elements ("patches"). Each patch
10453 : // is assumed to have the same radiance, i.e. the sky radiance is isotropic.
10454 : // The irradiance from each patch on a surface is calculated. Then these
10455 : // irradiances are summed to get the net irradiance on a surface, which
10456 : // the denominator of R1.
10457 : // To get the numerator of R1 the same summation is done, but for each surface
10458 : // and each patch the Shadow subroutine is called to determine how much
10459 : // radiation from a patch is blocked by shading surfaces.
10460 : // Also calculated is the following ratio (called DifShdgRatioHoriz in this routine):
10461 : // R2 = (Diffuse solar from sky horizon band on surface, with shading)/
10462 : // (Diffuse solar from sky horizon band on surface, without shading)
10463 : // For this ratio only a band of sky just above the horizon is considered.
10464 : // R1 and R2 are used in SUBROUTINE AnisoSkyViewFactors, which determines the
10465 : // sky diffuse solar irradiance on each exterior heat transfer surface each
10466 : // time step. In that routine the sky radiance distribution is a superposition
10467 : // of an isotropic distribution,
10468 : // a horizon brightening distribution and a circumsolar brightening distribution,
10469 : // where the proportion of each distribution depends
10470 : // on cloud cover, sun position and other factors. R1 multiplies the irradiance
10471 : // due to the isotropic component and R2 multiplies the irradiance due to the
10472 : // horizon brightening component.
10473 : // Calculates sky and ground IR view factors assuming sky IR is isotropic and
10474 : // shadowing surfaces are opaque to IR.
10475 :
10476 : // Using/Aliasing
10477 :
10478 : Real64 Fac1WoShdg; // Intermediate calculation factor, without shading
10479 : Real64 FracIlluminated; // Fraction of surface area illuminated by a sky patch
10480 : Real64 Fac1WithShdg; // Intermediate calculation factor, with shading
10481 : Real64 SurfArea; // Surface area (m2)
10482 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WithShdgIsoSky ! Diffuse solar irradiance from isotropic
10483 : // ! sky on surface, with shading
10484 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WoShdgIsoSky ! Diffuse solar from isotropic
10485 : // ! sky on surface, without shading
10486 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WithShdgHoriz ! Diffuse solar irradiance from horizon portion
10487 : // of
10488 : // ! sky on surface, with shading
10489 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WoShdgHoriz ! Diffuse solar irradiance from horizon portion
10490 : // of
10491 : // ! sky on surface, without shading
10492 : // INTEGER iHour,iTS
10493 :
10494 : // Initialize Surfaces Arrays
10495 113 : auto &s_surf = state.dataSurface;
10496 :
10497 122 : bool detailedShading = state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
10498 9 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal;
10499 113 : state.dataSolarShading->SurfSunlitArea = 0.0;
10500 113 : state.dataSolarShading->SurfWithShdgIsoSky.dimension(s_surf->TotSurfaces, 0.0);
10501 113 : state.dataSolarShading->SurfWoShdgIsoSky.dimension(s_surf->TotSurfaces, 0.0);
10502 113 : state.dataSolarShading->SurfWithShdgHoriz.dimension(s_surf->TotSurfaces, 0.0);
10503 113 : state.dataSolarShading->SurfWoShdgHoriz.dimension(s_surf->TotSurfaces, 0.0);
10504 113 : state.dataSolarShading->SurfDifShdgRatioIsoSky.allocate(s_surf->TotSurfaces);
10505 113 : state.dataSolarShading->SurfDifShdgRatioHoriz.allocate(s_surf->TotSurfaces);
10506 : // initialized as no shading
10507 113 : state.dataSolarShading->SurfDifShdgRatioIsoSky = 1.0;
10508 113 : state.dataSolarShading->SurfDifShdgRatioHoriz = 1.0;
10509 113 : if (detailedShading) {
10510 9 : state.dataSolarShading->SurfCurDifShdgRatioIsoSky.dimension(s_surf->TotSurfaces, 1.0);
10511 9 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS.allocate(state.dataGlobal->TimeStepsInHour, 24, s_surf->TotSurfaces);
10512 9 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS = 1.0;
10513 9 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS.allocate(state.dataGlobal->TimeStepsInHour, 24, s_surf->TotSurfaces);
10514 9 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS = 1.0;
10515 : }
10516 :
10517 659 : for (int SurfNum : s_surf->AllExtSolarSurfaceList) {
10518 546 : auto &surf = s_surf->Surface(SurfNum);
10519 :
10520 : // CurrentModuleObject='Surfaces'
10521 546 : if (detailedShading) {
10522 162 : SetupOutputVariable(state,
10523 : "Debug Surface Solar Shading Model DifShdgRatioIsoSky",
10524 : Constant::Units::None,
10525 81 : state.dataSolarShading->SurfCurDifShdgRatioIsoSky(SurfNum),
10526 : OutputProcessor::TimeStepType::Zone,
10527 : OutputProcessor::StoreType::Average,
10528 81 : surf.Name);
10529 : } else {
10530 930 : SetupOutputVariable(state,
10531 : "Debug Surface Solar Shading Model DifShdgRatioIsoSky",
10532 : Constant::Units::None,
10533 465 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum),
10534 : OutputProcessor::TimeStepType::Zone,
10535 : OutputProcessor::StoreType::Average,
10536 465 : surf.Name);
10537 : }
10538 1092 : SetupOutputVariable(state,
10539 : "Debug Surface Solar Shading Model DifShdgRatioHoriz",
10540 : Constant::Units::None,
10541 546 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum),
10542 : OutputProcessor::TimeStepType::Zone,
10543 : OutputProcessor::StoreType::Average,
10544 546 : surf.Name);
10545 1092 : SetupOutputVariable(state,
10546 : "Debug Surface Solar Shading Model WithShdgIsoSky",
10547 : Constant::Units::None,
10548 546 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum),
10549 : OutputProcessor::TimeStepType::Zone,
10550 : OutputProcessor::StoreType::Average,
10551 546 : surf.Name);
10552 1092 : SetupOutputVariable(state,
10553 : "Debug Surface Solar Shading Model WoShdgIsoSky",
10554 : Constant::Units::None,
10555 546 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum),
10556 : OutputProcessor::TimeStepType::Zone,
10557 : OutputProcessor::StoreType::Average,
10558 546 : surf.Name);
10559 113 : }
10560 :
10561 791 : for (int IPhi = 0; IPhi < NPhi; ++IPhi) { // Loop over patch altitude values
10562 678 : state.dataSolarShading->SUNCOS(3) = state.dataSolarShading->sin_Phi[IPhi];
10563 :
10564 16950 : for (int ITheta = 0; ITheta < NTheta; ++ITheta) { // Loop over patch azimuth values
10565 16272 : state.dataSolarShading->SUNCOS(1) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->cos_Theta[ITheta];
10566 16272 : state.dataSolarShading->SUNCOS(2) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->sin_Theta[ITheta];
10567 :
10568 94896 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
10569 78624 : auto &surf = s_surf->Surface(SurfNum);
10570 :
10571 : // Cosine of angle of incidence on surface of solar radiation from patch
10572 157248 : state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS.x * surf.OutNormVec.x +
10573 78624 : state.dataSolarShading->SUNCOS.y * surf.OutNormVec.y +
10574 78624 : state.dataSolarShading->SUNCOS.z * surf.OutNormVec.z;
10575 16272 : }
10576 :
10577 16272 : SHADOW(state, 24, 0);
10578 :
10579 94896 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
10580 78624 : auto &surf = s_surf->Surface(SurfNum);
10581 :
10582 78624 : if (state.dataSolarShading->SurfSunCosTheta(SurfNum) < 0.0) {
10583 36252 : continue;
10584 : }
10585 :
10586 42372 : Fac1WoShdg = state.dataSolarShading->cos_Phi[IPhi] * DThetaDPhi * state.dataSolarShading->SurfSunCosTheta(SurfNum);
10587 42372 : SurfArea = surf.NetAreaShadowCalc;
10588 42372 : if (SurfArea > Eps) {
10589 42372 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
10590 : } else {
10591 0 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / (SurfArea + Eps);
10592 : }
10593 42372 : Fac1WithShdg = Fac1WoShdg * FracIlluminated;
10594 42372 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) += Fac1WithShdg;
10595 42372 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) += Fac1WoShdg;
10596 :
10597 : // Horizon region
10598 42372 : if (IPhi == 0) {
10599 7047 : state.dataSolarShading->SurfWithShdgHoriz(SurfNum) += Fac1WithShdg;
10600 7047 : state.dataSolarShading->SurfWoShdgHoriz(SurfNum) += Fac1WoShdg;
10601 : }
10602 16272 : } // End of surface loop
10603 : } // End of Theta loop
10604 : } // End of Phi loop
10605 :
10606 659 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
10607 :
10608 546 : if (std::abs(state.dataSolarShading->SurfWoShdgIsoSky(SurfNum)) > Eps) {
10609 494 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) =
10610 494 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum));
10611 : } else {
10612 52 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) =
10613 52 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) + Eps);
10614 : }
10615 546 : if (std::abs(state.dataSolarShading->SurfWoShdgHoriz(SurfNum)) > Eps) {
10616 494 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum) =
10617 494 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum));
10618 : } else {
10619 52 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum) =
10620 52 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum) + Eps);
10621 : }
10622 113 : }
10623 :
10624 : // Get IR view factors. An exterior surface can receive IR radiation from
10625 : // sky, ground or shadowing surfaces. Assume shadowing surfaces have same
10626 : // temperature as outside air (and therefore same temperature as ground),
10627 : // so that the view factor to these shadowing surfaces can be included in
10628 : // the ground view factor. Sky IR is assumed to be isotropic and shadowing
10629 : // surfaces are assumed to be opaque to IR so they totally "shade" IR from
10630 : // sky or ground.
10631 :
10632 943 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
10633 830 : auto &surface = s_surf->Surface(SurfNum);
10634 911 : if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm || !s_surf->ShadingTransmittanceVaries ||
10635 81 : state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
10636 749 : surface.ViewFactorSkyIR *= state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum);
10637 : } else {
10638 81 : surface.ViewFactorSkyIR *= state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(1, 1, SurfNum);
10639 : }
10640 830 : surface.ViewFactorGroundIR = 1.0 - surface.ViewFactorSkyIR;
10641 :
10642 830 : if (surface.SurfHasSurroundingSurfProperty) {
10643 1 : surface.ViewFactorGroundIR = 1.0 - surface.ViewFactorSkyIR - surface.ViewFactorSrdSurfs;
10644 : }
10645 : }
10646 :
10647 : // DEALLOCATE(WithShdgIsoSky)
10648 : // DEALLOCATE(WoShdgIsoSky)
10649 : // DEALLOCATE(WithShdgHoriz)
10650 : // DEALLOCATE(WoShdgHoriz)
10651 :
10652 122 : if (state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
10653 9 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
10654 90 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
10655 162 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS({1, state.dataGlobal->TimeStepsInHour}, {1, 24}, SurfNum) =
10656 162 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum);
10657 162 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS({1, state.dataGlobal->TimeStepsInHour}, {1, 24}, SurfNum) =
10658 162 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum);
10659 : }
10660 : }
10661 113 : }
10662 :
10663 71216 : void CalcWindowProfileAngles(EnergyPlusData &state)
10664 : {
10665 :
10666 : // SUBROUTINE INFORMATION:
10667 : // AUTHOR Fred Winkelmann
10668 : // DATE WRITTEN April 2002
10669 : // MODIFIED na
10670 : // RE-ENGINEERED na
10671 : // PURPOSE OF THIS SUBROUTINE:
10672 : // Called by CalcPerSolarBeam for wholly or partially sunlit exterior windows
10673 : // Calculates horizontal and vertical beam solar profile angles
10674 :
10675 : Real64 ElevSun; // Sun elevation; angle between sun and horizontal
10676 : Real64 ElevWin; // Window elevation: angle between window outward normal and horizontal
10677 : Real64 AzimWin; // Window azimuth (radians)
10678 : Real64 AzimSun; // Sun azimuth (radians)
10679 : Real64 ProfileAngHor; // Solar profile angle (radians) for horizontally oriented window elements
10680 : // such as the top and bottom of a frame.
10681 : // This is the incidence angle in a plane that is normal to the window
10682 : // and parallel to the Y-axis of the window (the axis along
10683 : // which the height of the window is measured).
10684 : Real64 ProfileAngVert; // Solar profile angle (radians) for vertically oriented elements
10685 : // such as the sides of a frame.
10686 : // This is the incidence angle in a plane that is normal to the window
10687 : // and parallel to the X-axis of the window (the axis along
10688 : // which the width of the window is measured).
10689 71216 : Vector3<Real64> WinNorm; // Unit vector normal to window
10690 71216 : Vector3<Real64> WinNormCrossBase; // Cross product of WinNorm and vector along window baseline
10691 71216 : Vector3<Real64> SunPrime; // Projection of sun vector onto plane (perpendicular to
10692 71216 : Vector3<Real64> const SolCosVec(state.dataEnvrn->SOLCOS); // Local Vector3 copy for speed (until SOLCOS mig to Vector3)
10693 : // window plane) determined by WinNorm and vector along
10694 : // baseline of window
10695 : Real64 ThWin; // Azimuth angle of WinNorm (radians)
10696 : Real64 dot1;
10697 : Real64 dot2;
10698 : Real64 dot3;
10699 :
10700 71216 : auto &s_surf = state.dataSurface;
10701 :
10702 71216 : ElevSun = Constant::PiOvr2 - std::acos(SolCosVec.z);
10703 71216 : AzimSun = std::atan2(SolCosVec.x, SolCosVec.y);
10704 :
10705 71216 : Real64 const cos_ElevSun = std::cos(ElevSun);
10706 71216 : Real64 const sin_ElevSun = std::sin(ElevSun);
10707 :
10708 170521 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
10709 211316 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
10710 112011 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
10711 112011 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
10712 112011 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
10713 143115 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
10714 31104 : auto &surf = s_surf->Surface(SurfNum);
10715 31104 : if (surf.ExtBoundCond != ExternalEnvironment && surf.ExtBoundCond != OtherSideCondModeledExt) {
10716 0 : continue;
10717 : }
10718 :
10719 31104 : s_surf->SurfWinProfileAngHor(SurfNum) = 0.0;
10720 31104 : s_surf->SurfWinProfileAngVert(SurfNum) = 0.0;
10721 31104 : if (state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) <= 0.0) {
10722 14294 : continue;
10723 : }
10724 :
10725 16810 : ElevWin = Constant::PiOvr2 - surf.Tilt * Constant::DegToRad;
10726 16810 : AzimWin = surf.Azimuth * Constant::DegToRad;
10727 :
10728 16810 : ProfileAngHor = std::atan(sin_ElevSun / std::abs(cos_ElevSun * std::cos(AzimWin - AzimSun))) - ElevWin;
10729 :
10730 : // CR9280 - were having negative profile angles on west sides. commenting out previous code
10731 : // (original code) for vertical windows
10732 : // IF(ABS(ElevWin) < 0.1d0) THEN ! Near-vertical window
10733 : // ProfileAngVert = ABS(AzimWin-AzimSun)
10734 : // ELSE
10735 16810 : WinNorm = surf.OutNormVec;
10736 16810 : ThWin = AzimWin - Constant::PiOvr2;
10737 16810 : Real64 const sin_Elevwin(std::sin(ElevWin));
10738 16810 : WinNormCrossBase.x = -(sin_Elevwin * std::cos(ThWin));
10739 16810 : WinNormCrossBase.y = sin_Elevwin * std::sin(ThWin);
10740 16810 : WinNormCrossBase.z = std::cos(ElevWin);
10741 16810 : SunPrime = SolCosVec - WinNormCrossBase * dot(SolCosVec, WinNormCrossBase);
10742 16810 : dot1 = dot(WinNorm, SunPrime);
10743 16810 : dot2 = SunPrime.magnitude();
10744 16810 : dot3 = dot1 / dot2;
10745 16810 : if (dot3 > 1.0) {
10746 0 : dot3 = 1.0;
10747 16810 : } else if (dot3 < -1.0) {
10748 0 : dot3 = -1.0;
10749 : }
10750 : // ProfileAngVert =
10751 : // ABS(ACOS(DOT_PRODUCT(WinNorm,SunPrime)/SQRT(DOT_PRODUCT(SunPrime,SunPrime))))
10752 16810 : ProfileAngVert = std::abs(std::acos(dot3));
10753 : // END IF
10754 : // Constrain to 0 to pi
10755 16810 : if (ProfileAngVert > Constant::Pi) {
10756 0 : ProfileAngVert = Constant::TwoPi - ProfileAngVert;
10757 : }
10758 :
10759 16810 : s_surf->SurfWinProfileAngHor(SurfNum) = ProfileAngHor / Constant::DegToRad;
10760 16810 : s_surf->SurfWinProfileAngVert(SurfNum) = ProfileAngVert / Constant::DegToRad;
10761 16810 : s_surf->SurfWinTanProfileAngHor(SurfNum) = std::abs(std::tan(ProfileAngHor));
10762 16810 : s_surf->SurfWinTanProfileAngVert(SurfNum) = std::abs(std::tan(ProfileAngVert));
10763 : }
10764 99305 : }
10765 : }
10766 71216 : }
10767 :
10768 17 : void CalcFrameDividerShadow(EnergyPlusData &state,
10769 : int const SurfNum, // Surface number
10770 : int const FrDivNum, // Frame/divider number
10771 : int const HourNum // Hour number
10772 : )
10773 : {
10774 :
10775 : // SUBROUTINE INFORMATION:
10776 : // AUTHOR Fred Winkelmann
10777 : // DATE WRITTEN June 2000
10778 : // MODIFIED Aug 2000, FW: add effective shadowing by inside
10779 : // projections
10780 : // RE-ENGINEERED na
10781 :
10782 : // PURPOSE OF THIS SUBROUTINE:
10783 : // Called by CalcPerSolarBeam for wholly or partially sunlit exterior windows
10784 : // with a frame and/or divider. Using beam solar profile angles,
10785 : // calculates fraction of glass shaded by exterior frame and divider projections,
10786 : // The frame and divider profiles are assumed to be rectangular.
10787 : // A similar shadowing approach is used to calculate the fraction of glass area
10788 : // that produces beam solar illumination on interior frame and divider projections.
10789 : // This fraction is used in CalcWinFrameAndDividerTemps to determine the
10790 : // beam solar absorbed by inside projections. Beam solar reflected by inside projections
10791 : // is assumed to stay in the zone (as beam solar) although in actuality roughly
10792 : // half of this is reflected back onto the glass and the half that is reflected
10793 : // into the zone is diffuse.
10794 : // For multipane glazing the effect of solar absorbed by the exposed portion of
10795 : // frame or divider between the panes is not calculated. Beam solar incident on
10796 : // these portions is assumed to be transmitted into the zone unchanged.
10797 : // The shadowing of diffuse solar radiation by projections is not considered.
10798 :
10799 : Real64 ElevSun; // Sun elevation; angle between sun and horizontal
10800 : Real64 ElevWin; // Window elevation: angle between window outward normal and horizontal
10801 : Real64 AzimWin; // Window azimuth (radians)
10802 : Real64 AzimSun; // Sun azimuth (radians)
10803 : Real64 ProfileAngHor; // Solar profile angle (radians) for horizontally oriented projections
10804 : // such as the top and bottom of a frame or horizontal dividers.
10805 : // This is the incidence angle in a plane that is normal to the window
10806 : // and parallel to the Y-axis of the window (the axis along
10807 : // which the height of the window is measured).
10808 : Real64 ProfileAngVert; // Solar profile angle (radians) for vertically oriented projections
10809 : // such as the top and bottom of a frame or horizontal dividers.
10810 : // This is the incidence angle in a plane that is normal to the window
10811 : // and parallel to the X-axis of the window (the axis along
10812 : // which the width of the window is measured).
10813 : Real64 TanProfileAngHor; // Tangent of ProfileAngHor
10814 : Real64 TanProfileAngVert; // Tangent of ProfileAngVert
10815 : Real64 FrWidth; // Frame width (m)
10816 : Real64 DivWidth; // Divider width (m)
10817 : Real64 FrProjOut; // Outside frame projection (m)
10818 : Real64 DivProjOut; // Outside divider projection (m)
10819 : Real64 FrProjIn; // Inside frame projection (m)
10820 : Real64 DivProjIn; // Inside divider projection (m)
10821 : int NHorDiv; // Number of horizontal dividers
10822 : int NVertDiv; // Number of vertical dividers
10823 : Real64 GlArea; // Glazed area (m2)
10824 : Real64 Arealite; // Area of a single lite of glass (m2); glazed area, GlArea,
10825 : // if there is no divider (in which case there is only one lite).
10826 : Real64 ArealiteCol; // Area of a vertical column of lites (m2)
10827 : Real64 ArealiteRow; // Area of a horizontal row of lites (m2)
10828 : Real64 AshVDout; // Shaded area from all vertical divider outside projections (m2)
10829 : Real64 AshVDin; // Shaded area from all vertical divider inside projections (m2)
10830 : Real64 AshHDout; // Shaded area from all horizontal divider outside projections (m2)
10831 : Real64 AshHDin; // Shaded area from all horizontal divider inside projections (m2)
10832 : Real64 AshVFout; // Shaded area from outside projection of vertical sides of frame (m2)
10833 : Real64 AshVFin; // Shaded area from inside projection of vertical sides of frame (m2)
10834 : Real64 AshHFout; // Shaded area from outside projection of horizontal sides
10835 : // (top) of frame (m2)
10836 : Real64 AshHFin; // Shaded area from inside projection of horizontal sides
10837 : // (top) of frame (m2)
10838 : Real64 AshDDover; // Divider/divider shadow overlap area (m2)
10839 : Real64 AshFFover; // Frame/frame shadow overlap area (m2)
10840 : Real64 AshFVDover; // Frame/vertical divider overlap area (m2)
10841 : Real64 AshFHDover; // Frame/horizontal divider overlap area (m2)
10842 : Real64 AshFDtotOut; // Total outside projection shadow area (m2)
10843 : Real64 AshFDtotIn; // Total inside projection shadow area (m2)
10844 : Real64 FracShFDOut; // Fraction of glazing shadowed by frame and divider
10845 : // outside projections
10846 : Real64 FracShFDin; // Fraction of glazing that illuminates frame and divider
10847 : // inside projections with beam radiation
10848 :
10849 17 : Vector3<Real64> WinNorm(3); // Window outward normal unit vector // Why the (3)?
10850 : Real64 ThWin; // Azimuth angle of WinNorm
10851 17 : Vector3<Real64> SunPrime(3); // Projection of sun vector onto plane (perpendicular to // Why the (3)?
10852 : // window plane) determined by WinNorm and vector along
10853 : // baseline of window
10854 17 : Vector3<Real64> WinNormCrossBase(3); // Cross product of WinNorm and vector along window baseline // Why the (3)?
10855 :
10856 17 : auto &s_surf = state.dataSurface;
10857 :
10858 17 : if (s_surf->FrameDivider(FrDivNum).FrameProjectionOut == 0.0 && s_surf->FrameDivider(FrDivNum).FrameProjectionIn == 0.0 &&
10859 17 : s_surf->FrameDivider(FrDivNum).DividerProjectionOut == 0.0 && s_surf->FrameDivider(FrDivNum).DividerProjectionIn == 0.0) {
10860 0 : return;
10861 : }
10862 :
10863 17 : FrProjOut = s_surf->FrameDivider(FrDivNum).FrameProjectionOut;
10864 17 : FrProjIn = s_surf->FrameDivider(FrDivNum).FrameProjectionIn;
10865 17 : DivProjOut = s_surf->FrameDivider(FrDivNum).DividerProjectionOut;
10866 17 : DivProjIn = s_surf->FrameDivider(FrDivNum).DividerProjectionIn;
10867 :
10868 17 : auto &surf = s_surf->Surface(SurfNum);
10869 17 : GlArea = surf.Area;
10870 17 : ElevWin = Constant::PiOvr2 - surf.Tilt * Constant::DegToRad;
10871 17 : ElevSun = Constant::PiOvr2 - std::acos(state.dataSolarShading->SUNCOS(3));
10872 17 : AzimWin = surf.Azimuth * Constant::DegToRad;
10873 17 : AzimSun = std::atan2(state.dataSolarShading->SUNCOS(1), state.dataSolarShading->SUNCOS(2));
10874 :
10875 17 : ProfileAngHor = std::atan(std::sin(ElevSun) / std::abs(std::cos(ElevSun) * std::cos(AzimWin - AzimSun))) - ElevWin;
10876 17 : if (std::abs(ElevWin) < 0.1) { // Near-vertical window
10877 17 : ProfileAngVert = std::abs(AzimWin - AzimSun);
10878 : } else {
10879 0 : WinNorm = surf.OutNormVec;
10880 0 : ThWin = AzimWin - Constant::PiOvr2;
10881 0 : WinNormCrossBase(1) = -std::sin(ElevWin) * std::cos(ThWin);
10882 0 : WinNormCrossBase(2) = std::sin(ElevWin) * std::sin(ThWin);
10883 0 : WinNormCrossBase(3) = std::cos(ElevWin);
10884 0 : SunPrime = state.dataSolarShading->SUNCOS - WinNormCrossBase * dot(state.dataSolarShading->SUNCOS, WinNormCrossBase);
10885 0 : ProfileAngVert = std::abs(std::acos(dot(WinNorm, SunPrime) / magnitude(SunPrime)));
10886 : }
10887 : // Constrain to 0 to pi
10888 17 : if (ProfileAngVert > Constant::Pi) {
10889 0 : ProfileAngVert = 2 * Constant::Pi - ProfileAngVert;
10890 : }
10891 17 : TanProfileAngHor = std::abs(std::tan(ProfileAngHor));
10892 17 : TanProfileAngVert = std::abs(std::tan(ProfileAngVert));
10893 :
10894 17 : NHorDiv = s_surf->FrameDivider(FrDivNum).HorDividers;
10895 17 : NVertDiv = s_surf->FrameDivider(FrDivNum).VertDividers;
10896 17 : FrWidth = s_surf->FrameDivider(FrDivNum).FrameWidth;
10897 17 : DivWidth = s_surf->FrameDivider(FrDivNum).DividerWidth;
10898 :
10899 17 : Arealite = (surf.Height / (NHorDiv + 1.0) - DivWidth / 2.0) * (surf.Width / (NVertDiv + 1.0) - DivWidth / 2.0);
10900 17 : if (DivProjOut > 0.0 || DivProjIn > 0.0) {
10901 17 : ArealiteCol = (NHorDiv + 1) * Arealite;
10902 17 : ArealiteRow = (NVertDiv + 1) * Arealite;
10903 : } else {
10904 0 : ArealiteCol = GlArea;
10905 0 : ArealiteRow = GlArea;
10906 : }
10907 17 : AshVDout = 0.0;
10908 17 : AshVDin = 0.0;
10909 17 : AshHDout = 0.0;
10910 17 : AshHDin = 0.0;
10911 17 : AshVFout = 0.0;
10912 17 : AshVFin = 0.0;
10913 17 : AshHFout = 0.0;
10914 17 : AshHFin = 0.0;
10915 17 : AshDDover = 0.0;
10916 17 : AshFFover = 0.0;
10917 17 : AshFVDover = 0.0;
10918 17 : AshFHDover = 0.0;
10919 :
10920 17 : if (DivProjOut > 0.0 || DivProjIn > 0.0) {
10921 :
10922 : // Shaded area from all vertical dividers
10923 17 : AshVDout = NVertDiv * min((surf.Height - NHorDiv * DivWidth) * DivProjOut * TanProfileAngVert, ArealiteCol);
10924 17 : AshVDin = NVertDiv * min((surf.Height - NHorDiv * DivWidth) * DivProjIn * TanProfileAngVert, ArealiteCol);
10925 :
10926 : // Shaded area from all horizontal dividers
10927 17 : AshHDout = NHorDiv * min((surf.Width - NVertDiv * DivWidth) * DivProjOut * TanProfileAngHor, ArealiteRow);
10928 17 : AshHDin = NHorDiv * min((surf.Width - NVertDiv * DivWidth) * DivProjIn * TanProfileAngHor, ArealiteRow);
10929 :
10930 : // Horizontal divider/vertical divider shadow overlap
10931 17 : AshDDover = min(DivProjOut * TanProfileAngHor * DivProjOut * TanProfileAngVert, Arealite) * NHorDiv * NVertDiv;
10932 : }
10933 :
10934 17 : if (FrProjOut > 0.0 || FrProjIn > 0.0) {
10935 :
10936 : // Shaded area from sides of frame; to avoid complications from possible overlaps between
10937 : // shadow from side of frame and shadow from vertical divider the shaded area from side of
10938 : // frame is restricted to the area of one column of lites.
10939 17 : AshVFout = min((surf.Height - NHorDiv * DivWidth) * FrProjOut * TanProfileAngVert, ArealiteCol);
10940 17 : AshVFin = min((surf.Height - NHorDiv * DivWidth) * FrProjIn * TanProfileAngVert, ArealiteCol);
10941 :
10942 : // Shaded area from top or bottom of frame; to avoid complications from possible overlaps
10943 : // between shadow from top or bottom of frame and shadow from horizontal divider, the shaded
10944 : // area from the top or bottom of frame is restricted to the area of one row of lites.
10945 17 : AshHFout = min((surf.Width - NVertDiv * DivWidth) * FrProjOut * TanProfileAngHor, ArealiteRow);
10946 17 : AshHFin = min((surf.Width - NVertDiv * DivWidth) * FrProjIn * TanProfileAngHor, ArealiteRow);
10947 :
10948 : // Top/bottom of frame/side of frame shadow overlap
10949 17 : AshFFover = min(FrProjOut * TanProfileAngHor * FrProjOut * TanProfileAngVert, Arealite);
10950 17 : if (DivProjOut > 0.0) {
10951 : // Frame/vertical divider shadow overlap
10952 17 : AshFVDover = min(FrProjOut * DivProjOut * TanProfileAngHor * TanProfileAngVert, Arealite) * NVertDiv;
10953 : // Frame/horizontal divider shadow overlap
10954 17 : AshFHDover = min(FrProjOut * DivProjOut * TanProfileAngHor * TanProfileAngVert, Arealite) * NHorDiv;
10955 : }
10956 : }
10957 :
10958 17 : AshFDtotOut = AshVDout + AshHDout + AshVFout + AshHFout - (AshDDover + AshFFover + AshFVDover + AshFHDover);
10959 17 : AshFDtotIn =
10960 17 : (AshVDin + AshHDin) * s_surf->FrameDivider(FrDivNum).DividerSolAbsorp + (AshVFin + AshHFin) * s_surf->FrameDivider(FrDivNum).FrameSolAbsorp;
10961 :
10962 : // Divide by the glazed area of the window
10963 17 : FracShFDOut = AshFDtotOut / GlArea;
10964 17 : FracShFDin = AshFDtotIn / GlArea;
10965 17 : s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[HourNum] = 1.0 - FracShFDOut;
10966 17 : s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[HourNum] = 1.0 - (FracShFDin + FracShFDOut);
10967 17 : }
10968 :
10969 3 : void CalcBeamSolarOnWinRevealSurface(EnergyPlusData &state)
10970 : {
10971 :
10972 : // SUBROUTINE INFORMATION:
10973 : // AUTHOR F. Winkelmann
10974 : // DATE WRITTEN April 2002
10975 : // MODIFIED:na
10976 : // RE-ENGINEERED:na
10977 :
10978 : // PURPOSE OF THIS SUBROUTINE
10979 : // Called by InitHeatGains when the sun is up.
10980 : // Calculates beam solar radiation absorbed and reflected by top, bottom,
10981 : // right and left sides of outside and inside window reveal surfaces.
10982 : // In doing this calculation, the shadowing on a reveal surface by other reveal surfaces
10983 : // is determined using the orientation of the reveal surfaces and the sun position.
10984 : // It is assumed that:
10985 : // (1) The window is an exterior window and is rectangular.
10986 : // (2) The reveal surfaces are perpendicular to the window plane.
10987 : // (3) If an exterior shade or blind is in place, there is no beam solar on
10988 : // on exterior or interior reveal surfaces.
10989 : // (3) If an interior shade or blind is in place, there is no beam solar on
10990 : // interior reveal surfaces.
10991 : // (4) The effect of window divider, if present, is ignored, including shadowing
10992 : // of divider on inside reveal surfaces.
10993 :
10994 : // In the variable names, the "subscript" 1 = outside reveal, 2 = inside reveal
10995 : // The outside reveal surfaces (top, bottom, left, right) are assumed to have the same depth
10996 : // (given by Surface%Reveal and determined from vertices of window and vertices of parent
10997 : // wall) and the same solar absorptance. The inside reveal surfaces are divided into
10998 : // two categories: (1) the bottom reveal surface, called here the "inside sill;" and
10999 : // the other reveal surfaces (left, right and top). The left, right and top inside reveal
11000 : // surfaces are assumed to have the same depth and solar absorptance.
11001 : // The depth of the outside reveal is measured from the outside surface of the glazing;
11002 : // The depth of the inside sill and the other reveal surfaces is measured from the inside
11003 : // surface of the glazing. The inside sill is
11004 : // allowed to have depth and solar absorptance values that are different from the corresponding
11005 : // values for the other inside reveal surfaces. The inside sill depth is required to be
11006 : // greater than or equal to the depth of the other inside reveal surfaces. If the inside sill
11007 : // depth is greater than zero the depth of the other inside reveal surfaces is required to
11008 : // to be greater than zero.
11009 : // The reflection of beam solar radiation from all reveal surfaces is assumed to be isotropic
11010 : // diffuse; there is no specular component. Half of the beam solar reflected from outside
11011 : // reveal surfaces is assumed to go towards the window; the other half is assumed to go back
11012 : // to the exterior environment (i.e., reflection of this outward-going component from
11013 : // other outside reveal surfaces is not considered). The half that goes towards the window
11014 : // is added to the other radiation incident on the window.
11015 : // Correspondingly, half of the beam solar reflected from inside reveal surfaces is assumed
11016 : // to go towards the window, with the other half going into the zone (this half, and the portion
11017 : // going towards the window that is reflected) is added in CalcInteriorSolarDistribution
11018 : // to the variable BTOTzone, which is the total beam solar entering the zone as beam or diffuse.
11019 : // The portion going towards the window that is not reflected is absorbed in the glazing or
11020 : // transmitted back out into the exterior environment.
11021 : // The beam solar that is absorbed by outside reveal surfaces is added to the solar absorbed
11022 : // by the outside surface of the window's parent wall; similarly, the beam solar absorbed
11023 : // by the inside reveal surfaces is added to the solar absorbed by the inside surface of the
11024 : // parent wall (and is subtracted from BTOTzone).
11025 : // The net effect of beam solar reflected from outside reveal surfaces is to INCREASE the
11026 : // the heat gain to the zone, whereas the effect of beam solar reflected from interior reveal
11027 : // surfaces is to DECREASE the heat gain to the zone since part of this reflected solar is
11028 : // transmitted back out the window.
11029 : // If the window has a frame, the absorption of reflected beam solar by the inside and outside
11030 : // surfaces of the frame is considered. The shadowing of the frame onto interior reveal
11031 : // surfaces is also considered.
11032 :
11033 : // The total glazing thickness is taken to be the sum of the thickness of the glass layers
11034 : // and between-glass gas layers. If the window has an exterior, movable, storm window glass layer
11035 : // the presence of this layer and its adjacent air gap is considered in calculating the glazing
11036 : // properties (solar transmittance, etc.). But the storm window glass is assumed to be close
11037 : // enough to the rest of the glazing that its effect on total glazing thickness and outside
11038 : // reveal depth can be ignored.
11039 :
11040 : // METHODOLOGY EMPLOYED
11041 : // na
11042 :
11043 : // REFERENCES
11044 : // na
11045 :
11046 : // Locals
11047 : // SUBROUTINE ARGUMENT DEFINITIONS:na
11048 :
11049 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS
11050 :
11051 : int ConstrNum; // Construction number
11052 : int ConstrNumSh; // Shaded construction number
11053 : Real64 CosBetaBottom; // Cosine of beam solar angle of incidence on bottom reveal
11054 : Real64 CosBetaLeft; // Cosine of beam solar angle of incidence on left reveal
11055 : Real64 CosBeta; // ABS of CosBetaBottom or CosBetaLeft
11056 : Real64 d1; // Depth of outside reveal + half of glazing thickness (m)
11057 : Real64 d2; // Depth of inside sill or of inside reveal plus half of glazing thickness (m)
11058 : Real64 d2prime; // Depth of shadow cast on a reveal surface by opposite reveal (m)
11059 : Real64 d2prime2; // Depth of shadow cast by frame onto inside reveal (m)
11060 : Real64 d12; // d12 = d1 + d2 - d2prime (m)
11061 : Real64 TanAlpha; // Tangent of horizontal or vertical profile angle
11062 : Real64 TanGamma; // Tangent of vertical or horizontal profile angle
11063 : Real64 H; // Window height, width (m)
11064 : Real64 W;
11065 : Real64 L; // Window height or width (m)
11066 : Real64 A1sh; // Shadowed area of outside horizontal or vertical reveal (m2)
11067 : Real64 A2sh; // Shadowed area of inside horizontal or vertical reveal (m2)
11068 : Real64 A1ill; // Illuminated area of outside horizontal or vertical reveal (m2)
11069 : Real64 A2ill; // Illuminated area of inside horizontal or vertical reveal (m2)
11070 : Real64 SolTransGlass; // Beam solar transmittance of glazing
11071 : Real64 SolTransGlassSh; // For switchable glazing, beam solar trans in switched state
11072 : Real64 DiffReflGlass; // Diffuse back reflectance of glazing
11073 : Real64 DiffReflGlassSh; // For switchable glazing, diffuse back refl in switched state
11074 : int HorVertReveal; // Index: 1 = horizontal reveal, 2 = vertical reveal
11075 : Real64 OutsReveal; // Depth of outside reveal (from outside glazing plane to outside wall plane) (m)
11076 : Real64 InsReveal; // Depth of inside reveal (from inside glazing plane to inside wall plane (m)
11077 : Real64 InsSillDepth; // Depth of inside sill, measured from innermost face of glazing (m)
11078 : Real64 GlazingThickness; // Thickness of glazing, measured from innermost face to outermost face (m)
11079 : Real64 InsideRevealSolAbs; // Solar absorptance of inside reveal or inside sill
11080 : Real64 BmSolRefldOutsReveal; // Multiplied by beam solar gives beam solar reflected by horiz or vertical
11081 : // outside reveal surface (m2)
11082 : Real64 BmSolRefldInsReveal; // Multiplied by beam solar gives beam solar reflected by horiz or vertical
11083 : // inside reveal surface (m2)
11084 : WinShadingType ShadeFlag; // Shading flag
11085 : int FrameDivNum; // Frame/Divider number
11086 : Real64 FrameWidth; // Frame width (m)
11087 : Real64 P1; // Frame outside/inside projection plus half of glazing thickness (m)
11088 : Real64 P2;
11089 : Real64 f1; // f1=d1-P1, f2=d2-P2 (m)
11090 : Real64 f2;
11091 : Real64 L1; // Average distance of outside/inside illuminated area to frame;
11092 : Real64 L2;
11093 : // used in calculating view factor to frame (m)
11094 : Real64 FracToGlassOuts; // View factor from outside horizontal or vertical reveal to glass
11095 : Real64 FracToGlassIns; // View factor from inside horizontal or vertical reveal to glass
11096 : Real64 TanProfileAngVert; // Tangent of vertical profile angle (the profile angle appropriate for
11097 : // vertical reveal surfaces.
11098 : Real64 TanProfileAngHor; // Tangent of horizontal profile angle (the profile angle appropriate for
11099 : // horizontal reveal surfaces.
11100 :
11101 : Real64 tmp_SunlitFracWithoutReveal; // Temporary variable
11102 :
11103 3 : auto &s_surf = state.dataSurface;
11104 :
11105 6 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
11106 6 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
11107 3 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
11108 3 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
11109 3 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
11110 9 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
11111 : // Added TH for initialization. CR 7596 inside reveal causing high cooling loads
11112 : // for outside reveals
11113 6 : s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) = 0.0;
11114 6 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) = 0.0;
11115 6 : s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfNum) = 0.0;
11116 6 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) = 0.0;
11117 6 : s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) = 0.0;
11118 : // for inside reveals
11119 6 : s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) = 0.0;
11120 6 : s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) = 0.0;
11121 6 : s_surf->SurfWinBmSolRefldInsReveal(SurfNum) = 0.0;
11122 6 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) = 0.0;
11123 6 : s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfNum) = 0.0;
11124 6 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) = 0.0;
11125 6 : s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) = 0.0;
11126 6 : s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) = 0.0;
11127 6 : s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) = 0.0;
11128 6 : s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) = 0.0;
11129 6 : s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) = 0.0;
11130 :
11131 6 : auto &surf = s_surf->Surface(SurfNum);
11132 6 : if ((surf.ExtBoundCond != ExternalEnvironment && surf.ExtBoundCond != OtherSideCondModeledExt)) {
11133 0 : continue;
11134 : }
11135 6 : if (surf.Reveal == 0.0 && s_surf->SurfWinInsideReveal(SurfNum) == 0.0 && s_surf->SurfWinInsideSillDepth(SurfNum) == 0.0) {
11136 0 : continue;
11137 : }
11138 6 : if (surf.Sides != 4) {
11139 0 : continue;
11140 : }
11141 6 : if (s_surf->SurfWinInsideSillDepth(SurfNum) < s_surf->SurfWinInsideReveal(SurfNum)) {
11142 0 : continue;
11143 : }
11144 :
11145 6 : ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum);
11146 6 : if ((ShadeFlag == WinShadingType::ExtShade) || (ShadeFlag == WinShadingType::ExtBlind)) {
11147 0 : continue;
11148 : }
11149 :
11150 6 : if (state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) <= 0.0) {
11151 0 : continue;
11152 : }
11153 :
11154 6 : tmp_SunlitFracWithoutReveal =
11155 6 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
11156 :
11157 : // Calculate cosine of angle of incidence of beam solar on reveal surfaces,
11158 : // assumed to be perpendicular to window plane
11159 :
11160 6 : CosBetaBottom = -state.dataEnvrn->SOLCOS(1) * surf.SinAzim * surf.CosTilt - state.dataEnvrn->SOLCOS(2) * surf.CosAzim * surf.CosTilt +
11161 6 : state.dataEnvrn->SOLCOS(3) * surf.SinTilt;
11162 :
11163 6 : CosBetaLeft = -state.dataEnvrn->SOLCOS(1) * surf.CosAzim - state.dataEnvrn->SOLCOS(2) * surf.SinAzim;
11164 :
11165 : // Note: CosBetaTop = -CosBetaBottom, CosBetaRight = -CosBetaLeft
11166 :
11167 6 : OutsReveal = surf.Reveal;
11168 6 : InsReveal = s_surf->SurfWinInsideReveal(SurfNum);
11169 6 : InsideRevealSolAbs = 0.0;
11170 6 : GlazingThickness = s_surf->SurfWinTotGlazingThickness(SurfNum);
11171 6 : H = surf.Height;
11172 6 : W = surf.Width;
11173 6 : d1 = OutsReveal + 0.5 * GlazingThickness;
11174 6 : ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
11175 6 : ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(SurfNum);
11176 6 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
11177 :
11178 6 : SolTransGlass = Window::POLYF(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum),
11179 6 : thisConstruct.TransSolBeamCoef);
11180 6 : TanProfileAngVert = s_surf->SurfWinTanProfileAngVert(SurfNum);
11181 6 : TanProfileAngHor = s_surf->SurfWinTanProfileAngHor(SurfNum);
11182 6 : FrameDivNum = surf.FrameDivider;
11183 6 : FrameWidth = 0.0;
11184 6 : if (FrameDivNum != 0) {
11185 6 : FrameWidth = s_surf->FrameDivider(FrameDivNum).FrameWidth;
11186 6 : if (FrameWidth > 0.0) {
11187 6 : P1 = s_surf->FrameDivider(FrameDivNum).FrameProjectionOut + 0.5 * GlazingThickness;
11188 6 : P2 = s_surf->FrameDivider(FrameDivNum).FrameProjectionIn + 0.5 * GlazingThickness;
11189 6 : if (OutsReveal + 0.5 * GlazingThickness <= P1) {
11190 6 : d1 = P1 + 0.001;
11191 : }
11192 : }
11193 : }
11194 : // Loop over vertical and horizontal reveal surfaces
11195 18 : for (HorVertReveal = 1; HorVertReveal <= 2; ++HorVertReveal) {
11196 :
11197 12 : FracToGlassOuts = 0.5;
11198 12 : FracToGlassIns = 0.5;
11199 12 : BmSolRefldOutsReveal = 0.0;
11200 12 : BmSolRefldInsReveal = 0.0;
11201 12 : A1ill = 0.0;
11202 12 : A2ill = 0.0;
11203 :
11204 : // Added TH. 5/27/2009
11205 12 : A1sh = 0.0;
11206 12 : A2sh = 0.0;
11207 :
11208 12 : if (HorVertReveal == 1) { // Vertical reveal
11209 6 : TanAlpha = TanProfileAngHor;
11210 6 : TanGamma = TanProfileAngVert;
11211 6 : CosBeta = std::abs(CosBetaLeft);
11212 6 : L = surf.Height;
11213 6 : d2 = InsReveal + 0.5 * GlazingThickness;
11214 6 : d2prime = d1 + d2 - W / TanGamma;
11215 6 : InsideRevealSolAbs = s_surf->SurfWinInsideRevealSolAbs(SurfNum);
11216 : } else { // Horizontal reveal
11217 6 : InsSillDepth = s_surf->SurfWinInsideSillDepth(SurfNum);
11218 6 : TanAlpha = TanProfileAngVert;
11219 6 : TanGamma = TanProfileAngHor;
11220 6 : CosBeta = std::abs(CosBetaBottom);
11221 6 : L = surf.Width;
11222 6 : if (CosBetaBottom > 0.0) { // Bottom reveal surfaces may be illuminated
11223 6 : d2 = InsSillDepth + 0.5 * GlazingThickness;
11224 6 : InsideRevealSolAbs = s_surf->SurfWinInsideSillSolAbs(SurfNum);
11225 : } else { // Top reveal surfaces may be illuminated
11226 0 : d2 = InsReveal + 0.5 * GlazingThickness;
11227 0 : InsideRevealSolAbs = s_surf->SurfWinInsideRevealSolAbs(SurfNum);
11228 : }
11229 6 : d2prime = d1 + d2 - H / TanGamma;
11230 : }
11231 12 : if (d2prime < 0.0) {
11232 0 : d2prime = 0.0; // No shadow from opposing reveal
11233 : }
11234 12 : d12 = d1 + d2 - d2prime;
11235 :
11236 12 : if (FrameWidth <= 0.001) {
11237 : // Window without frame
11238 :
11239 : // Find inside and outside shadowed area of vertical or horizontal reveal surfaces
11240 : // that can be illuminated by beam solar; shadowing is by other reveal surfaces.
11241 :
11242 0 : if (d2prime <= d2) {
11243 0 : if (d12 * TanAlpha <= L) {
11244 0 : A1sh = 0.5 * TanAlpha * pow_2(d1);
11245 0 : A2sh = d2prime * L + 0.5 * TanAlpha * pow_2(d12) - A1sh;
11246 : } else { // d12*TanAlpha > L
11247 0 : if (d1 * TanAlpha <= L) {
11248 0 : A1sh = 0.5 * TanAlpha * pow_2(d1);
11249 0 : A2sh = d2 * L - 0.5 * TanAlpha * pow_2(L / TanAlpha - d1);
11250 : } else { // d1*TanAlpha > L
11251 0 : A1sh = d1 * L - (0.5 / TanAlpha) * pow_2(L);
11252 0 : A2sh = d2 * L;
11253 : }
11254 : }
11255 : } else { // d2prime > d2
11256 0 : A2sh = d2 * L;
11257 0 : if (d2prime < d1 + d2) {
11258 0 : if (d12 * TanAlpha <= L) {
11259 0 : A1sh = L * (d2prime - d2) + 0.5 * TanAlpha * pow_2(d12);
11260 : } else { // d12*TanAlpha > L
11261 0 : A1sh = d1 * L - 0.5 * pow_2(L) / TanAlpha;
11262 : }
11263 : } else { // d2prime >= d1+d2
11264 0 : A1sh = d1 * L;
11265 : }
11266 : }
11267 :
11268 : // Added TH. 5/27/2009
11269 0 : if (A1sh < 0.0) {
11270 0 : A1sh = 0.0;
11271 : }
11272 0 : if (A2sh < 0.0) {
11273 0 : A2sh = 0.0;
11274 : }
11275 :
11276 0 : if (OutsReveal >= 0.001) {
11277 0 : A1ill = d1 * L - A1sh; // A1ill = 0.0 if OutsReveal < 0.001
11278 : }
11279 0 : if (InsReveal >= 0.001) {
11280 0 : A2ill = d2 * L - A2sh; // A2ill = 0.0 if InsReveal < 0.001
11281 : }
11282 :
11283 : } else { // Window with frame; take into account shadowing
11284 : // of inside reveal surfaces by frame
11285 12 : f1 = d1 - P1;
11286 12 : f2 = d2 - P2;
11287 12 : d2prime2 = FrameWidth / TanGamma;
11288 12 : if (HorVertReveal == 1) { // Vertical reveal
11289 6 : if (InsReveal + 0.5 * GlazingThickness <= P2) {
11290 0 : d2 = P2 + 0.001;
11291 : }
11292 : } else { // Horizontal
11293 6 : if (CosBetaBottom > 0.0) { // Bottom reveal surfaces may be illuminated
11294 6 : if (InsSillDepth + 0.5 * GlazingThickness <= P2) {
11295 0 : d2 = P2 + 0.001;
11296 : }
11297 : } else { // Top reveal surfaces may be illuminated
11298 0 : if (InsReveal + 0.5 * GlazingThickness <= P2) {
11299 0 : d2 = P2 + 0.001;
11300 : }
11301 : }
11302 : }
11303 :
11304 12 : if (d2prime <= f2) { // Shadow from opposing reveal does not go beyond inside surface of frame
11305 :
11306 10 : if (d12 * TanAlpha <= L) {
11307 5 : A1sh = 0.5 * TanAlpha * pow_2(f1);
11308 5 : L1 = f1 * (f1 * TanAlpha / (6.0 * L) + 0.5);
11309 5 : if (d2 - (d2prime + d2prime2 + P2) >= 0.0) {
11310 5 : A2sh = (d2prime + d2prime2) * L + 0.5 * TanAlpha * (pow_2(d1 + d2 - d2prime) - pow_2(d1 + P2 + d2prime2));
11311 5 : L2 = d2prime2 + 0.5 * (d2 - (d2prime + d2prime2 + P2));
11312 : } else { // d2-(d2prime+d2prime2+P2) < 0. ! Inside reveal is fully shadowed by
11313 : // frame and/or opposing reveal
11314 0 : A2sh = f2 * L;
11315 0 : L2 = f2;
11316 : }
11317 : } else { // d12*TanAlpha >= L
11318 5 : if ((d1 + P2) * TanAlpha <= L) {
11319 5 : A1sh = 0.5 * TanAlpha * pow_2(f1);
11320 5 : L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
11321 5 : if ((d1 + P2 + d2prime2) * TanAlpha >= L) {
11322 0 : A2sh = f2 * L;
11323 0 : L2 = f2;
11324 : } else { // (d1+P2+d2prime2)*TanAlpha < L
11325 5 : A2sh = f2 * L - 0.5 * pow_2(L - (d1 + P2) * TanAlpha) / TanAlpha +
11326 5 : d2prime2 * (L - (d1 + P2 + d2prime2 / 2.0) * TanAlpha);
11327 5 : L2 = d2prime2 + (L / TanAlpha - (d1 + P2 + d2prime2)) / 3.0;
11328 : }
11329 : } else { // (d1+P2)*TanAlpha > L
11330 0 : L2 = f2;
11331 0 : A2sh = f2 * L;
11332 0 : if (f1 * TanAlpha <= L) {
11333 0 : A1sh = 0.5 * TanAlpha * pow_2(f1);
11334 0 : L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
11335 : } else { // f1*TanAlpha > L
11336 0 : A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
11337 0 : L1 = f1 - (L / TanAlpha) / 3.0;
11338 : }
11339 : }
11340 : }
11341 :
11342 : } else { // d2prime > f2 ! Shadow from opposing reveal goes beyond inside of frame
11343 :
11344 2 : A2sh = f2 * L;
11345 2 : L2 = f2;
11346 2 : if (d2prime >= d1 + d2) {
11347 0 : A1sh = 0.0;
11348 0 : L1 = f1;
11349 : } else { // d2prime < d1+d2
11350 2 : if (d2prime <= d2 + P1) {
11351 2 : if (f1 * TanAlpha <= L) {
11352 2 : A1sh = 0.5 * TanAlpha * pow_2(f1);
11353 2 : L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
11354 : } else { // f1*TanAlpha > L
11355 0 : A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
11356 0 : L1 = f1 - (L / TanAlpha) / 3.0;
11357 : }
11358 : } else { // d2prime > d2+P1
11359 0 : if (d12 * TanAlpha <= L) {
11360 0 : A1sh = L * (d2prime - (d2 + P1)) + 0.5 * TanAlpha * pow_2(d12);
11361 0 : L1 = (L * (f1 - d12 / 2.0) - d12 * TanAlpha * (f1 / 2 - d12 / 3.0)) / (L - d12 * TanAlpha / 2.0);
11362 : } else { // d12*TanAlpha > L
11363 0 : A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
11364 0 : L1 = f1 - (L / TanAlpha) / 3.0;
11365 : }
11366 : }
11367 : }
11368 : }
11369 :
11370 : // Added TH. 5/27/2009
11371 12 : if (A1sh < 0.0) {
11372 0 : A1sh = 0.0;
11373 : }
11374 12 : if (A2sh < 0.0) {
11375 0 : A2sh = 0.0;
11376 : }
11377 :
11378 12 : if (OutsReveal >= P1 + 0.5 * GlazingThickness + 0.001) {
11379 0 : A1ill = L * f1 - A1sh;
11380 : }
11381 12 : if (InsReveal >= P2 + 0.5 * GlazingThickness + 0.001) {
11382 12 : A2ill = L * f2 - A2sh;
11383 : }
11384 12 : if (L1 == 0.0) {
11385 0 : FracToGlassOuts = 0.0;
11386 : } else {
11387 12 : FracToGlassOuts = 0.5 * (1.0 - std::atan(FrameWidth / L1) / Constant::PiOvr2);
11388 : }
11389 12 : if (L2 == 0.0) {
11390 0 : FracToGlassIns = 0.0;
11391 : } else {
11392 12 : FracToGlassIns = 0.5 * (1.0 - std::atan(FrameWidth / L2) / Constant::PiOvr2);
11393 : }
11394 : } // End of check if window has frame
11395 :
11396 : // Added TH. 5/27/2009
11397 12 : if (A1ill < 0.0) {
11398 0 : A1ill = 0.0;
11399 : }
11400 12 : if (A2ill < 0.0) {
11401 0 : A2ill = 0.0;
11402 : }
11403 :
11404 : // Quantities related to outside reveal
11405 12 : if (A1ill > Constant::OneMillionth) {
11406 :
11407 0 : s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) +=
11408 0 : A1ill * s_surf->SurfWinOutsideRevealSolAbs(SurfNum) * CosBeta * tmp_SunlitFracWithoutReveal;
11409 :
11410 0 : BmSolRefldOutsReveal = A1ill * (1.0 - s_surf->SurfWinOutsideRevealSolAbs(SurfNum)) * CosBeta * tmp_SunlitFracWithoutReveal;
11411 :
11412 0 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) += state.dataEnvrn->BeamSolarRad * BmSolRefldOutsReveal;
11413 0 : s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfNum) =
11414 0 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) * state.dataGlobal->TimeStepZoneSec;
11415 :
11416 : // Reflected solar from outside horizontal and vertical reveal incident on glazing
11417 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) += FracToGlassOuts * BmSolRefldOutsReveal / surf.Area;
11418 :
11419 0 : if (FrameWidth > 0.0) {
11420 : // Reflected solar from outside horizontal and vertical reveal incident on frame
11421 0 : s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) +=
11422 0 : (0.5 - FracToGlassOuts) * BmSolRefldOutsReveal / s_surf->SurfWinFrameArea(SurfNum);
11423 : }
11424 :
11425 : } // End of check if A1ill > 0.0 (actually 10^-6)
11426 :
11427 : // Quantities related to inside reveal; inside reveal reflection/absorption is assumed
11428 : // to occur only if an interior shade or blind is not in place.
11429 :
11430 12 : if (NOT_SHADED(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
11431 :
11432 12 : if (A2ill > Constant::OneMillionth) {
11433 :
11434 10 : DiffReflGlass = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
11435 10 : if (ShadeFlag == WinShadingType::SwitchableGlazing) {
11436 0 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
11437 : SolTransGlassSh =
11438 0 : Window::POLYF(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum),
11439 0 : thisConstructSh.TransSolBeamCoef);
11440 0 : SolTransGlass = Window::InterpSw(s_surf->SurfWinSwitchingFactor(SurfNum), SolTransGlass, SolTransGlassSh);
11441 0 : DiffReflGlassSh = thisConstructSh.ReflectSolDiffBack;
11442 0 : DiffReflGlass = Window::InterpSw(s_surf->SurfWinSwitchingFactor(SurfNum), DiffReflGlass, DiffReflGlassSh);
11443 : }
11444 :
11445 : // Calc beam solar absorbed (m2)
11446 10 : s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +=
11447 10 : A2ill * SolTransGlass * InsideRevealSolAbs * CosBeta * tmp_SunlitFracWithoutReveal;
11448 :
11449 : // Added TH 5/26/2009 for reporting purpose - Beam solar absorbed by the inside reveal
11450 : // (W)
11451 10 : s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) +=
11452 10 : state.dataEnvrn->BeamSolarRad * A2ill * SolTransGlass * InsideRevealSolAbs * CosBeta * tmp_SunlitFracWithoutReveal;
11453 :
11454 : // in m2 = Area * solar transmitted fraction * inside reveal reflection fraction
11455 10 : BmSolRefldInsReveal = A2ill * SolTransGlass * (1.0 - InsideRevealSolAbs) * CosBeta * tmp_SunlitFracWithoutReveal;
11456 :
11457 10 : s_surf->SurfWinBmSolRefldInsReveal(SurfNum) += BmSolRefldInsReveal;
11458 :
11459 10 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) +=
11460 10 : state.dataEnvrn->BeamSolarRad * BmSolRefldInsReveal; // W, BeamSolarRad in W/m2
11461 10 : s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfNum) =
11462 10 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) * state.dataGlobal->TimeStepZoneSec;
11463 :
11464 : // Reflected solar from inside horizontal and vertical reveal incident on glazing
11465 10 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) += FracToGlassIns * BmSolRefldInsReveal / surf.Area;
11466 :
11467 : // Added TH 5/26/2009 for reporting purpose - diffuse on window glass from inside
11468 : // reveal (W)
11469 10 : s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) +=
11470 10 : state.dataEnvrn->BeamSolarRad * FracToGlassIns * BmSolRefldInsReveal;
11471 :
11472 : // Reflected solar from inside horizontal and vertical reveal incident on frame
11473 10 : if (FrameWidth > 0.0) {
11474 10 : s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) +=
11475 10 : (0.5 - FracToGlassIns) * BmSolRefldInsReveal / s_surf->SurfWinFrameArea(SurfNum);
11476 :
11477 : // Added TH 5/26/2009 for reporting purpose - diffuse on window frame from inside
11478 : // reveal (W)
11479 10 : s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) +=
11480 10 : state.dataEnvrn->BeamSolarRad * (0.5 - FracToGlassIns) * BmSolRefldInsReveal;
11481 : }
11482 :
11483 : // Reflected solar from inside reveal going directly into zone and reflected from
11484 : // glass. Assumes half of solar reflected from inside reveal goes as diffuse radiation
11485 : // into the zone and half goes as diffuse radiation towards window.
11486 10 : s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) += BmSolRefldInsReveal * (0.5 + DiffReflGlass * FracToGlassIns);
11487 :
11488 : // Added TH 5/26/2009 for reporting purpose - diffuse into zone from inside reveal (W)
11489 10 : s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) +=
11490 10 : state.dataEnvrn->BeamSolarRad * BmSolRefldInsReveal * (0.5 + DiffReflGlass * FracToGlassIns);
11491 :
11492 : } // End of check if A2ill > 0.0 (actually 10^-6)
11493 :
11494 : } // End of check if interior shade or blind is in place
11495 :
11496 : } // End of loop over vertical and horizontal reveal
11497 :
11498 : } // End of surface loop
11499 3 : }
11500 : }
11501 3 : }
11502 :
11503 249964 : void ReportSurfaceShading(EnergyPlusData &state)
11504 : {
11505 :
11506 : // SUBROUTINE INFORMATION:
11507 : // AUTHOR Linda Lawrie
11508 : // DATE WRITTEN April 2000
11509 : // MODIFIED na
11510 : // RE-ENGINEERED na
11511 :
11512 : // PURPOSE OF THIS SUBROUTINE:
11513 : // This subroutine uses the internal variables used in the Shading
11514 : // calculations and prepares them for reporting (at timestep level).
11515 :
11516 : // METHODOLOGY EMPLOYED:
11517 : // Because all of the calculations are done on a "daily" basis in this
11518 : // module, it is difficult to formulate the values that might be useful
11519 : // for reporting. SunlitFrac was the first of these two arrays to be
11520 : // made into "two dimensions". It is not clear that both have to be
11521 : // two dimensions.
11522 :
11523 : // REFERENCES:
11524 : // na
11525 :
11526 : // Using/Aliasing
11527 : using namespace OutputReportPredefined;
11528 :
11529 : // Locals
11530 : // SUBROUTINE ARGUMENT DEFINITIONS:
11531 : // na
11532 :
11533 : // SUBROUTINE PARAMETER DEFINITIONS:
11534 : // na
11535 :
11536 : // INTERFACE BLOCK SPECIFICATIONS
11537 : // na
11538 :
11539 : // DERIVED TYPE DEFINITIONS
11540 : // na
11541 :
11542 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
11543 : int SurfNum; // Loop Counter
11544 : int RepCol; // the column of the predefined report
11545 :
11546 249964 : auto &s_surf = state.dataSurface;
11547 2353997 : for (SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
11548 2104033 : auto &surf = s_surf->Surface(SurfNum);
11549 :
11550 2104033 : s_surf->SurfSunlitFrac(SurfNum) = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
11551 2104033 : s_surf->SurfSunlitArea(SurfNum) =
11552 2104033 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) * surf.Area;
11553 : }
11554 : // added for predefined reporting
11555 249964 : RepCol = 0;
11556 249964 : if (state.dataEnvrn->Month == 3 && state.dataEnvrn->DayOfMonth == 21) {
11557 0 : if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
11558 0 : RepCol = state.dataOutRptPredefined->pdchSlfMar21_9;
11559 0 : } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
11560 0 : RepCol = state.dataOutRptPredefined->pdchSlfMar21_12;
11561 0 : } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
11562 0 : RepCol = state.dataOutRptPredefined->pdchSlfMar21_15;
11563 : }
11564 249964 : } else if (state.dataEnvrn->Month == 6 && state.dataEnvrn->DayOfMonth == 21) {
11565 0 : if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
11566 0 : RepCol = state.dataOutRptPredefined->pdchSlfJun21_9;
11567 0 : } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
11568 0 : RepCol = state.dataOutRptPredefined->pdchSlfJun21_12;
11569 0 : } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
11570 0 : RepCol = state.dataOutRptPredefined->pdchSlfJun21_15;
11571 : }
11572 249964 : } else if (state.dataEnvrn->Month == 12 && state.dataEnvrn->DayOfMonth == 21) {
11573 73882 : if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
11574 472 : RepCol = state.dataOutRptPredefined->pdchSlfDec21_9;
11575 73410 : } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
11576 472 : RepCol = state.dataOutRptPredefined->pdchSlfDec21_12;
11577 72938 : } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
11578 472 : RepCol = state.dataOutRptPredefined->pdchSlfDec21_15;
11579 : }
11580 : }
11581 249964 : if (RepCol != 0) {
11582 9936 : for (SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
11583 8520 : auto &surf = s_surf->Surface(SurfNum);
11584 8520 : if (surf.Class == SurfaceClass::Window) {
11585 24 : PreDefTableEntry(state, RepCol, surf.Name, s_surf->SurfSunlitFrac(SurfNum));
11586 : }
11587 : }
11588 : }
11589 249964 : }
11590 :
11591 26 : void ReportSurfaceErrors(EnergyPlusData &state)
11592 : {
11593 :
11594 : // SUBROUTINE INFORMATION:
11595 : // AUTHOR Linda Lawrie
11596 : // DATE WRITTEN November 2004
11597 : // MODIFIED na
11598 : // RE-ENGINEERED na
11599 :
11600 : // PURPOSE OF THIS SUBROUTINE:
11601 : // This subroutine reports some recurring type errors that can get mixed up with more important
11602 : // errors in the error file.
11603 :
11604 : using namespace DataErrorTracking; // for error tracking
11605 :
11606 26 : static Array1D_string const MSG(4, {"misses", "", "within", "overlaps"});
11607 :
11608 : int Loop1;
11609 : int Loop2;
11610 : int Count;
11611 : int TotCount;
11612 26 : Array1D_bool SurfErrorReported;
11613 26 : Array1D_bool SurfErrorReported2;
11614 :
11615 26 : auto &s_surf = state.dataSurface;
11616 :
11617 26 : if (state.dataSolarShading->NumTooManyFigures + state.dataSolarShading->NumTooManyVertices + state.dataSolarShading->NumBaseSubSurround > 0) {
11618 0 : ShowMessage(state, "");
11619 0 : ShowMessage(state, "===== Recurring Surface Error Summary =====");
11620 0 : ShowMessage(state, "The following surface error messages occurred.");
11621 0 : ShowMessage(state, "");
11622 :
11623 0 : if (state.dataSolarShading->NumBaseSubSurround > 0) {
11624 0 : ShowMessage(state, "Base Surface does not surround subsurface errors occurring...");
11625 0 : ShowMessage(state,
11626 : "Check that the GlobalGeometryRules object is expressing the proper starting corner and "
11627 : "direction [CounterClockwise/Clockwise]");
11628 0 : ShowMessage(state, "");
11629 : }
11630 :
11631 0 : SurfErrorReported.dimension(s_surf->TotSurfaces, false);
11632 0 : TotCount = 0;
11633 0 : for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumBaseSubSurround; ++Loop1) {
11634 0 : Count = 0;
11635 0 : if (SurfErrorReported(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1)) {
11636 0 : continue;
11637 : }
11638 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumBaseSubSurround; ++Loop2) {
11639 0 : if (state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1 ==
11640 0 : state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex1 &&
11641 0 : state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex == state.dataSolarShading->TrackBaseSubSurround(Loop2).MiscIndex) {
11642 0 : ++Count;
11643 : }
11644 : }
11645 0 : TotCount += Count;
11646 0 : state.dataErrTracking->TotalWarningErrors += Count - 1;
11647 0 : ShowWarningError(state,
11648 0 : format("Base surface does not surround subsurface (CHKSBS), Overlap Status={}",
11649 0 : state.dataSolarShading->cOverLapStatus(state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex)));
11650 0 : ShowContinueError(state, format(" The base surround errors occurred {} times.", Count));
11651 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumBaseSubSurround; ++Loop2) {
11652 0 : if (state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1 ==
11653 0 : state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex1 &&
11654 0 : state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex == state.dataSolarShading->TrackBaseSubSurround(Loop2).MiscIndex) {
11655 0 : ShowContinueError(state,
11656 0 : format("Surface \"{}\" {} SubSurface \"{}\"",
11657 0 : s_surf->Surface(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1).Name,
11658 0 : MSG(state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex),
11659 0 : s_surf->Surface(state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex2).Name));
11660 : }
11661 : }
11662 0 : SurfErrorReported(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1) = true;
11663 : }
11664 0 : if (TotCount > 0) {
11665 0 : ShowMessage(state, "");
11666 0 : ShowContinueError(state, format(" The base surround errors occurred {} times (total).", TotCount));
11667 0 : ShowMessage(state, "");
11668 : }
11669 :
11670 0 : SurfErrorReported2.allocate(s_surf->TotSurfaces);
11671 0 : SurfErrorReported = false;
11672 0 : TotCount = 0;
11673 0 : if (state.dataSolarShading->NumTooManyVertices > 0) {
11674 0 : ShowMessage(state, format("Too many vertices [>={}] in shadow overlap errors occurring...", state.dataSolarShading->MaxHCV));
11675 0 : ShowMessage(state,
11676 : "These occur throughout the year and may occur several times for the same surfaces. You "
11677 : "may be able to reduce them by "
11678 : "adding Output:Diagnostics,DoNotMirrorDetachedShading;");
11679 : }
11680 0 : for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumTooManyVertices; ++Loop1) {
11681 0 : Count = 0;
11682 0 : SurfErrorReported2 = false;
11683 0 : if (SurfErrorReported(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1)) {
11684 0 : continue;
11685 : }
11686 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyVertices; ++Loop2) {
11687 0 : if (state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1 ==
11688 0 : state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex1) {
11689 0 : ++Count;
11690 : }
11691 : }
11692 0 : TotCount += Count;
11693 0 : state.dataErrTracking->TotalWarningErrors += Count - 1;
11694 0 : ShowMessage(state, "");
11695 0 : ShowWarningError(state, format("Too many vertices [>={}] in a shadow overlap", state.dataSolarShading->MaxHCV));
11696 0 : ShowContinueError(state,
11697 0 : format("Overlapping figure={}, Surface Class=[{}]",
11698 0 : s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1).Name,
11699 0 : cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1).Class)));
11700 0 : ShowContinueError(state, format(" This error occurred {} times.", Count));
11701 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyVertices; ++Loop2) {
11702 0 : if (state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1 ==
11703 0 : state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex1) {
11704 0 : if (SurfErrorReported2(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2)) {
11705 0 : continue;
11706 : }
11707 0 : ShowContinueError(state,
11708 0 : format("Figure being Overlapped={}, Surface Class=[{}]",
11709 0 : s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2).Name,
11710 0 : cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2).Class)));
11711 0 : SurfErrorReported2(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2) = true;
11712 : }
11713 : }
11714 0 : SurfErrorReported(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1) = true;
11715 : }
11716 0 : if (TotCount > 0) {
11717 0 : ShowMessage(state, "");
11718 0 : ShowContinueError(state, format(" The too many vertices errors occurred {} times (total).", TotCount));
11719 0 : ShowMessage(state, "");
11720 : }
11721 :
11722 0 : SurfErrorReported = false;
11723 0 : TotCount = 0;
11724 0 : if (state.dataSolarShading->NumTooManyFigures > 0) {
11725 0 : ShowMessage(state, format("Too many figures [>={}] in shadow overlap errors occurring...", state.dataSolarShading->MaxHCS));
11726 0 : ShowMessage(state,
11727 : "These occur throughout the year and may occur several times for the same surfaces. You "
11728 : "may be able to reduce them by "
11729 : "adding OutputDiagnostics,DoNotMirrorDetachedShading;");
11730 : }
11731 0 : for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumTooManyFigures; ++Loop1) {
11732 0 : Count = 0;
11733 0 : SurfErrorReported2 = false;
11734 0 : if (SurfErrorReported(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1)) {
11735 0 : continue;
11736 : }
11737 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyFigures; ++Loop2) {
11738 0 : if (state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1 == state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex1) {
11739 0 : ++Count;
11740 : }
11741 : }
11742 0 : TotCount += Count;
11743 0 : state.dataErrTracking->TotalWarningErrors += Count - 1;
11744 0 : ShowMessage(state, "");
11745 0 : ShowWarningError(state, format("Too many figures [>={}] in a shadow overlap", state.dataSolarShading->MaxHCS));
11746 0 : ShowContinueError(state,
11747 0 : format("Overlapping figure={}, Surface Class=[{}]",
11748 0 : s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1).Name,
11749 0 : cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1).Class)));
11750 0 : ShowContinueError(state, format(" This error occurred {} times.", Count));
11751 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyFigures; ++Loop2) {
11752 0 : if (state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1 == state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex1) {
11753 0 : if (SurfErrorReported2(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2)) {
11754 0 : continue;
11755 : }
11756 0 : ShowContinueError(state,
11757 0 : format("Figure being Overlapped={}, Surface Class=[{}]",
11758 0 : s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2).Name,
11759 0 : cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2).Class)));
11760 0 : SurfErrorReported2(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2) = true;
11761 : }
11762 : }
11763 0 : SurfErrorReported(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1) = true;
11764 : }
11765 0 : if (TotCount > 0) {
11766 0 : ShowMessage(state, "");
11767 0 : ShowContinueError(state, format(" The too many figures errors occurred {} times (total).", TotCount));
11768 0 : ShowMessage(state, "");
11769 : }
11770 0 : SurfErrorReported.deallocate();
11771 0 : SurfErrorReported2.deallocate();
11772 : }
11773 26 : }
11774 :
11775 114 : void ComputeWinShadeAbsorpFactors(EnergyPlusData &state)
11776 : {
11777 :
11778 : // SUBROUTINE INFORMATION:
11779 : // AUTHOR Fred Winkelmann
11780 : // DATE WRITTEN Mar 2001
11781 : // MODIFIED Oct 2002,FCW: change ConstrNumSh =
11782 : // WindowShadingControl(WinShadeCtrlNum)%ShadedConstruction
11783 : // to Surface(SurfNum)%ShadedConstruction
11784 : // RE-ENGINEERED na
11785 :
11786 : // PURPOSE OF THIS SUBROUTINE:
11787 : // Called by InitSolarCalculations. Finds fractions that apportion radiation absorbed by a
11788 : // window shade to the two faces of the shade. For radiation incident from the left,
11789 : // ShadeAbsFacFace(1) is the fraction of radiation absorbed in the left-hand half of the
11790 : // of the shade and ShadeAbsFacFace(2) is the fraction absorbed in the right-hand half.
11791 : // The shade is assumed to be homogeneous.
11792 :
11793 : // REFERENCES: See EnergyPlus engineering documentation
11794 : // USE STATEMENTS: na
11795 114 : auto &s_mat = state.dataMaterial;
11796 114 : auto &s_surf = state.dataSurface;
11797 :
11798 247 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
11799 283 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
11800 150 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
11801 150 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
11802 150 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
11803 206 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
11804 56 : auto &surf = s_surf->Surface(SurfNum);
11805 56 : if (surf.Class == SurfaceClass::Window && surf.HasShadeControl) {
11806 8 : int WinShadeCtrlNum = surf.activeWindowShadingControl; // Window shading control number
11807 :
11808 8 : int MatNumSh = 0; // Shade layer material number
11809 8 : Real64 AbsorpEff = 0.0; // Effective absorptance of isolated shade layer (fraction of
11810 : // of incident radiation remaining after reflected portion is
11811 : // removed that is absorbed
11812 8 : if (ANY_SHADE(s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType)) {
11813 0 : int const ConstrNumSh = surf.activeShadedConstruction; // Window construction number with shade
11814 0 : int TotLay = state.dataConstruction->Construct(ConstrNumSh).TotLayers; // Total layers in a construction
11815 :
11816 0 : if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::IntShade) {
11817 0 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay); // Interior shade
11818 0 : } else if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::ExtShade) {
11819 0 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(1); // Exterior shade
11820 0 : } else if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::BGShade) {
11821 0 : if (state.dataConstruction->Construct(ConstrNumSh).TotGlassLayers == 2) {
11822 : // Double pane with between-glass shade
11823 0 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(3);
11824 : } else {
11825 : // Triple pane with between-glass shade
11826 0 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(5);
11827 : }
11828 : }
11829 :
11830 0 : auto const *matSh = s_mat->materials(MatNumSh);
11831 0 : auto const *matFenSh = dynamic_cast<Material::MaterialFen const *>(matSh);
11832 0 : assert(matFenSh != nullptr);
11833 0 : AbsorpEff = matFenSh->AbsorpSolar / (matFenSh->AbsorpSolar + matFenSh->Trans + 0.0001);
11834 0 : AbsorpEff = min(max(AbsorpEff, 0.0001),
11835 : 0.999); // Constrain to avoid problems with following log eval
11836 0 : s_surf->SurfWinShadeAbsFacFace1(SurfNum) = (1.0 - std::exp(0.5 * std::log(1.0 - AbsorpEff))) / AbsorpEff;
11837 0 : s_surf->SurfWinShadeAbsFacFace2(SurfNum) = 1.0 - s_surf->SurfWinShadeAbsFacFace1(SurfNum);
11838 : }
11839 : }
11840 : }
11841 133 : }
11842 : }
11843 114 : }
11844 :
11845 71220 : void CalcWinTransDifSolInitialDistribution(EnergyPlusData &state)
11846 : {
11847 :
11848 : // SUBROUTINE INFORMATION:
11849 : // AUTHOR Rob Hitchcock
11850 : // DATE WRITTEN July 2007
11851 : // MODIFIED N/A
11852 : // RE-ENGINEERED N/A
11853 :
11854 : // PURPOSE OF THIS SUBROUTINE:
11855 : // This subroutine calculates the initial distribution
11856 : // of diffuse solar transmitted through exterior windows
11857 : // to individual heat transfer surfaces in each zone(or enclosure).
11858 :
11859 : // METHODOLOGY EMPLOYED:
11860 : // Apportions diffuse solar transmitted through each exterior window
11861 : // that is then absorbed, reflected, and/or transmitted
11862 : // by other heat transfer surfaces in the zone.
11863 : // Calculations use:
11864 : // 1. WinDifSolar calculated in SUBROUTINE CalcInteriorSolarDistribution,
11865 : // 2. view factors between each exterior window and
11866 : // other heat transfer surfaces in a zone
11867 : // calculated in SUBROUTINE CalcApproximateViewFactors, and
11868 : // 3. surface absorptances, reflectances, and transmittances
11869 : // determined here using revised code from SUBROUTINE InitIntSolarDistribution
11870 :
11871 : // Using/Aliasing
11872 : using namespace DataViewFactorInformation;
11873 : using namespace DataWindowEquivalentLayer;
11874 :
11875 : Real64 AbsInt; // Tmp var for Inside surface short-wave absorptance
11876 : Real64 InsideDifAbsorptance; // Inside diffuse solar absorptance of a surface
11877 : Real64 InsideDifReflectance; // Inside diffuse solar reflectance of a surface
11878 : int BlNum; // Blind number
11879 : Real64 BlAbsDiffBk; // Glass layer back diffuse solar absorptance when blind in place
11880 : Real64 AbsDiffBkBl; // Blind diffuse back solar absorptance as part of glazing system
11881 :
11882 : // REAL(r64) :: DividerSolAbs ! Window divider solar absorptance
11883 : // REAL(r64) :: DividerSolRefl ! Window divider solar reflectance
11884 : // INTEGER :: MatNumGl ! Glass layer material number
11885 : // INTEGER :: MatNumSh ! Shade layer material number
11886 : // REAL(r64) :: TransGl,ReflGl,AbsGl ! Glass layer solar transmittance, reflectance, absorptance
11887 :
11888 71220 : Real64 ViewFactor = 0.0; // temp var for view factor
11889 : // Real64 ViewFactorTotal; // debug var for view factor total
11890 71220 : Real64 WinDifSolarTrans = 0.0; // debug var for WinDifSolar() [W]
11891 : // Real64 WinDifSolarDistTotl; // debug var for window total
11892 : // distributed diffuse solar [W] Real64 WinDifSolarDistAbsorbedTotl; // debug
11893 : // var for individual exterior window total distributed
11894 : // diffuse solar absorbed [W]
11895 : // Real64 WinDifSolarDistReflectedTotl; // debug var for individual exterior window total distributed
11896 : // diffuse solar reflected [W]
11897 : // Real64 WinDifSolarDistTransmittedTotl; // debug var for individual exterior window total distributed
11898 : // diffuse solar transmitted [W]
11899 71220 : Real64 WinDifSolLayAbsW = 0.0; // temp var for diffuse solar absorbed by individual glass layer [W]
11900 : // Real64 ZoneDifSolarTrans; // debug var for WinDifSolar() [W]
11901 : // Real64 ZoneDifSolarDistTotl; // debug var for zone total
11902 : // distributed diffuse solar [W] Real64 ZoneDifSolarDistAbsorbedTotl; //
11903 : // debug var for zone total distributed diffuse solar absorbed [W] Real64
11904 : // ZoneDifSolarDistReflectedTotl; // debug var for zone total distributed
11905 : // diffuse solar reflected [W] Real64 ZoneDifSolarDistTransmittedTotl; //
11906 : // debug var for zone total distributed diffuse solar transmitted [W]
11907 :
11908 71220 : Real64 DifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by surface [W]
11909 71220 : Real64 DifSolarAbs = 0.0; // temp var for diffuse solar absorbed by surface [W/m2]
11910 71220 : Real64 DifSolarReflW = 0.0; // temp var for diffuse solar reflected by surface [W]
11911 71220 : Real64 ShBlDifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by shade/blind [W]
11912 :
11913 71220 : Array2D<Real64> SurfWinAbsSolBeamEQL(2, CFSMAXNL + 1); // absorbed exterior beam radiation by layers fraction
11914 : Array2D<Real64> SurfWinAbsSolDiffEQL(2,
11915 71220 : CFSMAXNL + 1); // absorbed exterior diffuse radiation by layers fraction
11916 71220 : Array2D<Real64> SurfWinAbsSolBeamBackEQL(2, CFSMAXNL + 1); // absorbed interior beam radiation by layers fraction from back
11917 71220 : Array2D<Real64> AbsSolDiffBackEQL(2, CFSMAXNL + 1); // absorbed exterior diffuse radiation by layers fraction from back
11918 : int EQLNum; // equivalent layer fenestration index
11919 : int Lay; // equivalent layer fenestration layer index
11920 :
11921 71220 : auto &s_surf = state.dataSurface;
11922 :
11923 : // Init accumulators for absorbed diffuse solar for all surfaces for later heat balance calcs
11924 71220 : state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs = 0.0;
11925 71220 : state.dataHeatBal->SurfWinInitialDifSolwinAbs = 0.0;
11926 :
11927 : // Init accumulator for total reflected diffuse solar within each zone for interreflection calcs
11928 71220 : state.dataHeatBal->EnclSolInitialDifSolReflW = 0.0;
11929 :
11930 : // Init accumulator for transmitted diffuse solar for all surfaces for reporting
11931 71220 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans = 0.0;
11932 :
11933 : // Loop over all zones doing initial distribution of diffuse solar to interior heat transfer surfaces
11934 176528 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
11935 105308 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
11936 : // Init Zone accumulators for debugging
11937 : // ZoneDifSolarTrans = 0.0;
11938 : // ZoneDifSolarDistAbsorbedTotl = 0.0;
11939 : // ZoneDifSolarDistReflectedTotl = 0.0;
11940 : // ZoneDifSolarDistTransmittedTotl = 0.0;
11941 : // Loop over all diffuse solar transmitting surfaces (i.e., exterior windows and TDDs) in the current zone
11942 716995 : for (int const DifTransSurfNum : thisEnclosure.SurfacePtr) {
11943 : // Skip surfaces that are not exterior, except for TDD_Diffusers
11944 611687 : auto &difTransSurf = s_surf->Surface(DifTransSurfNum);
11945 611687 : if ((difTransSurf.ExtBoundCond != ExternalEnvironment) && (difTransSurf.ExtBoundCond != OtherSideCondModeledExt) &&
11946 207689 : (difTransSurf.OriginalClass != SurfaceClass::TDD_Diffuser)) {
11947 207689 : continue;
11948 : }
11949 :
11950 : // Do I need to do anything special for TDDs?
11951 : // if ( SurfaceWindow( DifTransSurfNum ).OriginalClass == SurfaceClass::TDD_Diffuser )
11952 : // {
11953 : // }
11954 :
11955 : // Skip surfaces that are not exterior windows or TDD diffusers
11956 403998 : if (difTransSurf.Class != SurfaceClass::Window && difTransSurf.OriginalClass != SurfaceClass::TDD_Diffuser) {
11957 372884 : continue;
11958 : }
11959 :
11960 : //----------------------------------------------------------------------------------------------------------
11961 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH EXTERIOR WINDOWS AND TDDS TO INTERIOR HEAT TRANSFER
11962 : // SURFACES
11963 : //----------------------------------------------------------------------------------------------------------
11964 :
11965 : // Init transmitted solar debug vars
11966 : // ViewFactorTotal = 0.0;
11967 31114 : WinDifSolarTrans = s_surf->SurfWinDifSolar(DifTransSurfNum);
11968 : // ZoneDifSolarTrans += WinDifSolarTrans;
11969 :
11970 : // Init Exterior Window accumulators for debugging
11971 : // WinDifSolarDistAbsorbedTotl = 0.0;
11972 : // WinDifSolarDistReflectedTotl = 0.0;
11973 : // WinDifSolarDistTransmittedTotl = 0.0;
11974 :
11975 : // Loop over all heat transfer surfaces in the current zone that might receive diffuse solar
11976 425000 : for (int const HeatTransSurfNum : thisEnclosure.SurfacePtr) {
11977 : // Skip surfaces that are not heat transfer surfaces
11978 : // Skip tubular daylighting device domes
11979 393886 : auto &surf = s_surf->Surface(HeatTransSurfNum);
11980 :
11981 393886 : if (surf.Class == SurfaceClass::TDD_Dome) {
11982 0 : continue;
11983 : }
11984 :
11985 : // View factor from current (sending) window DifTransSurfNum to current (receiving) surface
11986 : // HeatTransSurfNum
11987 393886 : int const HTenclosureSurfNum = surf.SolarEnclSurfIndex; // HT surface index for EnclSolInfo.SurfacePtr and F arrays
11988 393886 : int const enclosureNum = surf.SolarEnclIndex; // index for EnclSolInfo
11989 : int const DTenclSurfNum =
11990 393886 : s_surf->Surface(DifTransSurfNum).SolarEnclSurfIndex; // Window surface index for EnclSolInfo.SurfacePtr and F arrays
11991 :
11992 393886 : ViewFactor = state.dataViewFactor->EnclSolInfo(enclosureNum).F(HTenclosureSurfNum, DTenclSurfNum);
11993 : // debug ViewFactorTotal
11994 : // ViewFactorTotal += ViewFactor; // debug
11995 :
11996 : // Skip receiving surfaces with 0.0 view factor
11997 393886 : if (ViewFactor <= 0.0) {
11998 96750 : continue;
11999 : }
12000 :
12001 297136 : Real64 const WinDifSolarTrans_Factor(WinDifSolarTrans * ViewFactor);
12002 297136 : Real64 const win_SwitchingFactor(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum));
12003 297136 : Real64 const per_HTSurfaceArea(1.0 / surf.Area);
12004 :
12005 : // Calculate diffuse solar from current exterior window absorbed and reflected by current heat
12006 : // transfer surface And calculate transmitted diffuse solar to adjacent zones through interior
12007 : // windows
12008 297136 : int const ConstrNum = s_surf->SurfActiveConstruction(HeatTransSurfNum);
12009 297136 : if (state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) { // Interior Opaque Surface
12010 :
12011 : // Determine the inside (back) diffuse solar absorptance
12012 : // and reflectance of the current heat transfer surface
12013 219812 : InsideDifAbsorptance = state.dataHeatBalSurf->SurfAbsSolarInt(HeatTransSurfNum);
12014 : // Inside (back) diffuse solar reflectance is assumed to be 1 - absorptance
12015 219812 : InsideDifReflectance = 1.0 - InsideDifAbsorptance;
12016 :
12017 : // Absorbed diffuse solar [W] = current window transmitted diffuse solar [W]
12018 : // * view factor from current (sending) window DifTransSurfNum to current (receiving)
12019 : // surface HeatTransSurfNum
12020 : // * current surface inside solar absorptance
12021 219812 : DifSolarAbsW = WinDifSolarTrans_Factor * InsideDifAbsorptance; // [W]
12022 :
12023 : // Absorbed diffuse solar [W/m2] = Absorbed diffuse solar [W]
12024 : // / current surface net area
12025 219812 : DifSolarAbs = DifSolarAbsW * per_HTSurfaceArea;
12026 :
12027 : // Accumulate absorbed diffuse solar [W/m2] on this surface for heat balance calcs
12028 219812 : state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs(HeatTransSurfNum) += DifSolarAbs;
12029 :
12030 : // Reflected diffuse solar [W] = current window transmitted diffuse solar
12031 : // * view factor from current (sending) window DifTransSurfNum to current (receiving)
12032 : // surface HeatTransSurfNum
12033 : // * current window inside solar reflectance
12034 219812 : DifSolarReflW = WinDifSolarTrans_Factor * InsideDifReflectance;
12035 :
12036 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12037 : // interreflection calcs
12038 219812 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
12039 :
12040 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of
12041 : // energy For opaque surfaces all incident diffuse is either absorbed or reflected
12042 :
12043 : } else { // Exterior or Interior Window
12044 77324 : int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(HeatTransSurfNum);
12045 77324 : int TotGlassLayers = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
12046 77324 : WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(HeatTransSurfNum);
12047 :
12048 77324 : if (s_surf->SurfWinWindowModelType(HeatTransSurfNum) != WindowModel::EQL) {
12049 77322 : if (NOT_SHADED(ShadeFlag)) { // No window shading
12050 : // Init accumulator for transmittance calc below
12051 77322 : DifSolarAbsW = 0.0;
12052 :
12053 : // Calc diffuse solar absorbed by all window glass layers
12054 : // Note: I am assuming here that individual glass layer absorptances have been
12055 : // corrected
12056 : // to account for layer by layer transmittance and reflection effects.
12057 154686 : for (int IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
12058 : // Calc diffuse solar absorbed from the inside by each window glass layer [W]
12059 77364 : AbsInt = state.dataConstruction->Construct(ConstrNum).AbsDiffBack(IGlass);
12060 77364 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).AbsDiffBack(IGlass);
12061 :
12062 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
12063 : // transmittance calc below
12064 77364 : DifSolarAbsW += WinDifSolLayAbsW;
12065 :
12066 : // Accumulate diffuse solar absorbed from the inside by each window glass layer
12067 : // [W/m2] for heat balance calcs
12068 77364 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
12069 : }
12070 :
12071 : // Calc diffuse solar reflected back to zone
12072 : // I don't really care if this is a window or opaque surface since I am just
12073 : // accumulating all reflected diffuse solar in a zone bucket for "interreflected"
12074 : // distribution Reflected diffuse solar [W] = current window transmitted diffuse solar
12075 : // * view factor from current (sending) window DifTransSurfNum to current
12076 : // (receiving) surface HeatTransSurfNum
12077 : // * current window inside solar reflectance
12078 77322 : InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
12079 77322 : DifSolarReflW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
12080 :
12081 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12082 : // interreflection calcs
12083 77322 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
12084 :
12085 : //------------------------------------------------------------------------------
12086 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
12087 : //------------------------------------------------------------------------------
12088 :
12089 : // If this receiving window surface (HeatTransSurfNum) is an interior window,
12090 : // calc distributed solar transmitted to adjacent zone [W]
12091 : // NOTE: This calc is here because interior windows are currently assumed to have no
12092 : // shading
12093 :
12094 : // Get the adjacent surface number for this receiving window surface
12095 77322 : int AdjSurfNum = surf.ExtBoundCond;
12096 : // If the adjacent surface number is > 0, this is an interior window
12097 77322 : if (AdjSurfNum > 0) { // this is an interior window surface
12098 :
12099 : // Calc diffuse solar from current exterior window
12100 : // transmitted through this interior window to adjacent zone [W]
12101 : // Transmitted diffuse solar [W] = current exterior window transmitted diffuse
12102 : // solar
12103 : // * view factor from current (sending) window DifTransSurfNum to current
12104 : // (receiving) surface HeatTransSurfNum
12105 : // - diffuse absorbed by this interior window
12106 : // - diffuse reflected by this interior window
12107 0 : Real64 DifSolarTransThroughW = WinDifSolarTrans_Factor - DifSolarAbsW - DifSolarReflW;
12108 : // HERE 8/15/07 Note Construct(AdjConstrNum)%TransDiff could be used here since
12109 : // the "front" transmittance for an interior window in the adjacent zone is the
12110 : // correct direction as long as I use the Construct() of the Surface in the
12111 : // adjacent zone. However, the above calculation better conserves energy, although
12112 : // possibly at the expense of less accurate transmittance calcs. Preliminary tests
12113 : // showed fairly good agreement between the two DifSolarTransW calculation
12114 : // methods, but for consistency I stuck with the above. int AdjConstrNum =
12115 : // Surface(AdjSurfNum).Construction;
12116 : // DifSolarTransW = WinDifSolar(DifTransSurfNum) &
12117 : // * ViewFactor &
12118 : // * Construct(AdjConstrNum)%TransDiff
12119 :
12120 : // Get the adjacent zone index
12121 0 : int const adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
12122 :
12123 : // Call routine to distribute diffuse solar transmitted through this interior
12124 : // window into adjacent zone
12125 0 : CalcInteriorWinTransDifSolInitialDistribution(state, adjEnclosureNum, AdjSurfNum, DifSolarTransThroughW);
12126 : }
12127 :
12128 : // Calc transmitted Window and Zone total distributed diffuse solar to check for
12129 : // conservation of energy This is not very effective since it assigns whatever
12130 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
12131 : // Should be just total less reflected
12132 77322 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
12133 :
12134 : // Accumulate transmitted diffuse solar for reporting
12135 77322 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
12136 :
12137 0 : } else if (ShadeFlag == WinShadingType::SwitchableGlazing) { // Switchable glazing
12138 : // Init accumulator for transmittance calc below
12139 0 : DifSolarAbsW = 0.0;
12140 :
12141 0 : auto const &construct = state.dataConstruction->Construct(ConstrNum);
12142 0 : auto const &construct_AbsDiffBack = construct.AbsDiffBack;
12143 0 : auto const &construct_sh = state.dataConstruction->Construct(ConstrNumSh);
12144 0 : auto const &construct_sh_AbsDiffBack = construct_sh.AbsDiffBack;
12145 0 : for (int IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
12146 : // Calc diffuse solar absorbed in each window glass layer
12147 0 : WinDifSolLayAbsW =
12148 : WinDifSolarTrans_Factor *
12149 0 : Window::InterpSw(win_SwitchingFactor, construct_AbsDiffBack(IGlass), construct_sh_AbsDiffBack(IGlass));
12150 :
12151 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
12152 : // transmittance calc below
12153 0 : DifSolarAbsW += WinDifSolLayAbsW;
12154 :
12155 : // Accumulate diffuse solar absorbed from the inside by each window glass layer
12156 : // [W/m2] for heat balance calcs
12157 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
12158 : }
12159 :
12160 : // Calc diffuse solar reflected back to zone
12161 0 : DifSolarReflW = WinDifSolarTrans_Factor *
12162 0 : Window::InterpSw(win_SwitchingFactor, construct.ReflectSolDiffBack, construct_sh.ReflectSolDiffBack);
12163 :
12164 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12165 : // interreflection calcs
12166 0 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
12167 :
12168 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12169 : // conservation of energy This is not very effective since it assigns whatever
12170 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
12171 : // Should be just total less reflected
12172 0 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
12173 :
12174 : // Accumulate transmitted diffuse solar for reporting
12175 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
12176 :
12177 0 : } else if (ConstrNumSh != 0) {
12178 : // Interior, exterior or between-glass shade, screen or blind in place
12179 :
12180 : // Init accumulator for transmittance calc below
12181 0 : DifSolarAbsW = 0.0;
12182 0 : WinDifSolLayAbsW = 0.0;
12183 :
12184 : // First calc diffuse solar absorbed by each glass layer in this window with
12185 : // shade/blind in place
12186 0 : auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
12187 0 : auto const &surfShade = s_surf->surfShades(HeatTransSurfNum);
12188 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
12189 :
12190 0 : for (int IGlass = 1; IGlass <= constrSh.TotGlassLayers; ++IGlass) {
12191 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
12192 : // Calc diffuse solar absorbed in each window glass layer and shade
12193 0 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * constrSh.AbsDiffBack(IGlass);
12194 0 : } else if (ANY_BLIND(ShadeFlag)) {
12195 0 : auto const &slatDfAbsLo = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxLo];
12196 0 : auto const &slatDfAbsHi = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxHi];
12197 0 : BlAbsDiffBk = Interp(slatDfAbsLo.Sol.Bk.Df.Abs, slatDfAbsHi.Sol.Bk.Df.Abs, slatInterpFac);
12198 : // Calc diffuse solar absorbed in each window glass layer and shade
12199 0 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * BlAbsDiffBk;
12200 : }
12201 :
12202 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
12203 : // transmittance calc below
12204 0 : DifSolarAbsW += WinDifSolLayAbsW;
12205 :
12206 : // Accumulate diffuse solar absorbed from the inside by each window glass layer
12207 : // [W/m2] for heat balance calcs
12208 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
12209 : }
12210 :
12211 : // Next calc diffuse solar reflected back to zone from window with shade or blind on
12212 : // Diffuse back solar reflectance, bare glass or shade on
12213 0 : InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
12214 0 : if ((ShadeFlag == WinShadingType::IntBlind) || (ShadeFlag == WinShadingType::ExtBlind)) {
12215 0 : auto const &constr = state.dataConstruction->Construct(ConstrNum);
12216 0 : auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
12217 0 : auto const &btarSlatLo = constr.blindTARs[surfShade.blind.slatAngIdxLo];
12218 0 : auto const &btarSlatHi = constr.blindTARs[surfShade.blind.slatAngIdxHi];
12219 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
12220 : // Diffuse back solar reflectance, blind present, vs. slat angle
12221 0 : InsideDifReflectance = Interp(btarSlatLo.Sol.Bk.Df.Ref, btarSlatHi.Sol.Bk.Df.Ref, slatInterpFac);
12222 : }
12223 0 : DifSolarReflW = WinDifSolarTrans_Factor * InsideDifReflectance;
12224 :
12225 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12226 : // interreflection calcs
12227 0 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
12228 :
12229 : // Now calc diffuse solar absorbed by shade/blind itself
12230 0 : BlNum = surfShade.blind.matNum;
12231 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
12232 : // Calc diffuse solar absorbed by shade or screen [W]
12233 0 : ShBlDifSolarAbsW = WinDifSolarTrans_Factor * constrSh.AbsDiffBackShade;
12234 0 : } else if (ANY_BLIND(ShadeFlag)) {
12235 0 : auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
12236 0 : auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
12237 0 : auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
12238 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
12239 0 : AbsDiffBkBl = Interp(btarSlatLo.Sol.Bk.Df.Abs, btarSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
12240 0 : ShBlDifSolarAbsW = WinDifSolarTrans_Factor * AbsDiffBkBl;
12241 : }
12242 : // Correct for divider shadowing
12243 0 : if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
12244 0 : ShBlDifSolarAbsW *= s_surf->SurfaceWindow(HeatTransSurfNum).glazedFrac;
12245 : }
12246 :
12247 : // Accumulate diffuse solar absorbed by shade or screen [W/m2] for heat balance calcs
12248 0 : s_surf->SurfWinInitialDifSolAbsByShade(HeatTransSurfNum) += ShBlDifSolarAbsW * per_HTSurfaceArea;
12249 :
12250 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
12251 : // transmittance calc below
12252 0 : DifSolarAbsW += ShBlDifSolarAbsW;
12253 :
12254 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12255 : // conservation of energy This is not very effective since it assigns whatever
12256 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
12257 : // Should be just total less reflected
12258 0 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
12259 :
12260 : // Accumulate transmitted diffuse solar for reporting
12261 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
12262 : } // End of shading flag check
12263 :
12264 : } else {
12265 : // SurfaceWindow(HeatTransSurfNum)%WindowModelType == WindowModel:: EQL
12266 : // ConstrNum=Surface(HeatTransSurfNum)%Construction
12267 : // call the ASHWAT fenestration model for diffuse radiation here
12268 2 : WindowEquivalentLayer::CalcEQLOpticalProperty(state, HeatTransSurfNum, SolarArrays::DIFF, AbsSolDiffBackEQL);
12269 :
12270 2 : EQLNum = state.dataConstruction->Construct(ConstrNum).EQLConsPtr;
12271 6 : for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(EQLNum).NL; ++Lay) {
12272 :
12273 : // Calc diffuse solar absorbed from the inside by each layer of EQL model [W]
12274 : // WinDifSolLayAbsW = WinDifSolar(DifTransSurfNum)* ViewFactor *
12275 : // Construct(ConstrNum)%AbsDiffBack(Lay)
12276 4 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * AbsSolDiffBackEQL(2, Lay);
12277 :
12278 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
12279 : // transmittance calc below
12280 4 : DifSolarAbsW += WinDifSolLayAbsW;
12281 :
12282 : // Accumulate diffuse solar absorbed from the inside by each window layer [W/m2] for
12283 : // heat balance calcs
12284 4 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, Lay) += WinDifSolLayAbsW * per_HTSurfaceArea;
12285 :
12286 : // ASHWAT equivalent layer model may require not the individual layer absorption but
12287 : // the flux InitialDifSolwinEQL(HeatTransSurfNum) = WinDifSolar(DifTransSurfNum)*
12288 : // ViewFactor
12289 : }
12290 :
12291 : // Calc diffuse solar reflected back to zone
12292 : // I don't really care if this is a window or opaque surface since I am just
12293 : // accumulating all reflected diffuse solar in a zone bucket for "interreflected"
12294 : // distribution Reflected diffuse solar [W] = current window transmitted diffuse solar
12295 : // * view factor from current (sending) window DifTransSurfNum to current (receiving)
12296 : // surface HeatTransSurfNum
12297 : // * current window inside solar reflectance
12298 2 : InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
12299 2 : DifSolarReflW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
12300 :
12301 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12302 : // interreflection calcs
12303 2 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
12304 :
12305 : //------------------------------------------------------------------------------
12306 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
12307 : //------------------------------------------------------------------------------
12308 :
12309 : // If this receiving window surface (HeatTransSurfNum) is an interior window,
12310 : // calc distributed solar transmitted to adjacent zone [W]
12311 : // NOTE: This calc is here because interior windows are currently assumed to have no
12312 : // shading
12313 :
12314 : // Get the adjacent surface number for this receiving window surface
12315 2 : int const AdjSurfNum = s_surf->Surface(HeatTransSurfNum).ExtBoundCond;
12316 : // If the adjacent surface number is > 0, this is an interior window
12317 2 : if (AdjSurfNum > 0) { // this is an interior window surface
12318 :
12319 : // Calc diffuse solar from current exterior window
12320 : // transmitted through this interior window to adjacent zone [W]
12321 : // Transmitted diffuse solar [W] = current exterior window transmitted diffuse solar
12322 : // * view factor from current (sending) window DifTransSurfNum to current
12323 : // (receiving) surface HeatTransSurfNum
12324 0 : Real64 DifSolarTransW = AbsSolDiffBackEQL(2, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1) * ViewFactor;
12325 : // int AdjConstrNum = Surface(AdjSurfNum).Construction;
12326 : // Get the adjacent zone index
12327 0 : int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
12328 : // Call routine to distribute diffuse solar transmitted through this interior window
12329 : // into adjacent zone
12330 0 : CalcInteriorWinTransDifSolInitialDistribution(state, adjEnclosureNum, AdjSurfNum, DifSolarTransW);
12331 : }
12332 :
12333 : // Calc transmitted Window and Zone total distributed diffuse solar to check for
12334 : // conservation of energy This is not very effective since it assigns whatever
12335 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
12336 : // Should be just total less reflected
12337 2 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
12338 :
12339 : // Accumulate transmitted diffuse solar for reporting
12340 2 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
12341 :
12342 : } // IF (SurfaceWindow(HeatTransSurfNum)%WindowModelType /= WindowModel:: EQL) THEN
12343 :
12344 : // HERE 8/14/07 Ignore absorptance and reflectance of Frames and Dividers for now.
12345 : // I would need revised view factors that included these surface types.
12346 : // By ignoring them here, the diffuse solar is accounted for on the other surfaces
12347 :
12348 : // IF(SurfaceWindow(HeatTransSurfNum)%FrameArea > 0.0) THEN ! Window has a frame
12349 : // Note that FrameQRadInAbs is initially calculated in InitSolarHeatGains
12350 : // END IF
12351 :
12352 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerArea > 0.0) THEN ! Window has dividers
12353 : // DividerSolAbs = SurfaceWindow(HeatTransSurfNum)%DividerSolAbsorp
12354 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerType == Suspended) THEN ! Suspended
12355 : // divider; account for inside glass
12356 : // MatNumGl = Construct(ConstrNum)%LayerPoint(Construct(ConstrNum)%TotLayers)
12357 : // TransGl = dataMaterial.Material(MatNumGl)%Trans
12358 : // ReflGl = dataMaterial.Material(MatNumGl)%ReflectSolDiffBack
12359 : // AbsGl = 1.0d0-TransGl-ReflGl
12360 : // DividerSolRefl = 1.0d0-DividerSolAbs
12361 : // DividerSolAbs = AbsGl + TransGl*(DividerSolAbs +
12362 : // DividerSolRefl*AbsGl)/(1.0d0-DividerSolRefl*ReflGl)
12363 : // END IF
12364 : // Correct for interior shade transmittance
12365 : // IF(ShadeFlag == IntShadeOn) THEN
12366 : // MatNumSh = Construct(ConstrNumSh)%LayerPoint(Construct(ConstrNumSh)%TotLayers)
12367 : // DividerSolAbs = DividerSolAbs * dataMaterial.Material(MatNumSh)%Trans
12368 : // ELSE IF(ShadeFlag == WinShadingType::IntBlind) THEN
12369 : // DividerSolAbs = DividerSolAbs *
12370 : // InterpSlatAng(SurfaceWindow(HeatTransSurfNum)%SlatAngThisTS, &
12371 : // SurfaceWindow(HeatTransSurfNum)%MovableSlats,Blind(BlNum)%SolBackDiffDiffTrans)
12372 : // END IF
12373 : // Note that DividerQRadInAbs is initially calculated in InitSolarHeatGains
12374 :
12375 : // END IF ! Window has dividers
12376 :
12377 : } // opaque or window heat transfer surface
12378 :
12379 : } // HeatTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
12380 :
12381 : // Check debug var for view factors here
12382 : // ViewFactorTotal
12383 : // Check debug vars for individual transmitting surfaces here
12384 : // WinDifSolarDistTotl = WinDifSolarDistAbsorbedTotl + WinDifSolarDistReflectedTotl +
12385 : // WinDifSolarDistTransmittedTotl;
12386 : // WinDifSolarTrans
12387 :
12388 : } // DifTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
12389 :
12390 : // Check debug vars for zone totals here
12391 : // ZoneDifSolarDistTotl = ZoneDifSolarDistAbsorbedTotl + ZoneDifSolarDistReflectedTotl +
12392 : // ZoneDifSolarDistTransmittedTotl;
12393 : // ZoneDifSolarTrans
12394 : // ZoneDifSolarDistAbsorbedTotl
12395 : // ZoneDifSolarDistReflectedTotl
12396 : // ZoneDifSolarDistTransmittedTotl
12397 : // CALL DisplayString('Diffuse Solar Distribution Zone Totals')
12398 :
12399 : } // ZoneNum = 1, NumOfZones
12400 71220 : }
12401 0 : void CalcInteriorWinTransDifSolInitialDistribution(EnergyPlusData &state,
12402 : int const IntWinEnclosureNum, // Interior Window Enclosure index number
12403 : int const IntWinSurfNum, // Interior Window Surface number
12404 : Real64 const IntWinDifSolarTransW // Diffuse Solar transmitted through Interior Window
12405 : // IntWinSurfNum from adjacent enclosure [W]
12406 : )
12407 : {
12408 :
12409 : // SUBROUTINE INFORMATION:
12410 : // AUTHOR Rob Hitchcock
12411 : // DATE WRITTEN August 2007
12412 : // MODIFIED N/A
12413 : // RE-ENGINEERED N/A
12414 :
12415 : // PURPOSE OF THIS SUBROUTINE:
12416 : // This subroutine calculates the initial distribution
12417 : // of diffuse solar transmitted through the given interior window
12418 : // to individual heat transfer surfaces in the given enclosure.
12419 : // Diffuse solar transmitted through interior windows in this enclosure
12420 : // to adjacent enclosures, is added to the EnclSolInitialDifSolReflW
12421 : // of the adjacent enclosure for subsequent interreflection calcs
12422 :
12423 : // METHODOLOGY EMPLOYED:
12424 : // Similar to method used in CalcWinTransDifSolInitialDistribution.
12425 : // Apportions diffuse solar transmitted through an interior window
12426 : // that is then absorbed, reflected, and/or transmitted
12427 : // by other heat transfer surfaces in the given enclosure.
12428 : // Calculations use:
12429 : // 1. DifSolarTransW calculated in SUBROUTINE CalcWinTransDifSolInitialDistribution,
12430 : // 2. view factors between the interior window and
12431 : // other heat transfer surfaces in the given enclosure
12432 : // calculated in SUBROUTINE CalcApproximateViewFactors, and
12433 : // 3. surface absorptances, reflectances, and transmittances
12434 : // determined here using revised code from SUBROUTINE InitIntSolarDistribution
12435 :
12436 : // Using/Aliasing
12437 : using namespace DataViewFactorInformation;
12438 :
12439 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
12440 : int IGlass; // Glass layer counter
12441 : int TotGlassLayers; // Number of glass layers in a window construction
12442 : WinShadingType ShadeFlag; // Shading flag
12443 : Real64 AbsInt; // Tmp var for Inside surface short-wave absorptance
12444 : Real64 InsideDifAbsorptance; // Inside diffuse solar absorptance of a surface
12445 : Real64 InsideDifReflectance; // Inside diffuse solar reflectance of a surface
12446 : int BlNum; // Blind number
12447 : Real64 BlAbsDiffBk; // Glass layer back diffuse solar absorptance when blind in place
12448 : Real64 AbsDiffBkBl; // Blind diffuse back solar absorptance as part of glazing system
12449 :
12450 : // REAL(r64) :: DividerSolAbs ! Window divider solar absorptance
12451 : // REAL(r64) :: DividerSolRefl ! Window divider solar reflectance
12452 : // INTEGER :: MatNumGl ! Glass layer material number
12453 : // INTEGER :: MatNumSh ! Shade layer material number
12454 : // REAL(r64) :: TransGl,ReflGl,AbsGl ! Glass layer solar transmittance, reflectance, absorptance
12455 :
12456 : Real64 ViewFactor; // temp var for view factor
12457 : Real64 ViewFactorTotal; // debug var for view factor total
12458 : Real64 WinDifSolarTrans; // debug var for WinDifSolar() [W]
12459 : // Real64 WinDifSolarDistTotl; // debug var for window total distributed
12460 : // diffuse solar [W] Real64 WinDifSolarDistAbsorbedTotl( 0.0 ); // debug var
12461 : // for individual exterior window total
12462 : // distributed
12463 : // diffuse solar absorbed [W]
12464 : // Real64 WinDifSolarDistReflectedTotl( 0.0 ); // debug var for individual exterior window total
12465 : // distributed
12466 : // diffuse solar reflected [W]
12467 : // Real64 WinDifSolarDistTransmittedTotl( 0.0 ); // debug var for individual exterior window total
12468 : // distributed
12469 : // diffuse solar transmitted [W]
12470 : Real64 WinDifSolLayAbsW; // temp var for diffuse solar absorbed by individual glass layer [W]
12471 : // Real64 ZoneDifSolarTrans( 0.0 ); // debug var for WinDifSolar() [W]
12472 : // REAL(r64) :: ZoneDifSolarDistTotl ! debug var for zone total distributed diffuse solar [W]
12473 : // Real64 ZoneDifSolarDistAbsorbedTotl( 0.0 ); // debug var for zone total distributed diffuse solar
12474 : // absorbed [W] Real64 ZoneDifSolarDistReflectedTotl( 0.0 ); // debug var for zone total distributed
12475 : // diffuse solar reflected [W] Real64 ZoneDifSolarDistTransmittedTotl( 0.0 ); // debug var for zone
12476 : // total distributed diffuse solar transmitted [W]
12477 :
12478 0 : Real64 DifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by surface [W]
12479 0 : Real64 DifSolarAbs = 0.0; // temp var for diffuse solar absorbed by surface [W/m2]
12480 0 : Real64 DifSolarReflW = 0.0; // temp var for diffuse solar reflected by surface [W]
12481 0 : Real64 DifSolarTransW = 0.0; // temp var for diffuse solar transmitted through interior window surface [W]
12482 0 : Real64 ShBlDifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by shade/blind [W]
12483 :
12484 : //-------------------------------------------------------------------------------------------------
12485 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO INTERIOR HEAT TRANSFER SURFACES
12486 : //-------------------------------------------------------------------------------------------------
12487 :
12488 0 : auto &s_surf = state.dataSurface;
12489 :
12490 : // Init debug vars
12491 0 : ViewFactorTotal = 0.0;
12492 0 : WinDifSolarTrans = IntWinDifSolarTransW;
12493 :
12494 0 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(IntWinEnclosureNum);
12495 : // Loop over all heat transfer surfaces in the current zone that might receive diffuse solar
12496 0 : Real64 InitialZoneDifSolReflW_zone(0.0);
12497 0 : for (int const HeatTransSurfNum : thisEnclosure.SurfacePtr) {
12498 :
12499 0 : auto &surf = s_surf->Surface(HeatTransSurfNum);
12500 :
12501 : // Skip surfaces that are not heat transfer surfaces
12502 0 : if (!surf.HeatTransSurf) {
12503 0 : continue;
12504 : }
12505 : // Skip tubular daylighting device domes
12506 0 : if (surf.Class == SurfaceClass::TDD_Dome) {
12507 0 : continue;
12508 : }
12509 :
12510 : // View factor from current (sending) window IntWinSurfNum to current (receiving) surface HeatTransSurfNum
12511 0 : int HTenclosureSurfNum = surf.SolarEnclSurfIndex; // HT surface index for EnclSolInfo.SurfacePtr and F arrays
12512 0 : int enclosureNum = surf.SolarEnclIndex; // index for EnclSolInfo
12513 0 : int IntWinEnclSurfNum = s_surf->Surface(IntWinSurfNum).SolarEnclSurfIndex; // Window surface index for EnclSolInfo.SurfacePtr and F arrays
12514 :
12515 0 : ViewFactor = state.dataViewFactor->EnclSolInfo(enclosureNum).F(HTenclosureSurfNum, IntWinEnclSurfNum);
12516 : // debug ViewFactorTotal
12517 0 : ViewFactorTotal += ViewFactor; // debug
12518 :
12519 : // Skip receiving surfaces with 0.0 view factor
12520 0 : if (ViewFactor <= 0.0) {
12521 0 : continue;
12522 : }
12523 0 : Real64 const SolarTrans_ViewFactor(IntWinDifSolarTransW * ViewFactor);
12524 :
12525 : // Calculate diffuse solar from current interior window absorbed and reflected by current heat transfer
12526 : // surface And calculate transmitted diffuse solar to adjacent zones through interior windows
12527 0 : int const ConstrNum = s_surf->SurfActiveConstruction(HeatTransSurfNum);
12528 0 : if (state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) { // Interior Opaque Surface
12529 :
12530 : // Determine the inside (back) diffuse solar absorptance
12531 : // and reflectance of the current heat transfer surface
12532 0 : InsideDifAbsorptance = state.dataHeatBalSurf->SurfAbsSolarInt(HeatTransSurfNum);
12533 : // Inside (back) diffuse solar reflectance is assumed to be 1 - absorptance
12534 0 : InsideDifReflectance = 1.0 - InsideDifAbsorptance;
12535 :
12536 : // Absorbed diffuse solar [W] = current window transmitted diffuse solar [W]
12537 : // * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
12538 : // HeatTransSurfNum
12539 : // * current surface inside solar absorptance
12540 0 : DifSolarAbsW = SolarTrans_ViewFactor * InsideDifAbsorptance; // [W]
12541 :
12542 : // Absorbed diffuse solar [W/m2] = Absorbed diffuse solar [W]
12543 : // / current surface net area
12544 0 : DifSolarAbs = DifSolarAbsW / surf.Area;
12545 :
12546 : // Accumulate absorbed diffuse solar [W/m2] on this surface for heat balance calcs
12547 0 : state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs(HeatTransSurfNum) += DifSolarAbs;
12548 :
12549 : // Reflected diffuse solar [W] = current window transmitted diffuse solar
12550 : // * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
12551 : // HeatTransSurfNum
12552 : // * current window inside solar reflectance
12553 0 : DifSolarReflW = SolarTrans_ViewFactor * InsideDifReflectance;
12554 :
12555 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent interreflection
12556 : // calcs
12557 0 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12558 :
12559 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12560 : // For opaque surfaces all incident diffuse is either absorbed or reflected
12561 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug [W]
12562 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug [W]
12563 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug [W]
12564 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug [W]
12565 :
12566 : } else { // Exterior or Interior Window
12567 :
12568 0 : int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(HeatTransSurfNum);
12569 0 : auto const &construction = state.dataConstruction->Construct(ConstrNum);
12570 :
12571 0 : TotGlassLayers = construction.TotGlassLayers;
12572 0 : ShadeFlag = s_surf->SurfWinShadingFlag(HeatTransSurfNum);
12573 :
12574 0 : if (NOT_SHADED(ShadeFlag)) { // No window shading
12575 : // Init accumulator for transmittance calc below
12576 0 : DifSolarAbsW = 0.0;
12577 :
12578 : // Calc diffuse solar absorbed by all window glass layers
12579 : // Note: I am assuming here that individual glass layer absorptances have been corrected
12580 : // to account for layer by layer transmittance and reflection effects.
12581 0 : for (IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
12582 : // Calc diffuse solar absorbed from the inside by each window glass layer [W]
12583 0 : AbsInt = construction.AbsDiffBack(IGlass);
12584 0 : WinDifSolLayAbsW = SolarTrans_ViewFactor * construction.AbsDiffBack(IGlass);
12585 :
12586 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12587 : // below
12588 0 : DifSolarAbsW += WinDifSolLayAbsW;
12589 :
12590 : // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
12591 : // heat balance calcs
12592 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
12593 : }
12594 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12595 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12596 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12597 :
12598 : // Calc diffuse solar reflected back to zone
12599 : // I don't really care if this is a window or opaque surface since I am just
12600 : // accumulating all reflected diffuse solar in a zone bucket for "interreflected" distribution
12601 : // Reflected diffuse solar [W] = current window transmitted diffuse solar
12602 : // * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
12603 : // HeatTransSurfNum
12604 : // * current window inside solar reflectance
12605 0 : DifSolarReflW = SolarTrans_ViewFactor * construction.ReflectSolDiffBack;
12606 :
12607 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12608 : // interreflection calcs
12609 0 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12610 :
12611 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12612 :
12613 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
12614 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
12615 :
12616 : // Calc transmitted Window and Zone total distributed diffuse solar to check for conservation of
12617 : // energy This is not very effective since it assigns whatever distributed diffuse solar has not
12618 : // been absorbed or reflected to transmitted.
12619 0 : DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
12620 :
12621 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12622 : // conservation of energy
12623 : // WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12624 : // ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12625 :
12626 : // Accumulate transmitted diffuse solar for reporting
12627 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
12628 :
12629 : //-----------------------------------------------------------------------------------
12630 : // ADD TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
12631 : // TOTAL REFLECTED DIFFUSE SOLAR FOR SUBSEQUENT INTERREFLECTION CALCS
12632 : //-----------------------------------------------------------------------------------
12633 :
12634 : // If this receiving window surface (HeatTransSurfNum) is an interior window,
12635 : // add transmitted diffuse solar to adjacent zone total reflected distributed
12636 : // diffuse solar for subsequent interreflection calcs
12637 : // NOTE: This calc is here because interior windows are currently assumed to have no shading
12638 :
12639 : // Get the adjacent surface number for this receiving window surface
12640 0 : int const AdjSurfNum = surf.ExtBoundCond;
12641 : // If the adjacent surface number is > 0, this is an interior window
12642 0 : if (AdjSurfNum > 0) { // this is an interior window surface
12643 :
12644 : // Get the adjacent zone/enclosure index
12645 : // Add transmitted diffuse solar to total reflected distributed diffuse solar for each zone
12646 : // for subsequent interreflection calcs
12647 0 : state.dataHeatBal->EnclSolInitialDifSolReflW(s_surf->Surface(AdjSurfNum).SolarEnclIndex) += DifSolarTransW; // [W]
12648 : }
12649 :
12650 0 : } else if (ShadeFlag == WinShadingType::SwitchableGlazing) { // Switchable glazing
12651 : // Init accumulator for transmittance calc below
12652 0 : auto const &constructionSh = state.dataConstruction->Construct(ConstrNumSh);
12653 0 : DifSolarAbsW = 0.0;
12654 :
12655 0 : for (IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
12656 : // Calc diffuse solar absorbed in each window glass layer
12657 0 : WinDifSolLayAbsW = SolarTrans_ViewFactor * InterpSw(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum),
12658 0 : construction.AbsDiffBack(IGlass),
12659 0 : constructionSh.AbsDiffBack(IGlass));
12660 :
12661 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12662 : // below
12663 0 : DifSolarAbsW += WinDifSolLayAbsW;
12664 :
12665 : // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
12666 : // heat balance calcs
12667 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
12668 : }
12669 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12670 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12671 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12672 :
12673 : // Calc diffuse solar reflected back to zone
12674 0 : DifSolarReflW =
12675 : SolarTrans_ViewFactor *
12676 0 : InterpSw(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum), construction.ReflectSolDiffBack, constructionSh.ReflectSolDiffBack);
12677 :
12678 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12679 : // interreflection calcs
12680 0 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12681 :
12682 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12683 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
12684 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
12685 :
12686 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12687 : // conservation of energy This is not very effective since it assigns whatever distributed diffuse
12688 : // solar has not been absorbed or reflected to transmitted.
12689 0 : DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
12690 : // WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12691 : // ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug
12692 : //[W]
12693 :
12694 : // Accumulate transmitted diffuse solar for reporting
12695 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
12696 :
12697 : } else {
12698 0 : auto const &surfShade = s_surf->surfShades(HeatTransSurfNum);
12699 : // Interior, exterior or between-glass shade, screen or blind in place
12700 :
12701 : // Init accumulator for transmittance calc below
12702 0 : DifSolarAbsW = 0.0;
12703 0 : WinDifSolLayAbsW = 0.0;
12704 :
12705 : // First calc diffuse solar absorbed by each glass layer in this window with shade/blind in place
12706 0 : auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
12707 0 : for (IGlass = 1; IGlass <= constrSh.TotGlassLayers; ++IGlass) {
12708 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
12709 : // Calc diffuse solar absorbed in each window glass layer and shade
12710 0 : WinDifSolLayAbsW = SolarTrans_ViewFactor * constrSh.AbsDiffBack(IGlass);
12711 0 : } else if (ANY_BLIND(ShadeFlag)) {
12712 0 : auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
12713 0 : auto const &dfAbsSlatLo = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxLo];
12714 0 : auto const &dfAbsSlatHi = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxHi];
12715 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
12716 0 : BlAbsDiffBk = Interp(dfAbsSlatLo.Sol.Bk.Df.Abs, dfAbsSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
12717 : // Calc diffuse solar absorbed in each window glass layer and shade
12718 0 : WinDifSolLayAbsW = SolarTrans_ViewFactor * BlAbsDiffBk;
12719 : }
12720 :
12721 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12722 : // below
12723 0 : DifSolarAbsW += WinDifSolLayAbsW;
12724 :
12725 : // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
12726 : // heat balance calcs
12727 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
12728 : }
12729 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12730 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12731 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12732 :
12733 : // Next calc diffuse solar reflected back to zone from window with shade or blind on
12734 : // Diffuse back solar reflectance, bare glass or shade on
12735 0 : InsideDifReflectance = construction.ReflectSolDiffBack;
12736 0 : if ((ShadeFlag == WinShadingType::IntBlind) || (ShadeFlag == WinShadingType::ExtBlind)) {
12737 0 : auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
12738 0 : auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
12739 0 : auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
12740 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
12741 : // Diffuse back solar reflectance, blind present, vs. slat angle
12742 0 : InsideDifReflectance = Interp(btarSlatLo.Sol.Bk.Df.Ref, btarSlatHi.Sol.Bk.Df.Ref, slatInterpFac);
12743 : }
12744 0 : DifSolarReflW = SolarTrans_ViewFactor * InsideDifReflectance;
12745 :
12746 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12747 : // interreflection calcs
12748 0 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12749 :
12750 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12751 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
12752 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
12753 :
12754 : // Now calc diffuse solar absorbed by shade/blind itself
12755 0 : BlNum = surfShade.blind.matNum;
12756 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
12757 : // Calc diffuse solar absorbed by shade or screen [W]
12758 0 : ShBlDifSolarAbsW = SolarTrans_ViewFactor * constrSh.AbsDiffBackShade;
12759 0 : } else if (ANY_BLIND(ShadeFlag)) {
12760 0 : auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
12761 0 : auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
12762 0 : auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
12763 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
12764 : // Calc diffuse solar absorbed by blind [W]
12765 0 : AbsDiffBkBl = Interp(btarSlatLo.Sol.Bk.Df.Abs, btarSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
12766 0 : ShBlDifSolarAbsW = SolarTrans_ViewFactor * AbsDiffBkBl;
12767 : }
12768 : // Correct for divider shadowing
12769 0 : if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
12770 0 : ShBlDifSolarAbsW *= s_surf->SurfaceWindow(HeatTransSurfNum).glazedFrac;
12771 : }
12772 :
12773 : // Accumulate diffuse solar absorbed by shade or screen [W/m2] for heat balance calcs
12774 0 : s_surf->SurfWinInitialDifSolAbsByShade(HeatTransSurfNum) += (ShBlDifSolarAbsW / surf.Area);
12775 :
12776 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12777 : // below
12778 0 : DifSolarAbsW += ShBlDifSolarAbsW;
12779 :
12780 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12781 : // WinDifSolarDistAbsorbedTotl += ShBlDifSolarAbsW; // debug
12782 : // ZoneDifSolarDistAbsorbedTotl += ShBlDifSolarAbsW; // debug
12783 :
12784 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12785 : // conservation of energy This is not very effective since it assigns whatever distributed diffuse
12786 : // solar has not been absorbed or reflected to transmitted.
12787 0 : DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
12788 : // WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12789 : // ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12790 :
12791 : // Accumulate transmitted diffuse solar for reporting
12792 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
12793 :
12794 : } // End of shading flag check
12795 :
12796 : // HERE 8/14/07 Ignore absorptance and reflectance of Frames and Dividers for now.
12797 : // I would need revised view factors that included these surface types.
12798 : // By ignoring them here, the diffuse solar is accounted for on the other surfaces
12799 :
12800 : // IF(SurfaceWindow(HeatTransSurfNum)%FrameArea > 0.0) THEN ! Window has a frame
12801 : // Note that FrameQRadInAbs is initially calculated in InitSolarHeatGains
12802 : // END IF
12803 :
12804 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerArea > 0.0) THEN ! Window has dividers
12805 : // DividerSolAbs = SurfaceWindow(HeatTransSurfNum)%DividerSolAbsorp
12806 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerType == Suspended) THEN ! Suspended divider;
12807 : // account for inside glass
12808 : // MatNumGl = Construct(ConstrNum)%LayerPoint(Construct(ConstrNum)%TotLayers)
12809 : // TransGl = dataMaterial.Material(MatNumGl)%Trans
12810 : // ReflGl = dataMaterial.Material(MatNumGl)%ReflectSolDiffBack
12811 : // AbsGl = 1.0d0-TransGl-ReflGl
12812 : // DividerSolRefl = 1.0d0-DividerSolAbs
12813 : // DividerSolAbs = AbsGl + TransGl*(DividerSolAbs +
12814 : // DividerSolRefl*AbsGl)/(1.0d0-DividerSolRefl*ReflGl)
12815 : // END IF
12816 : // Correct for interior shade transmittance
12817 : // IF(ShadeFlag == IntShadeOn) THEN
12818 : // MatNumSh = Construct(ConstrNumSh)%LayerPoint(Construct(ConstrNumSh)%TotLayers)
12819 : // DividerSolAbs = DividerSolAbs * dataMaterial.Material(MatNumSh)%Trans
12820 : // ELSE IF(ShadeFlag == WinShadingType::IntBlind) THEN
12821 : // DividerSolAbs = DividerSolAbs *
12822 : // InterpSlatAng(SurfaceWindow(HeatTransSurfNum)%SlatAngThisTS, &
12823 : // SurfaceWindow(HeatTransSurfNum)%MovableSlats,Blind(BlNum)%SolBackDiffDiffTrans)
12824 : // END IF
12825 : // Note that DividerQRadInAbs is initially calculated in InitSolarHeatGains
12826 :
12827 : // END IF ! Window has dividers
12828 : } // opaque or window heat transfer surface
12829 :
12830 : } // HeatTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
12831 0 : state.dataHeatBal->EnclSolInitialDifSolReflW(IntWinEnclosureNum) += InitialZoneDifSolReflW_zone;
12832 :
12833 : // Check debug var for view factors here
12834 : // ViewFactorTotal
12835 : // Check debug vars for individual transmitting surfaces here
12836 : // WinDifSolarDistTotl = WinDifSolarDistAbsorbedTotl + WinDifSolarDistReflectedTotl +
12837 : // WinDifSolarDistTransmittedTotl; //Debug
12838 : // WinDifSolarTrans
12839 0 : }
12840 :
12841 0 : void CalcComplexWindowOverlap(EnergyPlusData &state,
12842 : BSDFGeomDescr &Geom, // State Geometry
12843 : BSDFWindowGeomDescr const &Window, // Window Geometry
12844 : int const ISurf // Surface number of the complex fenestration
12845 : )
12846 : {
12847 : // SUBROUTINE INFORMATION:
12848 : // AUTHOR Simon Vidanovic
12849 : // DATE WRITTEN May 2012
12850 : // MODIFIED Simon Vidanovic (May 2013) - added overlaps calculations for daylighting
12851 : // RE-ENGINEERED na
12852 :
12853 : // PURPOSE OF THIS SUBROUTINE:
12854 : // For each of basis directions on back surface of the window calculates
12855 : // overlap areas. It also calculates overlap areas and reflectances for daylighting calculations
12856 :
12857 : using namespace Vectors;
12858 :
12859 : Real64 XShadowProjection; // temporary buffer
12860 : Real64 YShadowProjection; // temporary buffer
12861 :
12862 : Real64 XSp; // for calc BSDF projection direction
12863 : Real64 YSp; // for calc BSDF projection direction
12864 : Real64 ZSp; // for calc BSDF projection direction
12865 : Real64 SdotX; // temporary variable for manipulating .dot. product
12866 : Real64 SdotY; // temporary variable for manipulating .dot. product
12867 : Real64 SdotZ; // temporary variable for manipulating .dot. product
12868 : int BackSurfaceNumber; // current back surface number
12869 : int NVT; // Number of vertices of back surface
12870 : int NS1; // Number of the figure being overlapped
12871 : int NS2; // Number of the figure doing overlapping
12872 : int NS3; // Location to place results of overlap
12873 : int IRay; // Current ray of BSDF direction
12874 : int KBkSurf; // Current back surface
12875 : int N;
12876 :
12877 : // Daylighting
12878 : int IConst; // Construction number of back surface
12879 : int InsideConLay; // Construction's inside material layer number
12880 : Real64 VisibleReflectance; // Visible reflectance for inside surface material
12881 : Real64 TotAOverlap; // Total overlap area for given outgoing direction
12882 : Real64 TotARhoVisOverlap; // Total overlap area time reflectance for given outgoing direction
12883 :
12884 0 : auto &s_surf = state.dataSurface;
12885 :
12886 0 : state.dataSolarShading->XVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
12887 0 : state.dataSolarShading->YVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
12888 0 : state.dataSolarShading->ZVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
12889 :
12890 0 : Geom.AOverlap.dimension(Window.NBkSurf, Geom.Trn.NBasis, 0.0);
12891 0 : Geom.ARhoVisOverlap.dimension(Window.NBkSurf, Geom.Trn.NBasis, 0.0);
12892 0 : Geom.AveRhoVisOverlap.dimension(Geom.Trn.NBasis, 0.0);
12893 :
12894 : // First to calculate and store coordinates of the window surface
12895 0 : state.dataSolarShading->LOCHCA = 1;
12896 0 : int BaseSurf = s_surf->Surface(ISurf).BaseSurf; // Base surface number
12897 :
12898 : // Base surface contains current window surface (ISurf).
12899 : // Since that is case, below transformation should always return ZVT = 0.0
12900 : // for every possible transformation
12901 0 : CTRANS(state, ISurf, BaseSurf, NVT, state.dataSolarShading->XVertex, state.dataSolarShading->YVertex, state.dataSolarShading->ZVertex);
12902 :
12903 : // HTRANS routine is using coordinates stored in XVS and YVS in order to calculate
12904 : // surface area. Since both projections are equal to zero, then simply
12905 : // copy these values into XVS and YVS arrays
12906 0 : for (N = 1; N <= NVT; ++N) {
12907 0 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVertex(N);
12908 0 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVertex(N);
12909 : }
12910 :
12911 : // This calculates the area stored in XVS and YVS
12912 0 : HTRANS1(state, state.dataSolarShading->LOCHCA, NVT);
12913 :
12914 : // Calculation of overlap areas for each outgoing basis direction
12915 0 : for (IRay = 1; IRay <= Geom.Trn.NBasis; ++IRay) { // basis directions loop (on back surface)
12916 : // For current basis direction calculate dot product between window surface
12917 : // and basis direction. This will be used to calculate projection of each
12918 : // of the back surfaces to window surface for given basis direction
12919 0 : SdotX = dot(s_surf->Surface(ISurf).lcsx, Geom.sTrn(IRay));
12920 0 : SdotY = dot(s_surf->Surface(ISurf).lcsy, Geom.sTrn(IRay));
12921 0 : SdotZ = dot(s_surf->Surface(ISurf).lcsz, Geom.sTrn(IRay));
12922 0 : XSp = -SdotX;
12923 0 : YSp = -SdotY;
12924 0 : ZSp = -SdotZ;
12925 :
12926 : // Projection of shadows for current basis direction
12927 0 : if (std::abs(ZSp) > Constant::SmallDistance) {
12928 0 : XShadowProjection = XSp / ZSp;
12929 0 : YShadowProjection = YSp / ZSp;
12930 0 : if (std::abs(XShadowProjection) < 1.e-8) {
12931 0 : XShadowProjection = 0.0;
12932 : }
12933 0 : if (std::abs(YShadowProjection) < 1.e-8) {
12934 0 : YShadowProjection = 0.0;
12935 : }
12936 : } else {
12937 0 : XShadowProjection = 0.0;
12938 0 : YShadowProjection = 0.0;
12939 : }
12940 :
12941 0 : for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
12942 : // BaseSurf = Surface(ISurf).BaseSurf
12943 0 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
12944 :
12945 : // Transform coordinates of back surface from general system to the
12946 : // plane of the receiving surface
12947 0 : CTRANS(state,
12948 : BackSurfaceNumber,
12949 : BaseSurf,
12950 : NVT,
12951 0 : state.dataSolarShading->XVertex,
12952 0 : state.dataSolarShading->YVertex,
12953 0 : state.dataSolarShading->ZVertex);
12954 :
12955 : // Project "shadow" from back surface along sun's rays to receiving surface. Back surface vertices
12956 : // become clockwise sequential.
12957 :
12958 0 : for (N = 1; N <= NVT; ++N) {
12959 0 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVertex(N) - YShadowProjection * state.dataSolarShading->ZVertex(N);
12960 0 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVertex(N) - XShadowProjection * state.dataSolarShading->ZVertex(N);
12961 : }
12962 :
12963 : // Transform to the homogeneous coordinate system.
12964 :
12965 0 : NS3 = state.dataSolarShading->LOCHCA + 1;
12966 0 : state.dataSolarShading->HCT(NS3) = 0.0;
12967 0 : HTRANS1(state, NS3, NVT);
12968 :
12969 : // Determine area of overlap of projected back surface and receiving surface.
12970 :
12971 0 : NS1 = 1;
12972 0 : NS2 = NS3;
12973 0 : state.dataSolarShading->HCT(NS3) = 1.0;
12974 0 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
12975 :
12976 0 : if (state.dataSolarShading->OverlapStatus == NoOverlap) {
12977 0 : continue; // to next back surface
12978 : }
12979 0 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
12980 0 : break; // back surfaces DO loop
12981 : }
12982 :
12983 0 : state.dataSolarShading->LOCHCA = NS3;
12984 0 : state.dataSolarShading->HCNS(state.dataSolarShading->LOCHCA) = BackSurfaceNumber;
12985 0 : state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
12986 :
12987 0 : Geom.AOverlap(KBkSurf, IRay) = state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
12988 : } // DO KBkSurf = 1 , NBkSurf
12989 :
12990 : // If some of back surfaces is contained in base surface, then need to subtract shadow of subsurface
12991 : // from shadow on base surface. Reason is that above shadowing algorithm is calculating shadow without
12992 : // influence of subsurfaces
12993 0 : for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
12994 0 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
12995 : // CurBaseSurf is Current base surface number for shadow overlap calculations
12996 0 : int CurBaseSurf = s_surf->Surface(BackSurfaceNumber).BaseSurf;
12997 0 : if (CurBaseSurf != BackSurfaceNumber) {
12998 : // Search if that base surface in list of back surfaces for current window
12999 : // CurBackSurface is Current back surface number for base surface
13000 0 : int CurBackSurface = 0;
13001 0 : for (N = 1; N <= Window.NBkSurf; ++N) {
13002 0 : if (state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(N) == CurBaseSurf) {
13003 0 : CurBackSurface = N;
13004 0 : break;
13005 : }
13006 : }
13007 0 : if (CurBackSurface != 0) {
13008 0 : Geom.AOverlap(CurBackSurface, IRay) -= Geom.AOverlap(KBkSurf, IRay);
13009 : }
13010 : }
13011 : }
13012 :
13013 0 : auto &s_mat = state.dataMaterial;
13014 :
13015 : // Calculate overlap area times reflectance. This is necessary for complex fenestration daylighting
13016 : // calculations
13017 0 : TotAOverlap = 0.0;
13018 0 : TotARhoVisOverlap = 0.0;
13019 0 : for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
13020 0 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
13021 0 : IConst = s_surf->Surface(BackSurfaceNumber).Construction;
13022 0 : InsideConLay = state.dataConstruction->Construct(IConst).TotLayers;
13023 0 : if (s_surf->SurfWinWindowModelType(BackSurfaceNumber) == WindowModel::BSDF) {
13024 0 : VisibleReflectance = state.dataConstruction->Construct(IConst).ReflectVisDiffBack;
13025 : } else {
13026 0 : VisibleReflectance = (1.0 - s_mat->materials(InsideConLay)->AbsorpVisible);
13027 : }
13028 0 : Geom.ARhoVisOverlap(KBkSurf, IRay) = Geom.AOverlap(KBkSurf, IRay) * VisibleReflectance;
13029 0 : TotAOverlap += Geom.AOverlap(KBkSurf, IRay);
13030 0 : TotARhoVisOverlap += Geom.ARhoVisOverlap(KBkSurf, IRay);
13031 : }
13032 :
13033 0 : if (TotAOverlap != 0.0) {
13034 0 : Geom.AveRhoVisOverlap(IRay) = TotARhoVisOverlap / TotAOverlap;
13035 : }
13036 :
13037 : } // DO IRay = 1, Geom%Trn%NBasis
13038 :
13039 : // Reset back shadowing counter since complex windows do not need it anymore
13040 0 : state.dataSolarShading->LOCHCA = 1;
13041 0 : }
13042 :
13043 249956 : void TimestepInitComplexFenestration(EnergyPlusData &state)
13044 : {
13045 : // SUBROUTINE INFORMATION:
13046 : // AUTHOR Simon Vidanovic
13047 : // DATE WRITTEN May 2012
13048 : // MODIFIED May 2012 (Initialize complex fenestration in case of EMS)
13049 : // RE-ENGINEERED na
13050 :
13051 : // PURPOSE OF THIS SUBROUTINE:
13052 : // Performs initialization of complex fenestration. It also performs check if current surface containing
13053 : // complex fenestration have construction changed (by EMS) in which case performs addition of current states
13054 : // into complex fenestration array
13055 :
13056 : using WindowComplexManager::CheckCFSStates;
13057 :
13058 : // Locals
13059 : int iSurf; // Current surface number
13060 : int iState; // current state number
13061 : int NumOfStates; // number of states for current window
13062 :
13063 249956 : auto &s_surf = state.dataSurface;
13064 :
13065 2353940 : for (iSurf = 1; iSurf <= s_surf->TotSurfaces; ++iSurf) {
13066 2103984 : if (s_surf->SurfWinWindowModelType(iSurf) == WindowModel::BSDF) {
13067 : // This will check complex fenestrations state and add new one if necessary (EMS case)
13068 0 : CheckCFSStates(state, iSurf);
13069 :
13070 0 : NumOfStates = state.dataBSDFWindow->ComplexWind(iSurf).NumStates;
13071 :
13072 : // Check for overlap areas and initialize if necessary
13073 0 : for (iState = 1; iState <= NumOfStates; ++iState) {
13074 : // do initialization only once
13075 0 : if (state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState).InitState) {
13076 0 : CalcComplexWindowOverlap(
13077 0 : state, state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState), state.dataBSDFWindow->ComplexWind(iSurf), iSurf);
13078 0 : state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState).InitState = false;
13079 : }
13080 : }
13081 : }
13082 : }
13083 249956 : }
13084 :
13085 : } // namespace EnergyPlus::SolarShading
|