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) DisplayString(state, "Allocate Solar Module Arrays");
207 114 : AllocateModuleArrays(state);
208 :
209 114 : if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::FullInteriorExterior) {
210 104 : if (state.dataSolarShading->firstTime) DisplayString(state, "Computing Interior Solar Absorption Factors");
211 104 : ComputeIntSolarAbsorpFactors(state);
212 : }
213 :
214 114 : if (state.dataSolarShading->firstTime) DisplayString(state, "Determining Shadowing Combinations");
215 114 : DetermineShadowingCombinations(state);
216 114 : state.dataSolarShading->shd_stream.reset(); // Done writing to shd file
217 :
218 114 : if (state.dataSolarShading->firstTime) DisplayString(state, "Computing Window Shade Absorption Factors");
219 114 : ComputeWinShadeAbsorpFactors(state);
220 :
221 114 : if (s_surf->CalcSolRefl) {
222 0 : DisplayString(state, "Initializing Solar Reflection Factors");
223 0 : InitSolReflRecSurf(state);
224 : }
225 :
226 114 : if (state.dataSolarShading->firstTime) DisplayString(state, "Proceeding with Initializing Solar Calculations");
227 : }
228 :
229 119 : if (state.dataGlobal->BeginEnvrnFlag) {
230 107 : state.dataSolarShading->SurfSunCosTheta = 0.0;
231 107 : state.dataSolarShading->SurfSunlitArea = 0.0;
232 107 : s_surf->SurfSunlitArea = 0.0;
233 107 : s_surf->SurfSunlitFrac = 0.0;
234 107 : state.dataHeatBal->SurfSunlitFracHR = 0.0;
235 107 : state.dataHeatBal->SurfSunlitFrac = 0.0;
236 107 : state.dataHeatBal->SurfSunlitFracWithoutReveal = 0.0;
237 107 : state.dataHeatBal->SurfWinBackSurfaces = 0;
238 107 : state.dataHeatBal->SurfWinOverlapAreas = 0.0;
239 107 : state.dataHeatBal->SurfCosIncAngHR = 0.0;
240 107 : state.dataHeatBal->SurfCosIncAng = 0.0;
241 107 : state.dataSolarShading->SurfAnisoSkyMult = 1.0; // For isotropic sky; recalculated in AnisoSkyViewFactors if anisotropic radiance
242 : // WithShdgIsoSky=0.0
243 : // WoShdgIsoSky=0.0
244 : // WithShdgHoriz=0.0
245 : // WoShdgHoriz=0.0
246 : // DifShdgRatioIsoSky=0.0
247 : // DifShdgRatioHoriz=0.0
248 107 : state.dataSolarShading->SurfMultIsoSky = 0.0;
249 107 : state.dataSolarShading->SurfMultCircumSolar = 0.0;
250 107 : state.dataSolarShading->SurfMultHorizonZenith = 0.0;
251 107 : state.dataSolarShading->SurfWinRevealStatus = 0;
252 :
253 234 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
254 127 : state.dataHeatBal->ZoneWinHeatGain(zoneNum) = 0.0;
255 127 : state.dataHeatBal->ZoneWinHeatGainRep(zoneNum) = 0.0;
256 127 : state.dataHeatBal->ZoneWinHeatLossRep(zoneNum) = 0.0;
257 127 : state.dataHeatBal->ZoneWinHeatGainRepEnergy(zoneNum) = 0.0;
258 127 : state.dataHeatBal->ZoneWinHeatLossRepEnergy(zoneNum) = 0.0;
259 127 : state.dataHeatBal->ZoneOpaqSurfInsFaceCond(zoneNum) = 0.0;
260 127 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep(zoneNum) = 0.0;
261 127 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep(zoneNum) = 0.0;
262 127 : state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg(zoneNum) = 0.0;
263 127 : state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg(zoneNum) = 0.0;
264 : }
265 243 : for (int enclNum = 1; enclNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclNum) {
266 136 : state.dataHeatBal->ZoneTransSolar(enclNum) = 0.0;
267 136 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclNum) = 0.0;
268 136 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclNum) = 0.0;
269 136 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclNum) = 0.0;
270 136 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclNum) = 0.0;
271 136 : state.dataHeatBal->ZoneDifSolFrIntWinsRep(enclNum) = 0.0;
272 136 : state.dataHeatBal->ZoneTransSolarEnergy(enclNum) = 0.0;
273 136 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclNum) = 0.0;
274 136 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclNum) = 0.0;
275 136 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclNum) = 0.0;
276 136 : state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy(enclNum) = 0.0;
277 : }
278 878 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
279 771 : state.dataHeatBal->SurfQRadSWOutIncident(SurfNum) = 0.0;
280 771 : state.dataHeatBal->SurfQRadSWOutIncidentBeam(SurfNum) = 0.0;
281 771 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = 0.0;
282 771 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) = 0.0;
283 771 : state.dataHeatBal->SurfIntBmIncInsSurfIntensRep(SurfNum) = 0.0;
284 771 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRep(SurfNum) = 0.0;
285 771 : state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse(SurfNum) = 0.0;
286 771 : state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse(SurfNum) = 0.0;
287 771 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd(SurfNum) = 0.0;
288 771 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd(SurfNum) = 0.0;
289 771 : state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs(SurfNum) = 0.0;
290 771 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs(SurfNum) = 0.0;
291 771 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs(SurfNum) = 0.0;
292 771 : state.dataHeatBal->SurfCosIncidenceAngle(SurfNum) = 0.0;
293 771 : state.dataHeatBal->SurfSWInAbsTotalReport(SurfNum) = 0.0;
294 771 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) = 0.0;
295 771 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy(SurfNum) = 0.0;
296 771 : state.dataHeatBal->SurfInitialDifSolInAbsReport(SurfNum) = 0.0;
297 : }
298 234 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
299 272 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
300 145 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
301 145 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
302 145 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
303 191 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
304 :
305 46 : s_surf->SurfWinTransSolar(SurfNum) = 0.0;
306 46 : s_surf->SurfWinBmSolar(SurfNum) = 0.0;
307 46 : s_surf->SurfWinBmBmSolar(SurfNum) = 0.0;
308 46 : s_surf->SurfWinBmDifSolar(SurfNum) = 0.0;
309 46 : s_surf->SurfWinDifSolar(SurfNum) = 0.0;
310 :
311 46 : s_surf->SurfWinTransSolarEnergy(SurfNum) = 0.0;
312 46 : s_surf->SurfWinBmSolarEnergy(SurfNum) = 0.0;
313 46 : s_surf->SurfWinBmBmSolarEnergy(SurfNum) = 0.0;
314 46 : s_surf->SurfWinBmDifSolarEnergy(SurfNum) = 0.0;
315 :
316 46 : s_surf->SurfWinHeatGain(SurfNum) = 0.0;
317 46 : s_surf->SurfWinHeatGainRep(SurfNum) = 0.0;
318 46 : s_surf->SurfWinHeatLossRep(SurfNum) = 0.0;
319 : }
320 191 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
321 46 : s_surf->SurfWinGainConvGlazToZoneRep(SurfNum) = 0.0;
322 46 : s_surf->SurfWinGainIRGlazToZoneRep(SurfNum) = 0.0;
323 46 : s_surf->SurfWinLossSWZoneToOutWinRep(SurfNum) = 0.0;
324 46 : s_surf->SurfWinGainFrameDividerToZoneRep(SurfNum) = 0.0;
325 46 : s_surf->SurfWinGainConvShadeToZoneRep(SurfNum) = 0.0;
326 46 : s_surf->SurfWinGainIRShadeToZoneRep(SurfNum) = 0.0;
327 46 : s_surf->SurfWinGapConvHtFlowRep(SurfNum) = 0.0;
328 46 : s_surf->SurfWinShadingAbsorbedSolar(SurfNum) = 0.0;
329 :
330 46 : s_surf->SurfWinSysSolTransmittance(SurfNum) = 0.0;
331 46 : s_surf->SurfWinSysSolReflectance(SurfNum) = 0.0;
332 46 : s_surf->SurfWinSysSolAbsorptance(SurfNum) = 0.0;
333 : }
334 191 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
335 46 : s_surf->SurfWinDifSolarEnergy(SurfNum) = 0.0;
336 46 : s_surf->SurfWinHeatGainRepEnergy(SurfNum) = 0.0;
337 46 : s_surf->SurfWinHeatLossRepEnergy(SurfNum) = 0.0;
338 46 : s_surf->SurfWinGapConvHtFlowRepEnergy(SurfNum) = 0.0;
339 46 : s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfNum) = 0.0;
340 :
341 46 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfNum) = 0.0;
342 46 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfNum) = 0.0;
343 46 : state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfNum) = 0.0;
344 46 : state.dataHeatBal->SurfWinInitialDifSolInTransReport(SurfNum) = 0.0;
345 :
346 46 : s_surf->SurfWinInsideGlassCondensationFlag(SurfNum) = 0;
347 46 : s_surf->SurfWinInsideFrameCondensationFlag(SurfNum) = 0;
348 46 : s_surf->SurfWinInsideDividerCondensationFlag(SurfNum) = 0;
349 : }
350 : }
351 : }
352 : }
353 :
354 : // Initialize these once
355 833 : for (int IPhi = 1; IPhi <= NPhi; ++IPhi) { // Loop over patch altitude values
356 714 : Real64 Phi = PhiMin + (IPhi - 1) * DPhi; // 7.5,22.5,37.5,52.5,67.5,82.5 for NPhi = 6
357 714 : state.dataSolarShading->sin_Phi.push_back(std::sin(Phi));
358 714 : state.dataSolarShading->cos_Phi.push_back(std::cos(Phi));
359 : }
360 :
361 2975 : for (int ITheta = 1; ITheta <= NTheta; ++ITheta) { // Loop over patch azimuth values
362 2856 : Real64 Theta = (ITheta - 1) * DTheta; // 0,15,30,....,330,345 for NTheta = 24
363 2856 : state.dataSolarShading->sin_Theta.push_back(std::sin(Theta));
364 2856 : state.dataSolarShading->cos_Theta.push_back(std::cos(Theta));
365 : }
366 :
367 119 : state.dataSolarShading->firstTime = false;
368 119 : }
369 :
370 112 : void checkShadingSurfaceSchedules(EnergyPlusData &state)
371 : {
372 112 : auto &s_surf = state.dataSurface;
373 :
374 : // Shading surfaces with a transmittance schedule that is always 1.0 are marked IsTransparent during shading surface input processing
375 : // Now that EMS (and other types) actuators are set up, check to see if the schedule has an actuator and reset if needed
376 158 : for (int surfNum = s_surf->ShadingSurfaceFirst; surfNum <= s_surf->ShadingSurfaceLast; ++surfNum) {
377 46 : auto &thisSurface = s_surf->Surface(surfNum);
378 46 : if (!thisSurface.IsTransparent) continue;
379 : // creating some dummy bools here on purpose -- we need to do some renaming and/or consolidate these into a meaningful new global sometime
380 : // for now I want the logic to be as readable as possible, so creating shorthand variables makes it very clear
381 4 : bool const anyPlugins = size(state.dataPluginManager->plugins) > 0;
382 4 : bool const runningByAPI = state.dataGlobal->eplusRunningViaAPI;
383 4 : bool const anyEMS = state.dataGlobal->AnyEnergyManagementSystemInModel;
384 4 : if ((anyEMS && EMSManager::isScheduleManaged(state, thisSurface.shadowSurfSched)) || runningByAPI || anyPlugins) {
385 : // Transmittance schedule definitely has an actuator or may have one via python plugin or API
386 : // Set not transparent so it won't be skipped during shading calcs
387 0 : thisSurface.IsTransparent = false;
388 : // Also set global flags
389 0 : state.dataSolarShading->anyScheduledShadingSurface = true;
390 0 : s_surf->ShadingTransmittanceVaries = true;
391 4 : } else if (!thisSurface.MirroredSurf) {
392 : // Warning moved here from shading surface input processing (skip warning for mirrored surfaces)
393 4 : ShowWarningError(state,
394 4 : format(R"(Shading Surface="{}", Transmittance Schedule Name="{}", is always transparent.)",
395 2 : thisSurface.Name,
396 2 : thisSurface.shadowSurfSched->Name));
397 6 : ShowContinueError(state, "This shading surface will be ignored.");
398 : }
399 : }
400 112 : }
401 :
402 134 : void GetShadowingInput(EnergyPlusData &state)
403 : {
404 : // SUBROUTINE INFORMATION:
405 : // AUTHOR Linda K. Lawrie
406 : // DATE WRITTEN July 1999
407 : // MODIFIED B. Griffith, Nov 2012, add calculation method
408 :
409 : // PURPOSE OF THIS SUBROUTINE:
410 : // This subroutine gets the Shadowing Calculation object.
411 :
412 134 : auto &s_surf = state.dataSurface;
413 :
414 : // Using/Aliasing
415 : using DataSystemVariables::ShadingMethod;
416 :
417 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
418 : int NumItems;
419 : int NumNumbers;
420 : int NumAlphas;
421 : int IOStat;
422 134 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
423 134 : state.dataIPShortCut->rNumericArgs({1, 4}) = 0.0; // so if nothing gotten, defaults will be maintained.
424 134 : state.dataIPShortCut->cAlphaArgs(1) = "";
425 134 : state.dataIPShortCut->cAlphaArgs(2) = "";
426 134 : cCurrentModuleObject = "ShadowCalculation";
427 134 : NumItems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
428 134 : NumAlphas = 0;
429 134 : NumNumbers = 0;
430 134 : if (NumItems > 1) {
431 0 : ShowWarningError(state, format("{}: More than 1 occurrence of this object found, only first will be used.", cCurrentModuleObject));
432 : }
433 :
434 134 : if (NumItems != 0) {
435 46 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
436 : cCurrentModuleObject,
437 : 1,
438 23 : state.dataIPShortCut->cAlphaArgs,
439 : NumAlphas,
440 23 : state.dataIPShortCut->rNumericArgs,
441 : NumNumbers,
442 : IOStat,
443 23 : state.dataIPShortCut->lNumericFieldBlanks,
444 23 : state.dataIPShortCut->lAlphaFieldBlanks,
445 23 : state.dataIPShortCut->cAlphaFieldNames,
446 23 : state.dataIPShortCut->cNumericFieldNames);
447 23 : state.dataSolarShading->ShadowingCalcFrequency = state.dataIPShortCut->rNumericArgs(1);
448 : }
449 :
450 134 : if (state.dataSolarShading->ShadowingCalcFrequency <= 0) {
451 : // Set to default value
452 111 : state.dataSolarShading->ShadowingCalcFrequency = 20;
453 : }
454 134 : if (state.dataSolarShading->ShadowingCalcFrequency > 31) {
455 1 : ShowWarningError(state, format("{}: suspect {}", cCurrentModuleObject, state.dataIPShortCut->cNumericFieldNames(1)));
456 1 : ShowContinueError(state, format("Value entered=[{:.0R}], Shadowing Calculations will be inaccurate.", state.dataIPShortCut->rNumericArgs(1)));
457 : }
458 :
459 134 : if (state.dataIPShortCut->rNumericArgs(2) > 199.0) {
460 23 : state.dataSolarShading->MaxHCS = state.dataIPShortCut->rNumericArgs(2);
461 : } else {
462 111 : state.dataSolarShading->MaxHCS = 15000;
463 : }
464 :
465 134 : int aNum = 1;
466 134 : unsigned pixelRes = 512u;
467 134 : if (NumAlphas >= aNum) {
468 23 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Scheduled")) {
469 0 : state.dataSysVars->shadingMethod = ShadingMethod::Scheduled;
470 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "Scheduled";
471 0 : checkScheduledSurfacePresent(state);
472 23 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Imported")) {
473 0 : if (state.dataSched->ScheduleFileShadingProcessed) {
474 0 : state.dataSysVars->shadingMethod = ShadingMethod::Imported;
475 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "Imported";
476 : } else {
477 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
478 0 : ShowContinueError(state,
479 0 : format("Value entered=\"{}\" while no Schedule:File:Shading object is defined, InternalCalculation will be used.",
480 0 : state.dataIPShortCut->cAlphaArgs(aNum)));
481 : }
482 23 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "PolygonClipping")) {
483 19 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
484 19 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
485 4 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "PixelCounting")) {
486 4 : state.dataSysVars->shadingMethod = ShadingMethod::PixelCounting;
487 4 : state.dataIPShortCut->cAlphaArgs(aNum) = "PixelCounting";
488 4 : if (NumNumbers >= 3) {
489 4 : pixelRes = (unsigned)state.dataIPShortCut->rNumericArgs(3);
490 : }
491 : #ifdef EP_NO_OPENGL
492 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
493 : ShowContinueError(state, format("Value entered=\"{}\"", state.dataIPShortCut->cAlphaArgs(aNum)));
494 : ShowContinueError(state, "This version of EnergyPlus was not compiled to use OpenGL (required for PixelCounting)");
495 : ShowContinueError(state, "PolygonClipping will be used instead");
496 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
497 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
498 : #else
499 4 : if (Penumbra::Penumbra::is_valid_context()) {
500 4 : std::shared_ptr<EnergyPlusLogger> penumbra_logger = std::make_shared<EnergyPlusLogger>(EnergyPlusLogger::Log_level::Info);
501 4 : state.dataSolarShading->LoggerContext = std::make_pair<EnergyPlusData *, std::string>(&state, "");
502 4 : penumbra_logger->set_message_context(&state.dataSolarShading->LoggerContext);
503 4 : state.dataSolarShading->penumbra = std::make_unique<Penumbra::Penumbra>(pixelRes, penumbra_logger);
504 4 : } else {
505 0 : ShowWarningError(state, "No GPU found (required for PixelCounting)");
506 0 : ShowContinueError(state, "PolygonClipping will be used instead");
507 0 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
508 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
509 : }
510 : #endif
511 : } else {
512 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
513 0 : ShowContinueError(state, format("Value entered=\"{}\", PolygonClipping will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
514 : }
515 : } else {
516 111 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
517 111 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
518 : }
519 :
520 134 : aNum++;
521 134 : if (NumAlphas >= aNum) {
522 23 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Periodic")) {
523 14 : state.dataSysVars->DetailedSolarTimestepIntegration = false;
524 14 : state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
525 9 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Timestep")) {
526 9 : state.dataSysVars->DetailedSolarTimestepIntegration = true;
527 9 : state.dataIPShortCut->cAlphaArgs(aNum) = "Timestep";
528 : } else {
529 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
530 0 : ShowContinueError(state, format("Value entered=\"{}\", Periodic will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
531 0 : state.dataSysVars->DetailedSolarTimestepIntegration = false;
532 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
533 : }
534 : } else {
535 111 : state.dataSysVars->DetailedSolarTimestepIntegration = false;
536 111 : state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
537 : }
538 :
539 134 : aNum++;
540 134 : if (NumAlphas >= aNum) {
541 13 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SutherlandHodgman")) {
542 9 : state.dataSysVars->SutherlandHodgman = true;
543 9 : state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
544 4 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "ConvexWeilerAtherton")) {
545 2 : state.dataSysVars->SutherlandHodgman = false;
546 2 : state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
547 2 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SlaterBarskyandSutherlandHodgman")) {
548 2 : state.dataSysVars->SutherlandHodgman = true;
549 2 : state.dataSysVars->SlaterBarsky = true;
550 2 : state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
551 0 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(aNum)) {
552 0 : if (!state.dataSysVars->SutherlandHodgman) { // if already set.
553 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
554 : } else {
555 0 : if (!state.dataSysVars->SlaterBarsky) {
556 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
557 : } else {
558 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
559 : }
560 : }
561 : } else {
562 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
563 0 : if (!state.dataSysVars->SutherlandHodgman) {
564 0 : ShowContinueError(state, format("Value entered=\"{}\", ConvexWeilerAtherton will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
565 : } else {
566 0 : if (!state.dataSysVars->SlaterBarsky) {
567 0 : ShowContinueError(state, format("Value entered=\"{}\", SutherlandHodgman will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
568 : } else {
569 0 : ShowContinueError(
570 : state,
571 0 : format("Value entered=\"{}\", SlaterBarskyandSutherlandHodgman will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
572 : }
573 : }
574 : }
575 : } else {
576 121 : if (!state.dataSysVars->SutherlandHodgman) {
577 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
578 : } else {
579 121 : if (!state.dataSysVars->SlaterBarsky) {
580 121 : state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
581 : } else {
582 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
583 : }
584 : }
585 : }
586 :
587 134 : aNum++;
588 134 : if (NumAlphas >= aNum) {
589 13 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SimpleSkyDiffuseModeling")) {
590 5 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
591 5 : state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
592 8 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "DetailedSkyDiffuseModeling")) {
593 8 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = true;
594 8 : state.dataIPShortCut->cAlphaArgs(aNum) = "DetailedSkyDiffuseModeling";
595 0 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
596 0 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
597 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
598 : } else {
599 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
600 0 : ShowContinueError(state, format("Value entered=\"{}\", SimpleSkyDiffuseModeling will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
601 : }
602 : } else {
603 121 : state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
604 121 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
605 : }
606 :
607 134 : aNum++;
608 134 : if (NumAlphas >= aNum) {
609 2 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
610 0 : state.dataSysVars->ReportExtShadingSunlitFrac = true;
611 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
612 2 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
613 2 : state.dataSysVars->ReportExtShadingSunlitFrac = false;
614 2 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
615 : } else {
616 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
617 0 : ShowContinueError(state, format("Value entered=\"{}\", InternalCalculation will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
618 : }
619 : } else {
620 132 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
621 132 : state.dataSysVars->ReportExtShadingSunlitFrac = false;
622 : }
623 :
624 134 : aNum++;
625 134 : if (NumAlphas >= aNum) {
626 2 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
627 1 : state.dataSysVars->DisableSelfShadingWithinGroup = true;
628 1 : state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
629 1 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
630 1 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
631 : } else {
632 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
633 0 : ShowContinueError(state,
634 0 : format("Value entered=\"{}\", all shading effects would be considered.", state.dataIPShortCut->cAlphaArgs(aNum)));
635 : }
636 : } else {
637 132 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
638 : }
639 :
640 134 : aNum++;
641 134 : if (NumAlphas >= aNum) {
642 2 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
643 0 : state.dataSysVars->DisableSelfShadingBetweenGroup = true;
644 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
645 2 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
646 2 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
647 : } else {
648 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
649 0 : ShowContinueError(state,
650 0 : format("Value entered=\"{}\", all shading effects would be considered.", state.dataIPShortCut->cAlphaArgs(aNum)));
651 : }
652 : } else {
653 132 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
654 : }
655 :
656 134 : if (state.dataSysVars->DisableSelfShadingBetweenGroup && state.dataSysVars->DisableSelfShadingWithinGroup) {
657 0 : state.dataSysVars->DisableAllSelfShading = true;
658 134 : } else if (state.dataSysVars->DisableSelfShadingBetweenGroup || state.dataSysVars->DisableSelfShadingWithinGroup) {
659 1 : state.dataSysVars->DisableGroupSelfShading = true;
660 : }
661 :
662 134 : aNum++;
663 134 : state.dataSysVars->shadingGroupsNum = NumAlphas - (aNum - 1);
664 134 : state.dataSysVars->shadingGroupZoneListNames.allocate(state.dataSysVars->shadingGroupsNum);
665 135 : for (int numZone = 1; numZone <= state.dataSysVars->shadingGroupsNum; ++numZone) {
666 1 : state.dataSysVars->shadingGroupZoneListNames(numZone) = state.dataIPShortCut->cAlphaArgs(aNum - 1 + numZone);
667 : }
668 :
669 134 : if (!state.dataSysVars->DetailedSolarTimestepIntegration && s_surf->ShadingTransmittanceVaries &&
670 0 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
671 :
672 0 : ShowWarningError(state, "GetShadowingInput: The shading transmittance for shading devices may change throughout the year.");
673 0 : ShowContinueError(state,
674 0 : format("Choose Shading Calculation Update Frequency Method = Timestep in the {} object to capture all shading impacts.",
675 : cCurrentModuleObject));
676 : }
677 134 : if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
678 0 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
679 :
680 0 : ShowWarningError(state, "GetShadowingInput: The shading transmittance for shading devices may change throughout the year.");
681 0 : ShowContinueError(state, "Simulation has been reset to use DetailedSkyDiffuseModeling. Simulation continues.");
682 0 : ShowContinueError(state, format("Choose DetailedSkyDiffuseModeling in the {} object to remove this warning.", cCurrentModuleObject));
683 0 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = true;
684 0 : state.dataIPShortCut->cAlphaArgs(2) = "DetailedSkyDiffuseModeling";
685 0 : if (!state.dataSysVars->DetailedSolarTimestepIntegration && state.dataSolarShading->ShadowingCalcFrequency > 1) {
686 0 : ShowContinueError(state,
687 0 : format("Better accuracy may be gained by setting the {} to 1 in the {} object.",
688 0 : state.dataIPShortCut->cNumericFieldNames(1),
689 : cCurrentModuleObject));
690 : }
691 134 : } else if (state.dataSysVars->DetailedSkyDiffuseAlgorithm) {
692 8 : if (!s_surf->ShadingTransmittanceVaries || state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
693 16 : ShowWarningError(state,
694 : "GetShadowingInput: DetailedSkyDiffuseModeling is chosen but not needed as either the shading transmittance for "
695 : "shading devices does not change throughout the year");
696 16 : ShowContinueError(state, " or MinimalShadowing has been chosen.");
697 16 : ShowContinueError(state, "Simulation should be set to use SimpleSkyDiffuseModeling, but is left at Detailed for simulation.");
698 8 : ShowContinueError(state, format("Choose SimpleSkyDiffuseModeling in the {} object to reduce computation time.", cCurrentModuleObject));
699 : }
700 : }
701 :
702 134 : print(state.files.eio,
703 : "{}",
704 : "! <Shadowing/Sun Position Calculations Annual Simulations>, Shading Calculation Method, "
705 : "Shading Calculation Update Frequency Method, Shading Calculation Update Frequency {days}, "
706 : "Maximum Figures in Shadow Overlap Calculations {}, Polygon Clipping Algorithm, Pixel Counting Resolution, Sky Diffuse Modeling "
707 : "Algorithm, Output External Shading Calculation Results, Disable "
708 : "Self-Shading Within Shading Zone Groups, Disable Self-Shading From Shading Zone Groups to Other Zones\n");
709 938 : print(state.files.eio,
710 : "Shadowing/Sun Position Calculations Annual Simulations,{},{},{},{},{},{},{},{},{},{}\n",
711 134 : state.dataIPShortCut->cAlphaArgs(1),
712 134 : state.dataIPShortCut->cAlphaArgs(2),
713 134 : state.dataSolarShading->ShadowingCalcFrequency,
714 134 : state.dataSolarShading->MaxHCS,
715 134 : state.dataIPShortCut->cAlphaArgs(3),
716 : pixelRes,
717 134 : state.dataIPShortCut->cAlphaArgs(4),
718 134 : state.dataIPShortCut->cAlphaArgs(5),
719 134 : state.dataIPShortCut->cAlphaArgs(6),
720 134 : state.dataIPShortCut->cAlphaArgs(7));
721 134 : }
722 :
723 114 : void processShadowingInput(EnergyPlusData &state)
724 : {
725 : // all shadow input processing that needed zones and surfaces to already be read into data (part of fix for Defect #10299)
726 :
727 115 : if ((state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::PixelCounting) &&
728 1 : state.dataSolarShading->anyScheduledShadingSurface) {
729 2 : ShowSevereError(state, "The Shading Calculation Method of choice is \"PixelCounting\"; ");
730 2 : ShowContinueError(state, "and there is at least one shading surface of type ");
731 2 : ShowContinueError(state, "Shading:Site:Detailed, Shading:Building:Detailed, or Shading:Zone:Detailed, ");
732 2 : ShowContinueError(state, "that has an active transmittance schedule value greater than zero or may vary.");
733 2 : ShowContinueError(state, "With \"PixelCounting\" Shading Calculation Method, the shading surfaces will be treated as ");
734 2 : ShowContinueError(state, "completely opaque (transmittance = 0) during the shading calculation, ");
735 2 : ShowContinueError(state, "which may result in inaccurate or unexpected results.");
736 3 : ShowContinueError(state, "It is suggested switching to another Shading Calculation Method, such as \"PolygonClipping\".");
737 : }
738 :
739 114 : if (state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::Imported) {
740 0 : for (auto &surf : state.dataSurface->Surface) {
741 0 : if ((surf.surfExternalShadingSched = Sched::GetSchedule(state, surf.Name + "_shading")) != nullptr) {
742 0 : surf.SurfSchedExternalShadingFrac = true;
743 : } else {
744 0 : ShowWarningError(state,
745 0 : format("processShadowingInput: sunlit fraction schedule not found for {} when using ImportedShading.", surf.Name));
746 0 : ShowContinueError(state, "These values are set to 1.0.");
747 : }
748 : }
749 : }
750 :
751 : int SurfZoneGroup, CurZoneGroup;
752 114 : int Found = 0;
753 114 : if (state.dataSysVars->DisableGroupSelfShading) {
754 1 : Array1D_int DisableSelfShadingGroups;
755 1 : int NumOfShadingGroups = state.dataSysVars->shadingGroupsNum;
756 1 : if (NumOfShadingGroups > 0) {
757 1 : DisableSelfShadingGroups.allocate(NumOfShadingGroups);
758 2 : for (int i = 1; i <= NumOfShadingGroups; i++) {
759 1 : Found = Util::FindItemInList(
760 1 : state.dataSysVars->shadingGroupZoneListNames(i), state.dataHeatBal->ZoneList, state.dataHeatBal->NumOfZoneLists);
761 1 : if (Found != 0) DisableSelfShadingGroups(i) = Found;
762 : }
763 :
764 10 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
765 9 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond == 0) { // Loop through all exterior surfaces
766 9 : SurfZoneGroup = 0;
767 : // Check the shading zone group of each exterior surface
768 18 : for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups
769 9 : CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop);
770 11 : for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones;
771 : ZoneNum++) { // Loop through all zones in the zone list
772 9 : if (state.dataSurface->Surface(SurfNum).Zone == state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum)) {
773 7 : SurfZoneGroup = CurZoneGroup;
774 7 : break;
775 : }
776 : }
777 : }
778 : // if a surface is not in any zone group, no self shading is disabled for this surface
779 9 : if (SurfZoneGroup != 0) {
780 : // if DisableSelfShadingWithinGroup, add all zones in the same zone group to the surface's disabled zone list
781 : // if DisableSelfShadingBetweenGroups, add all zones in all other zone groups to the surface's disabled zone list
782 14 : for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups
783 7 : CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop);
784 7 : if (SurfZoneGroup == CurZoneGroup && state.dataSysVars->DisableSelfShadingWithinGroup) {
785 14 : for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones;
786 : ZoneNum++) { // Loop through all zones in the zone list
787 7 : state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back(
788 7 : state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum));
789 : }
790 0 : } else if (SurfZoneGroup != CurZoneGroup && state.dataSysVars->DisableSelfShadingBetweenGroup) {
791 0 : for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones; ZoneNum++) {
792 0 : state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back(
793 0 : state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum));
794 : }
795 : }
796 : }
797 : }
798 : }
799 : }
800 : } else {
801 0 : ShowFatalError(state, "No Shading groups are defined when disabling grouped self shading.");
802 : }
803 1 : }
804 114 : }
805 :
806 1 : void checkScheduledSurfacePresent(EnergyPlusData &state)
807 : {
808 : // User has chosen "Scheduled" for sunlit fraction so check to see which surfaces don't have a schedule
809 1 : int numNotDef = 0;
810 1 : int constexpr maxErrMessages = 50;
811 1 : auto &surfData = state.dataSurface;
812 6 : for (int surfNum = 1; surfNum <= surfData->TotSurfaces; ++surfNum) {
813 5 : auto &thisSurf = surfData->Surface(surfNum);
814 5 : if ((thisSurf.Class == SurfaceClass::Shading || thisSurf.Class == SurfaceClass::Detached_F || thisSurf.Class == SurfaceClass::Detached_B ||
815 4 : thisSurf.Class == SurfaceClass::Overhang || thisSurf.Class == SurfaceClass::Fin))
816 2 : continue; // skip shading surfaces
817 3 : if (!thisSurf.SurfSchedExternalShadingFrac) {
818 1 : numNotDef += 1;
819 1 : if (numNotDef == 1) {
820 2 : ShowWarningError(
821 : state,
822 2 : format("ShadowCalculation specified Schedule for the Shading Calculation Method but no schedule provided for {}", thisSurf.Name));
823 2 : ShowContinueError(
824 : state, "When Schedule is selected for the Shading Calculation Method and no schedule is provided for a particular surface,");
825 2 : ShowContinueError(
826 : state, "EnergyPlus will assume that the surface is not shaded. Use SurfaceProperty:LocalEnvironment to specify a schedule");
827 3 : ShowContinueError(state, "for sunlit fraction if this was not desired. Otherwise, this surface will not be shaded at all.");
828 0 : } else if (numNotDef <= maxErrMessages) {
829 0 : ShowWarningError(state, format("No schedule was provided for {} either. See above error message for more details", thisSurf.Name));
830 : }
831 : }
832 : }
833 1 : if (numNotDef > maxErrMessages)
834 0 : ShowContinueError(state, format("This message is only shown for the first {} occurrences of this issue.", maxErrMessages));
835 1 : }
836 :
837 141 : void AllocateModuleArrays(EnergyPlusData &state)
838 : {
839 :
840 : // SUBROUTINE INFORMATION:
841 : // AUTHOR Rick Strand
842 : // DATE WRITTEN February 1998
843 : // MODIFIED August 2005 JG - Added output variables for energy in J
844 :
845 : // PURPOSE OF THIS SUBROUTINE:
846 : // This routine allocates all of the arrays at the module level which
847 : // require allocation.
848 :
849 : // METHODOLOGY EMPLOYED:
850 : // Allocation is dependent on the user input file.
851 :
852 : int I;
853 : int NumOfLayers;
854 :
855 141 : auto &s_surf = state.dataSurface;
856 :
857 141 : state.dataSolarShading->SurfSunCosTheta.dimension(s_surf->TotSurfaces, 0.0);
858 141 : state.dataSolarShading->SurfSunlitArea.dimension(s_surf->TotSurfaces, 0.0);
859 141 : if (!state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() || !state.dataWindowManager->winOpticalModel->isSimplifiedModel()) {
860 141 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac.allocate(s_surf->TotSurfaces);
861 141 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac.allocate(s_surf->TotSurfaces);
862 141 : state.dataSolarShading->SurfWinTransBmSolar.allocate(s_surf->TotSurfaces);
863 141 : state.dataSolarShading->SurfWinTransDifSolar.allocate(s_surf->TotSurfaces);
864 141 : state.dataSolarShading->SurfWinTransDifSolarGnd.allocate(s_surf->TotSurfaces);
865 141 : state.dataSolarShading->SurfWinTransDifSolarSky.allocate(s_surf->TotSurfaces);
866 141 : state.dataSolarShading->SurfWinTransBmBmSolar.allocate(s_surf->TotSurfaces);
867 141 : state.dataSolarShading->SurfWinTransBmDifSolar.allocate(s_surf->TotSurfaces);
868 : }
869 141 : state.dataSolarShading->SurfAnisoSkyMult.dimension(s_surf->TotSurfaces, 1.0);
870 141 : state.dataSolarShading->SurfIntAbsFac.dimension(s_surf->TotSurfaces, 0.0);
871 : // For isotropic sky: recalculated in AnisoSkyViewFactors if anisotropic radiance
872 : // ALLOCATE(WithShdgIsoSky(TotSurfaces))
873 : // WithShdgIsoSky=0.0
874 : // ALLOCATE(WoShdgIsoSky(TotSurfaces))
875 : // WoShdgIsoSky=0.0
876 : // ALLOCATE(WithShdgHoriz(TotSurfaces))
877 : // WithShdgHoriz=0.0
878 : // ALLOCATE(WoShdgHoriz(TotSurfaces))
879 : // WoShdgHoriz=0.0
880 : // ALLOCATE(DifShdgRatioIsoSky(TotSurfaces))
881 : // DifShdgRatioIsoSky=0.0
882 : // ALLOCATE(DifShdgRatioHoriz(TotSurfaces))
883 : // DifShdgRatioHoriz=0.0
884 141 : state.dataSolarShading->SurfMultIsoSky.dimension(s_surf->TotSurfaces, 0.0);
885 141 : state.dataSolarShading->SurfMultCircumSolar.dimension(s_surf->TotSurfaces, 0.0);
886 141 : state.dataSolarShading->SurfMultHorizonZenith.dimension(s_surf->TotSurfaces, 0.0);
887 141 : state.dataSolarShading->SurfWinRevealStatus.dimension(24, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0);
888 :
889 : // Weiler-Atherton
890 141 : state.dataSolarShading->MAXHCArrayBounds = 2 * (s_surf->MaxVerticesPerSurface + 1);
891 141 : state.dataSolarShading->MAXHCArrayIncrement = s_surf->MaxVerticesPerSurface + 1;
892 141 : state.dataSolarShading->XTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
893 141 : state.dataSolarShading->YTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
894 141 : state.dataSolarShading->XVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
895 141 : state.dataSolarShading->XVS.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
896 141 : state.dataSolarShading->YVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
897 141 : state.dataSolarShading->YVS.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
898 141 : state.dataSolarShading->ZVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
899 :
900 : // Sutherland-Hodgman
901 141 : state.dataSolarShading->ATEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
902 141 : state.dataSolarShading->BTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
903 141 : state.dataSolarShading->CTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
904 141 : state.dataSolarShading->XTEMP1.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
905 141 : state.dataSolarShading->YTEMP1.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
906 :
907 141 : s_surf->SurfSunCosHourly.allocate(Constant::iHoursInDay);
908 3525 : for (int hour = 1; hour <= Constant::iHoursInDay; hour++) {
909 3384 : s_surf->SurfSunCosHourly(hour) = 0.0;
910 : }
911 141 : s_surf->SurfSunlitArea.dimension(s_surf->TotSurfaces, 0.0);
912 141 : s_surf->SurfSunlitFrac.dimension(s_surf->TotSurfaces, 0.0);
913 141 : s_surf->SurfSkySolarInc.dimension(s_surf->TotSurfaces, 0);
914 141 : s_surf->SurfGndSolarInc.dimension(s_surf->TotSurfaces, 0);
915 141 : s_surf->SurfBmToBmReflFacObs.dimension(s_surf->TotSurfaces, 0.0);
916 141 : s_surf->SurfBmToDiffReflFacObs.dimension(s_surf->TotSurfaces, 0.0);
917 141 : s_surf->SurfBmToDiffReflFacGnd.dimension(s_surf->TotSurfaces, 0.0);
918 141 : s_surf->SurfSkyDiffReflFacGnd.dimension(s_surf->TotSurfaces, 0.0);
919 141 : s_surf->SurfOpaqAI.dimension(s_surf->TotSurfaces, 0.0);
920 141 : s_surf->SurfOpaqAO.dimension(s_surf->TotSurfaces, 0.0);
921 141 : s_surf->SurfWinTransSolar.dimension(s_surf->TotSurfaces, 0.0);
922 141 : s_surf->SurfWinBmSolar.dimension(s_surf->TotSurfaces, 0.0);
923 141 : s_surf->SurfWinBmBmSolar.dimension(s_surf->TotSurfaces, 0.0);
924 141 : s_surf->SurfWinBmDifSolar.dimension(s_surf->TotSurfaces, 0.0);
925 141 : s_surf->SurfWinDifSolar.dimension(s_surf->TotSurfaces, 0.0);
926 141 : s_surf->SurfWinHeatGain.dimension(s_surf->TotSurfaces, 0.0);
927 141 : s_surf->SurfWinHeatGainRep.dimension(s_surf->TotSurfaces, 0.0);
928 141 : s_surf->SurfWinHeatLossRep.dimension(s_surf->TotSurfaces, 0.0);
929 141 : s_surf->SurfWinGainConvGlazToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
930 141 : s_surf->SurfWinGainIRGlazToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
931 141 : s_surf->SurfWinLossSWZoneToOutWinRep.dimension(s_surf->TotSurfaces, 0.0);
932 141 : s_surf->SurfWinGainFrameDividerToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
933 141 : s_surf->SurfWinGainConvShadeToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
934 141 : s_surf->SurfWinGainIRShadeToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
935 141 : s_surf->SurfWinGapConvHtFlowRep.dimension(s_surf->TotSurfaces, 0.0);
936 141 : s_surf->SurfWinShadingAbsorbedSolar.dimension(s_surf->TotSurfaces, 0.0);
937 141 : s_surf->SurfWinSysSolTransmittance.dimension(s_surf->TotSurfaces, 0.0);
938 141 : s_surf->SurfWinSysSolReflectance.dimension(s_surf->TotSurfaces, 0.0);
939 141 : s_surf->SurfWinSysSolAbsorptance.dimension(s_surf->TotSurfaces, 0.0);
940 141 : s_surf->SurfWinInsideGlassCondensationFlag.dimension(s_surf->TotSurfaces, 0);
941 141 : s_surf->SurfWinInsideFrameCondensationFlag.dimension(s_surf->TotSurfaces, 0);
942 141 : s_surf->SurfWinInsideDividerCondensationFlag.dimension(s_surf->TotSurfaces, 0);
943 :
944 141 : state.dataHeatBal->SurfSunlitFracHR.dimension(Constant::iHoursInDay, s_surf->TotSurfaces, 0.0);
945 141 : state.dataHeatBal->SurfSunlitFrac.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
946 141 : state.dataHeatBal->SurfSunlitFracWithoutReveal.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
947 564 : state.dataHeatBal->SurfWinBackSurfaces.dimension(
948 423 : Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, state.dataBSDFWindow->MaxBkSurf, s_surf->TotSurfaces, 0);
949 564 : state.dataHeatBal->SurfWinOverlapAreas.dimension(
950 423 : Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, state.dataBSDFWindow->MaxBkSurf, s_surf->TotSurfaces, 0.0);
951 141 : state.dataHeatBal->SurfCosIncAngHR.dimension(Constant::iHoursInDay, s_surf->TotSurfaces, 0.0);
952 141 : state.dataHeatBal->SurfCosIncAng.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
953 :
954 141 : state.dataHeatBal->ZoneTransSolar.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
955 141 : state.dataHeatBal->ZoneBmSolFrExtWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
956 141 : state.dataHeatBal->ZoneBmSolFrIntWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
957 141 : state.dataHeatBal->EnclSolInitialDifSolReflW.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
958 141 : state.dataHeatBal->ZoneDifSolFrExtWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
959 141 : state.dataHeatBal->ZoneDifSolFrIntWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
960 141 : state.dataHeatBal->ZoneWinHeatGain.dimension(state.dataGlobal->NumOfZones, 0.0);
961 141 : state.dataHeatBal->ZoneWinHeatGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
962 141 : state.dataHeatBal->ZoneWinHeatLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
963 141 : state.dataHeatBal->ZoneOpaqSurfInsFaceCond.dimension(state.dataGlobal->NumOfZones, 0.0);
964 141 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
965 141 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
966 141 : state.dataHeatBal->ZoneOpaqSurfExtFaceCond.dimension(state.dataGlobal->NumOfZones, 0.0);
967 141 : state.dataHeatBal->ZoneOpaqSurfExtFaceCondGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
968 141 : state.dataHeatBal->ZoneOpaqSurfExtFaceCondLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
969 :
970 141 : state.dataHeatBal->SurfQRadSWOutIncident.dimension(s_surf->TotSurfaces, 0.0);
971 141 : state.dataHeatBal->SurfQRadSWOutIncidentBeam.dimension(s_surf->TotSurfaces, 0.0);
972 141 : state.dataHeatBal->SurfBmIncInsSurfIntensRep.dimension(s_surf->TotSurfaces, 0.0);
973 141 : state.dataHeatBal->SurfBmIncInsSurfAmountRep.dimension(s_surf->TotSurfaces, 0.0);
974 : // ALLOCATE(DifIncInsSurfIntensRep(TotSurfaces))
975 : // DifIncInsSurfIntensRep=0.0
976 : // ALLOCATE(DifIncInsSurfAmountRep(TotSurfaces))
977 : // DifIncInsSurfAmountRep=0.0
978 141 : state.dataHeatBal->SurfIntBmIncInsSurfIntensRep.dimension(s_surf->TotSurfaces, 0.0);
979 141 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRep.dimension(s_surf->TotSurfaces, 0.0);
980 : // ALLOCATE(IntDifIncInsSurfIntensRep(TotSurfaces))
981 : // IntDifIncInsSurfIntensRep=0.0
982 : // ALLOCATE(IntDifIncInsSurfAmountRep(TotSurfaces))
983 : // IntDifIncInsSurfAmountRep=0.0
984 141 : state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse.dimension(s_surf->TotSurfaces, 0.0);
985 141 : state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse.dimension(s_surf->TotSurfaces, 0.0);
986 141 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd.dimension(s_surf->TotSurfaces, 0.0);
987 141 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd.dimension(s_surf->TotSurfaces, 0.0);
988 141 : state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs.dimension(s_surf->TotSurfaces, 0.0);
989 141 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs.dimension(s_surf->TotSurfaces, 0.0);
990 141 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs.dimension(s_surf->TotSurfaces, 0.0);
991 141 : state.dataHeatBal->SurfCosIncidenceAngle.dimension(s_surf->TotSurfaces, 0.0);
992 :
993 141 : state.dataHeatBal->SurfWinBSDFBeamDirectionRep.dimension(s_surf->TotSurfaces, 0);
994 141 : state.dataHeatBal->SurfWinBSDFBeamThetaRep.dimension(s_surf->TotSurfaces, 0.0);
995 141 : state.dataHeatBal->SurfWinBSDFBeamPhiRep.dimension(s_surf->TotSurfaces, 0.0);
996 141 : state.dataHeatBal->SurfWinQRadSWwinAbsTot.dimension(s_surf->TotSurfaces, 0.0);
997 141 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
998 141 : state.dataHeatBal->SurfWinFenLaySurfTempFront.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
999 141 : state.dataHeatBal->SurfWinFenLaySurfTempBack.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
1000 :
1001 141 : state.dataHeatBal->SurfWinSWwinAbsTotalReport.dimension(s_surf->TotSurfaces, 0.0);
1002 141 : state.dataHeatBal->SurfInitialDifSolInAbsReport.dimension(s_surf->TotSurfaces, 0.0);
1003 141 : state.dataHeatBal->SurfWinInitialDifSolInTransReport.dimension(s_surf->TotSurfaces, 0.0);
1004 141 : state.dataHeatBal->SurfSWInAbsTotalReport.dimension(s_surf->TotSurfaces, 0.0);
1005 :
1006 : // energy
1007 141 : s_surf->SurfWinTransSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1008 141 : s_surf->SurfWinBmSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1009 141 : s_surf->SurfWinBmBmSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1010 141 : s_surf->SurfWinBmDifSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1011 :
1012 141 : s_surf->SurfWinDifSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1013 141 : s_surf->SurfWinHeatGainRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1014 141 : s_surf->SurfWinHeatLossRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1015 141 : s_surf->SurfWinGapConvHtFlowRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1016 141 : s_surf->SurfWinHeatTransferRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1017 141 : s_surf->SurfWinShadingAbsorbedSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
1018 :
1019 141 : state.dataHeatBal->ZoneTransSolarEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1020 141 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1021 141 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1022 141 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1023 141 : state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1024 141 : state.dataHeatBal->ZoneWinHeatGainRepEnergy.dimension(state.dataGlobal->NumOfZones, 0.0);
1025 141 : state.dataHeatBal->ZoneWinHeatLossRepEnergy.dimension(state.dataGlobal->NumOfZones, 0.0);
1026 :
1027 141 : state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1028 141 : state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1029 141 : state.dataHeatBal->ZnOpqSurfExtFaceCondGnRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1030 141 : state.dataHeatBal->ZnOpqSurfExtFaceCondLsRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1031 : // ALLOCATE(DifIncInsSurfAmountRepEnergy(TotSurfaces))
1032 : // DifIncInsSurfAmountRepEnergy=0.0
1033 141 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1034 141 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
1035 : // ALLOCATE(IntDifIncInsSurfAmountRepEnergy(TotSurfaces))
1036 : // IntDifIncInsSurfAmountRepEnergy=0.0
1037 141 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy.dimension(s_surf->TotSurfaces, 0.0);
1038 :
1039 1153 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; SurfNum++) {
1040 1012 : s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) = 0.0;
1041 1012 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) = 0.0;
1042 1012 : s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) = 0.0;
1043 1012 : s_surf->SurfWinBmSolRefldInsReveal(SurfNum) = 0.0;
1044 1012 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) = 0.0;
1045 1012 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) = 0.0;
1046 1012 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) = 0.0;
1047 1012 : s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) = 0.0;
1048 1012 : s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) = 0.0;
1049 1012 : s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) = 0.0;
1050 : }
1051 :
1052 : // Added report variables for inside reveal to debug CR 7596. TH 5/26/2009
1053 1153 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; SurfNum++) {
1054 1012 : s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) = 0.0;
1055 1012 : s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) = 0.0;
1056 1012 : s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) = 0.0;
1057 1012 : s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) = 0.0;
1058 : }
1059 :
1060 141 : DisplayString(state, "Initializing Zone and Enclosure Report Variables");
1061 309 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
1062 168 : std::string &thisEnclosureName = state.dataViewFactor->EnclSolInfo(enclosureNum).Name;
1063 336 : SetupOutputVariable(state,
1064 : "Enclosure Windows Total Transmitted Solar Radiation Rate",
1065 : Constant::Units::W,
1066 168 : state.dataHeatBal->ZoneTransSolar(enclosureNum),
1067 : OutputProcessor::TimeStepType::Zone,
1068 : OutputProcessor::StoreType::Average,
1069 : thisEnclosureName);
1070 336 : SetupOutputVariable(state,
1071 : "Enclosure Exterior Windows Total Transmitted Beam Solar Radiation Rate",
1072 : Constant::Units::W,
1073 168 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum),
1074 : OutputProcessor::TimeStepType::Zone,
1075 : OutputProcessor::StoreType::Average,
1076 : thisEnclosureName);
1077 336 : SetupOutputVariable(state,
1078 : "Enclosure Interior Windows Total Transmitted Beam Solar Radiation Rate",
1079 : Constant::Units::W,
1080 168 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum),
1081 : OutputProcessor::TimeStepType::Zone,
1082 : OutputProcessor::StoreType::Average,
1083 : thisEnclosureName);
1084 336 : SetupOutputVariable(state,
1085 : "Enclosure Exterior Windows Total Transmitted Diffuse Solar Radiation Rate",
1086 : Constant::Units::W,
1087 168 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum),
1088 : OutputProcessor::TimeStepType::Zone,
1089 : OutputProcessor::StoreType::Average,
1090 : thisEnclosureName);
1091 336 : SetupOutputVariable(state,
1092 : "Enclosure Interior Windows Total Transmitted Diffuse Solar Radiation Rate",
1093 : Constant::Units::W,
1094 168 : state.dataHeatBal->ZoneDifSolFrIntWinsRep(enclosureNum),
1095 : OutputProcessor::TimeStepType::Zone,
1096 : OutputProcessor::StoreType::Average,
1097 : thisEnclosureName);
1098 : // Energy variables
1099 336 : SetupOutputVariable(state,
1100 : "Enclosure Windows Total Transmitted Solar Radiation Energy",
1101 : Constant::Units::J,
1102 168 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum),
1103 : OutputProcessor::TimeStepType::Zone,
1104 : OutputProcessor::StoreType::Sum,
1105 : thisEnclosureName);
1106 336 : SetupOutputVariable(state,
1107 : "Enclosure Exterior Windows Total Transmitted Beam Solar Radiation Energy",
1108 : Constant::Units::J,
1109 168 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum),
1110 : OutputProcessor::TimeStepType::Zone,
1111 : OutputProcessor::StoreType::Sum,
1112 : thisEnclosureName);
1113 336 : SetupOutputVariable(state,
1114 : "Enclosure Interior Windows Total Transmitted Beam Solar Radiation Energy",
1115 : Constant::Units::J,
1116 168 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclosureNum),
1117 : OutputProcessor::TimeStepType::Zone,
1118 : OutputProcessor::StoreType::Sum,
1119 : thisEnclosureName);
1120 336 : SetupOutputVariable(state,
1121 : "Enclosure Exterior Windows Total Transmitted Diffuse Solar Radiation Energy",
1122 : Constant::Units::J,
1123 168 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum),
1124 : OutputProcessor::TimeStepType::Zone,
1125 : OutputProcessor::StoreType::Sum,
1126 : thisEnclosureName);
1127 336 : SetupOutputVariable(state,
1128 : "Enclosure Interior Windows Total Transmitted Diffuse Solar Radiation Energy",
1129 : Constant::Units::J,
1130 168 : state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy(enclosureNum),
1131 : OutputProcessor::TimeStepType::Zone,
1132 : OutputProcessor::StoreType::Sum,
1133 : thisEnclosureName);
1134 : }
1135 300 : for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) {
1136 318 : SetupOutputVariable(state,
1137 : "Zone Windows Total Heat Gain Rate",
1138 : Constant::Units::W,
1139 159 : state.dataHeatBal->ZoneWinHeatGainRep(ZoneLoop),
1140 : OutputProcessor::TimeStepType::Zone,
1141 : OutputProcessor::StoreType::Average,
1142 159 : state.dataHeatBal->Zone(ZoneLoop).Name);
1143 318 : SetupOutputVariable(state,
1144 : "Zone Windows Total Heat Loss Rate",
1145 : Constant::Units::W,
1146 159 : state.dataHeatBal->ZoneWinHeatLossRep(ZoneLoop),
1147 : OutputProcessor::TimeStepType::Zone,
1148 : OutputProcessor::StoreType::Average,
1149 159 : state.dataHeatBal->Zone(ZoneLoop).Name);
1150 318 : SetupOutputVariable(state,
1151 : "Zone Windows Total Heat Gain Energy",
1152 : Constant::Units::J,
1153 159 : state.dataHeatBal->ZoneWinHeatGainRepEnergy(ZoneLoop),
1154 : OutputProcessor::TimeStepType::Zone,
1155 : OutputProcessor::StoreType::Sum,
1156 159 : state.dataHeatBal->Zone(ZoneLoop).Name);
1157 318 : SetupOutputVariable(state,
1158 : "Zone Windows Total Heat Loss Energy",
1159 : Constant::Units::J,
1160 159 : state.dataHeatBal->ZoneWinHeatLossRepEnergy(ZoneLoop),
1161 : OutputProcessor::TimeStepType::Zone,
1162 : OutputProcessor::StoreType::Sum,
1163 159 : state.dataHeatBal->Zone(ZoneLoop).Name);
1164 159 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
1165 : // CurrentModuleObject='Zone(Advanced)'
1166 0 : SetupOutputVariable(state,
1167 : "Zone Opaque Surface Inside Faces Total Conduction Heat Gain Rate",
1168 : Constant::Units::W,
1169 0 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep(ZoneLoop),
1170 : OutputProcessor::TimeStepType::Zone,
1171 : OutputProcessor::StoreType::Average,
1172 0 : state.dataHeatBal->Zone(ZoneLoop).Name);
1173 0 : SetupOutputVariable(state,
1174 : "Zone Opaque Surface Inside Faces Total Conduction Heat Loss Rate",
1175 : Constant::Units::W,
1176 0 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep(ZoneLoop),
1177 : OutputProcessor::TimeStepType::Zone,
1178 : OutputProcessor::StoreType::Average,
1179 0 : state.dataHeatBal->Zone(ZoneLoop).Name);
1180 : // Energy variables
1181 0 : SetupOutputVariable(state,
1182 : "Zone Opaque Surface Inside Faces Total Conduction Heat Gain Energy",
1183 : Constant::Units::J,
1184 0 : state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg(ZoneLoop),
1185 : OutputProcessor::TimeStepType::Zone,
1186 : OutputProcessor::StoreType::Sum,
1187 0 : state.dataHeatBal->Zone(ZoneLoop).Name);
1188 0 : SetupOutputVariable(state,
1189 : "Zone Opaque Surface Inside Faces Total Conduction Heat Loss Energy",
1190 : Constant::Units::J,
1191 0 : state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg(ZoneLoop),
1192 : OutputProcessor::TimeStepType::Zone,
1193 : OutputProcessor::StoreType::Sum,
1194 0 : state.dataHeatBal->Zone(ZoneLoop).Name);
1195 : }
1196 : }
1197 :
1198 141 : DisplayString(state, "Initializing Surface (Shading) Report Variables");
1199 : // CurrentModuleObject='Surfaces'
1200 1153 : for (int SurfLoop = 1; SurfLoop <= s_surf->TotSurfaces; ++SurfLoop) {
1201 1012 : auto &surf = s_surf->Surface(SurfLoop);
1202 2024 : SetupOutputVariable(state,
1203 : "Surface Outside Normal Azimuth Angle",
1204 : Constant::Units::deg,
1205 1012 : surf.Azimuth,
1206 : OutputProcessor::TimeStepType::Zone,
1207 : OutputProcessor::StoreType::Average,
1208 1012 : surf.Name);
1209 1012 : if (surf.ExtSolar) {
1210 1388 : SetupOutputVariable(state,
1211 : "Surface Outside Face Sunlit Area",
1212 : Constant::Units::m2,
1213 694 : s_surf->SurfSunlitArea(SurfLoop),
1214 : OutputProcessor::TimeStepType::Zone,
1215 : OutputProcessor::StoreType::Average,
1216 694 : surf.Name);
1217 1388 : SetupOutputVariable(state,
1218 : "Surface Outside Face Sunlit Fraction",
1219 : Constant::Units::None,
1220 694 : s_surf->SurfSunlitFrac(SurfLoop),
1221 : OutputProcessor::TimeStepType::Zone,
1222 : OutputProcessor::StoreType::Average,
1223 694 : surf.Name);
1224 1388 : SetupOutputVariable(state,
1225 : "Surface Outside Face Incident Solar Radiation Rate per Area",
1226 : Constant::Units::W_m2,
1227 694 : state.dataHeatBal->SurfQRadSWOutIncident(SurfLoop),
1228 : OutputProcessor::TimeStepType::Zone,
1229 : OutputProcessor::StoreType::Average,
1230 694 : surf.Name);
1231 1388 : SetupOutputVariable(state,
1232 : "Surface Outside Face Incident Beam Solar Radiation Rate per Area",
1233 : Constant::Units::W_m2,
1234 694 : state.dataHeatBal->SurfQRadSWOutIncidentBeam(SurfLoop),
1235 : OutputProcessor::TimeStepType::Zone,
1236 : OutputProcessor::StoreType::Average,
1237 694 : surf.Name);
1238 1388 : SetupOutputVariable(state,
1239 : "Surface Outside Face Incident Sky Diffuse Solar Radiation Rate per Area",
1240 : Constant::Units::W_m2,
1241 694 : state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse(SurfLoop),
1242 : OutputProcessor::TimeStepType::Zone,
1243 : OutputProcessor::StoreType::Average,
1244 694 : surf.Name);
1245 1388 : SetupOutputVariable(state,
1246 : "Surface Outside Face Incident Ground Diffuse Solar Radiation Rate per Area",
1247 : Constant::Units::W_m2,
1248 694 : state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse(SurfLoop),
1249 : OutputProcessor::TimeStepType::Zone,
1250 : OutputProcessor::StoreType::Average,
1251 694 : surf.Name);
1252 1388 : SetupOutputVariable(state,
1253 : "Surface Outside Face Beam Solar Incident Angle Cosine Value",
1254 : Constant::Units::None,
1255 694 : state.dataHeatBal->SurfCosIncidenceAngle(SurfLoop),
1256 : OutputProcessor::TimeStepType::Zone,
1257 : OutputProcessor::StoreType::Average,
1258 694 : surf.Name);
1259 1388 : SetupOutputVariable(state,
1260 : "Surface Outside Face Incident Sky Diffuse Ground Reflected Solar Radiation Rate per Area",
1261 : Constant::Units::W_m2,
1262 694 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd(SurfLoop),
1263 : OutputProcessor::TimeStepType::Zone,
1264 : OutputProcessor::StoreType::Average,
1265 694 : surf.Name);
1266 1388 : SetupOutputVariable(state,
1267 : "Surface Outside Face Incident Sky Diffuse Surface Reflected Solar Radiation Rate per Area",
1268 : Constant::Units::W_m2,
1269 694 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs(SurfLoop),
1270 : OutputProcessor::TimeStepType::Zone,
1271 : OutputProcessor::StoreType::Average,
1272 694 : surf.Name);
1273 1388 : SetupOutputVariable(state,
1274 : "Surface Outside Face Incident Beam To Beam Surface Reflected Solar Radiation Rate per Area",
1275 : Constant::Units::W_m2,
1276 694 : state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs(SurfLoop),
1277 : OutputProcessor::TimeStepType::Zone,
1278 : OutputProcessor::StoreType::Average,
1279 694 : surf.Name);
1280 1388 : SetupOutputVariable(state,
1281 : "Surface Outside Face Incident Beam To Diffuse Surface Reflected Solar Radiation Rate per Area",
1282 : Constant::Units::W_m2,
1283 694 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs(SurfLoop),
1284 : OutputProcessor::TimeStepType::Zone,
1285 : OutputProcessor::StoreType::Average,
1286 694 : surf.Name);
1287 1388 : SetupOutputVariable(state,
1288 : "Surface Outside Face Incident Beam To Diffuse Ground Reflected Solar Radiation Rate per Area",
1289 : Constant::Units::W_m2,
1290 694 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd(SurfLoop),
1291 : OutputProcessor::TimeStepType::Zone,
1292 : OutputProcessor::StoreType::Average,
1293 694 : surf.Name);
1294 1388 : SetupOutputVariable(state,
1295 : "Surface Anisotropic Sky Multiplier",
1296 : Constant::Units::None,
1297 694 : state.dataSolarShading->SurfAnisoSkyMult(SurfLoop),
1298 : OutputProcessor::TimeStepType::Zone,
1299 : OutputProcessor::StoreType::Average,
1300 694 : surf.Name);
1301 694 : SetupOutputVariable(state,
1302 : "Surface Window BSDF Beam Direction Number",
1303 : Constant::Units::None,
1304 694 : state.dataHeatBal->SurfWinBSDFBeamDirectionRep(SurfLoop),
1305 : OutputProcessor::TimeStepType::Zone,
1306 : OutputProcessor::StoreType::Average,
1307 694 : surf.Name);
1308 1388 : SetupOutputVariable(state,
1309 : "Surface Window BSDF Beam Theta Angle",
1310 : Constant::Units::rad,
1311 694 : state.dataHeatBal->SurfWinBSDFBeamThetaRep(SurfLoop),
1312 : OutputProcessor::TimeStepType::Zone,
1313 : OutputProcessor::StoreType::Average,
1314 694 : surf.Name);
1315 1388 : SetupOutputVariable(state,
1316 : "Surface Window BSDF Beam Phi Angle",
1317 : Constant::Units::rad,
1318 694 : state.dataHeatBal->SurfWinBSDFBeamPhiRep(SurfLoop),
1319 : OutputProcessor::TimeStepType::Zone,
1320 : OutputProcessor::StoreType::Average,
1321 694 : surf.Name);
1322 : }
1323 1012 : if (!surf.HeatTransSurf) continue;
1324 :
1325 942 : if (surf.Class == SurfaceClass::Window) {
1326 : // CurrentModuleObject='Windows/GlassDoors'
1327 73 : if (surf.ExtSolar) {
1328 142 : SetupOutputVariable(state,
1329 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
1330 : Constant::Units::W,
1331 71 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
1332 : OutputProcessor::TimeStepType::Zone,
1333 : OutputProcessor::StoreType::Average,
1334 71 : surf.Name);
1335 142 : SetupOutputVariable(state,
1336 : "Surface Window Total Glazing Layers Absorbed Shortwave Radiation Rate",
1337 : Constant::Units::W,
1338 71 : state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfLoop),
1339 : OutputProcessor::TimeStepType::Zone,
1340 : OutputProcessor::StoreType::Average,
1341 71 : surf.Name);
1342 :
1343 71 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF) {
1344 1 : NumOfLayers = state.dataConstruction->Construct(surf.Construction).TotSolidLayers;
1345 : } else {
1346 70 : NumOfLayers = state.dataConstruction->Construct(surf.Construction).TotLayers;
1347 : }
1348 222 : for (I = 1; I <= NumOfLayers; ++I) {
1349 151 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF) {
1350 9 : SetupOutputVariable(state,
1351 6 : format("Surface Window Total Absorbed Shortwave Radiation Rate Layer {}", I),
1352 : Constant::Units::W,
1353 3 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfLoop, I),
1354 : OutputProcessor::TimeStepType::Zone,
1355 : OutputProcessor::StoreType::Average,
1356 3 : surf.Name);
1357 : }
1358 151 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF || (I == 1)) {
1359 219 : SetupOutputVariable(state,
1360 146 : format("Surface Window Front Face Temperature Layer {}", I),
1361 : Constant::Units::C,
1362 73 : state.dataHeatBal->SurfWinFenLaySurfTempFront(SurfLoop, I),
1363 : OutputProcessor::TimeStepType::Zone,
1364 : OutputProcessor::StoreType::Average,
1365 73 : surf.Name);
1366 : }
1367 151 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF || (I == NumOfLayers)) {
1368 219 : SetupOutputVariable(state,
1369 146 : format("Surface Window Back Face Temperature Layer {}", I),
1370 : Constant::Units::C,
1371 73 : state.dataHeatBal->SurfWinFenLaySurfTempBack(SurfLoop, I),
1372 : OutputProcessor::TimeStepType::Zone,
1373 : OutputProcessor::StoreType::Average,
1374 73 : surf.Name);
1375 : }
1376 : }
1377 :
1378 142 : SetupOutputVariable(state,
1379 : "Surface Window Transmitted Solar Radiation Rate",
1380 : Constant::Units::W,
1381 71 : s_surf->SurfWinTransSolar(SurfLoop),
1382 : OutputProcessor::TimeStepType::Zone,
1383 : OutputProcessor::StoreType::Average,
1384 71 : surf.Name);
1385 142 : SetupOutputVariable(state,
1386 : "Surface Window Transmitted Beam Solar Radiation Rate",
1387 : Constant::Units::W,
1388 71 : s_surf->SurfWinBmSolar(SurfLoop),
1389 : OutputProcessor::TimeStepType::Zone,
1390 : OutputProcessor::StoreType::Average,
1391 71 : surf.Name);
1392 :
1393 : // added TH 12/9/2009
1394 142 : SetupOutputVariable(state,
1395 : "Surface Window Transmitted Beam To Beam Solar Radiation Rate",
1396 : Constant::Units::W,
1397 71 : s_surf->SurfWinBmBmSolar(SurfLoop),
1398 : OutputProcessor::TimeStepType::Zone,
1399 : OutputProcessor::StoreType::Average,
1400 71 : surf.Name);
1401 142 : SetupOutputVariable(state,
1402 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Rate",
1403 : Constant::Units::W,
1404 71 : s_surf->SurfWinBmDifSolar(SurfLoop),
1405 : OutputProcessor::TimeStepType::Zone,
1406 : OutputProcessor::StoreType::Average,
1407 71 : surf.Name);
1408 :
1409 142 : SetupOutputVariable(state,
1410 : "Surface Window Transmitted Diffuse Solar Radiation Rate",
1411 : Constant::Units::W,
1412 71 : s_surf->SurfWinDifSolar(SurfLoop),
1413 : OutputProcessor::TimeStepType::Zone,
1414 : OutputProcessor::StoreType::Average,
1415 71 : surf.Name);
1416 142 : SetupOutputVariable(state,
1417 : "Surface Window Heat Gain Rate",
1418 : Constant::Units::W,
1419 71 : s_surf->SurfWinHeatGainRep(SurfLoop),
1420 : OutputProcessor::TimeStepType::Zone,
1421 : OutputProcessor::StoreType::Average,
1422 71 : surf.Name);
1423 142 : SetupOutputVariable(state,
1424 : "Surface Window Heat Loss Rate",
1425 : Constant::Units::W,
1426 71 : s_surf->SurfWinHeatLossRep(SurfLoop),
1427 : OutputProcessor::TimeStepType::Zone,
1428 : OutputProcessor::StoreType::Average,
1429 71 : surf.Name);
1430 142 : SetupOutputVariable(state,
1431 : "Surface Window Gap Convective Heat Transfer Rate",
1432 : Constant::Units::W,
1433 71 : s_surf->SurfWinGapConvHtFlowRep(SurfLoop),
1434 : OutputProcessor::TimeStepType::Zone,
1435 : OutputProcessor::StoreType::Average,
1436 71 : surf.Name);
1437 142 : SetupOutputVariable(state,
1438 : "Surface Window Shading Device Absorbed Solar Radiation Rate",
1439 : Constant::Units::W,
1440 71 : s_surf->SurfWinShadingAbsorbedSolar(SurfLoop),
1441 : OutputProcessor::TimeStepType::Zone,
1442 : OutputProcessor::StoreType::Average,
1443 71 : surf.Name);
1444 142 : SetupOutputVariable(state,
1445 : "Surface Window Net Heat Transfer Rate",
1446 : Constant::Units::W,
1447 71 : s_surf->SurfWinHeatGain(SurfLoop),
1448 : OutputProcessor::TimeStepType::Zone,
1449 : OutputProcessor::StoreType::Average,
1450 71 : surf.Name);
1451 :
1452 71 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
1453 : // CurrentModuleObject='Windows/GlassDoors(Advanced)'
1454 0 : SetupOutputVariable(state,
1455 : "Surface Window Inside Face Glazing Zone Convection Heat Gain Rate",
1456 : Constant::Units::W,
1457 0 : s_surf->SurfWinGainConvGlazToZoneRep(SurfLoop),
1458 : OutputProcessor::TimeStepType::Zone,
1459 : OutputProcessor::StoreType::Average,
1460 0 : surf.Name);
1461 0 : SetupOutputVariable(state,
1462 : "Surface Window Inside Face Glazing Net Infrared Heat Transfer Rate",
1463 : Constant::Units::W,
1464 0 : s_surf->SurfWinGainIRGlazToZoneRep(SurfLoop),
1465 : OutputProcessor::TimeStepType::Zone,
1466 : OutputProcessor::StoreType::Average,
1467 0 : surf.Name);
1468 0 : SetupOutputVariable(state,
1469 : "Surface Window Shortwave from Zone Back Out Window Heat Transfer Rate",
1470 : Constant::Units::W,
1471 0 : s_surf->SurfWinLossSWZoneToOutWinRep(SurfLoop),
1472 : OutputProcessor::TimeStepType::Zone,
1473 : OutputProcessor::StoreType::Average,
1474 0 : surf.Name);
1475 0 : SetupOutputVariable(state,
1476 : "Surface Window Inside Face Frame and Divider Zone Heat Gain Rate",
1477 : Constant::Units::W,
1478 0 : s_surf->SurfWinGainFrameDividerToZoneRep(SurfLoop),
1479 : OutputProcessor::TimeStepType::Zone,
1480 : OutputProcessor::StoreType::Average,
1481 0 : surf.Name);
1482 0 : SetupOutputVariable(state,
1483 : "Surface Window Inside Face Gap between Shade and Glazing Zone Convection Heat Gain Rate",
1484 : Constant::Units::W,
1485 0 : s_surf->SurfWinConvHeatFlowNatural(SurfLoop),
1486 : OutputProcessor::TimeStepType::Zone,
1487 : OutputProcessor::StoreType::Average,
1488 0 : surf.Name);
1489 0 : SetupOutputVariable(state,
1490 : "Surface Window Inside Face Shade Zone Convection Heat Gain Rate",
1491 : Constant::Units::W,
1492 0 : s_surf->SurfWinGainConvShadeToZoneRep(SurfLoop),
1493 : OutputProcessor::TimeStepType::Zone,
1494 : OutputProcessor::StoreType::Average,
1495 0 : surf.Name);
1496 0 : SetupOutputVariable(state,
1497 : "Surface Window Inside Face Shade Net Infrared Heat Transfer Rate",
1498 : Constant::Units::W,
1499 0 : s_surf->SurfWinGainIRShadeToZoneRep(SurfLoop),
1500 : OutputProcessor::TimeStepType::Zone,
1501 : OutputProcessor::StoreType::Average,
1502 0 : surf.Name);
1503 0 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
1504 0 : SetupOutputVariable(state,
1505 : "Surface Window Inside Face Other Convection Heat Gain Rate",
1506 : Constant::Units::W,
1507 0 : s_surf->SurfWinOtherConvHeatGain(SurfLoop),
1508 : OutputProcessor::TimeStepType::Zone,
1509 : OutputProcessor::StoreType::Average,
1510 0 : surf.Name);
1511 : }
1512 : }
1513 :
1514 : // Added TH 12/23/2008 for thermochromic windows
1515 : // CurrentModuleObject='Thermochromic Windows'
1516 71 : if (state.dataConstruction->Construct(surf.Construction).isTCWindow) {
1517 0 : SetupOutputVariable(state,
1518 : "Surface Window Thermochromic Layer Temperature",
1519 : Constant::Units::C,
1520 0 : s_surf->SurfWinTCLayerTemp(SurfLoop),
1521 : OutputProcessor::TimeStepType::Zone,
1522 : OutputProcessor::StoreType::Average,
1523 0 : surf.Name);
1524 0 : SetupOutputVariable(state,
1525 : "Surface Window Thermochromic Layer Property Specification Temperature",
1526 : Constant::Units::C,
1527 0 : s_surf->SurfWinSpecTemp(SurfLoop),
1528 : OutputProcessor::TimeStepType::Zone,
1529 : OutputProcessor::StoreType::Average,
1530 0 : surf.Name);
1531 : }
1532 :
1533 : // Added TH 5/26/2009 for switchable windows to report switching factor (tinted level)
1534 : // CurrentModuleObject='Switchable Windows'
1535 71 : if (surf.HasShadeControl) {
1536 8 : if (s_surf->WindowShadingControl(surf.activeWindowShadingControl).ShadingType == WinShadingType::SwitchableGlazing) {
1537 : // IF (SurfaceWindow(SurfLoop)%ShadingFlag == WinShadingType::SwitchableGlazing) THEN !ShadingFlag is not set to
1538 : // WinShadingType::SwitchableGlazing yet!
1539 0 : SetupOutputVariable(state,
1540 : "Surface Window Switchable Glazing Switching Factor",
1541 : Constant::Units::None,
1542 0 : s_surf->SurfWinSwitchingFactor(SurfLoop),
1543 : OutputProcessor::TimeStepType::Zone,
1544 : OutputProcessor::StoreType::Average,
1545 0 : surf.Name);
1546 0 : SetupOutputVariable(state,
1547 : "Surface Window Switchable Glazing Visible Transmittance",
1548 : Constant::Units::None,
1549 0 : s_surf->SurfWinVisTransSelected(SurfLoop),
1550 : OutputProcessor::TimeStepType::Zone,
1551 : OutputProcessor::StoreType::Average,
1552 0 : surf.Name);
1553 : }
1554 : }
1555 :
1556 71 : if (s_surf->SurfWinFrameArea(SurfLoop) > 0.0) {
1557 : // CurrentModuleObject='Window Frames'
1558 40 : SetupOutputVariable(state,
1559 : "Surface Window Frame Heat Gain Rate",
1560 : Constant::Units::W,
1561 20 : s_surf->SurfWinFrameHeatGain(SurfLoop),
1562 : OutputProcessor::TimeStepType::Zone,
1563 : OutputProcessor::StoreType::Average,
1564 20 : surf.Name);
1565 40 : SetupOutputVariable(state,
1566 : "Surface Window Frame Heat Loss Rate",
1567 : Constant::Units::W,
1568 20 : s_surf->SurfWinFrameHeatLoss(SurfLoop),
1569 : OutputProcessor::TimeStepType::Zone,
1570 : OutputProcessor::StoreType::Average,
1571 20 : surf.Name);
1572 40 : SetupOutputVariable(state,
1573 : "Surface Window Frame Inside Temperature",
1574 : Constant::Units::C,
1575 20 : s_surf->SurfWinFrameTempIn(SurfLoop),
1576 : OutputProcessor::TimeStepType::Zone,
1577 : OutputProcessor::StoreType::Average,
1578 20 : surf.Name);
1579 40 : SetupOutputVariable(state,
1580 : "Surface Window Frame Outside Temperature",
1581 : Constant::Units::C,
1582 20 : s_surf->SurfWinFrameTempSurfOut(SurfLoop),
1583 : OutputProcessor::TimeStepType::Zone,
1584 : OutputProcessor::StoreType::Average,
1585 20 : surf.Name);
1586 : }
1587 71 : if (s_surf->SurfWinDividerArea(SurfLoop) > 0.0) {
1588 : // CurrentModuleObject='Window Dividers'
1589 40 : SetupOutputVariable(state,
1590 : "Surface Window Divider Heat Gain Rate",
1591 : Constant::Units::W,
1592 20 : s_surf->SurfWinDividerHeatGain(SurfLoop),
1593 : OutputProcessor::TimeStepType::Zone,
1594 : OutputProcessor::StoreType::Average,
1595 20 : surf.Name);
1596 40 : SetupOutputVariable(state,
1597 : "Surface Window Divider Heat Loss Rate",
1598 : Constant::Units::W,
1599 20 : s_surf->SurfWinDividerHeatLoss(SurfLoop),
1600 : OutputProcessor::TimeStepType::Zone,
1601 : OutputProcessor::StoreType::Average,
1602 20 : surf.Name);
1603 40 : SetupOutputVariable(state,
1604 : "Surface Window Divider Inside Temperature",
1605 : Constant::Units::C,
1606 20 : s_surf->SurfWinDividerTempIn(SurfLoop),
1607 : OutputProcessor::TimeStepType::Zone,
1608 : OutputProcessor::StoreType::Average,
1609 20 : surf.Name);
1610 40 : SetupOutputVariable(state,
1611 : "Surface Window Divider Outside Temperature",
1612 : Constant::Units::C,
1613 20 : s_surf->SurfWinDividerTempSurfOut(SurfLoop),
1614 : OutputProcessor::TimeStepType::Zone,
1615 : OutputProcessor::StoreType::Average,
1616 20 : surf.Name);
1617 : }
1618 :
1619 : // CurrentModuleObject='Windows'
1620 : // Energy
1621 142 : SetupOutputVariable(state,
1622 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
1623 : Constant::Units::J,
1624 71 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
1625 : OutputProcessor::TimeStepType::Zone,
1626 : OutputProcessor::StoreType::Sum,
1627 71 : surf.Name);
1628 142 : SetupOutputVariable(state,
1629 : "Surface Window Transmitted Solar Radiation Energy",
1630 : Constant::Units::J,
1631 71 : s_surf->SurfWinTransSolarEnergy(SurfLoop),
1632 : OutputProcessor::TimeStepType::Zone,
1633 : OutputProcessor::StoreType::Sum,
1634 71 : surf.Name);
1635 142 : SetupOutputVariable(state,
1636 : "Surface Window Transmitted Beam Solar Radiation Energy",
1637 : Constant::Units::J,
1638 71 : s_surf->SurfWinBmSolarEnergy(SurfLoop),
1639 : OutputProcessor::TimeStepType::Zone,
1640 : OutputProcessor::StoreType::Sum,
1641 71 : surf.Name);
1642 :
1643 : // added TH 12/9/2009
1644 142 : SetupOutputVariable(state,
1645 : "Surface Window Transmitted Beam To Beam Solar Radiation Energy",
1646 : Constant::Units::J,
1647 71 : s_surf->SurfWinBmBmSolarEnergy(SurfLoop),
1648 : OutputProcessor::TimeStepType::Zone,
1649 : OutputProcessor::StoreType::Sum,
1650 71 : surf.Name);
1651 142 : SetupOutputVariable(state,
1652 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Energy",
1653 : Constant::Units::J,
1654 71 : s_surf->SurfWinBmDifSolarEnergy(SurfLoop),
1655 : OutputProcessor::TimeStepType::Zone,
1656 : OutputProcessor::StoreType::Sum,
1657 71 : surf.Name);
1658 :
1659 142 : SetupOutputVariable(state,
1660 : "Surface Window Transmitted Diffuse Solar Radiation Energy",
1661 : Constant::Units::J,
1662 71 : s_surf->SurfWinDifSolarEnergy(SurfLoop),
1663 : OutputProcessor::TimeStepType::Zone,
1664 : OutputProcessor::StoreType::Sum,
1665 71 : surf.Name);
1666 142 : SetupOutputVariable(state,
1667 : "Surface Window Heat Gain Energy",
1668 : Constant::Units::J,
1669 71 : s_surf->SurfWinHeatGainRepEnergy(SurfLoop),
1670 : OutputProcessor::TimeStepType::Zone,
1671 : OutputProcessor::StoreType::Sum,
1672 71 : surf.Name);
1673 142 : SetupOutputVariable(state,
1674 : "Surface Window Heat Loss Energy",
1675 : Constant::Units::J,
1676 71 : s_surf->SurfWinHeatLossRepEnergy(SurfLoop),
1677 : OutputProcessor::TimeStepType::Zone,
1678 : OutputProcessor::StoreType::Sum,
1679 71 : surf.Name);
1680 142 : SetupOutputVariable(state,
1681 : "Surface Window Gap Convective Heat Transfer Energy",
1682 : Constant::Units::J,
1683 71 : s_surf->SurfWinGapConvHtFlowRepEnergy(SurfLoop),
1684 : OutputProcessor::TimeStepType::Zone,
1685 : OutputProcessor::StoreType::Sum,
1686 71 : surf.Name);
1687 142 : SetupOutputVariable(state,
1688 : "Surface Window Shading Device Absorbed Solar Radiation Energy",
1689 : Constant::Units::J,
1690 71 : s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfLoop),
1691 : OutputProcessor::TimeStepType::Zone,
1692 : OutputProcessor::StoreType::Sum,
1693 71 : surf.Name);
1694 142 : SetupOutputVariable(state,
1695 : "Surface Window Net Heat Transfer Energy",
1696 : Constant::Units::J,
1697 71 : s_surf->SurfWinHeatTransferRepEnergy(SurfLoop),
1698 : OutputProcessor::TimeStepType::Zone,
1699 : OutputProcessor::StoreType::Sum,
1700 71 : surf.Name);
1701 :
1702 142 : SetupOutputVariable(state,
1703 : "Surface Window System Solar Transmittance",
1704 : Constant::Units::None,
1705 71 : s_surf->SurfWinSysSolTransmittance(SurfLoop),
1706 : OutputProcessor::TimeStepType::Zone,
1707 : OutputProcessor::StoreType::Average,
1708 71 : surf.Name);
1709 142 : SetupOutputVariable(state,
1710 : "Surface Window System Solar Reflectance",
1711 : Constant::Units::None,
1712 71 : s_surf->SurfWinSysSolReflectance(SurfLoop),
1713 : OutputProcessor::TimeStepType::Zone,
1714 : OutputProcessor::StoreType::Average,
1715 71 : surf.Name);
1716 142 : SetupOutputVariable(state,
1717 : "Surface Window System Solar Absorptance",
1718 : Constant::Units::None,
1719 71 : s_surf->SurfWinSysSolAbsorptance(SurfLoop),
1720 : OutputProcessor::TimeStepType::Zone,
1721 : OutputProcessor::StoreType::Average,
1722 71 : surf.Name);
1723 71 : SetupOutputVariable(state,
1724 : "Surface Window Inside Face Glazing Condensation Status",
1725 : Constant::Units::None,
1726 71 : s_surf->SurfWinInsideGlassCondensationFlag(SurfLoop),
1727 : OutputProcessor::TimeStepType::Zone,
1728 : OutputProcessor::StoreType::Average,
1729 71 : surf.Name);
1730 71 : SetupOutputVariable(state,
1731 : "Surface Window Inside Face Frame Condensation Status",
1732 : Constant::Units::None,
1733 71 : s_surf->SurfWinInsideFrameCondensationFlag(SurfLoop),
1734 : OutputProcessor::TimeStepType::Zone,
1735 : OutputProcessor::StoreType::Average,
1736 71 : surf.Name);
1737 71 : SetupOutputVariable(state,
1738 : "Surface Window Inside Face Divider Condensation Status",
1739 : Constant::Units::None,
1740 71 : s_surf->SurfWinInsideDividerCondensationFlag(SurfLoop),
1741 : OutputProcessor::TimeStepType::Zone,
1742 : OutputProcessor::StoreType::Average,
1743 71 : surf.Name);
1744 :
1745 : // Outside reveal report variables
1746 : // IF (Surface(SurfLoop)%Reveal > 0.0) THEN
1747 142 : SetupOutputVariable(state,
1748 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Rate",
1749 : Constant::Units::W,
1750 71 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfLoop),
1751 : OutputProcessor::TimeStepType::Zone,
1752 : OutputProcessor::StoreType::Average,
1753 71 : surf.Name);
1754 : // Energy
1755 142 : SetupOutputVariable(state,
1756 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Energy",
1757 : Constant::Units::J,
1758 71 : s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfLoop),
1759 : OutputProcessor::TimeStepType::Zone,
1760 : OutputProcessor::StoreType::Sum,
1761 71 : surf.Name);
1762 : // ENDIF
1763 :
1764 : // Inside reveal report variables
1765 71 : if (s_surf->SurfWinInsideReveal(SurfLoop) > 0.0 || s_surf->SurfWinInsideSillDepth(SurfLoop) > 0.0) {
1766 0 : SetupOutputVariable(state,
1767 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Rate",
1768 : Constant::Units::W,
1769 0 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfLoop),
1770 : OutputProcessor::TimeStepType::Zone,
1771 : OutputProcessor::StoreType::Average,
1772 0 : surf.Name);
1773 : // Energy
1774 0 : SetupOutputVariable(state,
1775 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Energy",
1776 : Constant::Units::J,
1777 0 : s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfLoop),
1778 : OutputProcessor::TimeStepType::Zone,
1779 : OutputProcessor::StoreType::Sum,
1780 0 : surf.Name);
1781 :
1782 : // Added report variables for inside reveal to debug CR 7596. TH 5/26/2009
1783 : // All reflected solar by the inside reveal is turned into diffuse
1784 0 : SetupOutputVariable(state,
1785 : "Surface Window Inside Reveal Absorbed Beam Solar Radiation Rate",
1786 : Constant::Units::W,
1787 0 : s_surf->SurfWinBmSolAbsdInsRevealReport(SurfLoop),
1788 : OutputProcessor::TimeStepType::Zone,
1789 : OutputProcessor::StoreType::Average,
1790 0 : surf.Name);
1791 0 : SetupOutputVariable(state,
1792 : "Surface Window Inside Reveal Reflected Diffuse Zone Solar Radiation Rate",
1793 : Constant::Units::W,
1794 0 : s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfLoop),
1795 : OutputProcessor::TimeStepType::Zone,
1796 : OutputProcessor::StoreType::Average,
1797 0 : surf.Name);
1798 0 : SetupOutputVariable(state,
1799 : "Surface Window Inside Reveal Reflected Diffuse Frame Solar Radiation Rate",
1800 : Constant::Units::W,
1801 0 : s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfLoop),
1802 : OutputProcessor::TimeStepType::Zone,
1803 : OutputProcessor::StoreType::Average,
1804 0 : surf.Name);
1805 0 : SetupOutputVariable(state,
1806 : "Surface Window Inside Reveal Reflected Diffuse Glazing Solar Radiation Rate",
1807 : Constant::Units::W,
1808 0 : s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfLoop),
1809 : OutputProcessor::TimeStepType::Zone,
1810 : OutputProcessor::StoreType::Average,
1811 0 : surf.Name);
1812 : }
1813 :
1814 : // Output blind report variables only when blinds are used
1815 71 : auto &surfShade = s_surf->surfShades(SurfLoop);
1816 71 : if (surfShade.blind.matNum > 0) {
1817 : // CurrentModuleObject='Window Blinds'
1818 16 : SetupOutputVariable(state,
1819 : "Surface Window Blind Beam to Beam Solar Transmittance",
1820 : Constant::Units::None,
1821 8 : s_surf->SurfWinBlTsolBmBm(SurfLoop),
1822 : OutputProcessor::TimeStepType::Zone,
1823 : OutputProcessor::StoreType::Average,
1824 8 : surf.Name);
1825 16 : SetupOutputVariable(state,
1826 : "Surface Window Blind Beam to Diffuse Solar Transmittance",
1827 : Constant::Units::None,
1828 8 : s_surf->SurfWinBlTsolBmDif(SurfLoop),
1829 : OutputProcessor::TimeStepType::Zone,
1830 : OutputProcessor::StoreType::Average,
1831 8 : surf.Name);
1832 16 : SetupOutputVariable(state,
1833 : "Surface Window Blind Diffuse to Diffuse Solar Transmittance",
1834 : Constant::Units::None,
1835 8 : s_surf->SurfWinBlTsolDifDif(SurfLoop),
1836 : OutputProcessor::TimeStepType::Zone,
1837 : OutputProcessor::StoreType::Average,
1838 8 : surf.Name);
1839 16 : SetupOutputVariable(state,
1840 : "Surface Window Blind and Glazing System Beam Solar Transmittance",
1841 : Constant::Units::None,
1842 8 : s_surf->SurfWinBlGlSysTsolBmBm(SurfLoop),
1843 : OutputProcessor::TimeStepType::Zone,
1844 : OutputProcessor::StoreType::Average,
1845 8 : surf.Name);
1846 16 : SetupOutputVariable(state,
1847 : "Surface Window Blind and Glazing System Diffuse Solar Transmittance",
1848 : Constant::Units::None,
1849 8 : s_surf->SurfWinBlGlSysTsolDifDif(SurfLoop),
1850 : OutputProcessor::TimeStepType::Zone,
1851 : OutputProcessor::StoreType::Average,
1852 8 : surf.Name);
1853 : }
1854 :
1855 : // Output screen report variables only when screens are used
1856 71 : if (s_surf->SurfaceWindow(SurfLoop).screenNum > 0) {
1857 : // CurrentModuleObject='Window Screens'
1858 0 : SetupOutputVariable(state,
1859 : "Surface Window Screen Beam to Beam Solar Transmittance",
1860 : Constant::Units::None,
1861 0 : s_surf->SurfWinScTsolBmBm(SurfLoop),
1862 : OutputProcessor::TimeStepType::Zone,
1863 : OutputProcessor::StoreType::Average,
1864 0 : surf.Name);
1865 0 : SetupOutputVariable(state,
1866 : "Surface Window Screen Beam to Diffuse Solar Transmittance",
1867 : Constant::Units::None,
1868 0 : s_surf->SurfWinScTsolBmDif(SurfLoop),
1869 : OutputProcessor::TimeStepType::Zone,
1870 : OutputProcessor::StoreType::Average,
1871 0 : surf.Name);
1872 0 : SetupOutputVariable(state,
1873 : "Surface Window Screen Diffuse to Diffuse Solar Transmittance",
1874 : Constant::Units::None,
1875 0 : s_surf->SurfWinScTsolDifDif(SurfLoop),
1876 : OutputProcessor::TimeStepType::Zone,
1877 : OutputProcessor::StoreType::Average,
1878 0 : surf.Name);
1879 0 : SetupOutputVariable(state,
1880 : "Surface Window Screen and Glazing System Beam Solar Transmittance",
1881 : Constant::Units::None,
1882 0 : s_surf->SurfWinScGlSysTsolBmBm(SurfLoop),
1883 : OutputProcessor::TimeStepType::Zone,
1884 : OutputProcessor::StoreType::Average,
1885 0 : surf.Name);
1886 0 : SetupOutputVariable(state,
1887 : "Surface Window Screen and Glazing System Diffuse Solar Transmittance",
1888 : Constant::Units::None,
1889 0 : s_surf->SurfWinScGlSysTsolDifDif(SurfLoop),
1890 : OutputProcessor::TimeStepType::Zone,
1891 : OutputProcessor::StoreType::Average,
1892 0 : surf.Name);
1893 : }
1894 :
1895 : // CurrentModuleObject='Windows'
1896 142 : SetupOutputVariable(state,
1897 : "Surface Window Solar Horizontal Profile Angle",
1898 : Constant::Units::deg,
1899 71 : s_surf->SurfWinProfileAngHor(SurfLoop),
1900 : OutputProcessor::TimeStepType::Zone,
1901 : OutputProcessor::StoreType::Average,
1902 71 : surf.Name);
1903 142 : SetupOutputVariable(state,
1904 : "Surface Window Solar Vertical Profile Angle",
1905 : Constant::Units::deg,
1906 71 : s_surf->SurfWinProfileAngVert(SurfLoop),
1907 : OutputProcessor::TimeStepType::Zone,
1908 : OutputProcessor::StoreType::Average,
1909 71 : surf.Name);
1910 142 : SetupOutputVariable(state,
1911 : "Surface Window Glazing Beam to Beam Solar Transmittance",
1912 : Constant::Units::None,
1913 71 : s_surf->SurfWinGlTsolBmBm(SurfLoop),
1914 : OutputProcessor::TimeStepType::Zone,
1915 : OutputProcessor::StoreType::Average,
1916 71 : surf.Name);
1917 142 : SetupOutputVariable(state,
1918 : "Surface Window Glazing Beam to Diffuse Solar Transmittance",
1919 : Constant::Units::None,
1920 71 : s_surf->SurfWinGlTsolBmDif(SurfLoop),
1921 : OutputProcessor::TimeStepType::Zone,
1922 : OutputProcessor::StoreType::Average,
1923 71 : surf.Name);
1924 142 : SetupOutputVariable(state,
1925 : "Surface Window Glazing Diffuse to Diffuse Solar Transmittance",
1926 : Constant::Units::None,
1927 71 : s_surf->SurfWinGlTsolDifDif(SurfLoop),
1928 : OutputProcessor::TimeStepType::Zone,
1929 : OutputProcessor::StoreType::Average,
1930 71 : surf.Name);
1931 71 : SetupOutputVariable(state,
1932 : "Surface Window Model Solver Iteration Count",
1933 : Constant::Units::None,
1934 71 : s_surf->SurfWinWindowCalcIterationsRep(SurfLoop),
1935 : OutputProcessor::TimeStepType::Zone,
1936 : OutputProcessor::StoreType::Average,
1937 71 : surf.Name);
1938 : } else { // Not ExtSolar
1939 2 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
1940 : // CurrentModuleObject='InteriorWindows(Advanced)'
1941 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
1942 0 : SetupOutputVariable(state,
1943 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
1944 : Constant::Units::W,
1945 0 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
1946 : OutputProcessor::TimeStepType::Zone,
1947 : OutputProcessor::StoreType::Average,
1948 0 : surf.Name);
1949 : }
1950 0 : SetupOutputVariable(state,
1951 : "Surface Window Total Glazing Layers Absorbed Shortwave Radiation Rate",
1952 : Constant::Units::W,
1953 0 : state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfLoop),
1954 : OutputProcessor::TimeStepType::Zone,
1955 : OutputProcessor::StoreType::Average,
1956 0 : surf.Name);
1957 :
1958 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
1959 0 : SetupOutputVariable(state,
1960 : "Surface Window Transmitted Solar Radiation Rate",
1961 : Constant::Units::W,
1962 0 : s_surf->SurfWinTransSolar(SurfLoop),
1963 : OutputProcessor::TimeStepType::Zone,
1964 : OutputProcessor::StoreType::Average,
1965 0 : surf.Name);
1966 : }
1967 0 : SetupOutputVariable(state,
1968 : "Surface Window Transmitted Beam Solar Radiation Rate",
1969 : Constant::Units::W,
1970 0 : s_surf->SurfWinBmSolar(SurfLoop),
1971 : OutputProcessor::TimeStepType::Zone,
1972 : OutputProcessor::StoreType::Average,
1973 0 : surf.Name);
1974 :
1975 : // added TH 12/9/2009
1976 0 : SetupOutputVariable(state,
1977 : "Surface Window Transmitted Beam To Beam Solar Radiation Rate",
1978 : Constant::Units::W,
1979 0 : s_surf->SurfWinBmBmSolar(SurfLoop),
1980 : OutputProcessor::TimeStepType::Zone,
1981 : OutputProcessor::StoreType::Average,
1982 0 : surf.Name);
1983 0 : SetupOutputVariable(state,
1984 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Rate",
1985 : Constant::Units::W,
1986 0 : s_surf->SurfWinBmDifSolar(SurfLoop),
1987 : OutputProcessor::TimeStepType::Zone,
1988 : OutputProcessor::StoreType::Average,
1989 0 : surf.Name);
1990 :
1991 0 : SetupOutputVariable(state,
1992 : "Surface Window Transmitted Diffuse Solar Radiation Rate",
1993 : Constant::Units::W,
1994 0 : s_surf->SurfWinDifSolar(SurfLoop),
1995 : OutputProcessor::TimeStepType::Zone,
1996 : OutputProcessor::StoreType::Average,
1997 0 : surf.Name);
1998 0 : SetupOutputVariable(state,
1999 : "Surface Window Heat Gain Rate",
2000 : Constant::Units::W,
2001 0 : s_surf->SurfWinHeatGainRep(SurfLoop),
2002 : OutputProcessor::TimeStepType::Zone,
2003 : OutputProcessor::StoreType::Average,
2004 0 : surf.Name);
2005 0 : SetupOutputVariable(state,
2006 : "Surface Window Heat Loss Rate",
2007 : Constant::Units::W,
2008 0 : s_surf->SurfWinHeatLossRep(SurfLoop),
2009 : OutputProcessor::TimeStepType::Zone,
2010 : OutputProcessor::StoreType::Average,
2011 0 : surf.Name);
2012 0 : SetupOutputVariable(state,
2013 : "Surface Window Gap Convective Heat Transfer Rate",
2014 : Constant::Units::W,
2015 0 : s_surf->SurfWinGapConvHtFlowRep(SurfLoop),
2016 : OutputProcessor::TimeStepType::Zone,
2017 : OutputProcessor::StoreType::Average,
2018 0 : surf.Name);
2019 0 : SetupOutputVariable(state,
2020 : "Surface Window Shading Device Absorbed Solar Radiation Rate",
2021 : Constant::Units::W,
2022 0 : s_surf->SurfWinShadingAbsorbedSolar(SurfLoop),
2023 : OutputProcessor::TimeStepType::Zone,
2024 : OutputProcessor::StoreType::Average,
2025 0 : surf.Name);
2026 0 : if (s_surf->SurfWinFrameArea(SurfLoop) > 0.0) {
2027 0 : SetupOutputVariable(state,
2028 : "Surface Window Frame Heat Gain Rate",
2029 : Constant::Units::W,
2030 0 : s_surf->SurfWinFrameHeatGain(SurfLoop),
2031 : OutputProcessor::TimeStepType::Zone,
2032 : OutputProcessor::StoreType::Average,
2033 0 : surf.Name);
2034 0 : SetupOutputVariable(state,
2035 : "Surface Window Frame Heat Loss Rate",
2036 : Constant::Units::W,
2037 0 : s_surf->SurfWinFrameHeatLoss(SurfLoop),
2038 : OutputProcessor::TimeStepType::Zone,
2039 : OutputProcessor::StoreType::Average,
2040 0 : surf.Name);
2041 0 : SetupOutputVariable(state,
2042 : "Surface Window Frame Inside Temperature",
2043 : Constant::Units::C,
2044 0 : s_surf->SurfWinFrameTempIn(SurfLoop),
2045 : OutputProcessor::TimeStepType::Zone,
2046 : OutputProcessor::StoreType::Average,
2047 0 : surf.Name);
2048 0 : SetupOutputVariable(state,
2049 : "Surface Window Frame Outside Temperature",
2050 : Constant::Units::C,
2051 0 : s_surf->SurfWinFrameTempSurfOut(SurfLoop),
2052 : OutputProcessor::TimeStepType::Zone,
2053 : OutputProcessor::StoreType::Average,
2054 0 : surf.Name);
2055 : }
2056 0 : if (s_surf->SurfWinDividerArea(SurfLoop) > 0.0) {
2057 0 : SetupOutputVariable(state,
2058 : "Surface Window Divider Heat Gain Rate",
2059 : Constant::Units::W,
2060 0 : s_surf->SurfWinDividerHeatGain(SurfLoop),
2061 : OutputProcessor::TimeStepType::Zone,
2062 : OutputProcessor::StoreType::Average,
2063 0 : surf.Name);
2064 0 : SetupOutputVariable(state,
2065 : "Surface Window Divider Heat Loss Rate",
2066 : Constant::Units::W,
2067 0 : s_surf->SurfWinDividerHeatLoss(SurfLoop),
2068 : OutputProcessor::TimeStepType::Zone,
2069 : OutputProcessor::StoreType::Average,
2070 0 : surf.Name);
2071 0 : SetupOutputVariable(state,
2072 : "Surface Window Divider Inside Temperature",
2073 : Constant::Units::C,
2074 0 : s_surf->SurfWinDividerTempIn(SurfLoop),
2075 : OutputProcessor::TimeStepType::Zone,
2076 : OutputProcessor::StoreType::Average,
2077 0 : surf.Name);
2078 0 : SetupOutputVariable(state,
2079 : "Surface Window Divider Outside Temperature",
2080 : Constant::Units::C,
2081 0 : s_surf->SurfWinDividerTempSurfOut(SurfLoop),
2082 : OutputProcessor::TimeStepType::Zone,
2083 : OutputProcessor::StoreType::Average,
2084 0 : surf.Name);
2085 : }
2086 : // Energy
2087 :
2088 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
2089 0 : SetupOutputVariable(state,
2090 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
2091 : Constant::Units::J,
2092 0 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
2093 : OutputProcessor::TimeStepType::Zone,
2094 : OutputProcessor::StoreType::Sum,
2095 0 : surf.Name);
2096 : }
2097 :
2098 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
2099 0 : SetupOutputVariable(state,
2100 : "Surface Window Transmitted Solar Radiation Energy",
2101 : Constant::Units::J,
2102 0 : s_surf->SurfWinTransSolarEnergy(SurfLoop),
2103 : OutputProcessor::TimeStepType::Zone,
2104 : OutputProcessor::StoreType::Sum,
2105 0 : surf.Name);
2106 : }
2107 0 : SetupOutputVariable(state,
2108 : "Surface Window Transmitted Beam Solar Radiation Energy",
2109 : Constant::Units::J,
2110 0 : s_surf->SurfWinBmSolarEnergy(SurfLoop),
2111 : OutputProcessor::TimeStepType::Zone,
2112 : OutputProcessor::StoreType::Sum,
2113 0 : surf.Name);
2114 :
2115 0 : SetupOutputVariable(state,
2116 : "Surface Window Transmitted Beam To Beam Solar Radiation Energy",
2117 : Constant::Units::J,
2118 0 : s_surf->SurfWinBmBmSolarEnergy(SurfLoop),
2119 : OutputProcessor::TimeStepType::Zone,
2120 : OutputProcessor::StoreType::Sum,
2121 0 : surf.Name);
2122 0 : SetupOutputVariable(state,
2123 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Energy",
2124 : Constant::Units::J,
2125 0 : s_surf->SurfWinBmDifSolarEnergy(SurfLoop),
2126 : OutputProcessor::TimeStepType::Zone,
2127 : OutputProcessor::StoreType::Sum,
2128 0 : surf.Name);
2129 :
2130 0 : SetupOutputVariable(state,
2131 : "Surface Window Transmitted Diffuse Solar Radiation Energy",
2132 : Constant::Units::J,
2133 0 : s_surf->SurfWinDifSolarEnergy(SurfLoop),
2134 : OutputProcessor::TimeStepType::Zone,
2135 : OutputProcessor::StoreType::Sum,
2136 0 : surf.Name);
2137 0 : SetupOutputVariable(state,
2138 : "Surface Window Heat Gain Energy",
2139 : Constant::Units::J,
2140 0 : s_surf->SurfWinHeatGainRepEnergy(SurfLoop),
2141 : OutputProcessor::TimeStepType::Zone,
2142 : OutputProcessor::StoreType::Sum,
2143 0 : surf.Name);
2144 0 : SetupOutputVariable(state,
2145 : "Surface Window Heat Loss Energy",
2146 : Constant::Units::J,
2147 0 : s_surf->SurfWinHeatLossRepEnergy(SurfLoop),
2148 : OutputProcessor::TimeStepType::Zone,
2149 : OutputProcessor::StoreType::Sum,
2150 0 : surf.Name);
2151 0 : SetupOutputVariable(state,
2152 : "Surface Window Gap Convective Heat Transfer Energy",
2153 : Constant::Units::J,
2154 0 : s_surf->SurfWinGapConvHtFlowRepEnergy(SurfLoop),
2155 : OutputProcessor::TimeStepType::Zone,
2156 : OutputProcessor::StoreType::Sum,
2157 0 : surf.Name);
2158 0 : SetupOutputVariable(state,
2159 : "Surface Window Shading Device Absorbed Solar Radiation Energy",
2160 : Constant::Units::J,
2161 0 : s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfLoop),
2162 : OutputProcessor::TimeStepType::Zone,
2163 : OutputProcessor::StoreType::Sum,
2164 0 : surf.Name);
2165 :
2166 0 : SetupOutputVariable(state,
2167 : "Surface Window System Solar Transmittance",
2168 : Constant::Units::None,
2169 0 : s_surf->SurfWinSysSolTransmittance(SurfLoop),
2170 : OutputProcessor::TimeStepType::Zone,
2171 : OutputProcessor::StoreType::Average,
2172 0 : surf.Name);
2173 0 : SetupOutputVariable(state,
2174 : "Surface Window System Solar Reflectance",
2175 : Constant::Units::None,
2176 0 : s_surf->SurfWinSysSolReflectance(SurfLoop),
2177 : OutputProcessor::TimeStepType::Zone,
2178 : OutputProcessor::StoreType::Average,
2179 0 : surf.Name);
2180 0 : SetupOutputVariable(state,
2181 : "Surface Window System Solar Absorptance",
2182 : Constant::Units::None,
2183 0 : s_surf->SurfWinSysSolAbsorptance(SurfLoop),
2184 : OutputProcessor::TimeStepType::Zone,
2185 : OutputProcessor::StoreType::Average,
2186 0 : surf.Name);
2187 0 : SetupOutputVariable(state,
2188 : "Surface Window Inside Face Glazing Condensation Status",
2189 : Constant::Units::None,
2190 0 : s_surf->SurfWinInsideGlassCondensationFlag(SurfLoop),
2191 : OutputProcessor::TimeStepType::Zone,
2192 : OutputProcessor::StoreType::Average,
2193 0 : surf.Name);
2194 0 : SetupOutputVariable(state,
2195 : "Surface Window Inside Face Frame Condensation Status",
2196 : Constant::Units::None,
2197 0 : s_surf->SurfWinInsideFrameCondensationFlag(SurfLoop),
2198 : OutputProcessor::TimeStepType::Zone,
2199 : OutputProcessor::StoreType::Average,
2200 0 : surf.Name);
2201 0 : SetupOutputVariable(state,
2202 : "Surface Window Inside Face Divider Condensation Status",
2203 : Constant::Units::None,
2204 0 : s_surf->SurfWinInsideDividerCondensationFlag(SurfLoop),
2205 : OutputProcessor::TimeStepType::Zone,
2206 : OutputProcessor::StoreType::Average,
2207 0 : surf.Name);
2208 0 : SetupOutputVariable(state,
2209 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Rate",
2210 : Constant::Units::W,
2211 0 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfLoop),
2212 : OutputProcessor::TimeStepType::Zone,
2213 : OutputProcessor::StoreType::Average,
2214 0 : surf.Name);
2215 0 : SetupOutputVariable(state,
2216 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Rate",
2217 : Constant::Units::W,
2218 0 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfLoop),
2219 : OutputProcessor::TimeStepType::Zone,
2220 : OutputProcessor::StoreType::Average,
2221 0 : surf.Name);
2222 : // Energy
2223 0 : SetupOutputVariable(state,
2224 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Energy",
2225 : Constant::Units::J,
2226 0 : s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfLoop),
2227 : OutputProcessor::TimeStepType::Zone,
2228 : OutputProcessor::StoreType::Sum,
2229 0 : surf.Name);
2230 0 : SetupOutputVariable(state,
2231 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Energy",
2232 : Constant::Units::J,
2233 0 : s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfLoop),
2234 : OutputProcessor::TimeStepType::Zone,
2235 : OutputProcessor::StoreType::Sum,
2236 0 : surf.Name);
2237 :
2238 : // Output blind report variables only when blinds are used
2239 0 : auto &surfShade = s_surf->surfShades(SurfLoop);
2240 0 : if (surfShade.blind.matNum > 0) {
2241 0 : SetupOutputVariable(state,
2242 : "Surface Window Blind Beam to Beam Solar Transmittance",
2243 : Constant::Units::None,
2244 0 : s_surf->SurfWinBlTsolBmBm(SurfLoop),
2245 : OutputProcessor::TimeStepType::Zone,
2246 : OutputProcessor::StoreType::Average,
2247 0 : surf.Name);
2248 0 : SetupOutputVariable(state,
2249 : "Surface Window Blind Beam to Diffuse Solar Transmittance",
2250 : Constant::Units::None,
2251 0 : s_surf->SurfWinBlTsolBmDif(SurfLoop),
2252 : OutputProcessor::TimeStepType::Zone,
2253 : OutputProcessor::StoreType::Average,
2254 0 : surf.Name);
2255 0 : SetupOutputVariable(state,
2256 : "Surface Window Blind Diffuse to Diffuse Solar Transmittance",
2257 : Constant::Units::None,
2258 0 : s_surf->SurfWinBlTsolDifDif(SurfLoop),
2259 : OutputProcessor::TimeStepType::Zone,
2260 : OutputProcessor::StoreType::Average,
2261 0 : surf.Name);
2262 0 : SetupOutputVariable(state,
2263 : "Surface Window Blind and Glazing System Beam Solar Transmittance",
2264 : Constant::Units::None,
2265 0 : s_surf->SurfWinBlGlSysTsolBmBm(SurfLoop),
2266 : OutputProcessor::TimeStepType::Zone,
2267 : OutputProcessor::StoreType::Average,
2268 0 : surf.Name);
2269 0 : SetupOutputVariable(state,
2270 : "Surface Window Blind and Glazing System Diffuse Solar Transmittance",
2271 : Constant::Units::None,
2272 0 : s_surf->SurfWinBlGlSysTsolDifDif(SurfLoop),
2273 : OutputProcessor::TimeStepType::Zone,
2274 : OutputProcessor::StoreType::Average,
2275 0 : surf.Name);
2276 : }
2277 :
2278 : // Output screen report variables only when screens are used
2279 0 : if (s_surf->SurfaceWindow(SurfLoop).screenNum > 0) {
2280 0 : SetupOutputVariable(state,
2281 : "Surface Window Screen Beam to Beam Solar Transmittance",
2282 : Constant::Units::None,
2283 0 : s_surf->SurfWinScTsolBmBm(SurfLoop),
2284 : OutputProcessor::TimeStepType::Zone,
2285 : OutputProcessor::StoreType::Average,
2286 0 : surf.Name);
2287 0 : SetupOutputVariable(state,
2288 : "Surface Window Screen Beam to Diffuse Solar Transmittance",
2289 : Constant::Units::None,
2290 0 : s_surf->SurfWinScTsolBmDif(SurfLoop),
2291 : OutputProcessor::TimeStepType::Zone,
2292 : OutputProcessor::StoreType::Average,
2293 0 : surf.Name);
2294 0 : SetupOutputVariable(state,
2295 : "Surface Window Screen Diffuse to Diffuse Solar Transmittance",
2296 : Constant::Units::None,
2297 0 : s_surf->SurfWinScTsolDifDif(SurfLoop),
2298 : OutputProcessor::TimeStepType::Zone,
2299 : OutputProcessor::StoreType::Average,
2300 0 : surf.Name);
2301 0 : SetupOutputVariable(state,
2302 : "Surface Window Screen and Glazing System Beam Solar Transmittance",
2303 : Constant::Units::None,
2304 0 : s_surf->SurfWinScGlSysTsolBmBm(SurfLoop),
2305 : OutputProcessor::TimeStepType::Zone,
2306 : OutputProcessor::StoreType::Average,
2307 0 : surf.Name);
2308 0 : SetupOutputVariable(state,
2309 : "Surface Window Screen and Glazing System Diffuse Solar Transmittance",
2310 : Constant::Units::None,
2311 0 : s_surf->SurfWinScGlSysTsolDifDif(SurfLoop),
2312 : OutputProcessor::TimeStepType::Zone,
2313 : OutputProcessor::StoreType::Average,
2314 0 : surf.Name);
2315 : }
2316 :
2317 0 : SetupOutputVariable(state,
2318 : "Surface Window Solar Horizontal Profile Angle",
2319 : Constant::Units::deg,
2320 0 : s_surf->SurfWinProfileAngHor(SurfLoop),
2321 : OutputProcessor::TimeStepType::Zone,
2322 : OutputProcessor::StoreType::Average,
2323 0 : surf.Name);
2324 0 : SetupOutputVariable(state,
2325 : "Surface Window Solar Vertical Profile Angle",
2326 : Constant::Units::deg,
2327 0 : s_surf->SurfWinProfileAngVert(SurfLoop),
2328 : OutputProcessor::TimeStepType::Zone,
2329 : OutputProcessor::StoreType::Average,
2330 0 : surf.Name);
2331 0 : SetupOutputVariable(state,
2332 : "Surface Window Glazing Beam to Beam Solar Transmittance",
2333 : Constant::Units::None,
2334 0 : s_surf->SurfWinGlTsolBmBm(SurfLoop),
2335 : OutputProcessor::TimeStepType::Zone,
2336 : OutputProcessor::StoreType::Average,
2337 0 : surf.Name);
2338 0 : SetupOutputVariable(state,
2339 : "Surface Window Glazing Beam to Diffuse Solar Transmittance",
2340 : Constant::Units::None,
2341 0 : s_surf->SurfWinGlTsolBmDif(SurfLoop),
2342 : OutputProcessor::TimeStepType::Zone,
2343 : OutputProcessor::StoreType::Average,
2344 0 : surf.Name);
2345 0 : SetupOutputVariable(state,
2346 : "Surface Window Glazing Diffuse to Diffuse Solar Transmittance",
2347 : Constant::Units::None,
2348 0 : s_surf->SurfWinGlTsolDifDif(SurfLoop),
2349 : OutputProcessor::TimeStepType::Zone,
2350 : OutputProcessor::StoreType::Average,
2351 0 : surf.Name);
2352 0 : SetupOutputVariable(state,
2353 : "Surface Window Model Solver Iteration Count",
2354 : Constant::Units::None,
2355 0 : s_surf->SurfWinWindowCalcIterationsRep(SurfLoop),
2356 : OutputProcessor::TimeStepType::Zone,
2357 : OutputProcessor::StoreType::Average,
2358 0 : surf.Name);
2359 : }
2360 : } // end non extsolar reporting as advanced variables
2361 : } // Window Reporting
2362 942 : if (surf.Class == SurfaceClass::Window && surf.ExtBoundCond > 0 && surf.ExtBoundCond != SurfLoop) { // Interzone window
2363 : // CurrentModuleObject='InterzoneWindows'
2364 0 : SetupOutputVariable(state,
2365 : "Surface Window Transmitted Beam Solar Radiation Rate",
2366 : Constant::Units::W,
2367 0 : s_surf->SurfWinBmSolTransThruIntWinRep(SurfLoop),
2368 : OutputProcessor::TimeStepType::Zone,
2369 : OutputProcessor::StoreType::Average,
2370 0 : surf.Name);
2371 : // energy
2372 0 : SetupOutputVariable(state,
2373 : "Surface Window Transmitted Beam Solar Radiation Energy",
2374 : Constant::Units::J,
2375 0 : s_surf->SurfWinBmSolTransThruIntWinRepEnergy(SurfLoop),
2376 : OutputProcessor::TimeStepType::Zone,
2377 : OutputProcessor::StoreType::Sum,
2378 0 : surf.Name);
2379 : }
2380 942 : if (surf.Class == SurfaceClass::TDD_Dome && surf.ExtSolar) {
2381 : // CurrentModuleObject='TDD Domes'
2382 4 : SetupOutputVariable(state,
2383 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
2384 : Constant::Units::W,
2385 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
2386 : OutputProcessor::TimeStepType::Zone,
2387 : OutputProcessor::StoreType::Average,
2388 2 : surf.Name);
2389 4 : SetupOutputVariable(state,
2390 : "Surface Window Transmitted Solar Radiation Rate",
2391 : Constant::Units::W,
2392 2 : s_surf->SurfWinTransSolar(SurfLoop),
2393 : OutputProcessor::TimeStepType::Zone,
2394 : OutputProcessor::StoreType::Average,
2395 2 : surf.Name);
2396 : // energy
2397 4 : SetupOutputVariable(state,
2398 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
2399 : Constant::Units::J,
2400 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
2401 : OutputProcessor::TimeStepType::Zone,
2402 : OutputProcessor::StoreType::Sum,
2403 2 : surf.Name);
2404 4 : SetupOutputVariable(state,
2405 : "Surface Window Transmitted Solar Radiation Energy",
2406 : Constant::Units::J,
2407 2 : s_surf->SurfWinTransSolarEnergy(SurfLoop),
2408 : OutputProcessor::TimeStepType::Zone,
2409 : OutputProcessor::StoreType::Sum,
2410 2 : surf.Name);
2411 : }
2412 942 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
2413 : // CurrentModuleObject='TDD Diffusers'
2414 4 : SetupOutputVariable(state,
2415 : "Surface Outside Face Incident Solar Radiation Rate per Area",
2416 : Constant::Units::W_m2,
2417 2 : state.dataHeatBal->SurfQRadSWOutIncident(SurfLoop),
2418 : OutputProcessor::TimeStepType::Zone,
2419 : OutputProcessor::StoreType::Average,
2420 2 : surf.Name);
2421 4 : SetupOutputVariable(state,
2422 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
2423 : Constant::Units::W,
2424 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
2425 : OutputProcessor::TimeStepType::Zone,
2426 : OutputProcessor::StoreType::Average,
2427 2 : surf.Name);
2428 4 : SetupOutputVariable(state,
2429 : "Surface Window Transmitted Solar Radiation Rate",
2430 : Constant::Units::W,
2431 2 : s_surf->SurfWinTransSolar(SurfLoop),
2432 : OutputProcessor::TimeStepType::Zone,
2433 : OutputProcessor::StoreType::Average,
2434 2 : surf.Name);
2435 : // energy
2436 4 : SetupOutputVariable(state,
2437 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
2438 : Constant::Units::J,
2439 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
2440 : OutputProcessor::TimeStepType::Zone,
2441 : OutputProcessor::StoreType::Sum,
2442 2 : surf.Name);
2443 4 : SetupOutputVariable(state,
2444 : "Surface Window Transmitted Solar Radiation Energy",
2445 : Constant::Units::J,
2446 2 : s_surf->SurfWinTransSolarEnergy(SurfLoop),
2447 : OutputProcessor::TimeStepType::Zone,
2448 : OutputProcessor::StoreType::Sum,
2449 2 : surf.Name);
2450 : }
2451 : }
2452 :
2453 1153 : for (int SurfLoop = 1; SurfLoop <= s_surf->TotSurfaces; ++SurfLoop) {
2454 1012 : auto &surf = s_surf->Surface(SurfLoop);
2455 1012 : if (!surf.HeatTransSurf) continue;
2456 : // CurrentModuleObject='Surfaces'
2457 1884 : SetupOutputVariable(state,
2458 : "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Rate per Area",
2459 : Constant::Units::W_m2,
2460 942 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfLoop),
2461 : OutputProcessor::TimeStepType::Zone,
2462 : OutputProcessor::StoreType::Average,
2463 942 : surf.Name);
2464 1884 : SetupOutputVariable(state,
2465 : "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Rate",
2466 : Constant::Units::W,
2467 942 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfLoop),
2468 : OutputProcessor::TimeStepType::Zone,
2469 : OutputProcessor::StoreType::Average,
2470 942 : surf.Name);
2471 1884 : SetupOutputVariable(state,
2472 : "Surface Inside Face Interior Windows Incident Beam Solar Radiation Rate per Area",
2473 : Constant::Units::W_m2,
2474 942 : state.dataHeatBal->SurfIntBmIncInsSurfIntensRep(SurfLoop),
2475 : OutputProcessor::TimeStepType::Zone,
2476 : OutputProcessor::StoreType::Average,
2477 942 : surf.Name);
2478 1884 : SetupOutputVariable(state,
2479 : "Surface Inside Face Interior Windows Incident Beam Solar Radiation Rate",
2480 : Constant::Units::W,
2481 942 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRep(SurfLoop),
2482 : OutputProcessor::TimeStepType::Zone,
2483 : OutputProcessor::StoreType::Average,
2484 942 : surf.Name);
2485 1884 : SetupOutputVariable(state,
2486 : "Surface Inside Face Initial Transmitted Diffuse Absorbed Solar Radiation Rate",
2487 : Constant::Units::W,
2488 942 : state.dataHeatBal->SurfInitialDifSolInAbsReport(SurfLoop),
2489 : OutputProcessor::TimeStepType::Zone,
2490 : OutputProcessor::StoreType::Average,
2491 942 : surf.Name);
2492 1884 : SetupOutputVariable(state,
2493 : "Surface Inside Face Initial Transmitted Diffuse Transmitted Out Window Solar Radiation Rate",
2494 : Constant::Units::W,
2495 942 : state.dataHeatBal->SurfWinInitialDifSolInTransReport(SurfLoop),
2496 : OutputProcessor::TimeStepType::Zone,
2497 : OutputProcessor::StoreType::Average,
2498 942 : surf.Name);
2499 1884 : SetupOutputVariable(state,
2500 : "Surface Inside Face Absorbed Shortwave Radiation Rate",
2501 : Constant::Units::W,
2502 942 : state.dataHeatBal->SurfSWInAbsTotalReport(SurfLoop),
2503 : OutputProcessor::TimeStepType::Zone,
2504 : OutputProcessor::StoreType::Average,
2505 942 : surf.Name);
2506 : // energy
2507 1884 : SetupOutputVariable(state,
2508 : "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Energy",
2509 : Constant::Units::J,
2510 942 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfLoop),
2511 : OutputProcessor::TimeStepType::Zone,
2512 : OutputProcessor::StoreType::Sum,
2513 942 : surf.Name);
2514 1884 : SetupOutputVariable(state,
2515 : "Surface Inside Face Interior Windows Incident Beam Solar Radiation Energy",
2516 : Constant::Units::J,
2517 942 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy(SurfLoop),
2518 : OutputProcessor::TimeStepType::Zone,
2519 : OutputProcessor::StoreType::Sum,
2520 942 : surf.Name);
2521 : }
2522 141 : }
2523 :
2524 71212 : void AnisoSkyViewFactors(EnergyPlusData &state)
2525 : {
2526 :
2527 : // SUBROUTINE INFORMATION:
2528 : // AUTHOR Fred Winkelmann
2529 : // DATE WRITTEN April 1999
2530 : // MODIFIED LKL; Dec 2002 -- Anisotropic is only sky radiance option
2531 : // RE-ENGINEERED na
2532 :
2533 : // PURPOSE OF THIS SUBROUTINE:
2534 : // Calculates view factor multiplier, SurfAnisoSkyMult, for diffuse
2535 : // sky irradiance on exterior surfaces taking into account
2536 : // anisotropic radiance of the sky. Called by InitSurfaceHeatBalance
2537 : // In this case the diffuse sky irradiance on a surface is given by
2538 : // SurfAnisoSkyMult(SurfNum) * DifSolarRad
2539 : // SurfAnisoSkyMult accounts not only for the sky radiance distribution but
2540 : // also for the effects of shading of sky diffuse radiation by
2541 : // shadowing surfaces such as overhangs. It does not account for reflection
2542 : // of sky diffuse radiation from shadowing surfaces.
2543 : // Based on an empirical model described in
2544 : // R. Perez, P. Ineichen, R. Seals, J. Michalsky and R. Stewart,
2545 : // "Modeling Daylight Availability and Irradiance Components from Direct
2546 : // and Global Irradiance," Solar Energy 44, 271-289, 1990.
2547 : // In this model the radiance of the sky consists of three distributions
2548 : // that are superimposed:
2549 :
2550 : // (1) An isotropic distribution that covers the entire sky dome;
2551 : // (2) A circumsolar brightening centered around the position of the sun;
2552 : // (3) A horizon brightening
2553 : // The circumsolar brightening is assumed to be concentrated at a point
2554 : // source at the center of the sun although this region actually begins at the
2555 : // periphery of the solar disk and falls off in intensity with increasing
2556 : // angular distance from the periphery.
2557 : // The horizon brightening is assumed to be concentrated at the horizon and
2558 : // to be independent of azimuth. In actuality, for clear skies, the horizon
2559 : // brightening is highest at the horizon and decreases in intensity away from
2560 : // the horizon. For overcast skies the horizon brightening has a negative value
2561 : // since for such skies the sky radiance increases rather than decreases away
2562 : // from the horizon.
2563 : // The F11R, F12R, etc. values were provided by R. Perez, private communication,
2564 : // 5/21/99. These values have higher precision than those listed in the above
2565 : // paper.
2566 :
2567 : // Using/Aliasing
2568 :
2569 : // Locals
2570 : // SUBROUTINE PARAMETER DEFINITIONS:
2571 : static constexpr std::array<Real64, 7> EpsilonLimit = {
2572 : 1.065, 1.23, 1.5, 1.95, 2.8, 4.5, 6.2}; // Upper limit of bins of the sky clearness parameter, Epsilon
2573 : // Circumsolar brightening coefficients; index corresponds to range of Epsilon, the sky clearness parameter
2574 : static constexpr std::array<Real64, 8> F11R = {-0.0083117, 0.1299457, 0.3296958, 0.5682053, 0.8730280, 1.1326077, 1.0601591, 0.6777470};
2575 : static constexpr std::array<Real64, 8> F12R = {0.5877285, 0.6825954, 0.4868735, 0.1874525, -0.3920403, -1.2367284, -1.5999137, -0.3272588};
2576 : static constexpr std::array<Real64, 8> F13R = {-0.0620636, -0.1513752, -0.2210958, -0.2951290, -0.3616149, -0.4118494, -0.3589221, -0.2504286};
2577 : // Horizon/zenith brightening coefficient array; index corresponds to range of Epsilon, the sky clearness parameter
2578 : static constexpr std::array<Real64, 8> F21R = {-0.0596012, -0.0189325, 0.0554140, 0.1088631, 0.2255647, 0.2877813, 0.2642124, 0.1561313};
2579 : static constexpr std::array<Real64, 8> F22R = {0.0721249, 0.0659650, -0.0639588, -0.1519229, -0.4620442, -0.8230357, -1.1272340, -1.3765031};
2580 : static constexpr std::array<Real64, 8> F23R = {-0.0220216, -0.0288748, -0.0260542, -0.0139754, 0.0012448, 0.0558651, 0.1310694, 0.2506212};
2581 :
2582 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2583 :
2584 : Real64 CosZenithAng; // Cosine of solar zenith angle
2585 : Real64 ZenithAng; // Solar zenith angle (radians)
2586 : Real64 ZenithAngDeg; // Solar zenith angle (degrees)
2587 : Real64 F1; // Circumsolar brightening coefficient
2588 : Real64 F2; // Horizon/zenith brightening coefficient
2589 : Real64 Epsilon; // Sky clearness parameter
2590 : Real64 Delta; // Sky brightness parameter
2591 : Real64 CosIncAngBeamOnSurface; // Cosine of incidence angle of beam solar on surface
2592 : int EpsilonBin; // Sky clearness (Epsilon) bin index
2593 : Real64 AirMass; // Relative air mass
2594 : Real64 AirMassH; // Intermediate variable for relative air mass calculation
2595 : Real64 CircumSolarFac; // Ratio of cosine of incidence angle to cosine of zenith angle
2596 : Real64 KappaZ3; // Intermediate variable
2597 : Real64 ViewFactorSkyGeom; // Geometrical sky view factor
2598 71212 : Real64 constexpr cosine_tolerance(0.0001);
2599 :
2600 71212 : auto &s_surf = state.dataSurface;
2601 :
2602 : #ifdef EP_Count_Calls
2603 : ++state.dataTimingsData->NumAnisoSky_Calls;
2604 : #endif
2605 :
2606 71212 : CosZenithAng = state.dataEnvrn->SOLCOS(3);
2607 71212 : ZenithAng = std::acos(CosZenithAng);
2608 71212 : ZenithAngDeg = ZenithAng / Constant::DegToRad;
2609 :
2610 71212 : state.dataSolarShading->SurfAnisoSkyMult = 0.0;
2611 :
2612 : // Relative air mass
2613 71212 : AirMassH = (1.0 - 0.1 * state.dataEnvrn->Elevation / 1000.0);
2614 71212 : if (ZenithAngDeg <= 75.0) {
2615 56901 : AirMass = AirMassH / CosZenithAng;
2616 : } else {
2617 14311 : AirMass = AirMassH / (CosZenithAng + 0.15 * std::pow(93.9 - ZenithAngDeg, -1.253));
2618 : }
2619 71212 : KappaZ3 = 1.041 * pow_3(ZenithAng);
2620 71212 : Epsilon = ((state.dataEnvrn->BeamSolarRad + state.dataEnvrn->DifSolarRad) / state.dataEnvrn->DifSolarRad + KappaZ3) / (1.0 + KappaZ3);
2621 71212 : Delta = state.dataEnvrn->DifSolarRad * AirMass / 1353.0; // 1353 is average extraterrestrial irradiance (W/m2)
2622 : // Circumsolar (F1) and horizon/zenith (F2) brightening coefficients
2623 487897 : for (EpsilonBin = 0; EpsilonBin < 8; ++EpsilonBin) {
2624 487897 : if (EpsilonBin == 7) break;
2625 460196 : if (Epsilon < EpsilonLimit[EpsilonBin]) break;
2626 : }
2627 71212 : F1 = max(0.0, F11R[EpsilonBin] + F12R[EpsilonBin] * Delta + F13R[EpsilonBin] * ZenithAng);
2628 71212 : F2 = F21R[EpsilonBin] + F22R[EpsilonBin] * Delta + F23R[EpsilonBin] * ZenithAng;
2629 :
2630 462398 : for (int SurfNum : s_surf->AllExtSolarSurfaceList) {
2631 :
2632 391186 : CosIncAngBeamOnSurface = state.dataEnvrn->SOLCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
2633 391186 : state.dataEnvrn->SOLCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
2634 391186 : state.dataEnvrn->SOLCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
2635 :
2636 : // 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
2637 : // for
2638 391186 : if (CosIncAngBeamOnSurface > 1.0) {
2639 0 : if (CosIncAngBeamOnSurface > (1.0 + cosine_tolerance)) {
2640 0 : ShowSevereError(state, "Cosine of incident angle of beam solar on surface out of range...too high");
2641 0 : ShowContinueError(state, "This is a diagnostic error that should not be encountered under normal circumstances");
2642 0 : ShowContinueError(state, format("Occurs on surface: {}", s_surf->Surface(SurfNum).Name));
2643 0 : ShowContinueError(state, format("Current value = {} ... should be within [-1, +1]", CosIncAngBeamOnSurface));
2644 0 : ShowFatalError(state, "Anisotropic solar calculation causes fatal error");
2645 : }
2646 0 : CosIncAngBeamOnSurface = 1.0;
2647 391186 : } else if (CosIncAngBeamOnSurface < -1.0) {
2648 0 : if (CosIncAngBeamOnSurface < (-1.0 - cosine_tolerance)) {
2649 0 : ShowSevereError(state, "Cosine of incident angle of beam solar on surface out of range...too low");
2650 0 : ShowContinueError(state, "This is a diagnostic error that should not be encountered under normal circumstances");
2651 0 : ShowContinueError(state, format("Occurs on surface: {}", s_surf->Surface(SurfNum).Name));
2652 0 : ShowContinueError(state, format("Current value = {} ... should be within [-1, +1]", CosIncAngBeamOnSurface));
2653 0 : ShowFatalError(state, "Anisotropic solar calculation causes fatal error");
2654 : }
2655 0 : CosIncAngBeamOnSurface = -1.0;
2656 : }
2657 :
2658 391186 : ViewFactorSkyGeom = s_surf->Surface(SurfNum).ViewFactorSky;
2659 391186 : state.dataSolarShading->SurfMultIsoSky(SurfNum) = ViewFactorSkyGeom * (1.0 - F1);
2660 : // 0.0871557 below corresponds to a zenith angle of 85 deg
2661 391186 : CircumSolarFac = max(0.0, CosIncAngBeamOnSurface) / max(0.0871557, CosZenithAng);
2662 : // For near-horizontal roofs, model has an inconsistency that gives sky diffuse
2663 : // irradiance significantly different from DifSolarRad when zenith angle is
2664 : // above 85 deg. The following forces irradiance to be very close to DifSolarRad
2665 : // in this case.
2666 391186 : if (CircumSolarFac > 0.0 && CosZenithAng < 0.0871557 && s_surf->Surface(SurfNum).Tilt < 2.0) CircumSolarFac = 1.0;
2667 391186 : state.dataSolarShading->SurfMultCircumSolar(SurfNum) = F1 * CircumSolarFac;
2668 391186 : state.dataSolarShading->SurfMultHorizonZenith(SurfNum) = F2 * s_surf->Surface(SurfNum).SinTilt;
2669 :
2670 391186 : if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm || !s_surf->ShadingTransmittanceVaries ||
2671 0 : state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
2672 391186 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum) =
2673 391186 : state.dataSolarShading->SurfMultIsoSky(SurfNum) * state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) +
2674 391186 : state.dataSolarShading->SurfMultCircumSolar(SurfNum) *
2675 391186 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) +
2676 391186 : state.dataSolarShading->SurfMultHorizonZenith(SurfNum) * state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum);
2677 : } else {
2678 0 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum) =
2679 0 : state.dataSolarShading->SurfMultIsoSky(SurfNum) *
2680 0 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum) +
2681 0 : state.dataSolarShading->SurfMultCircumSolar(SurfNum) *
2682 0 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) +
2683 0 : state.dataSolarShading->SurfMultHorizonZenith(SurfNum) *
2684 0 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum);
2685 0 : state.dataSolarShading->SurfCurDifShdgRatioIsoSky(SurfNum) =
2686 0 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum);
2687 : }
2688 391186 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum) = max(0.0, state.dataSolarShading->SurfAnisoSkyMult(SurfNum)); // make sure not negative.
2689 : }
2690 71212 : }
2691 :
2692 43 : void CHKBKS(EnergyPlusData &state,
2693 : int const NBS, // Surface Number of the potential back surface
2694 : int const NRS // Surface Number of the potential shadow receiving surface
2695 : )
2696 : {
2697 :
2698 : // SUBROUTINE INFORMATION:
2699 : // AUTHOR Legacy Code
2700 : // DATE WRITTEN
2701 : // MODIFIED Nov 2001, FW: Reverse subroutine arguments NRS and NBS to
2702 : // correspond to how CHKBKS is called
2703 : // Jan 2002, FW: change error message
2704 : // RE-ENGINEERED Lawrie, Oct 2000
2705 : // Sep 2020: Revised the vector computation method to reliably produce CVec,
2706 : // and simplified the warning messages.
2707 :
2708 : // PURPOSE OF THIS SUBROUTINE:
2709 : // Determines whether a any vertices of the back surface are in front of the receiving surface;
2710 : // if so, gives severe error. Only base heat transfer surfaces are checked.
2711 :
2712 : // METHODOLOGY EMPLOYED:
2713 : // na
2714 :
2715 : // REFERENCES:
2716 : // BLAST/IBLAST code, original author George Walton
2717 :
2718 : // Using/Aliasing
2719 : using namespace Vectors;
2720 :
2721 : int N; // Loop Control (vertex counter)
2722 : int NVRS; // Number of vertices of the receiving surface
2723 : int NVBS; // Number of vertices of the back surface
2724 : Real64 DOTP; // Dot product of C and D
2725 :
2726 : // Object Data
2727 43 : Vector CVec(0.0); // Vector perpendicular to surface at vertex 1
2728 43 : Vector DVec(0.0); // Vector from vertex 1 of first surface to vertex 'n' of second surface
2729 :
2730 43 : auto &s_surf = state.dataSurface;
2731 :
2732 43 : NVRS = s_surf->Surface(NRS).Sides;
2733 43 : NVBS = s_surf->Surface(NBS).Sides;
2734 :
2735 : // SEE IF ANY VERTICES OF THE back surface ARE IN FRONT OF THE receiving surface
2736 :
2737 133 : for (N = 2; N < NVRS; N++) {
2738 180 : CVec += cross(s_surf->Surface(NRS).Vertex(N) - s_surf->Surface(NRS).Vertex(1),
2739 270 : s_surf->Surface(NRS).Vertex((N + 1)) - s_surf->Surface(NRS).Vertex(1));
2740 : }
2741 43 : CVec /= (NVRS >= 3 ? NVRS : 3);
2742 :
2743 171 : for (N = 1; N <= NVBS; ++N) {
2744 144 : DVec = s_surf->Surface(NBS).Vertex(N) - s_surf->Surface(NRS).Vertex(1);
2745 144 : DOTP = dot(CVec, DVec);
2746 144 : if (DOTP > 0.0009) {
2747 32 : ShowSevereError(state, "Problem in interior solar distribution calculation (CHKBKS)");
2748 16 : ShowContinueError(state, format(" Solar Distribution = FullInteriorExterior will not work in Zone={}", s_surf->Surface(NRS).ZoneName));
2749 32 : ShowContinueError(state,
2750 32 : format(" because one or more of vertices, such as Vertex {} of back surface={}, is in front of receiving surface={}",
2751 : N,
2752 16 : s_surf->Surface(NBS).Name,
2753 16 : s_surf->Surface(NRS).Name));
2754 16 : ShowContinueError(state, format(" (Dot Product indicator={:20.4F})", DOTP));
2755 32 : ShowContinueError(state,
2756 : " Check surface geometry; if OK, use Solar Distribution = FullExterior instead. Use Output:Diagnostics, "
2757 : "DisplayExtraWarnings; for more details.");
2758 16 : if (!state.dataGlobal->DisplayExtraWarnings) break;
2759 : }
2760 : }
2761 43 : }
2762 :
2763 2568 : void CHKGSS(EnergyPlusData &state,
2764 : int const NRS, // Surface number of the potential shadow receiving surface
2765 : int const NSS, // Surface number of the potential shadow casting surface
2766 : Real64 const ZMIN, // Lowest point of the receiving surface
2767 : bool &CannotShade // TRUE if shadow casting surface cannot shade receiving surface.
2768 : )
2769 : {
2770 :
2771 : // SUBROUTINE INFORMATION:
2772 : // AUTHOR Legacy Code
2773 : // DATE WRITTEN
2774 : // MODIFIED na
2775 : // RE-ENGINEERED Lawrie, Oct 2000
2776 :
2777 : // PURPOSE OF THIS SUBROUTINE:
2778 : // Determines the possible shadowing combinations. The
2779 : // routine checks detached shadowing or base heat transfer surfaces
2780 : // for the possibility that they cannot shade a given base heat transfer surface.
2781 :
2782 : // METHODOLOGY EMPLOYED:
2783 : // Shadowing is not possible if:
2784 : // 1. The lowest point of the shadow receiving surface (receiving surface)
2785 : // Is higher than the highest point of the shadow casting surface (s.s.)
2786 : // 2. The shadow casting surface Faces up (e.g. A flat roof)
2787 : // 3. The shadow casting surface Is behind the receiving surface
2788 : // 4. The receiving surface is behind the shadow casting surface
2789 :
2790 : // REFERENCES:
2791 : // BLAST/IBLAST code, original author George Walton
2792 :
2793 : // Using/Aliasing
2794 : using namespace Vectors;
2795 :
2796 : // Object Data
2797 :
2798 2568 : CannotShade = true;
2799 :
2800 2568 : auto &s_surf = state.dataSurface;
2801 :
2802 : // see if no point of shadow casting surface is above low point of receiving surface
2803 :
2804 2568 : auto const &surface_C = s_surf->Surface(NSS);
2805 3262 : if (surface_C.OutNormVec(3) > 0.9999) return; // Shadow Casting Surface is horizontal and facing upward
2806 2062 : auto const &vertex_C = surface_C.Vertex;
2807 2062 : Real64 ZMAX(vertex_C(1).z);
2808 8282 : for (int i = 2, e = surface_C.Sides; i <= e; ++i) {
2809 6220 : ZMAX = std::max(ZMAX, vertex_C(i).z);
2810 : }
2811 2062 : if (ZMAX <= ZMIN) return;
2812 :
2813 : // SEE IF ANY VERTICES OF THE Shadow Casting Surface ARE ABOVE THE PLANE OF THE receiving surface
2814 :
2815 1368 : auto const &surface_R = s_surf->Surface(NRS);
2816 1368 : auto const &vertex_R = surface_R.Vertex;
2817 1368 : Vector const &vertex_R_2 = vertex_R(2);
2818 1368 : Vector const AVec = (vertex_R(1) - vertex_R_2); // Vector from vertex 2 to vertex 1 of receiving surface
2819 1368 : Vector const BVec = (vertex_R(3) - vertex_R_2); // Vector from vertex 2 to vertex 3 of receiving surface
2820 :
2821 1368 : Vector const CVec = cross(BVec, AVec); // Vector perpendicular to surface at vertex 2
2822 :
2823 1368 : int const NVSS = surface_C.Sides; // Number of vertices of the shadow casting surface
2824 1368 : Real64 DOTP(0.0); // Dot Product
2825 5725 : for (int I = 1; I <= NVSS; ++I) {
2826 4662 : DOTP = dot(CVec, vertex_C(I) - vertex_R_2);
2827 4662 : if (DOTP > state.dataSolarShading->TolValue) break; // DO loop
2828 : }
2829 :
2830 : // SEE IF ANY VERTICES OF THE receiving surface ARE ABOVE THE PLANE OF THE S.S.
2831 :
2832 1368 : if (DOTP > state.dataSolarShading->TolValue) {
2833 :
2834 305 : Vector const &vertex_C_2 = vertex_C(2);
2835 305 : Vector const AVec(vertex_C(1) - vertex_C_2);
2836 305 : Vector const BVec(vertex_C(3) - vertex_C_2);
2837 :
2838 305 : Vector const CVec(cross(BVec, AVec));
2839 :
2840 305 : int const NVRS = surface_R.Sides; // Number of vertices of the receiving surface
2841 1097 : for (int I = 1; I <= NVRS; ++I) {
2842 918 : DOTP = dot(CVec, vertex_R(I) - vertex_C_2);
2843 918 : if (DOTP > state.dataSolarShading->TolValue) {
2844 126 : CannotShade = false;
2845 126 : break; // DO loop
2846 : }
2847 : }
2848 305 : }
2849 1368 : }
2850 :
2851 70 : void CHKSBS(EnergyPlusData &state,
2852 : int const HTS, // Heat transfer surface number of the general receiving surf
2853 : int const GRSNR, // Surface number of general receiving surface
2854 : int const SBSNR // Surface number of subsurface
2855 : )
2856 : {
2857 :
2858 : // SUBROUTINE INFORMATION:
2859 : // AUTHOR Legacy Code
2860 : // DATE WRITTEN
2861 : // MODIFIED na
2862 : // RE-ENGINEERED Lawrie, Oct 2000
2863 :
2864 : // PURPOSE OF THIS SUBROUTINE:
2865 : // Checks that a subsurface is completely
2866 : // enclosed by its base surface.
2867 :
2868 : // REFERENCES:
2869 : // BLAST/IBLAST code, original author George Walton
2870 :
2871 : // 3D Planar Polygons
2872 : // In 3D applications, one sometimes wants to test a point and polygon that are in the same plane.
2873 : // For example, one may have the intersection point of a ray with the plane of a polyhedron's face,
2874 : // and want to test if it is inside the face. Or one may want to know if the base of a 3D perpendicular
2875 : // dropped from a point is inside a planar polygon.
2876 :
2877 : // 3D inclusion is easily determined by projecting the point and polygon into 2D. To do this, one simply
2878 : // ignores one of the 3D coordinates and uses the other two. To optimally select the coordinate to ignore,
2879 : // compute a normal vector to the plane, and select the coordinate with the largest absolute value [Snyder & Barr, 1987].
2880 : // This gives the projection of the polygon with maximum area, and results in robust computations.
2881 : // John M. Snyder & Alan H. Barr, "Ray Tracing Complex Models Containing Surface Tessellations",
2882 : // Computer Graphics 21(4), 119-126 (1987) [also in the Proceedings of SIGGRAPH 1987]
2883 : //--- using adapted routine from Triangulation code -- EnergyPlus.
2884 :
2885 : // MSG - for error message
2886 70 : static Array1D_string const MSG(4, {"misses", "", "within", "overlaps"});
2887 :
2888 : int N; // Loop Control
2889 : int NVT; // Number of vertices
2890 : int NS1; // Number of the figure being overlapped
2891 : int NS2; // Number of the figure doing overlapping
2892 : int NS3; // Location to place results of overlap
2893 :
2894 : bool inside;
2895 :
2896 : bool Out;
2897 : Real64 X1; // ,SX,SY,SZ
2898 : Real64 Y1;
2899 : Real64 Z1;
2900 : Real64 X2;
2901 : Real64 Y2;
2902 : Real64 Z2;
2903 : Real64 BX;
2904 : Real64 BY;
2905 : Real64 BZ;
2906 : Real64 BMAX;
2907 : // INTEGER M
2908 :
2909 70 : auto &s_surf = state.dataSurface;
2910 :
2911 70 : if (state.dataSolarShading->CHKSBSOneTimeFlag) {
2912 33 : state.dataSolarShading->XVT.allocate(s_surf->MaxVerticesPerSurface + 1);
2913 33 : state.dataSolarShading->YVT.allocate(s_surf->MaxVerticesPerSurface + 1);
2914 33 : state.dataSolarShading->ZVT.allocate(s_surf->MaxVerticesPerSurface + 1);
2915 33 : state.dataSolarShading->XVT = 0.0;
2916 33 : state.dataSolarShading->YVT = 0.0;
2917 33 : state.dataSolarShading->ZVT = 0.0;
2918 33 : state.dataSolarShading->CHKSBSOneTimeFlag = false;
2919 : }
2920 :
2921 70 : NS1 = 1;
2922 70 : NS2 = 2;
2923 70 : NS3 = 3;
2924 70 : state.dataSolarShading->HCT(1) = 0.0;
2925 70 : state.dataSolarShading->HCT(2) = 0.0;
2926 :
2927 : // Put coordinates of base surface into clockwise sequence on the x'-y' plane.
2928 :
2929 70 : state.dataSolarShading->XVT = 0.0;
2930 70 : state.dataSolarShading->YVT = 0.0;
2931 70 : state.dataSolarShading->ZVT = 0.0;
2932 70 : state.dataSolarShading->XVS = 0.0;
2933 70 : state.dataSolarShading->YVS = 0.0;
2934 70 : CTRANS(state, GRSNR, HTS, NVT, state.dataSolarShading->XVT, state.dataSolarShading->YVT, state.dataSolarShading->ZVT);
2935 350 : for (N = 1; N <= NVT; ++N) {
2936 280 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVT(NVT + 1 - N);
2937 280 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVT(NVT + 1 - N);
2938 : }
2939 :
2940 70 : HTRANS1(state, NS2, NVT);
2941 :
2942 : // Put coordinates of the subsurface into clockwise sequence.
2943 :
2944 70 : state.dataSolarShading->NVS = s_surf->Surface(SBSNR).Sides;
2945 350 : for (N = 1; N <= state.dataSolarShading->NVS; ++N) {
2946 280 : state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(state.dataSolarShading->NVS + 1 - N);
2947 280 : state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(state.dataSolarShading->NVS + 1 - N);
2948 : }
2949 70 : HTRANS1(state, NS1, state.dataSolarShading->NVS);
2950 :
2951 : // Determine the overlap condition.
2952 :
2953 70 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
2954 :
2955 : // Print error condition if necessary.
2956 :
2957 70 : if (state.dataSolarShading->OverlapStatus != FirstSurfWithinSecond) {
2958 0 : Out = false;
2959 : // C COMPUTE COMPONENTS OF VECTOR
2960 : // C NORMAL TO BASE SURFACE.
2961 0 : X1 = s_surf->Surface(GRSNR).Vertex(1).x - s_surf->Surface(GRSNR).Vertex(2).x; // XV(1,GRSNR)-XV(2,GRSNR)
2962 0 : Y1 = s_surf->Surface(GRSNR).Vertex(1).y - s_surf->Surface(GRSNR).Vertex(2).y; // YV(1,GRSNR)-YV(2,GRSNR)
2963 0 : Z1 = s_surf->Surface(GRSNR).Vertex(1).z - s_surf->Surface(GRSNR).Vertex(2).z; // ZV(1,GRSNR)-ZV(2,GRSNR)
2964 0 : X2 = s_surf->Surface(GRSNR).Vertex(3).x - s_surf->Surface(GRSNR).Vertex(2).x; // XV(3,GRSNR)-XV(2,GRSNR)
2965 0 : Y2 = s_surf->Surface(GRSNR).Vertex(3).y - s_surf->Surface(GRSNR).Vertex(2).y; // YV(3,GRSNR)-YV(2,GRSNR)
2966 0 : Z2 = s_surf->Surface(GRSNR).Vertex(3).z - s_surf->Surface(GRSNR).Vertex(2).z; // ZV(3,GRSNR)-ZV(2,GRSNR)
2967 0 : BX = Y1 * Z2 - Y2 * Z1;
2968 0 : BY = Z1 * X2 - Z2 * X1;
2969 0 : BZ = X1 * Y2 - X2 * Y1;
2970 : // C FIND LARGEST COMPONENT.
2971 0 : BMAX = max(std::abs(BX), std::abs(BY), std::abs(BZ));
2972 : // C
2973 0 : if (std::abs(BX) == BMAX) {
2974 : // write(outputfiledebug,*) ' looking bx-bmax',bmax
2975 0 : for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
2976 0 : inside = polygon_contains_point(
2977 0 : s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), true, false, false);
2978 0 : if (!inside) {
2979 0 : Out = true;
2980 : // do m=1,surface(grsnr)%sides
2981 : // write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
2982 : // write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
2983 : // enddo
2984 : // EXIT
2985 : }
2986 : // Y1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(NV(GRSNR),GRSNR)-YV(N,SBSNR)
2987 : // Z1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(NV(GRSNR),GRSNR)-ZV(N,SBSNR)
2988 : // DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
2989 : // Y2 = Y1
2990 : // Z2 = Z1
2991 : // Y1 = Surface(GRSNR)%Vertex(M)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(M,GRSNR)-YV(N,SBSNR)
2992 : // Z1 = Surface(GRSNR)%Vertex(M)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(M,GRSNR)-ZV(N,SBSNR)
2993 : // SX = Y1*Z2-Y2*Z1
2994 : // IF(SX*BX.LT.-1.0d-6) THEN
2995 : // OUT=.TRUE.
2996 : // write(outputfiledebug,*) 'sx*bx=',sx*bx
2997 : // write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
2998 : // write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
2999 : // endif
3000 : // ENDDO
3001 : // IF (OUT) EXIT
3002 : }
3003 0 : } else if (std::abs(BY) == BMAX) {
3004 : // write(outputfiledebug,*) ' looking by-bmax',bmax
3005 0 : for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
3006 0 : inside = polygon_contains_point(
3007 0 : s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), false, true, false);
3008 0 : if (!inside) {
3009 0 : Out = true;
3010 : // do m=1,surface(grsnr)%sides
3011 : // write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
3012 : // write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
3013 : // enddo
3014 : // EXIT
3015 : }
3016 : // Z1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(NV(GRSNR),GRSNR)-ZV(N,SBSNR)
3017 : // X1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%X-Surface(SBSNR)%Vertex(N)%X !XV(NV(GRSNR),GRSNR)-XV(N,SBSNR)
3018 : // DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
3019 : // Z2 = Z1
3020 : // X2 = X1
3021 : // Z1 = Surface(GRSNR)%Vertex(M)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(M,GRSNR)-ZV(N,SBSNR)
3022 : // X1 = Surface(GRSNR)%Vertex(M)%X-Surface(SBSNR)%Vertex(N)%X !XV(M,GRSNR)-XV(N,SBSNR)
3023 : // SY = Z1*X2-Z2*X1
3024 : // IF(SY*BY.LT.-1.0d-6) THEN
3025 : // OUT=.TRUE.
3026 : // write(outputfiledebug,*) 'sy*by=',sy*by
3027 : // write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
3028 : // write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
3029 : // ENDIF
3030 : // ENDDO
3031 : // IF (OUT) EXIT
3032 : }
3033 : } else {
3034 : // write(outputfiledebug,*) ' looking bz-bmax',bmax
3035 0 : for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
3036 0 : inside = polygon_contains_point(
3037 0 : s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), false, false, true);
3038 0 : if (!inside) {
3039 0 : Out = true;
3040 : // do m=1,surface(grsnr)%sides
3041 : // write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
3042 : // write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
3043 : // enddo
3044 : // EXIT
3045 : }
3046 : // X1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%X-Surface(SBSNR)%Vertex(N)%X !XV(NV(GRSNR),GRSNR)-XV(N,SBSNR)
3047 : // Y1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(NV(GRSNR),GRSNR)-YV(N,SBSNR)
3048 : // DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
3049 : // X2 = X1
3050 : // Y2 = Y1
3051 : // X1 = Surface(GRSNR)%Vertex(M)%X-Surface(SBSNR)%Vertex(N)%X !XV(M,GRSNR)-XV(N,SBSNR)
3052 : // Y1 = Surface(GRSNR)%Vertex(M)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(M,GRSNR)-YV(N,SBSNR)
3053 : // SZ = X1*Y2-X2*Y1
3054 : // IF(SZ*BZ.LT.-1.0d-6) THEN
3055 : // OUT=.TRUE.
3056 : // write(outputfiledebug,*) 'sz*bz=',sz*bz
3057 : // write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
3058 : // write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
3059 : // ENDIF
3060 : // ENDDO
3061 : // IF (OUT) EXIT
3062 : }
3063 : }
3064 : // CALL ShowWarningError(state, 'Base surface does not surround subsurface (CHKSBS), Overlap Status='// &
3065 : // TRIM(cOverLapStatus(OverlapStatus)))
3066 : // CALL ShowContinueError(state, 'Surface "'//TRIM(Surface(GRSNR)%Name)//'" '//TRIM(MSG(OverlapStatus))// &
3067 : // ' SubSurface "'//TRIM(Surface(SBSNR)%Name)//'"')
3068 : // IF (FirstSurroundError) THEN
3069 : // CALL ShowWarningError(state, 'Base Surface does not surround subsurface errors occurring...'// &
3070 : // 'Check that the SurfaceGeometry object is expressing the proper starting corner and '// &
3071 : // 'direction [CounterClockwise/Clockwise]')
3072 : // FirstSurroundError=.FALSE.
3073 : // ENDIF
3074 0 : if (Out) {
3075 0 : state.dataSolarShading->TrackBaseSubSurround.redimension(++state.dataSolarShading->NumBaseSubSurround);
3076 0 : state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).SurfIndex1 = GRSNR;
3077 0 : state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).SurfIndex2 = SBSNR;
3078 0 : state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).MiscIndex =
3079 0 : state.dataSolarShading->OverlapStatus;
3080 : // CALL ShowRecurringWarningErrorAtEnd(state, 'Base surface does not surround subsurface (CHKSBS), Overlap Status='// &
3081 : // TRIM(cOverLapStatus(OverlapStatus)), &
3082 : // TrackBaseSubSurround(GRSNR)%ErrIndex1)
3083 : // CALL ShowRecurringContinueErrorAtEnd(state, 'Surface "'//TRIM(Surface(GRSNR)%Name)//'" '//TRIM(MSG(OverlapStatus))// &
3084 : // ' SubSurface "'//TRIM(Surface(SBSNR)%Name)//'"', &
3085 : // TrackBaseSubSurround(SBSNR)%ErrIndex2)
3086 0 : if (state.dataSolarShading->shd_stream) {
3087 0 : *state.dataSolarShading->shd_stream << "==== Base does not Surround subsurface details ====\n";
3088 0 : *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(GRSNR).Name << ' '
3089 0 : << state.dataSolarShading->cOverLapStatus(state.dataSolarShading->OverlapStatus) << '\n';
3090 0 : *state.dataSolarShading->shd_stream << "Surface#=" << std::setw(5) << GRSNR << " NSides=" << std::setw(5)
3091 0 : << s_surf->Surface(GRSNR).Sides << '\n';
3092 0 : *state.dataSolarShading->shd_stream << std::fixed << std::setprecision(2);
3093 0 : for (N = 1; N <= s_surf->Surface(GRSNR).Sides; ++N) {
3094 0 : Vector const &v(s_surf->Surface(GRSNR).Vertex(N));
3095 0 : *state.dataSolarShading->shd_stream << "Vertex " << std::setw(5) << N << "=(" << std::setw(15) << v.x << ',' << std::setw(15)
3096 0 : << v.y << ',' << std::setw(15) << v.z << ")\n";
3097 : }
3098 0 : *state.dataSolarShading->shd_stream << "SubSurface=" << s_surf->Surface(SBSNR).Name << '\n';
3099 0 : *state.dataSolarShading->shd_stream << "Surface#=" << std::setw(5) << SBSNR << " NSides=" << std::setw(5)
3100 0 : << s_surf->Surface(SBSNR).Sides << '\n';
3101 0 : for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) {
3102 0 : Vector const &v(s_surf->Surface(SBSNR).Vertex(N));
3103 0 : *state.dataSolarShading->shd_stream << "Vertex " << std::setw(5) << N << "=(" << std::setw(15) << v.x << ',' << std::setw(15)
3104 0 : << v.y << ',' << std::setw(15) << v.z << ")\n";
3105 : }
3106 0 : *state.dataSolarShading->shd_stream << "================================\n";
3107 : }
3108 : }
3109 : }
3110 70 : }
3111 :
3112 6 : bool polygon_contains_point(int const nsides, // number of sides (vertices)
3113 : Array1D<Vector> &polygon_3d, // points of polygon
3114 : Vector const &point_3d, // point to be tested
3115 : bool const ignorex,
3116 : bool const ignorey,
3117 : bool const ignorez)
3118 : {
3119 :
3120 : // Function information:
3121 : // Author Linda Lawrie
3122 : // Date written October 2005
3123 : // Modified na
3124 : // Re-engineered na
3125 :
3126 : // Purpose of this function:
3127 : // Determine if a point is inside a simple 2d polygon. For a simple polygon (one whose
3128 : // boundary never crosses itself). The polygon does not need to be convex.
3129 :
3130 : // References:
3131 : // M Shimrat, Position of Point Relative to Polygon, ACM Algorithm 112,
3132 : // Communications of the ACM, Volume 5, Number 8, page 434, August 1962.
3133 :
3134 : // Use statements:
3135 : // Using/Aliasing
3136 : using namespace DataVectorTypes;
3137 :
3138 : // return value, true=inside, false = not inside
3139 :
3140 6 : EP_SIZE_CHECK(polygon_3d, nsides);
3141 :
3142 : int ip1;
3143 :
3144 : // Object Data
3145 6 : Array1D<Vector_2d> polygon(nsides);
3146 6 : Vector_2d point;
3147 :
3148 6 : bool inside = false;
3149 6 : if (ignorex) {
3150 10 : for (int i = 1; i <= nsides; ++i) {
3151 8 : polygon(i).x = polygon_3d(i).y;
3152 8 : polygon(i).y = polygon_3d(i).z;
3153 : }
3154 2 : point.x = point_3d.y;
3155 2 : point.y = point_3d.z;
3156 4 : } else if (ignorey) {
3157 10 : for (int i = 1; i <= nsides; ++i) {
3158 8 : polygon(i).x = polygon_3d(i).x;
3159 8 : polygon(i).y = polygon_3d(i).z;
3160 : }
3161 2 : point.x = point_3d.x;
3162 2 : point.y = point_3d.z;
3163 2 : } else if (ignorez) {
3164 10 : for (int i = 1; i <= nsides; ++i) {
3165 8 : polygon(i).x = polygon_3d(i).x;
3166 8 : polygon(i).y = polygon_3d(i).y;
3167 : }
3168 2 : point.x = point_3d.x;
3169 2 : point.y = point_3d.y;
3170 : } else { // Illegal
3171 0 : assert(false);
3172 : point.x = point.y = 0.0; // Elim possibly used uninitialized warnings
3173 : }
3174 :
3175 30 : for (int i = 1; i <= nsides; ++i) {
3176 :
3177 24 : if (i < nsides) {
3178 18 : ip1 = i + 1;
3179 : } else {
3180 6 : ip1 = 1;
3181 : }
3182 :
3183 24 : if ((polygon(i).y < point.y && point.y <= polygon(ip1).y) || (point.y <= polygon(i).y && polygon(ip1).y < point.y)) {
3184 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) {
3185 3 : inside = !inside;
3186 : }
3187 : }
3188 : }
3189 :
3190 6 : return inside;
3191 6 : }
3192 :
3193 104 : void ComputeIntSolarAbsorpFactors(EnergyPlusData &state)
3194 : {
3195 :
3196 : // SUBROUTINE INFORMATION:
3197 : // AUTHOR Legacy Code
3198 : // MODIFIED B. Griffith, Oct 2010, deal with no floor case
3199 : // L. Lawrie, Mar 2012, relax >154 tilt even further (>120 considered non-wall by ASHRAE)
3200 : // RE-ENGINEERED Lawrie, Oct 2000
3201 :
3202 : // PURPOSE OF THIS SUBROUTINE:
3203 : // This routine computes the fractions of diffusely transmitted
3204 : // solar energy absorbed by each zone surface.
3205 :
3206 : // METHODOLOGY EMPLOYED:
3207 : // It is assumed that all transmitted solar energy is incident
3208 : // on the floors of the zone (or enclosure). The fraction directly absorbed in
3209 : // the floor is given by 'ISABSF'. It is proportional to the
3210 : // area * solar absorptance. The remaining solar energy is then
3211 : // distributed uniformly around the room according to
3212 : // area*absorptance product
3213 :
3214 : // REFERENCES:
3215 : // BLAST/IBLAST code, original author George Walton
3216 :
3217 : using namespace DataWindowEquivalentLayer;
3218 :
3219 : Real64 AreaSum; // Intermediate calculation value
3220 : int Lay; // Window glass layer number
3221 : Real64 AbsDiffTotWin; // Sum of a window's glass layer solar absorptances
3222 : Real64 TestFractSum;
3223 : Real64 HorizAreaSum;
3224 :
3225 104 : auto &s_surf = state.dataSurface;
3226 :
3227 236 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
3228 132 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
3229 :
3230 132 : AreaSum = 0.0;
3231 132 : TestFractSum = 0.0;
3232 844 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
3233 712 : if (state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType == StandardZone && s_surf->Surface(SurfNum).CosTilt < -0.5) {
3234 145 : AreaSum += s_surf->Surface(SurfNum).Area;
3235 : }
3236 : }
3237 :
3238 132 : HorizAreaSum = AreaSum;
3239 :
3240 132 : if ((thisEnclosure.FloorArea <= 0.0) && (HorizAreaSum > 0.0)) {
3241 : // fill floor area even though surfs not called "Floor", they are roughly horizontal and face upwards.
3242 0 : thisEnclosure.FloorArea = HorizAreaSum;
3243 0 : ShowWarningError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
3244 0 : ShowContinueError(state, format("...Enclosure=\"{}\" has no floor, but has approximate horizontal surfaces.", thisEnclosure.Name));
3245 0 : ShowContinueError(state, format("...these Tilt > 120 degrees, (area=[{:.2R}] m2) will be used.", HorizAreaSum));
3246 : }
3247 :
3248 : // Compute ISABSF
3249 :
3250 844 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
3251 :
3252 : // only horizontal surfaces. ! !CR 8229, relaxed from -0.99 to -0.5 (Tilt > 154)
3253 : // only horizontal surfaces. ! !CR8769 use ASHRAE std of >120, -0.9 to -0.5 (Tilt > 120)
3254 857 : if ((state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType != StandardZone || s_surf->Surface(SurfNum).CosTilt < -0.5) &&
3255 145 : (state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType == StandardZone || s_surf->Surface(SurfNum).ExtBoundCond > 0)) {
3256 :
3257 145 : int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
3258 145 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
3259 : // last minute V3.1
3260 145 : if (thisConstruct.TransDiff <= 0.0) { // Opaque surface
3261 143 : if (AreaSum > 0.0)
3262 143 : state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * thisConstruct.InsideAbsorpSolar / AreaSum;
3263 : } else { // Window (floor windows are assumed to have no shading device and no divider,
3264 : // and assumed to be non-switchable)
3265 2 : AbsDiffTotWin = 0.0;
3266 2 : if (!state.dataConstruction->Construct(s_surf->Surface(SurfNum).Construction).WindowTypeEQL) {
3267 6 : for (Lay = 1; Lay <= thisConstruct.TotGlassLayers; ++Lay) {
3268 4 : AbsDiffTotWin += thisConstruct.AbsDiffBack(Lay);
3269 : }
3270 : } else {
3271 0 : for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(thisConstruct.EQLConsPtr).NL; ++Lay) {
3272 0 : AbsDiffTotWin += thisConstruct.AbsDiffBackEQL(Lay);
3273 : }
3274 : }
3275 2 : if (AreaSum > 0.0) state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * AbsDiffTotWin / AreaSum;
3276 : }
3277 : }
3278 : // CR 8229 test ISABSF for problems
3279 712 : TestFractSum += state.dataSolarShading->SurfIntAbsFac(SurfNum);
3280 : }
3281 :
3282 132 : if (TestFractSum <= 0.0) {
3283 9 : if (thisEnclosure.ExtWindowArea > 0.0) { // we have a problem, the sun has no floor to go to
3284 3 : if (thisEnclosure.FloorArea <= 0.0) {
3285 0 : ShowSevereError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
3286 0 : ShowContinueError(state, format("but Zone or Enclosure =\"{}\" does not appear to have any floor surfaces.", thisEnclosure.Name));
3287 0 : ShowContinueError(state, "Solar gains will be spread evenly on all surfaces in the zone, and the simulation continues...");
3288 : } else { // Floor Area > 0 but still can't absorb
3289 6 : ShowSevereError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
3290 3 : ShowContinueError(state, format("but Zone or Enclosure =\"{}\" floor cannot absorb any solar gains. ", thisEnclosure.Name));
3291 6 : ShowContinueError(state, "Check the solar absorptance of the inside layer of the floor surface construction/material.");
3292 9 : ShowContinueError(state, "Solar gains will be spread evenly on all surfaces in the zone, and the simulation continues...");
3293 : }
3294 :
3295 : // try again but use an even spread across all the surfaces in the zone, regardless of horizontal
3296 : // so as to not lose solar energy
3297 3 : AreaSum = 0.0;
3298 3 : for (int SurfNum : thisEnclosure.SurfacePtr) {
3299 0 : AreaSum += s_surf->Surface(SurfNum).Area;
3300 : }
3301 :
3302 3 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
3303 0 : int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
3304 0 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
3305 0 : if (thisConstruct.TransDiff <= 0.0) { // Opaque surface
3306 0 : if (AreaSum > 0.0)
3307 0 : state.dataSolarShading->SurfIntAbsFac(SurfNum) =
3308 0 : s_surf->Surface(SurfNum).Area * thisConstruct.InsideAbsorpSolar / AreaSum;
3309 : } else { // Window (floor windows are assumed to have no shading device and no divider,
3310 : // and assumed to be non-switchable)
3311 0 : AbsDiffTotWin = 0.0;
3312 0 : if (!state.dataConstruction->Construct(s_surf->Surface(SurfNum).Construction).WindowTypeEQL) {
3313 0 : for (Lay = 1; Lay <= thisConstruct.TotGlassLayers; ++Lay) {
3314 0 : AbsDiffTotWin += thisConstruct.AbsDiffBack(Lay);
3315 : }
3316 : } else {
3317 0 : for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(thisConstruct.EQLConsPtr).NL; ++Lay) {
3318 0 : AbsDiffTotWin += thisConstruct.AbsDiffBackEQL(Lay);
3319 : }
3320 : }
3321 :
3322 0 : if (AreaSum > 0.0) state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * AbsDiffTotWin / AreaSum;
3323 : }
3324 : }
3325 : }
3326 : }
3327 :
3328 : } // enclosure loop
3329 104 : }
3330 :
3331 11826 : void CLIP(EnergyPlusData &state, int const NVT, Array1D<Real64> &XVT, Array1D<Real64> &YVT, Array1D<Real64> &ZVT)
3332 : {
3333 :
3334 : // SUBROUTINE INFORMATION:
3335 : // AUTHOR Legacy Code
3336 : // DATE WRITTEN
3337 : // MODIFIED na
3338 : // RE-ENGINEERED Lawrie, Oct 2000
3339 :
3340 : // PURPOSE OF THIS SUBROUTINE:
3341 : // This subroutine 'clips' the shadow casting surface polygon so that
3342 : // none of it lies below the plane of the receiving surface polygon. This
3343 : // prevents the casting of 'false' shadows.
3344 :
3345 : // REFERENCES:
3346 : // BLAST/IBLAST code, original author George Walton
3347 :
3348 11826 : int NABOVE(0); // Number of vertices of shadow casting surface. above the plane of receiving surface
3349 11826 : int NEXT(0); // First vertex above plane of receiving surface
3350 11826 : int NON(0); // Number of vertices of shadow casting surface. on plane of receiving surface
3351 11826 : Real64 XIN(0.0); // X of entry point of shadow casting surface. into plane of receiving surface
3352 11826 : Real64 XOUT(0.0); // X of exit point of shadow casting surface. from plane of receiving surface
3353 11826 : Real64 YIN(0.0); // Y of entry point of shadow casting surface. into plane of receiving surface
3354 11826 : Real64 YOUT(0.0); // Y of exit point of shadow casting surface. from plane of receiving surface
3355 : // INTEGER NVS ! Number of vertices of the shadow/clipped surface
3356 :
3357 : // Determine if the shadow casting surface. is above, below, or intersects with the plane of the receiving surface
3358 :
3359 11826 : state.dataSolarShading->NumVertInShadowOrClippedSurface = state.dataSolarShading->NVS;
3360 59098 : for (int N = 1; N <= NVT; ++N) {
3361 47272 : Real64 const ZVT_N(ZVT(N));
3362 47272 : if (ZVT_N > 0.0) {
3363 33104 : ++NABOVE;
3364 14168 : } else if (ZVT_N == 0.0) {
3365 6998 : ++NON;
3366 : }
3367 : }
3368 :
3369 11826 : if (NABOVE + NON == NVT) { // Rename the unclipped shadow casting surface.
3370 :
3371 8241 : state.dataSolarShading->NVS = NVT;
3372 8241 : state.dataSolarShading->NumVertInShadowOrClippedSurface = NVT;
3373 41173 : for (int N = 1; N <= NVT; ++N) {
3374 32932 : state.dataSolarShading->XVC(N) = XVT(N);
3375 32932 : state.dataSolarShading->YVC(N) = YVT(N);
3376 32932 : state.dataSolarShading->ZVC(N) = ZVT(N);
3377 : }
3378 :
3379 3585 : } else if (NABOVE == 0) { // Totally submerged shadow casting surface.
3380 :
3381 0 : state.dataSolarShading->NVS = 0;
3382 0 : state.dataSolarShading->NumVertInShadowOrClippedSurface = 0;
3383 :
3384 : } else { // Remove (clip) that portion of the shadow casting surface. which is below the receiving surface
3385 :
3386 3585 : state.dataSolarShading->NVS = NABOVE + 2;
3387 3585 : state.dataSolarShading->NumVertInShadowOrClippedSurface = NABOVE + 2;
3388 3585 : Real64 ZVT_N, ZVT_P(ZVT(1));
3389 3585 : XVT(NVT + 1) = XVT(1);
3390 3585 : YVT(NVT + 1) = YVT(1);
3391 3585 : ZVT(NVT + 1) = ZVT_P;
3392 17925 : for (int N = 1, P = 2; N <= NVT; ++N, ++P) {
3393 14340 : ZVT_N = ZVT_P;
3394 14340 : ZVT_P = ZVT(P);
3395 14340 : if (ZVT_N >= 0.0 && ZVT_P < 0.0) { // Line enters plane of receiving surface
3396 3585 : Real64 const ZVT_fac(1.0 / (ZVT_P - ZVT_N));
3397 3585 : XIN = (ZVT_P * XVT(N) - ZVT_N * XVT(P)) * ZVT_fac;
3398 3585 : YIN = (ZVT_P * YVT(N) - ZVT_N * YVT(P)) * ZVT_fac;
3399 14340 : } else if (ZVT_N <= 0.0 && ZVT_P > 0.0) { // Line exits plane of receiving surface
3400 3585 : NEXT = N + 1;
3401 3585 : Real64 const ZVT_fac(1.0 / (ZVT_P - ZVT_N));
3402 3585 : XOUT = (ZVT_P * XVT(N) - ZVT_N * XVT(P)) * ZVT_fac;
3403 3585 : YOUT = (ZVT_P * YVT(N) - ZVT_N * YVT(P)) * ZVT_fac;
3404 : }
3405 : }
3406 :
3407 : // Renumber the vertices of the clipped shadow casting surface. so they are still counter-clockwise sequential.
3408 :
3409 3585 : state.dataSolarShading->XVC(1) = XOUT; //? Verify that the IN and OUT values were ever set?
3410 3585 : state.dataSolarShading->YVC(1) = YOUT;
3411 3585 : state.dataSolarShading->ZVC(1) = 0.0;
3412 3585 : state.dataSolarShading->XVC(state.dataSolarShading->NVS) = XIN;
3413 3585 : state.dataSolarShading->YVC(state.dataSolarShading->NVS) = YIN;
3414 3585 : state.dataSolarShading->ZVC(state.dataSolarShading->NVS) = 0.0;
3415 10755 : for (int N = 1; N <= NABOVE; ++N) {
3416 7170 : if (NEXT > NVT) NEXT = 1;
3417 7170 : state.dataSolarShading->XVC(N + 1) = XVT(NEXT);
3418 7170 : state.dataSolarShading->YVC(N + 1) = YVT(NEXT);
3419 7170 : state.dataSolarShading->ZVC(N + 1) = ZVT(NEXT);
3420 7170 : ++NEXT;
3421 : }
3422 : }
3423 11826 : }
3424 :
3425 29799 : void CTRANS(EnergyPlusData &state,
3426 : int const NS, // Surface number whose vertex coordinates are being transformed
3427 : int const NGRS, // Base surface number for surface NS
3428 : int &NVT, // Number of vertices for surface NS
3429 : Array1D<Real64> &XVT, // XYZ coordinates of vertices of NS in plane of NGRS
3430 : Array1D<Real64> &YVT,
3431 : Array1D<Real64> &ZVT)
3432 : {
3433 :
3434 : // SUBROUTINE INFORMATION:
3435 : // AUTHOR Legacy Code
3436 : // DATE WRITTEN
3437 : // MODIFIED na
3438 : // RE-ENGINEERED Lawrie, Oct 2000
3439 :
3440 : // PURPOSE OF THIS SUBROUTINE:
3441 : // Transforms the general coordinates of the vertices
3442 : // of surface NS to coordinates in the plane of the receiving surface NGRS.
3443 : // See subroutine 'CalcCoordinateTransformation' SurfaceGeometry Module.
3444 :
3445 : // REFERENCES:
3446 : // BLAST/IBLAST code, original author George Walton
3447 : // NECAP subroutine 'SHADOW'
3448 :
3449 : Real64 Xdif; // Intermediate Result
3450 : Real64 Ydif; // Intermediate Result
3451 : Real64 Zdif; // Intermediate Result
3452 :
3453 29799 : auto &s_surf = state.dataSurface;
3454 :
3455 : // Tuned
3456 29799 : auto const &surface = s_surf->Surface(NS);
3457 29799 : auto const &base_surface = s_surf->Surface(NGRS);
3458 29799 : auto const &base_lcsx = base_surface.lcsx;
3459 29799 : auto const &base_lcsy = base_surface.lcsy;
3460 29799 : auto const &base_lcsz = base_surface.lcsz;
3461 29799 : Real64 const base_X0 = s_surf->X0(NGRS);
3462 29799 : Real64 const base_Y0 = s_surf->Y0(NGRS);
3463 29799 : Real64 const base_Z0 = s_surf->Z0(NGRS);
3464 :
3465 29799 : NVT = surface.Sides;
3466 :
3467 : // Perform transformation
3468 148963 : for (int N = 1; N <= NVT; ++N) {
3469 119164 : auto const &vertex = surface.Vertex(N);
3470 :
3471 119164 : Xdif = vertex.x - base_X0;
3472 119164 : Ydif = vertex.y - base_Y0;
3473 119164 : Zdif = vertex.z - base_Z0;
3474 :
3475 119164 : if (std::abs(Xdif) <= 1.E-15) Xdif = 0.0;
3476 119164 : if (std::abs(Ydif) <= 1.E-15) Ydif = 0.0;
3477 119164 : if (std::abs(Zdif) <= 1.E-15) Zdif = 0.0;
3478 :
3479 119164 : XVT(N) = base_lcsx.x * Xdif + base_lcsx.y * Ydif + base_lcsx.z * Zdif;
3480 119164 : YVT(N) = base_lcsy.x * Xdif + base_lcsy.y * Ydif + base_lcsy.z * Zdif;
3481 119164 : ZVT(N) = base_lcsz.x * Xdif + base_lcsz.y * Ydif + base_lcsz.z * Zdif;
3482 : }
3483 29799 : }
3484 :
3485 0 : void HTRANS(EnergyPlusData &state,
3486 : int const I, // Mode selector: 0 - Compute H.C. of sides
3487 : int const NS, // Figure Number
3488 : int const NumVertices // Number of vertices
3489 : )
3490 : {
3491 :
3492 : // SUBROUTINE INFORMATION:
3493 : // AUTHOR Legacy Code
3494 : // DATE WRITTEN
3495 : // MODIFIED na
3496 : // RE-ENGINEERED Lawrie, Oct 2000
3497 :
3498 : // PURPOSE OF THIS SUBROUTINE:
3499 : // This subroutine sets up the homogeneous coordinates.
3500 : // This routine converts the cartesian coordinates of a surface
3501 : // or shadow polygon to homogeneous coordinates. It also
3502 : // computes the area of the polygon.
3503 :
3504 : // METHODOLOGY EMPLOYED:
3505 : // Note: Original legacy code used integer arithmetic (tests in subroutines
3506 : // INCLOS and INTCPT are sensitive to round-off error). However, porting to Fortran 77
3507 : // (BLAST/IBLAST) required some variables to become REAL(r64) instead.
3508 :
3509 : // Notes on homogeneous coordinates:
3510 : // A point (X,Y) is represented by a 3-element vector
3511 : // (W*X,W*Y,W), where W may be any REAL(r64) number except 0. a line
3512 : // is also represented by a 3-element vector (A,B,C). The
3513 : // directed line (A,B,C) from point (W*X1,W*Y1,W) to point
3514 : // (V*X2,V*Y2,V) is given by (A,B,C) = (W*X1,W*Y1,W) cross
3515 : // (V*X2,V*Y2,V). The sequence of the cross product is a
3516 : // convention to determine sign. The condition that a point lie
3517 : // on a line is that (A,B,C) dot (W*X,W*Y,W) = 0. 'Normalize'
3518 : // the representation of a point by setting W to 1. Then if
3519 : // (A,B,C) dot (X,Y,1) > 0.0, The point is to the left of the
3520 : // line, and if it is less than zero, the point is to the right
3521 : // of the line. The intercept of two lines is given by
3522 : // (W*X,W*Y,W) = (A1,B1,C1) cross (A2,B2,C3).
3523 :
3524 : // REFERENCES:
3525 : // BLAST/IBLAST code, original author George Walton
3526 : // W. M. Newman & R. F. Sproull, 'Principles of Interactive Computer Graphics', Appendix II, McGraw-Hill, 1973.
3527 : // 'CRC Math Tables', 22 ED, 'Analytic Geometry', P.369
3528 :
3529 : // Using/Aliasing
3530 :
3531 : // Locals
3532 : // SUBROUTINE ARGUMENT DEFINITIONS:
3533 : // 1 - Compute H.C. of vertices & sides
3534 :
3535 0 : if (NS > 2 * state.dataSolarShading->MaxHCS) {
3536 0 : ShowFatalError(state, format("Solar Shading: HTrans: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
3537 : }
3538 :
3539 0 : state.dataSolarShading->HCNV(NS) = NumVertices;
3540 :
3541 : // Tuned Linear indexing
3542 :
3543 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
3544 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
3545 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
3546 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
3547 0 : int const l1(state.dataSolarShading->HCX.index(NS, 1));
3548 0 : if (I != 0) { // Transform vertices of figure ns.
3549 :
3550 : // See comment at top of module regarding HCMULT
3551 0 : int l(l1);
3552 0 : for (int N = 1; N <= NumVertices; ++N, ++l) { // [ l ] == ( NS, N )
3553 0 : state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XVS(N) * HCMULT);
3554 0 : state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YVS(N) * HCMULT);
3555 : }
3556 : }
3557 :
3558 : // Establish extra point for finding lines between points.
3559 :
3560 0 : int l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
3561 0 : Int64 HCX_m = state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]; // [ l ] == ( NS, NumVertices + 1 ), [ l1 ] == ( NS, 1 )
3562 0 : Int64 HCY_m = state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]; // [ l ] == ( NS, NumVertices + 1 ), [ l1 ] == ( NS, 1 )
3563 :
3564 : // Determine lines between points.
3565 0 : l = l1;
3566 0 : int m = l1 + 1u;
3567 : Int64 HCX_l;
3568 : Int64 HCY_l;
3569 0 : Real64 SUM = 0.0; // Sum variable
3570 0 : for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
3571 0 : HCX_l = HCX_m;
3572 0 : HCY_l = HCY_m;
3573 0 : HCX_m = state.dataSolarShading->HCX[m];
3574 0 : HCY_m = state.dataSolarShading->HCY[m];
3575 0 : state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
3576 0 : state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
3577 0 : SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
3578 : }
3579 :
3580 : // Compute area of polygon.
3581 : // SUM=0.0D0
3582 : // DO N = 1, NumVertices
3583 : // 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
3584 : // END DO
3585 0 : state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
3586 : // HCAREA(NS)=0.5d0*SUM*(kHCMULT)
3587 0 : }
3588 :
3589 34858 : void HTRANS0(EnergyPlusData &state,
3590 : int const NS, // Figure Number
3591 : int const NumVertices // Number of vertices
3592 : )
3593 : {
3594 : // Using/Aliasing
3595 :
3596 : // Locals
3597 :
3598 34858 : if (NS > 2 * state.dataSolarShading->MaxHCS) {
3599 0 : ShowFatalError(state, format("Solar Shading: HTrans0: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
3600 : }
3601 :
3602 34858 : state.dataSolarShading->HCNV(NS) = NumVertices;
3603 :
3604 : // Tuned Linear indexing
3605 :
3606 34858 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
3607 34858 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
3608 34858 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
3609 34858 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
3610 :
3611 34858 : int const l1 = state.dataSolarShading->HCX.index(NS, 1);
3612 :
3613 34858 : int l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
3614 34858 : Int64 HCX_m = state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]; // [ l1 ] == ( NS, 1 )
3615 34858 : Int64 HCY_m = state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]; // [ l1 ] == ( NS, 1 )
3616 :
3617 34858 : l = l1;
3618 34858 : int m = l1 + 1u;
3619 : Int64 HCX_l;
3620 : Int64 HCY_l;
3621 34858 : Real64 SUM(0.0);
3622 149503 : for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
3623 114645 : HCX_l = HCX_m;
3624 114645 : HCY_l = HCY_m;
3625 114645 : HCX_m = state.dataSolarShading->HCX[m];
3626 114645 : HCY_m = state.dataSolarShading->HCY[m];
3627 114645 : state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
3628 114645 : state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
3629 114645 : SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
3630 : }
3631 :
3632 34858 : state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
3633 34858 : }
3634 :
3635 38197 : void HTRANS1(EnergyPlusData &state,
3636 : int const NS, // Figure Number
3637 : int const NumVertices // Number of vertices
3638 : )
3639 : {
3640 : // Using/Aliasing
3641 :
3642 38197 : if (NS > 2 * state.dataSolarShading->MaxHCS) {
3643 0 : ShowFatalError(state, format("Solar Shading: HTrans1: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
3644 : }
3645 :
3646 38197 : state.dataSolarShading->HCNV(NS) = NumVertices;
3647 :
3648 : // Tuned Linear indexing
3649 :
3650 38197 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
3651 38197 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
3652 38197 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
3653 38197 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
3654 :
3655 38197 : int const l1 = state.dataSolarShading->HCX.index(NS, 1);
3656 :
3657 : // only in HTRANS1
3658 38197 : int l = l1;
3659 190953 : for (int N = 1; N <= NumVertices; ++N, ++l) { // [ l ] == ( NS, N )
3660 152756 : state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XVS(N) * HCMULT);
3661 152756 : state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YVS(N) * HCMULT);
3662 : }
3663 :
3664 38197 : l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
3665 38197 : Int64 HCX_m(state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]); // [ l1 ] == ( NS, 1 )
3666 38197 : Int64 HCY_m(state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]);
3667 :
3668 38197 : l = l1;
3669 38197 : int m = l1 + 1u;
3670 : Int64 HCX_l;
3671 : Int64 HCY_l;
3672 38197 : Real64 SUM = 0.0;
3673 190953 : for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
3674 152756 : HCX_l = HCX_m;
3675 152756 : HCY_l = HCY_m;
3676 152756 : HCX_m = state.dataSolarShading->HCX[m];
3677 152756 : HCY_m = state.dataSolarShading->HCY[m];
3678 152756 : state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
3679 152756 : state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
3680 152756 : SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
3681 : }
3682 :
3683 38197 : state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
3684 38197 : }
3685 :
3686 0 : void INCLOS(EnergyPlusData &state,
3687 : int const N1, // Figure number of figure 1
3688 : int const N1NumVert, // Number of vertices of figure 1
3689 : int const N2, // Figure number of figure 2
3690 : int const N2NumVert, // Number of vertices of figure 2
3691 : int &NumVerticesOverlap, // Number of vertices which overlap
3692 : int &NIN // Number of vertices of figure 1 within figure 2
3693 : )
3694 : {
3695 :
3696 : // SUBROUTINE INFORMATION:
3697 : // AUTHOR Legacy Code
3698 : // DATE WRITTEN
3699 : // MODIFIED na
3700 : // RE-ENGINEERED Lawrie, Oct 2000
3701 :
3702 : // PURPOSE OF THIS SUBROUTINE:
3703 : // This subroutine determines which vertices of figure N1 lie within figure N2.
3704 :
3705 : // METHODOLOGY EMPLOYED:
3706 : // For vertex N of figure N1 to lie within figure N2, it must be
3707 : // on or to the right of all sides of figure N2, assuming
3708 : // figure N2 is convex.
3709 :
3710 : // REFERENCES:
3711 : // BLAST/IBLAST code, original author George Walton
3712 :
3713 : int K; // Vertex number of the overlap
3714 : int M; // Side number of figure N2
3715 : int N; // Vertex number of figure N1
3716 : bool CycleMainLoop; // Sets when to cycle main loop
3717 : Real64 HFunct;
3718 :
3719 0 : NIN = 0;
3720 :
3721 0 : for (N = 1; N <= N1NumVert; ++N) {
3722 :
3723 0 : CycleMainLoop = false;
3724 :
3725 : // Eliminate cases where vertex N is to the left of side M.
3726 :
3727 0 : for (M = 1; M <= N2NumVert; ++M) {
3728 0 : HFunct = state.dataSolarShading->HCX(N1, N) * state.dataSolarShading->HCA(N2, M) +
3729 0 : state.dataSolarShading->HCY(N1, N) * state.dataSolarShading->HCB(N2, M) + state.dataSolarShading->HCC(N2, M);
3730 0 : if (HFunct > 0.0) {
3731 0 : CycleMainLoop = true; // Set to cycle to the next value of N
3732 0 : break; // M DO loop
3733 : }
3734 : }
3735 :
3736 0 : if (CycleMainLoop) continue;
3737 0 : ++NIN;
3738 :
3739 : // Check for duplication of previously determined points.
3740 :
3741 0 : if (NumVerticesOverlap != 0) {
3742 0 : for (K = 1; K <= NumVerticesOverlap; ++K) {
3743 0 : if ((state.dataSolarShading->XTEMP(K) == state.dataSolarShading->HCX(N1, N)) &&
3744 0 : (state.dataSolarShading->YTEMP(K) == state.dataSolarShading->HCY(N1, N))) {
3745 0 : CycleMainLoop = true; // Set to cycle to the next value of N
3746 0 : break; // K DO loop
3747 : }
3748 : }
3749 0 : if (CycleMainLoop) continue;
3750 : }
3751 :
3752 : // Record enclosed vertices in temporary arrays.
3753 :
3754 0 : ++NumVerticesOverlap;
3755 0 : state.dataSolarShading->XTEMP(NumVerticesOverlap) = state.dataSolarShading->HCX(N1, N);
3756 0 : state.dataSolarShading->YTEMP(NumVerticesOverlap) = state.dataSolarShading->HCY(N1, N);
3757 : }
3758 0 : }
3759 :
3760 0 : void INTCPT(EnergyPlusData &state,
3761 : int const NV1, // Number of vertices of figure NS1
3762 : int const NV2, // Number of vertices of figure NS2
3763 : int &NV3, // Number of vertices of figure NS3
3764 : int const NS1, // Number of the figure being overlapped
3765 : int const NS2 // Number of the figure doing overlapping
3766 : )
3767 : {
3768 :
3769 : // SUBROUTINE INFORMATION:
3770 : // AUTHOR Legacy Code
3771 : // DATE WRITTEN
3772 : // MODIFIED na
3773 : // RE-ENGINEERED Lawrie, Oct 2000
3774 :
3775 : // PURPOSE OF THIS SUBROUTINE:
3776 : // This subroutine determines all intercepts between the sides of figure NS1
3777 : // and the sides of figure NS2.
3778 :
3779 : // METHODOLOGY EMPLOYED:
3780 : // The requirements for intersection are that the end points of
3781 : // line N lie on both sides of line M and vice versa. Also
3782 : // eliminate cases where the end point of one line lies exactly
3783 : // on the other to reduce duplication with the enclosed points.
3784 :
3785 : // REFERENCES:
3786 : // BLAST/IBLAST code, original author George Walton
3787 :
3788 : Real64 W; // Normalization factor
3789 : Real64 XUntrunc; // Untruncated X coordinate
3790 : Real64 YUntrunc; // Untruncated Y coordinate
3791 : Int64 I1; // Intermediate result for testing intersection
3792 : Int64 I2; // Intermediate result for testing intersection
3793 : int K;
3794 : int KK;
3795 : int M; // Side number of figure NS2
3796 : int N; // Side number of figure NS1
3797 :
3798 0 : for (N = 1; N <= NV1; ++N) {
3799 0 : for (M = 1; M <= NV2; ++M) {
3800 :
3801 : // Eliminate cases where sides N and M do not intersect.
3802 :
3803 0 : I1 = state.dataSolarShading->HCA(NS1, N) * state.dataSolarShading->HCX(NS2, M) +
3804 0 : state.dataSolarShading->HCB(NS1, N) * state.dataSolarShading->HCY(NS2, M) + state.dataSolarShading->HCC(NS1, N);
3805 0 : I2 = state.dataSolarShading->HCA(NS1, N) * state.dataSolarShading->HCX(NS2, M + 1) +
3806 0 : state.dataSolarShading->HCB(NS1, N) * state.dataSolarShading->HCY(NS2, M + 1) + state.dataSolarShading->HCC(NS1, N);
3807 0 : if (I1 >= 0 && I2 >= 0) continue;
3808 0 : if (I1 <= 0 && I2 <= 0) continue;
3809 :
3810 0 : I1 = state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCX(NS1, N) +
3811 0 : state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCY(NS1, N) + state.dataSolarShading->HCC(NS2, M);
3812 0 : I2 = state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCX(NS1, N + 1) +
3813 0 : state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCY(NS1, N + 1) + state.dataSolarShading->HCC(NS2, M);
3814 0 : if (I1 >= 0 && I2 >= 0) continue;
3815 0 : if (I1 <= 0 && I2 <= 0) continue;
3816 :
3817 : // Determine the point of intersection and record in the temporary array.
3818 :
3819 0 : KK = NV3;
3820 0 : ++NV3;
3821 0 : W = state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCA(NS1, N) -
3822 0 : state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCB(NS1, N);
3823 0 : XUntrunc = (state.dataSolarShading->HCC(NS2, M) * state.dataSolarShading->HCB(NS1, N) -
3824 0 : state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCC(NS1, N)) /
3825 : W;
3826 0 : YUntrunc = (state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCC(NS1, N) -
3827 0 : state.dataSolarShading->HCC(NS2, M) * state.dataSolarShading->HCA(NS1, N)) /
3828 : W;
3829 0 : if (NV3 > isize(state.dataSolarShading->XTEMP)) {
3830 0 : state.dataSolarShading->XTEMP.redimension(isize(state.dataSolarShading->XTEMP) + 10, 0.0);
3831 0 : state.dataSolarShading->YTEMP.redimension(isize(state.dataSolarShading->YTEMP) + 10, 0.0);
3832 : }
3833 0 : state.dataSolarShading->XTEMP(NV3) = nint64(XUntrunc);
3834 0 : state.dataSolarShading->YTEMP(NV3) = nint64(YUntrunc);
3835 :
3836 : // Eliminate near-duplicate points.
3837 :
3838 0 : if (KK != 0) {
3839 0 : Real64 const x(state.dataSolarShading->XTEMP(NV3));
3840 0 : Real64 const y(state.dataSolarShading->YTEMP(NV3));
3841 0 : for (K = 1; K <= KK; ++K) {
3842 0 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
3843 0 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
3844 0 : NV3 = KK;
3845 0 : break; // K DO loop
3846 : }
3847 : }
3848 : }
3849 : }
3850 0 : }
3851 :
3852 2349 : inline bool neq(Real64 a, Real64 b)
3853 : {
3854 2349 : return std::abs(a - b) > 2.0;
3855 : }
3856 :
3857 3486 : inline bool d_eq(Real64 a, Real64 b)
3858 : {
3859 3486 : return std::abs(a - b) < 2.0;
3860 : }
3861 :
3862 737 : void CLIPLINE(Real64 &x0, Real64 &x1, Real64 &y0, Real64 &y1, Real64 maxX, Real64 minX, Real64 maxY, Real64 minY, bool &visible)
3863 : {
3864 :
3865 : // Line segment clipping
3866 : // Reference:
3867 : // Liang, Y.D., Barsky, B.A., Slater, M.
3868 : // 2D line and polygon clipping based on space subdivision.
3869 : // The Visual Computer 10, 407–422 (1994).
3870 :
3871 : // Tweaked via microbenchmarking to improve efficiency
3872 :
3873 737 : bool rev = false;
3874 737 : if (x0 > x1) { // reverse for efficiency
3875 311 : std::swap(x0, x1);
3876 311 : std::swap(y0, y1);
3877 311 : rev = true;
3878 : }
3879 :
3880 737 : if (x0 > maxX || x1 < minX) {
3881 : // Both points are outside the clip window, so they can't cross it
3882 52 : return;
3883 : }
3884 :
3885 : // defining variables
3886 685 : Real64 const dx = x1 - x0; // >= 0
3887 685 : Real64 const dy = y1 - y0;
3888 :
3889 685 : Real64 const q1 = x0 - minX;
3890 685 : Real64 const q2 = maxX - x0;
3891 685 : Real64 const q3 = y0 - minY;
3892 685 : Real64 const q4 = maxY - y0;
3893 :
3894 685 : Real64 u1 = 0;
3895 685 : Real64 u2 = 1;
3896 :
3897 685 : if ((dx == 0 && (q1 < 0 || q2 < 0)) || (dy == 0 && (q3 < 0 || q4 < 0))) {
3898 : // Line is parallel to clipping window
3899 98 : return;
3900 : }
3901 587 : if (dx != 0) {
3902 520 : Real64 const r1 = q1 / -dx;
3903 520 : if (r1 > u1) {
3904 138 : u1 = r1;
3905 : }
3906 520 : Real64 const r2 = q2 / dx;
3907 520 : if (r2 < u2) {
3908 136 : u2 = r2;
3909 : }
3910 : }
3911 587 : if (dy != 0) {
3912 341 : Real64 const r3 = q3 / -dy;
3913 341 : Real64 const r4 = q4 / dy;
3914 341 : if (dy > 0) {
3915 173 : if (r3 > u1) {
3916 54 : u1 = r3;
3917 : }
3918 173 : if (r4 < u2) {
3919 16 : u2 = r4;
3920 : }
3921 : } else {
3922 168 : if (r4 > u1) {
3923 16 : u1 = r4;
3924 : }
3925 168 : if (r3 < u2) {
3926 55 : u2 = r3;
3927 : }
3928 : }
3929 : }
3930 :
3931 587 : if (u1 > u2) { // reject
3932 : // Line is outside the clipping window
3933 4 : return;
3934 : }
3935 :
3936 583 : visible = true;
3937 :
3938 583 : Real64 const xn0 = x0 + dx * u1;
3939 583 : Real64 const yn0 = y0 + dy * u1;
3940 :
3941 583 : Real64 const xn1 = x0 + dx * u2;
3942 583 : Real64 const yn1 = y0 + dy * u2;
3943 :
3944 583 : if (rev) {
3945 229 : x0 = xn1;
3946 229 : y0 = yn1;
3947 229 : x1 = xn0;
3948 229 : y1 = yn0;
3949 : } else {
3950 354 : x0 = xn0;
3951 354 : y0 = yn0;
3952 354 : x1 = xn1;
3953 354 : y1 = yn1;
3954 : }
3955 : }
3956 :
3957 157 : void CLIPRECT(EnergyPlusData &state, int const NS2, int const NV1, int &NV3)
3958 : {
3959 : // Polygon clipping by line segment clipping for rectangles
3960 : // Reference:
3961 : // Slater, M., Barsky, B.A.
3962 : // 2D line and polygon clipping based on space subdivision.
3963 : // The Visual Computer 10, 407–422 (1994).
3964 157 : bool INTFLAG = false;
3965 157 : int l = state.dataSolarShading->HCA.index(NS2, 1);
3966 : Real64 maxX, minX, maxY, minY;
3967 157 : if (state.dataSolarShading->HCX[l] > state.dataSolarShading->HCX[l + 2]) {
3968 157 : maxX = state.dataSolarShading->HCX[l];
3969 157 : minX = state.dataSolarShading->HCX[l + 2];
3970 : } else {
3971 0 : maxX = state.dataSolarShading->HCX[l + 2];
3972 0 : minX = state.dataSolarShading->HCX[l];
3973 : }
3974 157 : if (state.dataSolarShading->HCY[l] > state.dataSolarShading->HCY[l + 2]) {
3975 157 : maxY = state.dataSolarShading->HCY[l];
3976 157 : minY = state.dataSolarShading->HCY[l + 2];
3977 : } else {
3978 0 : maxY = state.dataSolarShading->HCY[l + 2];
3979 0 : minY = state.dataSolarShading->HCY[l];
3980 : }
3981 :
3982 : Real64 arrx[20]; // Temp array for output X
3983 : Real64 arry[20]; // Temp array for output Y
3984 157 : int arrc = 0; // Number of items in output
3985 :
3986 797 : for (int j = 0; j < NV1; ++j) {
3987 640 : Real64 x_1 = state.dataSolarShading->XTEMP[j];
3988 640 : Real64 y_1 = state.dataSolarShading->YTEMP[j];
3989 640 : Real64 x_2 = state.dataSolarShading->XTEMP[(j + 1) % NV1];
3990 640 : Real64 y_2 = state.dataSolarShading->YTEMP[(j + 1) % NV1];
3991 640 : Real64 x1 = x_1, x2 = x_2, y1 = y_1, y2 = y_2;
3992 :
3993 640 : bool visible = false;
3994 640 : CLIPLINE(x_1, x_2, y_1, y_2, maxX, minX, maxY, minY, visible);
3995 640 : if (visible) {
3996 514 : if ((x_1 != x1 || y_1 != y1) || (x_2 != x2 || y_2 != y2)) {
3997 274 : INTFLAG = true;
3998 : }
3999 : // if line on edge, or inside, add both points
4000 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)))) {
4001 213 : arrx[arrc] = x_1;
4002 213 : arry[arrc] = y_1;
4003 213 : arrc += 1;
4004 213 : if ((neq(x_1, x_2) || neq(y_1, y_2)) && (neq(arrx[0], x_2) || neq(arry[0], y_2))) {
4005 183 : arrx[arrc] = x_2;
4006 183 : arry[arrc] = y_2;
4007 183 : arrc += 1;
4008 : }
4009 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))) {
4010 136 : arrx[arrc] = x_2;
4011 136 : arry[arrc] = y_2;
4012 136 : arrc += 1;
4013 : }
4014 : }
4015 : }
4016 157 : NV3 = arrc;
4017 :
4018 : // Re-populate XTEMP/YTEMP
4019 157 : if (NV3 > 1) {
4020 147 : int LastEdgeIndex = -1, incr = 0;
4021 147 : double cornerXs[4] = {minX, minX, maxX, maxX};
4022 147 : double cornerYs[4] = {minY, maxY, maxY, minY};
4023 147 : Real64 edges[4] = {minX, maxY, maxX, minY};
4024 : Real64 LastEdgeX, LastEdgeY;
4025 826 : for (int i = 0; i <= arrc; i++) {
4026 679 : int k = i % arrc;
4027 :
4028 679 : Real64 currX = arrx[k], currY = arry[k];
4029 :
4030 679 : int edgeCount = 0, EdgeIndex = -1;
4031 3395 : for (int m = 0; m < 4; m++) {
4032 2716 : if (m % 2 == 0 && d_eq(currX, edges[m])) { // MinX or MaxX
4033 486 : edgeCount++;
4034 486 : EdgeIndex = m;
4035 2230 : } else if (m % 2 == 1 && d_eq(currY, edges[m])) {
4036 501 : edgeCount++;
4037 501 : EdgeIndex = m;
4038 : }
4039 : }
4040 679 : if (edgeCount == 0) { // On inside
4041 77 : if (i != arrc) {
4042 77 : state.dataSolarShading->XTEMP[incr] = currX;
4043 77 : state.dataSolarShading->YTEMP[incr] = currY;
4044 77 : incr++;
4045 : }
4046 77 : continue;
4047 602 : } else if (edgeCount > 1) { // On corner
4048 385 : if (d_eq(currX, minX)) {
4049 250 : if (d_eq(currY, minY)) {
4050 8 : EdgeIndex = 3;
4051 : } else {
4052 242 : EdgeIndex = 0;
4053 : }
4054 : } else {
4055 135 : if (d_eq(currY, maxY)) {
4056 131 : EdgeIndex = 1;
4057 : } else {
4058 4 : EdgeIndex = 2;
4059 : }
4060 : }
4061 : }
4062 602 : if ((LastEdgeIndex > -1 && EdgeIndex > -1) && LastEdgeIndex != EdgeIndex) {
4063 386 : int jumpCount = 0;
4064 386 : if ((EdgeIndex == 0 && LastEdgeIndex == 3) || (EdgeIndex - LastEdgeIndex == 1)) {
4065 237 : jumpCount = 1;
4066 149 : } else if (EdgeIndex % 2 == LastEdgeIndex % 2) {
4067 : // Clockwise double jump
4068 112 : jumpCount = 2;
4069 37 : } else if ((EdgeIndex == 3 && LastEdgeIndex == 0) || (LastEdgeIndex - EdgeIndex == 1)) {
4070 : // Clockwise triple jump
4071 37 : jumpCount = 3;
4072 : }
4073 386 : if (jumpCount > 0) {
4074 : Real64 cornerX;
4075 : Real64 cornerY;
4076 386 : int startIndex = (LastEdgeIndex + 1) % 4;
4077 386 : int added = 0;
4078 958 : for (int i1 = startIndex, j1 = 0; j1 < jumpCount; i1 = (i1 + 1) % 4, j1++) {
4079 572 : cornerX = cornerXs[i1];
4080 572 : cornerY = cornerYs[i1];
4081 572 : if (cornerX == LastEdgeX && cornerY == LastEdgeY) continue; // skip if jump started on corner
4082 :
4083 308 : bool insideFlag = true;
4084 979 : for (int j = 0; j < NV1; ++j) {
4085 921 : if ((state.dataSolarShading->ATEMP[j] * cornerX) + (cornerY * state.dataSolarShading->BTEMP[j]) +
4086 921 : state.dataSolarShading->CTEMP[j] >
4087 : 0.0) {
4088 250 : insideFlag = false;
4089 250 : break;
4090 : }
4091 : }
4092 :
4093 366 : if (insideFlag &&
4094 58 : (incr == 0 ||
4095 144 : ((neq(cornerX, state.dataSolarShading->XTEMP[incr - 1]) || neq(cornerY, state.dataSolarShading->YTEMP[incr - 1])) &&
4096 84 : (neq(cornerX, state.dataSolarShading->XTEMP[0]) || neq(cornerY, state.dataSolarShading->YTEMP[0]))))) {
4097 56 : state.dataSolarShading->XTEMP[incr] = cornerX;
4098 56 : state.dataSolarShading->YTEMP[incr] = cornerY;
4099 56 : incr++;
4100 56 : added++;
4101 : }
4102 : }
4103 386 : if (jumpCount > 2 && (added == jumpCount && edgeCount == 1)) {
4104 0 : if (i != arrc) {
4105 0 : state.dataSolarShading->XTEMP[incr] = currX;
4106 0 : state.dataSolarShading->YTEMP[incr] = currY;
4107 0 : incr++;
4108 : }
4109 0 : break;
4110 : }
4111 : }
4112 : }
4113 602 : if (i != arrc) {
4114 455 : state.dataSolarShading->XTEMP[incr] = currX;
4115 455 : state.dataSolarShading->YTEMP[incr] = currY;
4116 455 : incr++;
4117 : }
4118 602 : LastEdgeIndex = EdgeIndex;
4119 602 : LastEdgeX = currX;
4120 602 : LastEdgeY = currY;
4121 : }
4122 147 : NV3 = incr;
4123 :
4124 : } else {
4125 10 : if (NV3 == 1) {
4126 0 : state.dataSolarShading->XTEMP[0] = arrx[0];
4127 0 : state.dataSolarShading->YTEMP[0] = arry[0];
4128 : }
4129 10 : if (NV3 == 0) {
4130 10 : double cornerXs[4] = {minX, minX, maxX, maxX};
4131 10 : double cornerYs[4] = {minY, maxY, maxY, minY};
4132 10 : Real64 cornerX = cornerXs[0];
4133 10 : Real64 cornerY = cornerYs[0];
4134 10 : bool insideFlag = true;
4135 50 : for (int j = 0; j < NV1; ++j) {
4136 40 : if ((state.dataSolarShading->ATEMP[j] * cornerX) + (cornerY * state.dataSolarShading->BTEMP[j]) + state.dataSolarShading->CTEMP[j] >=
4137 : 0.0) {
4138 0 : insideFlag = false;
4139 0 : break;
4140 : }
4141 : }
4142 10 : if (insideFlag) {
4143 50 : for (int i1 = 0; i1 < 4; i1++) {
4144 40 : state.dataSolarShading->XTEMP[i1] = cornerXs[i1];
4145 40 : state.dataSolarShading->YTEMP[i1] = cornerYs[i1];
4146 : }
4147 10 : NV3 = 4;
4148 10 : INTFLAG = true;
4149 : }
4150 : }
4151 : }
4152 :
4153 : // update homogeneous edges A,B,C
4154 157 : if (NV3 > 0) {
4155 157 : Real64 const X_0(state.dataSolarShading->XTEMP[0]);
4156 157 : Real64 const Y_0(state.dataSolarShading->YTEMP[0]);
4157 157 : Real64 XP_0 = X_0, XP_1;
4158 157 : Real64 YP_0 = Y_0, YP_1;
4159 628 : for (int P = 0; P < NV3 - 1; ++P) {
4160 471 : XP_1 = state.dataSolarShading->XTEMP[P + 1];
4161 471 : YP_1 = state.dataSolarShading->YTEMP[P + 1];
4162 :
4163 471 : state.dataSolarShading->ATEMP[P] = YP_0 - YP_1;
4164 471 : state.dataSolarShading->BTEMP[P] = XP_1 - XP_0;
4165 471 : state.dataSolarShading->CTEMP[P] = XP_0 * YP_1 - YP_0 * XP_1;
4166 471 : XP_0 = XP_1;
4167 471 : YP_0 = YP_1;
4168 : }
4169 :
4170 157 : state.dataSolarShading->ATEMP[NV3 - 1] = YP_1 - Y_0;
4171 157 : state.dataSolarShading->BTEMP[NV3 - 1] = X_0 - XP_1;
4172 157 : state.dataSolarShading->CTEMP[NV3 - 1] = XP_1 * Y_0 - YP_1 * X_0;
4173 : }
4174 :
4175 : // Determine overlap status
4176 157 : if (NV3 < 3) { // Determine overlap status
4177 0 : state.dataSolarShading->OverlapStatus = NoOverlap;
4178 157 : } else if (!INTFLAG) {
4179 12 : state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
4180 : }
4181 157 : }
4182 :
4183 20917 : void CLIPPOLY(EnergyPlusData &state,
4184 : int const NS1, // Figure number of figure 1 (The subject polygon)
4185 : int const NS2, // Figure number of figure 2 (The clipping polygon)
4186 : int const NV1, // Number of vertices of figure 1
4187 : int const NV2, // Number of vertices of figure 2
4188 : int &NV3 // Number of vertices of figure 3
4189 : )
4190 : {
4191 :
4192 : // SUBROUTINE INFORMATION:
4193 : // AUTHOR Tyler Hoyt
4194 : // DATE WRITTEN May 4, 2010
4195 : // MODIFIED na
4196 : // RE-ENGINEERED na
4197 :
4198 : // PURPOSE OF THIS SUBROUTINE:
4199 : // Populate global arrays XTEMP and YTEMP with the vertices
4200 : // of the overlap between NS1 and NS2, and determine relevant
4201 : // overlap status.
4202 :
4203 : // METHODOLOGY EMPLOYED:
4204 : // The Sutherland-Hodgman algorithm for polygon clipping is employed.
4205 :
4206 : using General::SafeDivide;
4207 :
4208 : typedef Array2D<Int64>::size_type size_type;
4209 : bool INTFLAG; // For overlap status
4210 : int S; // Test vertex
4211 : int KK; // Duplicate test index
4212 : int NVOUT; // Current output length for loops
4213 : int NVTEMP;
4214 :
4215 : Real64 W; // Normalization factor
4216 : Real64 HFunct;
4217 :
4218 20917 : auto &s_surf = state.dataSurface;
4219 :
4220 : #ifdef EP_Count_Calls
4221 : ++state.dataTimingsData->NumClipPoly_Calls;
4222 : #endif
4223 : // Tuned Linear indexing
4224 :
4225 20917 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
4226 20917 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
4227 20917 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
4228 20917 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
4229 :
4230 : // Populate the arrays with the original polygon
4231 104901 : for (size_type j = 0, l = state.dataSolarShading->HCX.index(NS1, 1), e = NV1; j < e; ++j, ++l) {
4232 83984 : state.dataSolarShading->XTEMP[j] = state.dataSolarShading->HCX[l]; // [ l ] == ( NS1, j+1 )
4233 83984 : state.dataSolarShading->YTEMP[j] = state.dataSolarShading->HCY[l];
4234 83984 : state.dataSolarShading->ATEMP[j] = state.dataSolarShading->HCA[l];
4235 83984 : state.dataSolarShading->BTEMP[j] = state.dataSolarShading->HCB[l];
4236 83984 : state.dataSolarShading->CTEMP[j] = state.dataSolarShading->HCC[l];
4237 : }
4238 :
4239 20917 : NVOUT = NV1; // First point-loop is the length of the subject polygon.
4240 20917 : INTFLAG = false;
4241 20917 : NVTEMP = 0;
4242 20917 : KK = 0;
4243 :
4244 : // Check if clipping polygon is rectangle
4245 20917 : if (state.dataSysVars->SlaterBarsky) {
4246 422 : int l1 = state.dataSolarShading->HCA.index(NS2, 1);
4247 844 : bool rectFlag = ((NV2 == 4) && (((((state.dataSolarShading->HCX[l1] == state.dataSolarShading->HCX[l1 + 1] &&
4248 157 : state.dataSolarShading->HCY[l1] != state.dataSolarShading->HCY[l1 + 1]) &&
4249 157 : ((state.dataSolarShading->HCY[l1 + 2] == state.dataSolarShading->HCY[l1 + 1] &&
4250 157 : state.dataSolarShading->HCY[l1 + 3] == state.dataSolarShading->HCY[l1]))) &&
4251 157 : state.dataSolarShading->HCX[l1 + 2] == state.dataSolarShading->HCX[l1 + 3]) ||
4252 265 : ((((state.dataSolarShading->HCY[l1] == state.dataSolarShading->HCY[l1 + 1] &&
4253 24 : state.dataSolarShading->HCX[l1] != state.dataSolarShading->HCX[l1 + 1]) &&
4254 24 : (state.dataSolarShading->HCX[l1 + 2] == state.dataSolarShading->HCX[l1 + 1] &&
4255 0 : state.dataSolarShading->HCX[l1 + 3] == state.dataSolarShading->HCX[l1])) &&
4256 0 : (state.dataSolarShading->HCY[l1 + 2] == state.dataSolarShading->HCY[l1 + 3]))))));
4257 422 : if (rectFlag) {
4258 157 : CLIPRECT(state, NS2, NV1, NV3);
4259 157 : return;
4260 : }
4261 : }
4262 :
4263 20760 : int l = state.dataSolarShading->HCA.index(NS2, 1);
4264 88491 : for (int E = 1; E <= NV2; ++E, ++l) { // Loop over edges of the clipping polygon
4265 377790 : for (int P = 1; P <= NVOUT; ++P) {
4266 304257 : state.dataSolarShading->XTEMP1(P) = state.dataSolarShading->XTEMP(P);
4267 304257 : state.dataSolarShading->YTEMP1(P) = state.dataSolarShading->YTEMP(P);
4268 : }
4269 73533 : S = NVOUT;
4270 73533 : Real64 const HCA_E(state.dataSolarShading->HCA[l]);
4271 73533 : Real64 const HCB_E(state.dataSolarShading->HCB[l]);
4272 73533 : Real64 const HCC_E(state.dataSolarShading->HCC[l]);
4273 73533 : Real64 XTEMP1_S(state.dataSolarShading->XTEMP1(S));
4274 73533 : Real64 YTEMP1_S(state.dataSolarShading->YTEMP1(S));
4275 377790 : for (int P = 1; P <= NVOUT; ++P) {
4276 304257 : Real64 const XTEMP1_P(state.dataSolarShading->XTEMP1(P));
4277 304257 : Real64 const YTEMP1_P(state.dataSolarShading->YTEMP1(P));
4278 304257 : HFunct = XTEMP1_P * HCA_E + YTEMP1_P * HCB_E + HCC_E;
4279 : // S is constant within this block
4280 304257 : if (HFunct <= 0.0) { // Vertex is not in the clipping plane
4281 222766 : HFunct = XTEMP1_S * HCA_E + YTEMP1_S * HCB_E + HCC_E;
4282 222766 : if (HFunct > 0.0) { // Test vertex is in the clipping plane
4283 :
4284 : // Find/store the intersection of the clip edge and the line connecting S and P
4285 30580 : KK = NVTEMP;
4286 30580 : ++NVTEMP;
4287 30580 : Real64 const ATEMP_S(state.dataSolarShading->ATEMP(S));
4288 30580 : Real64 const BTEMP_S(state.dataSolarShading->BTEMP(S));
4289 30580 : Real64 const CTEMP_S(state.dataSolarShading->CTEMP(S));
4290 30580 : W = HCB_E * ATEMP_S - HCA_E * BTEMP_S;
4291 30580 : if (W != 0.0) {
4292 30580 : Real64 const W_inv(1.0 / W);
4293 30580 : state.dataSolarShading->XTEMP(NVTEMP) = nint64((HCC_E * BTEMP_S - HCB_E * CTEMP_S) * W_inv);
4294 30580 : state.dataSolarShading->YTEMP(NVTEMP) = nint64((HCA_E * CTEMP_S - HCC_E * ATEMP_S) * W_inv);
4295 : } else {
4296 0 : state.dataSolarShading->XTEMP(NVTEMP) = SafeDivide(HCC_E * BTEMP_S - HCB_E * CTEMP_S, W);
4297 0 : state.dataSolarShading->YTEMP(NVTEMP) = SafeDivide(HCA_E * CTEMP_S - HCC_E * ATEMP_S, W);
4298 : }
4299 30580 : INTFLAG = true;
4300 :
4301 30580 : if (E == NV2) { // Remove near-duplicates on last edge
4302 6024 : if (KK != 0) {
4303 3585 : Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
4304 3585 : Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
4305 8189 : for (int K = 1; K <= KK; ++K) {
4306 4604 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
4307 141 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
4308 0 : NVTEMP = KK;
4309 0 : break; // K loop
4310 : }
4311 : }
4312 : }
4313 : }
4314 :
4315 222766 : KK = NVTEMP;
4316 222766 : ++NVTEMP;
4317 222766 : if (NVTEMP > state.dataSolarShading->MAXHCArrayBounds) {
4318 0 : int const NewArrayBounds(state.dataSolarShading->MAXHCArrayBounds + state.dataSolarShading->MAXHCArrayIncrement);
4319 0 : state.dataSolarShading->XTEMP.redimension(NewArrayBounds, 0.0);
4320 0 : state.dataSolarShading->YTEMP.redimension(NewArrayBounds, 0.0);
4321 0 : state.dataSolarShading->XTEMP1.redimension(NewArrayBounds, 0.0);
4322 0 : state.dataSolarShading->YTEMP1.redimension(NewArrayBounds, 0.0);
4323 0 : state.dataSolarShading->ATEMP.redimension(NewArrayBounds, 0.0);
4324 0 : state.dataSolarShading->BTEMP.redimension(NewArrayBounds, 0.0);
4325 0 : state.dataSolarShading->CTEMP.redimension(NewArrayBounds, 0.0);
4326 0 : state.dataSolarShading->MAXHCArrayBounds = NewArrayBounds;
4327 : }
4328 :
4329 222766 : state.dataSolarShading->XTEMP(NVTEMP) = XTEMP1_P;
4330 222766 : state.dataSolarShading->YTEMP(NVTEMP) = YTEMP1_P;
4331 :
4332 222766 : if (E == NV2) { // Remove near-duplicates on last edge
4333 50965 : if (KK != 0) {
4334 41120 : Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
4335 41120 : Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
4336 120257 : for (int K = 1; K <= KK; ++K) {
4337 83665 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
4338 21028 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
4339 4528 : NVTEMP = KK;
4340 4528 : break; // K loop
4341 : }
4342 : }
4343 : }
4344 :
4345 : } else {
4346 81491 : HFunct = XTEMP1_S * HCA_E + YTEMP1_S * HCB_E + HCC_E;
4347 81491 : if (HFunct <= 0.0) { // Test vertex is not in the clipping plane
4348 30580 : if (NVTEMP < 2 * (s_surf->MaxVerticesPerSurface + 1)) { // avoid assigning to element outside of XTEMP array size
4349 30580 : KK = NVTEMP;
4350 30580 : ++NVTEMP;
4351 30580 : Real64 const ATEMP_S(state.dataSolarShading->ATEMP(S));
4352 30580 : Real64 const BTEMP_S(state.dataSolarShading->BTEMP(S));
4353 30580 : Real64 const CTEMP_S(state.dataSolarShading->CTEMP(S));
4354 30580 : W = HCB_E * ATEMP_S - HCA_E * BTEMP_S;
4355 30580 : if (W != 0.0) {
4356 30580 : Real64 const W_inv(1.0 / W);
4357 30580 : state.dataSolarShading->XTEMP(NVTEMP) = nint64((HCC_E * BTEMP_S - HCB_E * CTEMP_S) * W_inv);
4358 30580 : state.dataSolarShading->YTEMP(NVTEMP) = nint64((HCA_E * CTEMP_S - HCC_E * ATEMP_S) * W_inv);
4359 : } else {
4360 0 : state.dataSolarShading->XTEMP(NVTEMP) = SafeDivide(HCC_E * BTEMP_S - HCB_E * CTEMP_S, W);
4361 0 : state.dataSolarShading->YTEMP(NVTEMP) = SafeDivide(HCA_E * CTEMP_S - HCC_E * ATEMP_S, W);
4362 : }
4363 30580 : INTFLAG = true;
4364 :
4365 30580 : if (E == NV2) { // Remove near-duplicates on last edge
4366 6024 : if (KK != 0) {
4367 3350 : Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
4368 3350 : Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
4369 11212 : for (int K = 1; K <= KK; ++K) {
4370 8062 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
4371 1537 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
4372 200 : NVTEMP = KK;
4373 200 : break; // K loop
4374 : }
4375 : }
4376 : }
4377 : }
4378 : }
4379 : }
4380 304257 : S = P;
4381 304257 : XTEMP1_S = XTEMP1_P;
4382 304257 : YTEMP1_S = YTEMP1_P;
4383 : } // end loop over points of subject polygon
4384 :
4385 73533 : NVOUT = NVTEMP;
4386 73533 : if (NVOUT == 0) break; // Added to avoid array bounds violation of XTEMP1 and YTEMP1 and wasted looping
4387 67731 : NVTEMP = 0;
4388 :
4389 67731 : if (E != NV2) {
4390 52773 : if (NVOUT > 2) { // Compute HC values for edges of output polygon
4391 52773 : Real64 const X_1(state.dataSolarShading->XTEMP(1));
4392 52773 : Real64 const Y_1(state.dataSolarShading->YTEMP(1));
4393 52773 : Real64 X_P(X_1), X_P1;
4394 52773 : Real64 Y_P(Y_1), Y_P1;
4395 220913 : for (int P = 1; P < NVOUT; ++P) {
4396 168140 : X_P1 = state.dataSolarShading->XTEMP(P + 1);
4397 168140 : Y_P1 = state.dataSolarShading->YTEMP(P + 1);
4398 168140 : state.dataSolarShading->ATEMP(P) = Y_P - Y_P1;
4399 168140 : state.dataSolarShading->BTEMP(P) = X_P1 - X_P;
4400 168140 : state.dataSolarShading->CTEMP(P) = X_P * Y_P1 - Y_P * X_P1;
4401 168140 : X_P = X_P1;
4402 168140 : Y_P = Y_P1;
4403 : }
4404 52773 : state.dataSolarShading->ATEMP(NVOUT) = Y_P1 - Y_1;
4405 52773 : state.dataSolarShading->BTEMP(NVOUT) = X_1 - X_P1;
4406 52773 : state.dataSolarShading->CTEMP(NVOUT) = X_P1 * Y_1 - Y_P1 * X_1;
4407 : }
4408 : }
4409 :
4410 : } // end loop over edges in NS2
4411 :
4412 20760 : NV3 = NVOUT;
4413 :
4414 20760 : if (NV3 < 3) { // Determine overlap status
4415 6406 : state.dataSolarShading->OverlapStatus = NoOverlap;
4416 14354 : } else if (!INTFLAG) {
4417 1557 : state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
4418 : }
4419 : }
4420 :
4421 5346 : void MULTOL(EnergyPlusData &state,
4422 : int const NNN, // argument
4423 : int const LOC0, // Location in the homogeneous coordinate array
4424 : int const NRFIGS // Number of figures overlapped
4425 : )
4426 : {
4427 :
4428 : // SUBROUTINE INFORMATION:
4429 : // AUTHOR Legacy Code
4430 : // DATE WRITTEN
4431 : // MODIFIED na
4432 : // RE-ENGINEERED Lawrie, Oct 2000
4433 :
4434 : // PURPOSE OF THIS SUBROUTINE:
4435 : // This subroutine determines the overlaps of figure 'NS2' with previous figures
4436 : // 'LOC0+1' through 'LOC0+NRFIGS'. For example, if NS2
4437 : // is a shadow, overlap with previous shadows.
4438 :
4439 : // REFERENCES:
4440 : // BLAST/IBLAST code, original author George Walton
4441 :
4442 : int I; // Loop Control
4443 : int NS1; // Number of the figure being overlapped
4444 : int NS2; // Number of the figure doing overlapping
4445 : int NS3; // Location to place results of overlap
4446 :
4447 5346 : state.dataSolarShading->maxNumberOfFigures = max(state.dataSolarShading->maxNumberOfFigures, NRFIGS);
4448 :
4449 5346 : NS2 = NNN;
4450 12252 : for (I = 1; I <= NRFIGS; ++I) {
4451 6906 : NS1 = LOC0 + I;
4452 6906 : NS3 = state.dataSolarShading->LOCHCA + 1;
4453 :
4454 6906 : DeterminePolygonOverlap(state, NS1, NS2, NS3); // Find overlap of figure NS2 on figure NS1.
4455 :
4456 : // Process overlap cases:
4457 :
4458 6906 : if (state.dataSolarShading->OverlapStatus == NoOverlap) continue;
4459 :
4460 5302 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) break;
4461 :
4462 5302 : state.dataSolarShading->LOCHCA = NS3; // Increment h.c. arrays pointer.
4463 : }
4464 5346 : }
4465 :
4466 0 : void ORDER(EnergyPlusData &state,
4467 : int const NV3, // Number of vertices of figure NS3
4468 : int const NS3 // Location to place results of overlap
4469 : )
4470 : {
4471 :
4472 : // SUBROUTINE INFORMATION:
4473 : // AUTHOR Legacy Code
4474 : // DATE WRITTEN
4475 : // MODIFIED na
4476 : // RE-ENGINEERED Lawrie, Oct 2000
4477 :
4478 : // PURPOSE OF THIS SUBROUTINE:
4479 : // This subroutine sorts the vertices found by inclosure and
4480 : // intercept in to clockwise order so that the overlap polygon
4481 : // may be used in computing subsequent overlaps.
4482 :
4483 : // METHODOLOGY EMPLOYED:
4484 : // The slopes of the lines from the left-most vertex to all
4485 : // others are found. The slopes are sorted into descending
4486 : // sequence. This sequence puts the vertices in clockwise order.
4487 :
4488 : // REFERENCES:
4489 : // BLAST/IBLAST code, original author George Walton
4490 :
4491 : Real64 DELTAX; // Difference between X coordinates of two vertices
4492 : Real64 DELTAY; // Difference between Y coordinates of two vertices
4493 : Real64 SAVES; // Temporary location for exchange of variables
4494 : Real64 SAVEX; // Temporary location for exchange of variables
4495 : Real64 SAVEY; // Temporary location for exchange of variables
4496 : Real64 XMIN; // X coordinate of left-most vertex
4497 : Real64 YXMIN;
4498 : int I; // Sort index
4499 : int IM1; // Sort control
4500 : int J; // Sort index
4501 : int M; // Number of slopes to be sorted
4502 : int N; // Vertex number
4503 : int P; // Location of first slope to be sorted
4504 :
4505 0 : auto &s_surf = state.dataSurface;
4506 :
4507 0 : if (state.dataSolarShading->ORDERFirstTimeFlag) {
4508 0 : state.dataSolarShading->SLOPE.allocate(max(10, s_surf->MaxVerticesPerSurface + 1));
4509 0 : state.dataSolarShading->ORDERFirstTimeFlag = false;
4510 : }
4511 : // Determine left-most vertex.
4512 :
4513 0 : XMIN = state.dataSolarShading->XTEMP(1);
4514 0 : YXMIN = state.dataSolarShading->YTEMP(1);
4515 0 : for (N = 2; N <= NV3; ++N) {
4516 0 : if (state.dataSolarShading->XTEMP(N) >= XMIN) continue;
4517 0 : XMIN = state.dataSolarShading->XTEMP(N);
4518 0 : YXMIN = state.dataSolarShading->YTEMP(N);
4519 : }
4520 :
4521 : // Determine slopes from left-most vertex to all others. Identify
4522 : // first and second or last points as they occur.
4523 :
4524 0 : P = 1;
4525 0 : M = 0;
4526 0 : for (N = 1; N <= NV3; ++N) {
4527 :
4528 0 : DELTAX = state.dataSolarShading->XTEMP(N) - XMIN;
4529 0 : DELTAY = state.dataSolarShading->YTEMP(N) - YXMIN;
4530 :
4531 0 : if (std::abs(DELTAX) > 0.5) {
4532 :
4533 0 : ++M;
4534 0 : state.dataSolarShading->SLOPE(M) = DELTAY / DELTAX;
4535 0 : state.dataSolarShading->XTEMP(M) = state.dataSolarShading->XTEMP(N);
4536 0 : state.dataSolarShading->YTEMP(M) = state.dataSolarShading->YTEMP(N);
4537 :
4538 0 : } else if (DELTAY > 0.5) {
4539 :
4540 0 : P = 2;
4541 0 : state.dataSolarShading->HCX(NS3, 2) = nint64(state.dataSolarShading->XTEMP(N));
4542 0 : state.dataSolarShading->HCY(NS3, 2) = nint64(state.dataSolarShading->YTEMP(N));
4543 :
4544 0 : } else if (DELTAY < -0.5) {
4545 :
4546 0 : state.dataSolarShading->HCX(NS3, NV3) = nint64(state.dataSolarShading->XTEMP(N));
4547 0 : state.dataSolarShading->HCY(NS3, NV3) = nint64(state.dataSolarShading->YTEMP(N));
4548 :
4549 : } else {
4550 :
4551 0 : state.dataSolarShading->HCX(NS3, 1) = nint64(XMIN);
4552 0 : state.dataSolarShading->HCY(NS3, 1) = nint64(YXMIN);
4553 : }
4554 : }
4555 :
4556 : // Sequence the temporary arrays in order of decreasing slopes.(bubble sort)
4557 :
4558 0 : if (M != 1) {
4559 :
4560 0 : for (I = 2; I <= M; ++I) {
4561 0 : IM1 = I - 1;
4562 0 : for (J = 1; J <= IM1; ++J) {
4563 0 : if (state.dataSolarShading->SLOPE(I) <= state.dataSolarShading->SLOPE(J)) continue;
4564 0 : SAVEX = state.dataSolarShading->XTEMP(I);
4565 0 : SAVEY = state.dataSolarShading->YTEMP(I);
4566 0 : SAVES = state.dataSolarShading->SLOPE(I);
4567 0 : state.dataSolarShading->XTEMP(I) = state.dataSolarShading->XTEMP(J);
4568 0 : state.dataSolarShading->YTEMP(I) = state.dataSolarShading->YTEMP(J);
4569 0 : state.dataSolarShading->SLOPE(I) = state.dataSolarShading->SLOPE(J);
4570 0 : state.dataSolarShading->XTEMP(J) = SAVEX;
4571 0 : state.dataSolarShading->YTEMP(J) = SAVEY;
4572 0 : state.dataSolarShading->SLOPE(J) = SAVES;
4573 : }
4574 : }
4575 : }
4576 :
4577 : // Place sequenced points in the homogeneous coordinate arrays.
4578 :
4579 0 : for (N = 1; N <= M; ++N) {
4580 0 : state.dataSolarShading->HCX(NS3, N + P) = nint64(state.dataSolarShading->XTEMP(N));
4581 0 : state.dataSolarShading->HCY(NS3, N + P) = nint64(state.dataSolarShading->YTEMP(N));
4582 : }
4583 0 : }
4584 :
4585 20917 : void DeterminePolygonOverlap(EnergyPlusData &state,
4586 : int const NS1, // Number of the figure being overlapped
4587 : int const NS2, // Number of the figure doing overlapping
4588 : int const NS3 // Location to place results of overlap
4589 : )
4590 : {
4591 :
4592 : // SUBROUTINE INFORMATION:
4593 : // AUTHOR Legacy Code
4594 : // RE-ENGINEERED Lawrie, Oct 2000
4595 :
4596 : // PURPOSE OF THIS SUBROUTINE:
4597 : // This subroutine computes the possible overlap of two polygons.
4598 : // It uses homogeneous coordinate techniques to determine the overlap area
4599 : // between two convex polygons. Results are stored in the homogeneous coordinate (HC) arrays.
4600 :
4601 : // METHODOLOGY EMPLOYED:
4602 : // The vertices defining the overlap between fig.1 and fig.2
4603 : // consist of: the vertices of fig.1 enclosed by fig.2 (A)
4604 : // plus the vertices of fig.2 enclosed by fig.1 (B)
4605 : // plus the intercepts of fig.1 and fig.2 (C & D)
4606 :
4607 : // +----------------------+
4608 : // ! !
4609 : // ! FIG.2 !
4610 : // ! !
4611 : // +--------------C----------A !
4612 : // ! ! / !
4613 : // ! ! / !
4614 : // ! B-------D--------------+
4615 : // ! FIG.1 /
4616 : // ! /
4617 : // +-------------------+
4618 :
4619 : // REFERENCES:
4620 : // BLAST/IBLAST code, original author George Walton
4621 :
4622 : #ifdef EP_Count_Calls
4623 : ++state.dataTimingsData->NumDetPolyOverlap_Calls;
4624 : #endif
4625 :
4626 : // Check for exceeding array limits.
4627 20917 : if (NS3 > state.dataSolarShading->MaxHCS) {
4628 :
4629 0 : state.dataSolarShading->OverlapStatus = TooManyFigures;
4630 :
4631 0 : if (!state.dataSolarShading->TooManyFiguresMessage && !state.dataGlobal->DisplayExtraWarnings) {
4632 0 : ShowWarningError(state,
4633 0 : format("DeterminePolygonOverlap: Too many figures [>{}] detected in an overlap calculation. Use "
4634 : "Output:Diagnostics,DisplayExtraWarnings; for more details.",
4635 0 : state.dataSolarShading->MaxHCS));
4636 0 : state.dataSolarShading->TooManyFiguresMessage = true;
4637 : }
4638 :
4639 0 : if (state.dataGlobal->DisplayExtraWarnings) {
4640 0 : state.dataSolarShading->TrackTooManyFigures.redimension(++state.dataSolarShading->NumTooManyFigures);
4641 0 : state.dataSolarShading->TrackTooManyFigures(state.dataSolarShading->NumTooManyFigures).SurfIndex1 =
4642 0 : state.dataSolarShading->CurrentShadowingSurface;
4643 0 : state.dataSolarShading->TrackTooManyFigures(state.dataSolarShading->NumTooManyFigures).SurfIndex2 =
4644 0 : state.dataSolarShading->CurrentSurfaceBeingShadowed;
4645 : }
4646 :
4647 0 : return;
4648 : }
4649 :
4650 20917 : state.dataSolarShading->OverlapStatus = PartialOverlap;
4651 20917 : int NV1 = state.dataSolarShading->HCNV(NS1); // Number of vertices of figure NS1
4652 20917 : int NV2 = state.dataSolarShading->HCNV(NS2); // Number of vertices of figure NS2
4653 20917 : int NV3 = 0; // Number of vertices of figure NS3 (the overlap of NS1 and NS2)
4654 20917 : int NIN1 = 0; // Number of vertices of NS1 within NS2
4655 20917 : int NIN2 = 0; // Number of vertices of NS2 within NS1
4656 :
4657 20917 : if (!state.dataSysVars->SutherlandHodgman) {
4658 0 : INCLOS(state, NS1, NV1, NS2, NV2, NV3, NIN1); // Find vertices of NS1 within NS2.
4659 :
4660 0 : if (NIN1 >= NV1) {
4661 :
4662 0 : state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
4663 :
4664 : } else {
4665 :
4666 0 : INCLOS(state, NS2, NV2, NS1, NV1, NV3, NIN2); // Find vertices of NS2 within NS1.
4667 :
4668 0 : if (NIN2 >= NV2) {
4669 :
4670 0 : state.dataSolarShading->OverlapStatus = SecondSurfWithinFirst;
4671 :
4672 : } else {
4673 :
4674 0 : INTCPT(state, NV1, NV2, NV3, NS1, NS2); // Find intercepts of NS1 & NS2.
4675 :
4676 0 : if (NV3 < 3) { // Overlap must have 3 or more vertices
4677 0 : state.dataSolarShading->OverlapStatus = NoOverlap;
4678 0 : return;
4679 : }
4680 : }
4681 : }
4682 :
4683 : } else {
4684 : // simple polygon clipping
4685 20917 : CLIPPOLY(state, NS1, NS2, NV1, NV2, NV3);
4686 : }
4687 :
4688 20917 : if (NV3 < state.dataSolarShading->MaxHCV) {
4689 :
4690 20917 : if (!state.dataSysVars->SutherlandHodgman) {
4691 0 : ORDER(state, NV3, NS3); // Put vertices in clockwise order.
4692 : } else {
4693 20917 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
4694 20917 : int l = state.dataSolarShading->HCX.index(NS3, 1);
4695 79830 : for (int N = 1; N <= NV3; ++N, ++l) {
4696 58913 : state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XTEMP(N)); // [ l ] == ( N, NS3 )
4697 58913 : state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YTEMP(N));
4698 : }
4699 : }
4700 :
4701 20917 : HTRANS0(state, NS3, NV3); // Determine h.c. values of sides.
4702 : // Skip overlaps of negligible area.
4703 :
4704 20917 : if (std::abs(state.dataSolarShading->HCAREA(NS3)) * HCMULT < std::abs(state.dataSolarShading->HCAREA(NS1))) {
4705 6406 : state.dataSolarShading->OverlapStatus = NoOverlap;
4706 : } else {
4707 14511 : if (state.dataSolarShading->HCAREA(NS1) * state.dataSolarShading->HCAREA(NS2) > 0.0) {
4708 2221 : state.dataSolarShading->HCAREA(NS3) = -state.dataSolarShading->HCAREA(NS3); // Determine sign of area of overlap
4709 : }
4710 14511 : Real64 const HCT_1 = state.dataSolarShading->HCT(NS1);
4711 14511 : Real64 const HCT_2 = state.dataSolarShading->HCT(NS2);
4712 14511 : if (HCT_2 == 1.0 || HCT_1 == 1.0) {
4713 13851 : state.dataSolarShading->HCT(NS3) = HCT_1 * HCT_2;
4714 : } else {
4715 : // Determine transmission of overlap which corrects for prior shadows
4716 : // The resulting transmission of overlapping shadows is HCT_1 * HCT_2
4717 : // Shadows with HCT_1 and HCT_2 have already been applied in the overlapping area
4718 : // so the correction is the difference between (HCT_1+HCT_2) and (HCT_1*HCT_2)
4719 660 : state.dataSolarShading->HCT(NS3) = (HCT_1 + HCT_2) - HCT_1 * HCT_2;
4720 : }
4721 : }
4722 :
4723 : } else {
4724 :
4725 0 : state.dataSolarShading->OverlapStatus = TooManyVertices;
4726 :
4727 0 : if (!state.dataSolarShading->TooManyVerticesMessage && !state.dataGlobal->DisplayExtraWarnings) {
4728 0 : ShowWarningError(state,
4729 0 : format("DeterminePolygonOverlap: Too many vertices [>{}] detected in an overlap calculation. Use "
4730 : "Output:Diagnostics,DisplayExtraWarnings; for more details.",
4731 0 : state.dataSolarShading->MaxHCV));
4732 0 : state.dataSolarShading->TooManyVerticesMessage = true;
4733 : }
4734 :
4735 0 : if (state.dataGlobal->DisplayExtraWarnings) {
4736 0 : state.dataSolarShading->TrackTooManyVertices.redimension(++state.dataSolarShading->NumTooManyVertices);
4737 0 : state.dataSolarShading->TrackTooManyVertices(state.dataSolarShading->NumTooManyVertices).SurfIndex1 =
4738 0 : state.dataSolarShading->CurrentShadowingSurface;
4739 0 : state.dataSolarShading->TrackTooManyVertices(state.dataSolarShading->NumTooManyVertices).SurfIndex2 =
4740 0 : state.dataSolarShading->CurrentSurfaceBeingShadowed;
4741 : }
4742 : }
4743 : }
4744 :
4745 1838 : void CalcPerSolarBeam(EnergyPlusData &state,
4746 : Real64 const AvgEqOfTime, // Average value of Equation of Time for period
4747 : Real64 const AvgSinSolarDeclin, // Average value of Sine of Solar Declination for period
4748 : Real64 const AvgCosSolarDeclin // Average value of Cosine of Solar Declination for period
4749 : )
4750 : {
4751 :
4752 : // SUBROUTINE INFORMATION:
4753 : // AUTHOR Legacy Code
4754 : // DATE WRITTEN
4755 : // MODIFIED BG, Nov 2012 - Timestep solar. DetailedSolarTimestepIntegration
4756 : // RE-ENGINEERED Lawrie, Oct 2000
4757 :
4758 : // PURPOSE OF THIS SUBROUTINE:
4759 : // This subroutine manages computation of solar gain multipliers for beam radiation. These
4760 : // are calculated for a period of days depending on the input "Shadowing Calculations".
4761 :
4762 : // REFERENCES:
4763 : // BLAST/IBLAST code, original author George Walton
4764 :
4765 : // Using/Aliasing
4766 :
4767 : using WindowComplexManager::InitComplexWindows;
4768 : using WindowComplexManager::UpdateComplexWindows;
4769 :
4770 : int iHour; // Hour index number
4771 : int TS; // TimeStep Loop Countergit
4772 :
4773 1838 : auto &s_surf = state.dataSurface;
4774 :
4775 1838 : if (state.dataSolarShading->InitComplexOnce) InitComplexWindows(state);
4776 1838 : state.dataSolarShading->InitComplexOnce = false;
4777 :
4778 1838 : if (state.dataGlobal->KickOffSizing || state.dataGlobal->KickOffSimulation) return; // Skip solar calcs for these Initialization steps.
4779 :
4780 : #ifdef EP_Count_Calls
4781 : ++state.dataTimingsData->NumCalcPerSolBeam_Calls;
4782 : #endif
4783 :
4784 : // Initialize some values for the appropriate period
4785 1576 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4786 549 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
4787 689 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
4788 363 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
4789 363 : int firstSurf = thisSpace.OpaqOrIntMassSurfaceFirst;
4790 363 : int lastSurf = thisSpace.OpaqOrIntMassSurfaceLast;
4791 2264 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4792 1901 : s_surf->SurfOpaqAO(surfNum) = 0.0;
4793 : }
4794 363 : firstSurf = thisSpace.HTSurfaceFirst;
4795 363 : lastSurf = thisSpace.HTSurfaceLast;
4796 2375 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4797 2012 : state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
4798 : }
4799 9075 : for (int hour = 1; hour <= 24; ++hour) {
4800 57000 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4801 48288 : state.dataHeatBal->SurfSunlitFracHR(hour, surfNum) = 0.0;
4802 48288 : state.dataHeatBal->SurfCosIncAngHR(hour, surfNum) = 0.0;
4803 : }
4804 : }
4805 9075 : for (int hour = 1; hour <= 24; ++hour) {
4806 54264 : for (int timestep = 1; timestep <= state.dataGlobal->TimeStepsInHour; ++timestep) {
4807 295800 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4808 250248 : state.dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum) = 0.0;
4809 250248 : state.dataHeatBal->SurfCosIncAng(hour, timestep, surfNum) = 0.0;
4810 250248 : state.dataHeatBal->SurfSunlitFracWithoutReveal(hour, timestep, surfNum) = 0.0;
4811 : }
4812 : }
4813 : }
4814 9075 : for (int hour = 1; hour <= 24; ++hour) {
4815 54264 : for (int timestep = 1; timestep <= state.dataGlobal->TimeStepsInHour; ++timestep) {
4816 956592 : for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
4817 5916000 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4818 5004960 : state.dataHeatBal->SurfWinBackSurfaces(hour, timestep, backSurfNum, surfNum) = 0.0;
4819 5004960 : state.dataHeatBal->SurfWinOverlapAreas(hour, timestep, backSurfNum, surfNum) = 0.0;
4820 : }
4821 : }
4822 : } // for (timestep)
4823 : } // for (hour)
4824 : } // for (spaceNum)
4825 : } // for (zoneNum)
4826 :
4827 2278 : for (auto &e : s_surf->SurfaceWindow) {
4828 2055 : std::fill(e.OutProjSLFracMult.begin(), e.OutProjSLFracMult.end(), 1.0);
4829 2055 : std::fill(e.InOutProjSLFracMult.begin(), e.InOutProjSLFracMult.end(), 1.0);
4830 : }
4831 : } else {
4832 2705 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
4833 2704 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
4834 1352 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
4835 1352 : int const firstSurf = thisSpace.HTSurfaceFirst;
4836 1352 : int const lastSurf = thisSpace.HTSurfaceLast;
4837 5418 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4838 4066 : state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
4839 4066 : s_surf->SurfOpaqAO(surfNum) = 0.0;
4840 4066 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
4841 4066 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
4842 4066 : state.dataHeatBal->SurfSunlitFracHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
4843 4066 : state.dataHeatBal->SurfCosIncAngHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
4844 4066 : state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
4845 : }
4846 28392 : for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
4847 108360 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4848 81320 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0;
4849 81320 : state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0.0;
4850 : }
4851 : }
4852 : }
4853 : }
4854 :
4855 5434 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
4856 4081 : s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;
4857 4081 : s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;
4858 : }
4859 : }
4860 :
4861 1576 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4862 5575 : for (iHour = 1; iHour <= 24; ++iHour) { // Do for all hours
4863 34560 : for (TS = 1; TS <= state.dataGlobal->TimeStepsInHour; ++TS) {
4864 29208 : FigureSunCosines(state, iHour, TS, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
4865 : }
4866 : }
4867 : } else {
4868 1353 : FigureSunCosines(state, state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
4869 : }
4870 : // Initialize/update the Complex Fenestration geometry and optical properties
4871 1576 : UpdateComplexWindows(state);
4872 1576 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4873 5575 : for (iHour = 1; iHour <= 24; ++iHour) { // Do for all hours.
4874 34560 : for (TS = 1; TS <= state.dataGlobal->TimeStepsInHour; ++TS) {
4875 29208 : FigureSolarBeamAtTimestep(state, iHour, TS);
4876 : } // TimeStep Loop
4877 : } // Hour Loop
4878 : } else {
4879 1353 : FigureSolarBeamAtTimestep(state, state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
4880 : }
4881 : }
4882 :
4883 30561 : void FigureSunCosines(EnergyPlusData &state,
4884 : int const iHour,
4885 : int const iTimeStep,
4886 : Real64 const EqOfTime, // value of Equation of Time for period
4887 : Real64 const SinSolarDeclin, // value of Sine of Solar Declination for period
4888 : Real64 const CosSolarDeclin // value of Cosine of Solar Declination for period
4889 : )
4890 : {
4891 :
4892 : // SUBROUTINE INFORMATION:
4893 : // AUTHOR B. Griffith
4894 : // DATE WRITTEN October 2012
4895 : // MODIFIED na
4896 : // RE-ENGINEERED na
4897 :
4898 : // PURPOSE OF THIS SUBROUTINE:
4899 : // Determine solar position. Default for sun below horizon.
4900 :
4901 : // METHODOLOGY EMPLOYED:
4902 : // Given hour, timestep, equation of time, solar declination sine, and solar declination cosine,
4903 : // determine sun directions for use elsewhere
4904 :
4905 : // Using/Aliasing
4906 :
4907 : Real64 CurrentTime; // Current Time for passing to Solar Position Routine
4908 :
4909 30561 : auto &s_surf = state.dataSurface;
4910 :
4911 30561 : if (state.dataGlobal->TimeStepsInHour != 1) {
4912 30249 : CurrentTime = double(iHour - 1) + double(iTimeStep) * (state.dataGlobal->TimeStepZone);
4913 : } else {
4914 312 : CurrentTime = double(iHour) + state.dataEnvrn->TS1TimeOffset;
4915 : }
4916 30561 : SUN4(state, CurrentTime, EqOfTime, SinSolarDeclin, CosSolarDeclin);
4917 :
4918 : // Save hourly values for use in DaylightingManager
4919 30561 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4920 29208 : if (iTimeStep == state.dataGlobal->TimeStepsInHour) s_surf->SurfSunCosHourly(iHour) = state.dataSolarShading->SUNCOS;
4921 : } else {
4922 1353 : s_surf->SurfSunCosHourly(iHour) = state.dataSolarShading->SUNCOS;
4923 : }
4924 : // Save timestep values for use in WindowComplexManager
4925 30561 : state.dataBSDFWindow->SUNCOSTS(iTimeStep, iHour) = state.dataSolarShading->SUNCOS;
4926 30561 : }
4927 :
4928 30582 : void FigureSolarBeamAtTimestep(EnergyPlusData &state, int const iHour, int const iTimeStep)
4929 : {
4930 :
4931 : // SUBROUTINE INFORMATION:
4932 : // AUTHOR B.Griffith, derived from CalcPerSolarBeam, Legacy and Lawrie.
4933 : // DATE WRITTEN October 2012
4934 : // MODIFIED na
4935 : // RE-ENGINEERED na
4936 :
4937 : // PURPOSE OF THIS SUBROUTINE:
4938 : // This subroutine computes solar gain multipliers for beam solar
4939 :
4940 : using DataSystemVariables::ShadingMethod;
4941 :
4942 : Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
4943 : Real64 Fac1WoShdg; // Intermediate calculation factor, without shading
4944 : Real64 Fac1WithShdg; // Intermediate calculation factor, with shading
4945 : Real64 FracIlluminated; // Fraction of surface area illuminated by a sky patch
4946 :
4947 30582 : auto &s_surf = state.dataSurface;
4948 :
4949 : // Recover the sun direction from the array stored in previous loop
4950 30582 : state.dataSolarShading->SUNCOS = state.dataBSDFWindow->SUNCOSTS(iTimeStep, iHour);
4951 :
4952 30582 : state.dataSolarShading->SurfSunCosTheta = 0.0;
4953 :
4954 30582 : if (state.dataSolarShading->SUNCOS(3) < DataEnvironment::SunIsUpValue) return;
4955 :
4956 144356 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
4957 258554 : state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
4958 129277 : state.dataSolarShading->SUNCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
4959 129277 : state.dataSolarShading->SUNCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
4960 129277 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4961 127565 : if (iTimeStep == state.dataGlobal->TimeStepsInHour)
4962 24614 : state.dataHeatBal->SurfCosIncAngHR(iHour, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
4963 : } else {
4964 1712 : state.dataHeatBal->SurfCosIncAngHR(iHour, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
4965 : }
4966 129277 : state.dataHeatBal->SurfCosIncAng(iHour, iTimeStep, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
4967 : }
4968 :
4969 30157 : if ((state.dataSysVars->shadingMethod == ShadingMethod::Scheduled || state.dataSysVars->shadingMethod == ShadingMethod::Imported) &&
4970 30157 : !state.dataGlobal->DoingSizing && state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather) {
4971 10 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
4972 9 : auto &surf = s_surf->Surface(SurfNum);
4973 9 : if (surf.SurfSchedExternalShadingFrac) {
4974 1 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = surf.surfExternalShadingSched->getHrTsVal(state, iHour, iTimeStep);
4975 : } else {
4976 8 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 1.0;
4977 : }
4978 : }
4979 : } else {
4980 15078 : SHADOW(state, iHour, iTimeStep); // Determine sunlit areas and solar multipliers for all surfaces.
4981 144346 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
4982 129268 : if (s_surf->Surface(SurfNum).Area >= 1.e-10) {
4983 129268 : SurfArea = s_surf->Surface(SurfNum).NetAreaShadowCalc;
4984 129268 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4985 127556 : if (iTimeStep == state.dataGlobal->TimeStepsInHour)
4986 24614 : state.dataHeatBal->SurfSunlitFracHR(iHour, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
4987 : } else {
4988 1712 : state.dataHeatBal->SurfSunlitFracHR(iHour, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
4989 : }
4990 129268 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
4991 129268 : if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) < 1.e-5)
4992 85366 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 0.0;
4993 : }
4994 : // Added check
4995 129268 : if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) > 1.0) {
4996 0 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 1.0;
4997 : }
4998 : }
4999 : }
5000 : // Note -- if not the below, values are set in SkyDifSolarShading routine (constant for simulation)
5001 15096 : if (state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
5002 17 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
5003 148 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
5004 131 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) = 0.;
5005 131 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) = 0.;
5006 131 : state.dataSolarShading->SurfWithShdgHoriz(SurfNum) = 0.;
5007 131 : state.dataSolarShading->SurfWoShdgHoriz(SurfNum) = 0.;
5008 : }
5009 :
5010 119 : for (int IPhi = 0; IPhi < NPhi; ++IPhi) { // Loop over patch altitude values
5011 102 : state.dataSolarShading->SUNCOS(3) = state.dataSolarShading->sin_Phi[IPhi];
5012 :
5013 2550 : for (int ITheta = 0; ITheta < NTheta; ++ITheta) { // Loop over patch azimuth values
5014 2448 : state.dataSolarShading->SUNCOS(1) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->cos_Theta[ITheta];
5015 2448 : state.dataSolarShading->SUNCOS(2) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->sin_Theta[ITheta];
5016 :
5017 21312 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
5018 37728 : state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
5019 18864 : state.dataSolarShading->SUNCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
5020 18864 : state.dataSolarShading->SUNCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
5021 : }
5022 :
5023 2448 : SHADOW(state, iHour, iTimeStep); // Determine sunlit areas and solar multipliers for all surfaces.
5024 :
5025 21312 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
5026 :
5027 18864 : if (state.dataSolarShading->SurfSunCosTheta(SurfNum) < 0.0) continue;
5028 :
5029 8526 : Fac1WoShdg = state.dataSolarShading->cos_Phi[IPhi] * DThetaDPhi * state.dataSolarShading->SurfSunCosTheta(SurfNum);
5030 8526 : SurfArea = s_surf->Surface(SurfNum).NetAreaShadowCalc;
5031 8526 : if (SurfArea > Eps) {
5032 8526 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
5033 : } else {
5034 0 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / (SurfArea + Eps);
5035 : }
5036 8526 : Fac1WithShdg = Fac1WoShdg * FracIlluminated;
5037 8526 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) += Fac1WithShdg;
5038 8526 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) += Fac1WoShdg;
5039 :
5040 : // Horizon region
5041 8526 : if (IPhi == 0) {
5042 1421 : state.dataSolarShading->SurfWithShdgHoriz(SurfNum) += Fac1WithShdg;
5043 1421 : state.dataSolarShading->SurfWoShdgHoriz(SurfNum) += Fac1WoShdg;
5044 : }
5045 : } // End of surface loop
5046 : } // End of Theta loop
5047 : } // End of Phi loop
5048 :
5049 148 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
5050 : // Original conditions:
5051 : // if (!s_surf->Surface(SurfNum).IsShadowing &&
5052 : // (!s_surf->Surface(SurfNum).HeatTransSurf || !s_surf->Surface(SurfNum).ExtSolar))
5053 : // continue;
5054 :
5055 131 : if (std::abs(state.dataSolarShading->SurfWoShdgIsoSky(SurfNum)) > Eps) {
5056 95 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(iTimeStep, iHour, SurfNum) =
5057 95 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum));
5058 : } else {
5059 36 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(iTimeStep, iHour, SurfNum) =
5060 36 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) + Eps);
5061 : }
5062 131 : if (std::abs(state.dataSolarShading->SurfWoShdgHoriz(SurfNum)) > Eps) {
5063 95 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS(iTimeStep, iHour, SurfNum) =
5064 95 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum));
5065 : } else {
5066 36 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS(iTimeStep, iHour, SurfNum) =
5067 36 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum) + Eps);
5068 : }
5069 : }
5070 :
5071 : // ! Get IR view factors. An exterior surface can receive IR radiation from
5072 : // ! sky, ground or shadowing surfaces. Assume shadowing surfaces have same
5073 : // ! temperature as outside air (and therefore same temperature as ground),
5074 : // ! so that the view factor to these shadowing surfaces can be included in
5075 : // ! the ground view factor. Sky IR is assumed to be isotropic and shadowing
5076 : // ! surfaces are assumed to be opaque to IR so they totally "shade" IR from
5077 : // ! sky or ground.
5078 :
5079 : // DO SurfNum = 1,TotSurfaces
5080 : // Surface(SurfNum)%ViewFactorSkyIR = Surface(SurfNum)%ViewFactorSkyIR * DifShdgRatioIsoSky(SurfNum,IHOUR,TS)
5081 : // Surface(SurfNum)%ViewFactorGroundIR = 1.0 - Surface(SurfNum)%ViewFactorSkyIR
5082 : // END DO
5083 :
5084 : } // test for shading surfaces
5085 :
5086 15102 : for (int SurfNum : s_surf->AllExtSolWinWithFrameSurfaceList) {
5087 : // For exterior windows with frame/divider that are partially or fully sunlit,
5088 : // correct SunlitFrac due to shadowing of frame and divider projections onto window glass.
5089 : // Note: if SunlitFrac = 0.0 the window is either completely shaded or the sun is in back
5090 : // of the window; in either case, frame/divider shadowing doesn't have to be done.
5091 :
5092 23 : if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) > 0.0) {
5093 17 : CalcFrameDividerShadow(state, SurfNum, s_surf->Surface(SurfNum).FrameDivider, iHour);
5094 : }
5095 : }
5096 : }
5097 :
5098 133 : void DetermineShadowingCombinations(EnergyPlusData &state)
5099 : {
5100 :
5101 : // SUBROUTINE INFORMATION:
5102 : // AUTHOR From Legacy Code
5103 : // DATE WRITTEN
5104 : // MODIFIED LKL; March 2002 -- another missing translation from BLAST's routine
5105 : // FCW; Jan 2003 -- removed line that prevented beam solar through interior windows
5106 : // RE-ENGINEERED Rick Strand; 1998
5107 : // Linda Lawrie; Oct 2000
5108 :
5109 : // PURPOSE OF THIS SUBROUTINE:
5110 : // This routine prepares a list of heat transfer surfaces and
5111 : // their possible shadowers which is used to direct the hourly
5112 : // calculation of shadows and sunlit areas.
5113 :
5114 : // METHODOLOGY EMPLOYED:
5115 : // As appropriate surfaces are identified, they are placed into the
5116 : // ShadowComb data structure (module level) with the accompanying lists
5117 : // of other surface numbers.
5118 :
5119 : // REFERENCES:
5120 : // BLAST/IBLAST code, original author George Walton
5121 :
5122 : // Using/Aliasing
5123 : using namespace DataErrorTracking;
5124 :
5125 133 : Array1D_int GSS; // List of shadowing surfaces numbers for a receiving surface
5126 133 : Array1D_int BKS; // List of back surface numbers for a receiving surface
5127 133 : Array1D_int SBS; // List of subsurfaces for a receiving surface
5128 : bool CannotShade; // TRUE if subsurface cannot shade receiving surface
5129 : bool HasWindow; // TRUE if a window is present on receiving surface
5130 : Real64 ZMIN; // Lowest point on the receiving surface
5131 : int BackSurfaceNumber; // Back surface number
5132 : int HTS; // Heat transfer surface number for a receiving surface
5133 : int GRSNR; // Receiving surface number
5134 : int GSSNR; // Shadowing surface number
5135 : int SBSNR; // Subsurface number
5136 : int NBKS; // Number of back surfaces for a receiving surface
5137 : int NGSS; // Number of shadowing surfaces for a receiving surface
5138 : int NSBS; // Number of subsurfaces for a receiving surface
5139 : bool ShadowingSurf; // True if a receiving surface is a shadowing surface
5140 133 : Array1D_bool CastingSurface; // tracking during setup of ShadowComb
5141 :
5142 133 : auto &s_surf = state.dataSurface;
5143 :
5144 : #ifdef EP_Count_Calls
5145 : ++state.dataTimingsData->NumDetShadowCombs_Calls;
5146 : #endif
5147 :
5148 133 : state.dataShadowComb->ShadowComb.dimension(s_surf->TotSurfaces, ShadowingCombinations{}); // Set all elements to default constructed state
5149 :
5150 133 : CastingSurface.dimension(s_surf->TotSurfaces, false);
5151 :
5152 133 : state.dataSolarShading->HCA.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5153 133 : state.dataSolarShading->HCB.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5154 133 : state.dataSolarShading->HCC.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5155 133 : state.dataSolarShading->HCX.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5156 133 : state.dataSolarShading->HCY.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5157 133 : state.dataSolarShading->HCAREA.dimension(2 * state.dataSolarShading->MaxHCS, 0.0);
5158 133 : state.dataSolarShading->HCNS.dimension(2 * state.dataSolarShading->MaxHCS, 0);
5159 133 : state.dataSolarShading->HCNV.dimension(2 * state.dataSolarShading->MaxHCS, 0);
5160 133 : state.dataSolarShading->HCT.dimension(2 * state.dataSolarShading->MaxHCS, 0.0);
5161 :
5162 133 : GSS.dimension(state.dataSolarShading->MaxGSS, 0);
5163 133 : BKS.dimension(state.dataSolarShading->MaxGSS, 0);
5164 133 : SBS.dimension(state.dataSolarShading->MaxGSS, 0);
5165 :
5166 133 : state.dataSolarShading->penumbraIDs.clear();
5167 :
5168 133 : HTS = 0;
5169 :
5170 : // Check every surface as a possible shadow receiving surface ("RS" = receiving surface).
5171 133 : if (state.dataEnvrn->IgnoreSolarRadiation) {
5172 0 : return;
5173 : }
5174 :
5175 1110 : for (GRSNR = 1; GRSNR <= s_surf->TotSurfaces; ++GRSNR) { // Loop through all surfaces (looking for potential receiving surfaces)...
5176 :
5177 977 : ShadowingSurf = s_surf->Surface(GRSNR).IsShadowing;
5178 977 : NGSS = 0;
5179 977 : NSBS = 0;
5180 977 : NBKS = 0;
5181 :
5182 977 : if (!ShadowingSurf && !s_surf->Surface(GRSNR).HeatTransSurf) continue;
5183 975 : HTS = GRSNR;
5184 :
5185 : #ifndef EP_NO_OPENGL
5186 975 : if (state.dataSolarShading->penumbra) {
5187 0 : bool skipSurface = s_surf->Surface(GRSNR).MirroredSurf;
5188 : // Penumbra doesn't need mirrored surfaces TODO: Don't bother creating them in the first place?
5189 :
5190 : // Skip interior surfaces if the other side has already been added to penumbra
5191 0 : if (s_surf->Surface(GRSNR).ExtBoundCond > 0) {
5192 0 : if (s_surf->SurfPenumbraID(s_surf->Surface(GRSNR).ExtBoundCond) >= 0) {
5193 0 : s_surf->SurfPenumbraID(GRSNR) = s_surf->SurfPenumbraID(s_surf->Surface(GRSNR).ExtBoundCond);
5194 0 : skipSurface = true;
5195 : }
5196 : }
5197 :
5198 0 : if (!skipSurface) {
5199 : // Add surfaces to penumbra...
5200 0 : Penumbra::Polygon poly;
5201 :
5202 0 : if (s_surf->Surface(GRSNR).Reveal > 0.0) {
5203 0 : Real64 R = s_surf->Surface(GRSNR).Reveal;
5204 0 : auto &norm = s_surf->Surface(GRSNR).NewellSurfaceNormalVector;
5205 0 : auto &v = s_surf->Surface(GRSNR).Vertex;
5206 0 : for (unsigned i = 0; i < v.size(); ++i) {
5207 0 : poly.push_back(v[i].x);
5208 0 : poly.push_back(v[i].y);
5209 0 : poly.push_back(v[i].z);
5210 :
5211 0 : Vector vPrev;
5212 0 : if (i == 0) {
5213 0 : vPrev = v[v.size() - 1];
5214 : } else {
5215 0 : vPrev = v[i - 1];
5216 : }
5217 :
5218 0 : Penumbra::Polygon rPoly; // Reveal surface
5219 0 : rPoly.push_back(v[i].x);
5220 0 : rPoly.push_back(v[i].y);
5221 0 : rPoly.push_back(v[i].z);
5222 :
5223 0 : rPoly.push_back(v[i].x + norm.x * R);
5224 0 : rPoly.push_back(v[i].y + norm.y * R);
5225 0 : rPoly.push_back(v[i].z + norm.z * R);
5226 :
5227 0 : rPoly.push_back(vPrev.x + norm.x * R);
5228 0 : rPoly.push_back(vPrev.y + norm.y * R);
5229 0 : rPoly.push_back(vPrev.z + norm.z * R);
5230 :
5231 0 : rPoly.push_back(vPrev.x);
5232 0 : rPoly.push_back(vPrev.y);
5233 0 : rPoly.push_back(vPrev.z);
5234 :
5235 0 : Penumbra::Surface rSurf(rPoly, fmt::format("{} reveal {}", s_surf->Surface(GRSNR).Name, i));
5236 0 : state.dataSolarShading->penumbra->add_surface(rSurf);
5237 0 : }
5238 : } else {
5239 0 : for (auto const &v : s_surf->Surface(GRSNR).Vertex) {
5240 0 : poly.push_back(v.x);
5241 0 : poly.push_back(v.y);
5242 0 : poly.push_back(v.z);
5243 : }
5244 : }
5245 0 : Penumbra::Surface pSurf(poly, s_surf->Surface(GRSNR).Name);
5246 :
5247 : // Punch holes for subsurfaces
5248 0 : if (s_surf->Surface(GRSNR).BaseSurf == GRSNR) { // Only look for subsurfaces on base surfaces
5249 0 : for (int subSurface = 1; subSurface <= s_surf->TotSurfaces; ++subSurface) {
5250 0 : if (s_surf->Surface(subSurface).BaseSurf != GRSNR) continue; // Ignore subsurfaces of other surfaces
5251 0 : if (!s_surf->Surface(subSurface).HeatTransSurf) continue; // Skip non heat transfer subsurfaces
5252 0 : if (subSurface == GRSNR) continue; // Surface itself cannot be its own subsurface
5253 :
5254 0 : Penumbra::Polygon subPoly;
5255 0 : if (s_surf->Surface(subSurface).Reveal > 0.0) {
5256 0 : Real64 R = s_surf->Surface(subSurface).Reveal;
5257 0 : auto &norm = s_surf->Surface(subSurface).NewellSurfaceNormalVector;
5258 0 : for (auto const &v : s_surf->Surface(subSurface).Vertex) {
5259 0 : subPoly.push_back(v.x + norm.x * R);
5260 0 : subPoly.push_back(v.y + norm.y * R);
5261 0 : subPoly.push_back(v.z + norm.z * R);
5262 : }
5263 : } else {
5264 0 : for (auto const &v : s_surf->Surface(subSurface).Vertex) {
5265 0 : subPoly.push_back(v.x);
5266 0 : subPoly.push_back(v.y);
5267 0 : subPoly.push_back(v.z);
5268 : }
5269 : }
5270 :
5271 0 : pSurf.add_hole(subPoly);
5272 0 : }
5273 : }
5274 0 : s_surf->SurfPenumbraID(GRSNR) = state.dataSolarShading->penumbra->add_surface(pSurf);
5275 0 : state.dataSolarShading->penumbraIDs.push_back(s_surf->SurfPenumbraID(GRSNR));
5276 0 : }
5277 : }
5278 : #endif
5279 :
5280 975 : if (!ShadowingSurf && !s_surf->Surface(GRSNR).ExtSolar) continue; // Skip surfaces with no external solar
5281 :
5282 671 : if (!ShadowingSurf && s_surf->Surface(GRSNR).BaseSurf != GRSNR) { // Skip subsurfaces (SBS)
5283 70 : continue;
5284 : }
5285 :
5286 : // Get the lowest point of receiving surface
5287 601 : ZMIN = minval(s_surf->Surface(GRSNR).Vertex, &Vector::z);
5288 :
5289 : // Check every surface as a possible shadow casting surface ("SS" = shadow sending)
5290 601 : NGSS = 0;
5291 601 : if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) { // Except when doing simplified exterior shadowing.
5292 :
5293 5489 : for (GSSNR = 1; GSSNR <= s_surf->TotSurfaces; ++GSSNR) { // Loop through all surfaces, looking for ones that could shade GRSNR
5294 :
5295 5094 : if (GSSNR == GRSNR) continue; // Receiving surface cannot shade itself
5296 4699 : if ((s_surf->Surface(GSSNR).HeatTransSurf) && (s_surf->Surface(GSSNR).BaseSurf == GRSNR))
5297 63 : continue; // A heat transfer subsurface of a receiving surface
5298 : // cannot shade the receiving surface
5299 4636 : if (ShadowingSurf) {
5300 : // If receiving surf is a shadowing surface exclude matching shadow surface as sending surface
5301 : // IF((GSSNR == GRSNR+1 .AND. Surface(GSSNR)%Name(1:3) == 'Mir').OR. &
5302 : // (GSSNR == GRSNR-1 .AND. Surface(GRSNR)%Name(1:3) == 'Mir')) CYCLE
5303 1817 : if (((GSSNR == GRSNR + 1) && s_surf->Surface(GSSNR).MirroredSurf) ||
5304 893 : ((GSSNR == GRSNR - 1) && s_surf->Surface(GRSNR).MirroredSurf))
5305 62 : continue;
5306 : }
5307 :
5308 4574 : if (s_surf->Surface(GSSNR).BaseSurf == GRSNR) { // Shadowing subsurface of receiving surface
5309 :
5310 0 : ++NGSS;
5311 0 : if (NGSS > state.dataSolarShading->MaxGSS) {
5312 0 : GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
5313 : }
5314 0 : GSS(NGSS) = GSSNR;
5315 :
5316 8720 : } else if ((s_surf->Surface(GSSNR).BaseSurf == 0) ||
5317 4146 : ((s_surf->Surface(GSSNR).BaseSurf == GSSNR) &&
5318 3614 : ((s_surf->Surface(GSSNR).ExtBoundCond == ExternalEnvironment) ||
5319 1474 : s_surf->Surface(GSSNR).ExtBoundCond ==
5320 : OtherSideCondModeledExt))) { // Detached shadowing surface or | any other base surface
5321 : // exposed to outside environment
5322 :
5323 2568 : CHKGSS(state, GRSNR, GSSNR, ZMIN, CannotShade); // Check to see if this can shade the receiving surface
5324 2568 : if (!CannotShade) { // Update the shadowing surface data if shading is possible
5325 126 : ++NGSS;
5326 126 : if (NGSS > state.dataSolarShading->MaxGSS) {
5327 0 : GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
5328 : }
5329 126 : GSS(NGSS) = GSSNR;
5330 : }
5331 : }
5332 :
5333 : } // ...end of surfaces DO loop (GSSNR)
5334 : } else { // Simplified Distribution -- still check for Shading Subsurfaces
5335 :
5336 1483 : for (GSSNR = 1; GSSNR <= s_surf->TotSurfaces; ++GSSNR) { // Loop through all surfaces (looking for surfaces which could shade GRSNR) ...
5337 :
5338 1277 : if (GSSNR == GRSNR) continue; // Receiving surface cannot shade itself
5339 1071 : if ((s_surf->Surface(GSSNR).HeatTransSurf) && (s_surf->Surface(GSSNR).BaseSurf == GRSNR))
5340 7 : continue; // Skip heat transfer subsurfaces of receiving surface
5341 1064 : if (s_surf->Surface(GSSNR).BaseSurf == GRSNR) { // Shadowing subsurface of receiving surface
5342 0 : ++NGSS;
5343 0 : if (NGSS > state.dataSolarShading->MaxGSS) {
5344 0 : GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
5345 : }
5346 0 : GSS(NGSS) = GSSNR;
5347 : }
5348 : }
5349 :
5350 : } // ...end of check for simplified solar distribution
5351 :
5352 : // Check every surface as a receiving subsurface of the receiving surface
5353 601 : NSBS = 0;
5354 601 : HasWindow = false;
5355 : // legacy: IF (OSENV(HTS) > 10) WINDOW=.TRUE. -->Note: WINDOW was set true for roof ponds, solar walls, or other zones
5356 6972 : for (SBSNR = 1; SBSNR <= s_surf->TotSurfaces; ++SBSNR) { // Loop through the surfaces yet again (looking for subsurfaces of GRSNR)...
5357 :
5358 6371 : if (!s_surf->Surface(SBSNR).HeatTransSurf) continue; // Skip non heat transfer subsurfaces
5359 5819 : if (SBSNR == GRSNR) continue; // Surface itself cannot be its own subsurface
5360 5280 : if (s_surf->Surface(SBSNR).BaseSurf != GRSNR) continue; // Ignore subsurfaces of other surfaces and other surfaces
5361 :
5362 70 : if (state.dataConstruction->Construct(s_surf->Surface(SBSNR).Construction).TransDiff > 0.0) HasWindow = true; // Check for window
5363 70 : CHKSBS(state, HTS, GRSNR, SBSNR); // Check that the receiving surface completely encloses the subsurface;
5364 : // severe error if not
5365 70 : ++NSBS;
5366 70 : if (NSBS > state.dataSolarShading->MaxSBS) {
5367 0 : SBS.redimension(state.dataSolarShading->MaxSBS *= 2, 0);
5368 : }
5369 70 : SBS(NSBS) = SBSNR;
5370 :
5371 : } // ...end of surfaces DO loop (SBSNR)
5372 :
5373 : // Check every surface as a back surface
5374 601 : NBKS = 0;
5375 : // Except for simplified
5376 : // interior solar distribution,
5377 601 : if ((state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) &&
5378 : (HasWindow)) { // For full interior solar distribution | and a window present on base surface (GRSNR)
5379 :
5380 76 : for (BackSurfaceNumber = 1; BackSurfaceNumber <= s_surf->TotSurfaces;
5381 : ++BackSurfaceNumber) { // Loop through surfaces yet again, looking for back surfaces to GRSNR
5382 :
5383 69 : if (!s_surf->Surface(BackSurfaceNumber).HeatTransSurf) continue; // Skip non-heat transfer surfaces
5384 69 : if (s_surf->Surface(BackSurfaceNumber).BaseSurf == GRSNR) continue; // Skip subsurfaces of this GRSNR
5385 55 : if (BackSurfaceNumber == GRSNR) continue; // A back surface cannot be GRSNR itself
5386 55 : if (s_surf->Surface(BackSurfaceNumber).SolarEnclIndex != s_surf->Surface(GRSNR).SolarEnclIndex)
5387 14 : continue; // Skip if back surface not in same solar enclosure
5388 :
5389 41 : if (s_surf->Surface(BackSurfaceNumber).Class == SurfaceClass::IntMass) continue;
5390 :
5391 : // Following line removed 1/27/03 by FCW. Was in original code that didn't do beam solar transmitted through
5392 : // interior windows. Was removed to allow such beam solar but then somehow was put back in.
5393 : // IF (Surface(BackSurfaceNumber)%BaseSurf /= BackSurfaceNumber) CYCLE ! Not for subsurfaces of Back Surface
5394 :
5395 41 : if (!state.dataSolarShading->penumbra) {
5396 41 : CHKBKS(state, BackSurfaceNumber, GRSNR); // CHECK FOR CONVEX ZONE; severe error if not
5397 : }
5398 41 : ++NBKS;
5399 41 : if (NBKS > state.dataSolarShading->MaxBKS) {
5400 0 : BKS.redimension(state.dataSolarShading->MaxBKS *= 2, 0);
5401 : }
5402 41 : BKS(NBKS) = BackSurfaceNumber;
5403 :
5404 : } // ...end of surfaces DO loop (BackSurfaceNumber)
5405 : }
5406 :
5407 : // Put this into the ShadowComb data structure
5408 601 : state.dataShadowComb->ShadowComb(GRSNR).UseThisSurf = true;
5409 601 : state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf = NGSS;
5410 601 : state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf = NBKS;
5411 601 : state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf = NSBS;
5412 601 : state.dataSolarShading->MaxDim = max(state.dataSolarShading->MaxDim, NGSS, NBKS, NSBS);
5413 :
5414 601 : state.dataShadowComb->ShadowComb(GRSNR).GenSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf});
5415 601 : state.dataShadowComb->ShadowComb(GRSNR).GenSurf(0) = 0;
5416 601 : if (state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf > 0) {
5417 89 : state.dataShadowComb->ShadowComb(GRSNR).GenSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf}) = GSS({1, NGSS});
5418 : }
5419 :
5420 601 : state.dataShadowComb->ShadowComb(GRSNR).BackSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf});
5421 601 : state.dataShadowComb->ShadowComb(GRSNR).BackSurf(0) = 0;
5422 601 : if (state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf > 0) {
5423 7 : state.dataShadowComb->ShadowComb(GRSNR).BackSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf}) = BKS({1, NBKS});
5424 : }
5425 :
5426 601 : state.dataShadowComb->ShadowComb(GRSNR).SubSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf});
5427 601 : state.dataShadowComb->ShadowComb(GRSNR).SubSurf(0) = 0;
5428 601 : if (state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf > 0) {
5429 65 : state.dataShadowComb->ShadowComb(GRSNR).SubSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf}) = SBS({1, NSBS});
5430 : }
5431 :
5432 : } // ...end of surfaces (GRSNR) DO loop
5433 :
5434 133 : GSS.deallocate();
5435 133 : SBS.deallocate();
5436 133 : BKS.deallocate();
5437 :
5438 133 : if (!state.dataSolarShading->penumbra) {
5439 133 : if (state.dataSolarShading->shd_stream) {
5440 114 : *state.dataSolarShading->shd_stream << "Shadowing Combinations\n";
5441 114 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
5442 41 : *state.dataSolarShading->shd_stream
5443 41 : << "..Solar Distribution=Minimal Shadowing, Detached Shading will not be used in shadowing calculations\n";
5444 73 : } else if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullExterior) {
5445 63 : if (s_surf->CalcSolRefl) {
5446 0 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullExteriorWithReflectionsFromExteriorSurfaces\n";
5447 : } else {
5448 63 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullExterior\n";
5449 : }
5450 10 : } else if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
5451 10 : if (s_surf->CalcSolRefl) {
5452 0 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullInteriorAndExteriorWithReflectionsFromExteriorSurfaces\n";
5453 : } else {
5454 10 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullInteriorAndExterior\n";
5455 : }
5456 : } else {
5457 : }
5458 :
5459 114 : *state.dataSolarShading->shd_stream << "..In the following, only the first 10 reference surfaces will be shown.\n";
5460 114 : *state.dataSolarShading->shd_stream << "..But all surfaces are used in the calculations.\n";
5461 :
5462 943 : for (int HTSnum : s_surf->AllSurfaceListReportOrder) {
5463 829 : *state.dataSolarShading->shd_stream << "==================================\n";
5464 829 : if (state.dataShadowComb->ShadowComb(HTSnum).UseThisSurf) {
5465 484 : if (s_surf->Surface(HTSnum).IsConvex) {
5466 960 : *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
5467 960 : << " is used as Receiving Surface in calculations and is convex.\n";
5468 : } else {
5469 8 : *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
5470 8 : << " is used as Receiving Surface in calculations and is non-convex.\n";
5471 4 : if (state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf > 0) {
5472 2 : if (state.dataGlobal->DisplayExtraWarnings) {
5473 0 : ShowWarningError(state,
5474 0 : format("DetermineShadowingCombinations: Surface=\"{}\" is a receiving surface and is non-convex.",
5475 0 : s_surf->Surface(HTSnum).Name));
5476 0 : ShowContinueError(state,
5477 : "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5478 : } else {
5479 2 : ++state.dataErrTracking->TotalReceivingNonConvexSurfaces;
5480 : }
5481 : }
5482 : }
5483 : } else {
5484 690 : *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
5485 690 : << " is not used as Receiving Surface in calculations.\n";
5486 : }
5487 829 : *state.dataSolarShading->shd_stream << "Number of general casting surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf
5488 829 : << '\n';
5489 906 : for (NGSS = 1; NGSS <= state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf; ++NGSS) {
5490 77 : if (NGSS <= 10)
5491 77 : *state.dataSolarShading->shd_stream
5492 77 : << "..Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).GenSurf(NGSS)).Name << '\n';
5493 77 : CastingSurface(state.dataShadowComb->ShadowComb(HTSnum).GenSurf(NGSS)) = true;
5494 : }
5495 829 : *state.dataSolarShading->shd_stream << "Number of back surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumBackSurf << '\n';
5496 863 : for (NGSS = 1; NGSS <= min(10, state.dataShadowComb->ShadowComb(HTSnum).NumBackSurf); ++NGSS) {
5497 34 : *state.dataSolarShading->shd_stream
5498 34 : << "...Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).BackSurf(NGSS)).Name << '\n';
5499 : }
5500 829 : *state.dataSolarShading->shd_stream << "Number of receiving sub surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumSubSurf
5501 829 : << '\n';
5502 886 : for (NGSS = 1; NGSS <= min(10, state.dataShadowComb->ShadowComb(HTSnum).NumSubSurf); ++NGSS) {
5503 57 : *state.dataSolarShading->shd_stream
5504 57 : << "....Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).SubSurf(NGSS)).Name << '\n';
5505 : }
5506 : }
5507 : }
5508 :
5509 1110 : for (HTS = 1; HTS <= s_surf->TotSurfaces; ++HTS) {
5510 977 : if (CastingSurface(HTS) && !s_surf->Surface(HTS).IsConvex) {
5511 2 : if (state.dataGlobal->DisplayExtraWarnings) {
5512 0 : ShowSevereError(
5513 : state,
5514 0 : format("DetermineShadowingCombinations: Surface=\"{}\" is a casting surface and is non-convex.", s_surf->Surface(HTS).Name));
5515 0 : ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5516 : } else {
5517 2 : ++state.dataErrTracking->TotalCastingNonConvexSurfaces;
5518 : }
5519 : }
5520 : }
5521 :
5522 133 : if (state.dataErrTracking->TotalReceivingNonConvexSurfaces > 0) {
5523 6 : ShowWarningMessage(state,
5524 6 : format("DetermineShadowingCombinations: There are {} surfaces which are receiving surfaces and are non-convex.",
5525 3 : state.dataErrTracking->TotalReceivingNonConvexSurfaces));
5526 6 : ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5527 6 : ShowContinueError(state, "...Add Output:Diagnostics,DisplayExtraWarnings; to see individual warnings for each surface.");
5528 3 : state.dataErrTracking->TotalWarningErrors += state.dataErrTracking->TotalReceivingNonConvexSurfaces;
5529 : }
5530 :
5531 133 : if (state.dataErrTracking->TotalCastingNonConvexSurfaces > 0) {
5532 6 : ShowSevereMessage(state,
5533 6 : format("DetermineShadowingCombinations: There are {} surfaces which are casting surfaces and are non-convex.",
5534 3 : state.dataErrTracking->TotalCastingNonConvexSurfaces));
5535 6 : ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5536 6 : ShowContinueError(state, "...Add Output:Diagnostics,DisplayExtraWarnings; to see individual severes for each surface.");
5537 3 : state.dataErrTracking->TotalSevereErrors += state.dataErrTracking->TotalCastingNonConvexSurfaces;
5538 : }
5539 : }
5540 :
5541 133 : CastingSurface.deallocate();
5542 :
5543 : #ifndef EP_NO_OPENGL
5544 133 : if (state.dataSolarShading->penumbra && state.dataSolarShading->penumbra->get_number_of_surfaces() > 0) {
5545 0 : state.dataSolarShading->penumbra->set_model();
5546 : }
5547 : #endif
5548 133 : }
5549 :
5550 33798 : void SHADOW(EnergyPlusData &state,
5551 : int const iHour, // Hour index
5552 : int const TS // Time Step
5553 : )
5554 : {
5555 :
5556 : // SUBROUTINE INFORMATION:
5557 : // AUTHOR Legacy Code
5558 : // DATE WRITTEN
5559 : // MODIFIED Nov 2003, FCW: modify to do shadowing on shadowing surfaces
5560 : // RE-ENGINEERED Lawrie, Oct 2000
5561 :
5562 : // PURPOSE OF THIS SUBROUTINE:
5563 : // This subroutine is a driving routine for calculations of shadows
5564 : // and sunlit areas used in computing the solar beam flux multipliers.
5565 :
5566 : // REFERENCES:
5567 : // BLAST/IBLAST code, original author George Walton
5568 :
5569 : Real64 XS; // Intermediate result
5570 : Real64 YS; // Intermediate result
5571 : Real64 ZS; // Intermediate result
5572 : int N; // Vertex number
5573 : int NGRS; // Coordinate transformation index
5574 : int NVT;
5575 : int HTS; // Heat transfer surface number of the general receiving surface
5576 : int GRSNR; // Surface number of general receiving surface
5577 : int NBKS; // Number of back surfaces
5578 : int NGSS; // Number of general shadowing surfaces
5579 : int NSBS; // Number of subsurfaces (windows and doors)
5580 : Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
5581 : // For windows, includes divider area
5582 :
5583 33798 : auto &s_surf = state.dataSurface;
5584 :
5585 33798 : if (state.dataSolarShading->ShadowOneTimeFlag) {
5586 112 : state.dataSolarShading->XVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
5587 112 : state.dataSolarShading->YVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
5588 112 : state.dataSolarShading->ZVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
5589 112 : state.dataSolarShading->XVrt = 0.0;
5590 112 : state.dataSolarShading->YVrt = 0.0;
5591 112 : state.dataSolarShading->ZVrt = 0.0;
5592 112 : state.dataSolarShading->ShadowOneTimeFlag = false;
5593 : }
5594 :
5595 : #ifdef EP_Count_Calls
5596 : if (iHour == 0) {
5597 : ++state.dataTimingsData->NumShadow_Calls;
5598 : } else {
5599 : ++state.dataTimingsData->NumShadowAtTS_Calls;
5600 : }
5601 : #endif
5602 :
5603 33798 : state.dataSolarShading->SurfSunlitArea = 0.0;
5604 :
5605 : #ifndef EP_NO_OPENGL
5606 33798 : if (state.dataSolarShading->penumbra) {
5607 0 : Real64 ElevSun = Constant::PiOvr2 - std::acos(state.dataSolarShading->SUNCOS(3));
5608 0 : Real64 AzimSun = std::atan2(state.dataSolarShading->SUNCOS(1), state.dataSolarShading->SUNCOS(2));
5609 0 : state.dataSolarShading->penumbra->set_sun_position(AzimSun, ElevSun);
5610 0 : state.dataSolarShading->penumbra->submit_pssa();
5611 : }
5612 : #endif
5613 :
5614 301738 : for (GRSNR = 1; GRSNR <= s_surf->TotSurfaces; ++GRSNR) {
5615 :
5616 267940 : if (!state.dataShadowComb->ShadowComb(GRSNR).UseThisSurf) continue;
5617 :
5618 157882 : state.dataSolarShading->SurfSunlitArea(GRSNR) = 0.0;
5619 :
5620 157882 : NGSS = state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf;
5621 157882 : state.dataSolarShading->NGSSHC = 0;
5622 157882 : NBKS = state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf;
5623 157882 : state.dataSolarShading->NBKSHC = 0;
5624 157882 : NSBS = state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf;
5625 157882 : state.dataSolarShading->NRVLHC = 0;
5626 157882 : state.dataSolarShading->NSBSHC = 0;
5627 157882 : state.dataSolarShading->LOCHCA = 1;
5628 : // Temporarily determine the old heat transfer surface number (HTS)
5629 157882 : HTS = GRSNR;
5630 :
5631 157882 : if (state.dataSolarShading->SurfSunCosTheta(GRSNR) < DataEnvironment::SunIsUpValue) { //.001) THEN ! Receiving surface is not in the sun
5632 :
5633 74481 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
5634 74481 : SHDSBS(state, iHour, GRSNR, NBKS, NSBS, HTS, TS);
5635 :
5636 83401 : } else if ((NGSS <= 0) && (NSBS <= 0)) { // Simple surface--no shaders or subsurfaces
5637 :
5638 67614 : state.dataSolarShading->SurfSunlitArea(HTS) = s_surf->Surface(GRSNR).NetAreaShadowCalc;
5639 : } else { // Surface in sun and either shading surfaces or subsurfaces present (or both)
5640 :
5641 : #ifndef EP_NO_OPENGL
5642 15787 : int id = s_surf->SurfPenumbraID(HTS);
5643 15787 : if (state.dataSolarShading->penumbra && id >= 0) {
5644 : // SurfSunlitArea(HTS) = buildingPSSF.at(id) / SurfSunCosTheta(HTS);
5645 0 : state.dataSolarShading->SurfSunlitArea(HTS) =
5646 0 : state.dataSolarShading->penumbra->retrieve_pssa(id) / state.dataSolarShading->SurfSunCosTheta(HTS);
5647 : // SurfSunlitArea(HTS) = penumbra->fetchPSSA(Surface(HTS).PenumbraID)/SurfSunCosTheta(HTS);
5648 0 : for (int SS = 1; SS <= NSBS; ++SS) {
5649 0 : int HTSS = state.dataShadowComb->ShadowComb(HTS).SubSurf(SS);
5650 0 : id = s_surf->SurfPenumbraID(HTSS);
5651 0 : if (id >= 0) {
5652 : // SurfSunlitArea(HTSS) = buildingPSSF.at(id) / SurfSunCosTheta(HTSS);
5653 0 : state.dataSolarShading->SurfSunlitArea(HTSS) =
5654 0 : state.dataSolarShading->penumbra->retrieve_pssa(id) / state.dataSolarShading->SurfSunCosTheta(HTSS);
5655 : // SurfSunlitArea(HTSS) = penumbra->fetchPSSA(Surface(HTSS).PenumbraID)/SurfSunCosTheta(HTSS);
5656 0 : if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
5657 0 : if (iHour > 0 && TS > 0)
5658 0 : state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
5659 0 : state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).Area;
5660 : }
5661 : }
5662 : }
5663 15787 : } else if (!state.dataSolarShading->penumbra) {
5664 : #else
5665 : {
5666 : #endif
5667 15787 : NGRS = s_surf->Surface(GRSNR).BaseSurf;
5668 15787 : if (s_surf->Surface(GRSNR).IsShadowing) NGRS = GRSNR;
5669 :
5670 : // Compute the X and Y displacements of a shadow.
5671 15787 : XS = s_surf->Surface(NGRS).lcsx.x * state.dataSolarShading->SUNCOS(1) +
5672 15787 : s_surf->Surface(NGRS).lcsx.y * state.dataSolarShading->SUNCOS(2) +
5673 15787 : s_surf->Surface(NGRS).lcsx.z * state.dataSolarShading->SUNCOS(3);
5674 15787 : YS = s_surf->Surface(NGRS).lcsy.x * state.dataSolarShading->SUNCOS(1) +
5675 15787 : s_surf->Surface(NGRS).lcsy.y * state.dataSolarShading->SUNCOS(2) +
5676 15787 : s_surf->Surface(NGRS).lcsy.z * state.dataSolarShading->SUNCOS(3);
5677 15787 : ZS = s_surf->Surface(NGRS).lcsz.x * state.dataSolarShading->SUNCOS(1) +
5678 15787 : s_surf->Surface(NGRS).lcsz.y * state.dataSolarShading->SUNCOS(2) +
5679 15787 : s_surf->Surface(NGRS).lcsz.z * state.dataSolarShading->SUNCOS(3);
5680 :
5681 15787 : if (std::abs(ZS) > Constant::SmallDistance) {
5682 15787 : state.dataSolarShading->XShadowProjection = XS / ZS;
5683 15787 : state.dataSolarShading->YShadowProjection = YS / ZS;
5684 15787 : if (std::abs(state.dataSolarShading->XShadowProjection) < 1.e-8) state.dataSolarShading->XShadowProjection = 0.0;
5685 15787 : if (std::abs(state.dataSolarShading->YShadowProjection) < 1.e-8) state.dataSolarShading->YShadowProjection = 0.0;
5686 : } else {
5687 0 : state.dataSolarShading->XShadowProjection = 0.0;
5688 0 : state.dataSolarShading->YShadowProjection = 0.0;
5689 : }
5690 :
5691 15787 : CTRANS(state,
5692 : GRSNR,
5693 : NGRS,
5694 : NVT,
5695 15787 : state.dataSolarShading->XVrt,
5696 15787 : state.dataSolarShading->YVrt,
5697 15787 : state.dataSolarShading->ZVrt); // Transform coordinates of the receiving surface to 2-D form
5698 :
5699 : // Re-order its vertices to clockwise sequential.
5700 78935 : for (N = 1; N <= NVT; ++N) {
5701 63148 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVrt(NVT + 1 - N);
5702 63148 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVrt(NVT + 1 - N);
5703 : }
5704 :
5705 15787 : HTRANS1(state, 1, NVT); // Transform to homogeneous coordinates.
5706 :
5707 15787 : state.dataSolarShading->HCAREA(1) = -state.dataSolarShading->HCAREA(1); // Compute (+) gross surface area.
5708 15787 : state.dataSolarShading->HCT(1) = 1.0;
5709 :
5710 15787 : SHDGSS(state, NGRS, iHour, TS, GRSNR, NGSS, HTS); // Determine shadowing on surface.
5711 :
5712 15787 : if (!state.dataSolarShading->CalcSkyDifShading) {
5713 9865 : SHDBKS(state, s_surf->Surface(GRSNR).BaseSurf, GRSNR, NBKS, HTS); // Determine possible back surfaces.
5714 : }
5715 : }
5716 :
5717 15787 : SHDSBS(state, iHour, GRSNR, NBKS, NSBS, HTS, TS); // Subtract subsurf areas from total
5718 :
5719 : // Error checking: require that 0 <= SurfSunlitArea <= AREA. + or - .01*AREA added for round-off errors
5720 15787 : SurfArea = s_surf->Surface(GRSNR).NetAreaShadowCalc;
5721 15787 : state.dataSolarShading->SurfSunlitArea(HTS) = max(0.0, state.dataSolarShading->SurfSunlitArea(HTS));
5722 :
5723 15787 : state.dataSolarShading->SurfSunlitArea(HTS) = min(state.dataSolarShading->SurfSunlitArea(HTS), SurfArea);
5724 : } // ...end of surface in sun/surface with shaders and/or subsurfaces IF-THEN block
5725 :
5726 : // NOTE:
5727 : // There used to be a call to legacy subroutine SHDCVR here when the
5728 : // zone type was not a standard zone.
5729 : }
5730 33798 : }
5731 :
5732 9865 : void SHDBKS(EnergyPlusData &state,
5733 : int const NGRS, // Number of the general receiving surface
5734 : int const CurSurf,
5735 : int const NBKS, // Number of back surfaces
5736 : int const HTS // Heat transfer surface number of the general receiving surf
5737 : )
5738 : {
5739 :
5740 : // SUBROUTINE INFORMATION:
5741 : // AUTHOR Legacy Code
5742 : // DATE WRITTEN
5743 : // MODIFIED na
5744 : // RE-ENGINEERED Lawrie, Oct 2000
5745 :
5746 : // PURPOSE OF THIS SUBROUTINE:
5747 : // This is the driving subroutine for computing
5748 : // the sunlit areas for back surfaces.
5749 :
5750 : // REFERENCES:
5751 : // BLAST/IBLAST code, original author George Walton
5752 :
5753 : typedef Array2D<Int64>::size_type size_type;
5754 : int I;
5755 : int M;
5756 : int N;
5757 : int NVR;
5758 : int NVT; // Number of vertices of back surface
5759 : int BackSurfaceNumber;
5760 : int NS1; // Number of the figure being overlapped
5761 : int NS2; // Number of the figure doing overlapping
5762 : int NS3; // Location to place results of overlap
5763 :
5764 9865 : auto &s_surf = state.dataSurface;
5765 :
5766 : // Tuned Linear indexing
5767 :
5768 9865 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
5769 9865 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
5770 :
5771 9865 : if (state.dataSolarShading->SHDBKSOneTimeFlag) {
5772 27 : state.dataSolarShading->XVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
5773 27 : state.dataSolarShading->YVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
5774 27 : state.dataSolarShading->ZVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
5775 27 : state.dataSolarShading->XVrtx = 0.0;
5776 27 : state.dataSolarShading->YVrtx = 0.0;
5777 27 : state.dataSolarShading->ZVrtx = 0.0;
5778 27 : state.dataSolarShading->SHDBKSOneTimeFlag = false;
5779 : }
5780 :
5781 10570 : if ((NBKS <= 0) || (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0) || (state.dataSolarShading->OverlapStatus == TooManyVertices) ||
5782 705 : (state.dataSolarShading->OverlapStatus == TooManyFigures))
5783 9160 : return;
5784 :
5785 705 : state.dataSolarShading->FBKSHC = state.dataSolarShading->LOCHCA + 1;
5786 :
5787 4230 : for (I = 1; I <= NBKS; ++I) { // Loop through all back surfaces associated with the receiving surface
5788 :
5789 3525 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(CurSurf).BackSurf(I);
5790 :
5791 3525 : if (state.dataSolarShading->SurfSunCosTheta(BackSurfaceNumber) > -DataEnvironment::SunIsUpValue)
5792 1410 : continue; //-0.001) CYCLE ! go to next back surface since inside of this surface
5793 : // cannot be in sun if the outside can be
5794 :
5795 : // Transform coordinates of back surface from general system to the
5796 : // plane of the receiving surface
5797 :
5798 2115 : CTRANS(state, BackSurfaceNumber, NGRS, NVT, state.dataSolarShading->XVrtx, state.dataSolarShading->YVrtx, state.dataSolarShading->ZVrtx);
5799 :
5800 : // Project "shadow" from back surface along sun's rays to receiving surface. Back surface vertices
5801 : // become clockwise sequential.
5802 :
5803 10575 : for (N = 1; N <= NVT; ++N) {
5804 8460 : state.dataSolarShading->XVS(N) =
5805 8460 : state.dataSolarShading->XVrtx(N) - state.dataSolarShading->XShadowProjection * state.dataSolarShading->ZVrtx(N);
5806 8460 : state.dataSolarShading->YVS(N) =
5807 8460 : state.dataSolarShading->YVrtx(N) - state.dataSolarShading->YShadowProjection * state.dataSolarShading->ZVrtx(N);
5808 : }
5809 :
5810 : // Transform to the homogeneous coordinate system.
5811 :
5812 2115 : NS3 = state.dataSolarShading->LOCHCA + 1;
5813 2115 : state.dataSolarShading->HCT(NS3) = 0.0;
5814 2115 : HTRANS1(state, NS3, NVT);
5815 :
5816 : // Adjust near-duplicate points.
5817 :
5818 2115 : NVR = state.dataSolarShading->HCNV(1);
5819 2115 : int l3 = state.dataSolarShading->HCX.index(NS3, 1);
5820 10575 : for (N = 1; N <= NVT; ++N, ++l3) {
5821 8460 : Real64 const x3 = state.dataSolarShading->HCX[l3]; // [ l3 ] == ( NS3, N )
5822 8460 : Real64 const y3 = state.dataSolarShading->HCY[l3];
5823 8460 : size_type l1 = 0;
5824 35240 : for (M = 1; M <= NVR; ++M, ++l1) {
5825 29600 : if (std::abs(state.dataSolarShading->HCX[l1] - x3) > 6) continue; // [ l1 ] == ( 1, M )
5826 4230 : if (std::abs(state.dataSolarShading->HCY[l1] - y3) > 6) continue;
5827 2820 : state.dataSolarShading->HCX[l3] = state.dataSolarShading->HCX[l1];
5828 2820 : state.dataSolarShading->HCY[l3] = state.dataSolarShading->HCY[l1];
5829 2820 : break;
5830 : }
5831 : }
5832 :
5833 2115 : HTRANS0(state, NS3, NVT);
5834 :
5835 : // Determine area of overlap of projected back surface and receiving surface.
5836 :
5837 2115 : NS1 = 1;
5838 2115 : NS2 = NS3;
5839 2115 : state.dataSolarShading->HCT(NS3) = 1.0;
5840 2115 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
5841 :
5842 2115 : if (state.dataSolarShading->OverlapStatus == NoOverlap) continue; // to next back surface
5843 1446 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
5844 0 : break; // back surfaces DO loop
5845 :
5846 : // Increment back surface count.
5847 :
5848 1446 : state.dataSolarShading->LOCHCA = NS3;
5849 1446 : state.dataSolarShading->HCNS(state.dataSolarShading->LOCHCA) = BackSurfaceNumber;
5850 1446 : state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
5851 1446 : state.dataSolarShading->NBKSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FBKSHC + 1;
5852 : }
5853 : }
5854 :
5855 15787 : void SHDGSS(EnergyPlusData &state,
5856 : int const NGRS,
5857 : int const iHour, // Hour Counter
5858 : int const TS, // TimeStep
5859 : int const CurSurf, // Current Surface
5860 : int const NGSS, // Number of general shadowing surfaces
5861 : int const HTS // Heat transfer surface number of the general receiving surf
5862 : )
5863 : {
5864 :
5865 : // SUBROUTINE INFORMATION:
5866 : // AUTHOR Legacy Code
5867 : // DATE WRITTEN
5868 : // MODIFIED na
5869 : // RE-ENGINEERED Lawrie, Oct 2000
5870 :
5871 : // PURPOSE OF THIS SUBROUTINE:
5872 : // This subroutine determines the shadows on a general receiving surface.
5873 :
5874 : // REFERENCES:
5875 : // BLAST/IBLAST code, original author George Walton
5876 :
5877 : typedef Array2D<Int64>::size_type size_type;
5878 : int GSSNR; // General shadowing surface number
5879 : int MainOverlapStatus; // Overlap status of the main overlap calculation not the check for
5880 : // multiple overlaps (unless there was an error)
5881 : int NS1; // Number of the figure being overlapped
5882 : int NS2; // Number of the figure doing overlapping
5883 : int NS3; // Location to place results of overlap
5884 : Real64 SchValue; // Value for Schedule of shading transmittance
5885 :
5886 15787 : auto &s_surf = state.dataSurface;
5887 :
5888 15787 : if (state.dataSolarShading->SHDGSSOneTimeFlag) {
5889 29 : state.dataSolarShading->XVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
5890 29 : state.dataSolarShading->YVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
5891 29 : state.dataSolarShading->ZVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
5892 29 : state.dataSolarShading->SHDGSSOneTimeFlag = false;
5893 : }
5894 :
5895 15787 : state.dataSolarShading->FGSSHC = state.dataSolarShading->LOCHCA + 1;
5896 15787 : MainOverlapStatus = NoOverlap; // Set to ensure that the value from the last surface is not saved
5897 15787 : state.dataSolarShading->OverlapStatus = NoOverlap;
5898 :
5899 15787 : if (NGSS <= 0) { // IF NO S.S., receiving surface FULLY SUNLIT.
5900 :
5901 4958 : state.dataSolarShading->SurfSunlitArea(HTS) = state.dataSolarShading->HCAREA(1); // Surface fully sunlit
5902 :
5903 : } else {
5904 :
5905 10829 : int ExitLoopStatus = -1;
5906 10829 : auto const &GenSurf = state.dataShadowComb->ShadowComb(CurSurf).GenSurf;
5907 10829 : int const sunIsUp = DataEnvironment::SunIsUpValue;
5908 27796 : for (int I = 1; I <= NGSS; ++I) { // Loop through all shadowing surfaces...
5909 :
5910 17924 : GSSNR = GenSurf(I);
5911 :
5912 17924 : if (state.dataSolarShading->SurfSunCosTheta(GSSNR) > sunIsUp) continue; //.001) CYCLE ! NO SHADOW IF GSS IN SUNLIGHT.
5913 :
5914 12923 : auto const &surface = s_surf->Surface(GSSNR);
5915 12923 : bool const notHeatTransSurf = !surface.HeatTransSurf;
5916 :
5917 : // This used to check to see if the shadowing surface was not opaque (within the scheduled dates of
5918 : // transmittance value. Perhaps it ignored it if it were outside the range. (if so, was an error)
5919 : // The proper action seems to be delete this statement all together, but there would also be no shading if
5920 : // the shading surface were transparent...
5921 : //---former stmt IF ((.NOT.Surface(GSSNR)%HeatTransSurf) .AND. &
5922 : //---former stmt GetCurrentScheduleValue(state, Surface(GSSNR)%SchedShadowSurfIndex,IHOUR) == 0.0) CYCLE
5923 :
5924 12923 : if (notHeatTransSurf) {
5925 8315 : if (surface.IsTransparent) continue; // No shadow if shading surface is transparent
5926 8315 : if (surface.shadowSurfSched != nullptr) {
5927 6819 : if (surface.shadowSurfSched->getHrTsVal(state, iHour) == 1.0) continue;
5928 5722 : if (!state.dataSolarShading->CalcSkyDifShading) {
5929 3619 : if (surface.shadowSurfSched->getHrTsVal(state, iHour, TS) == 1.0) continue;
5930 : }
5931 : }
5932 : }
5933 : // Eliminate shadowing surfaces that is supposed to be disabled.
5934 11826 : if (state.dataSysVars->DisableAllSelfShading) {
5935 0 : if (surface.Zone != 0) {
5936 0 : continue; // Disable all shadowing surfaces in all zones. Attached shading surfaces are not part of a zone, zone value is 0.
5937 : }
5938 11826 : } else if (state.dataSysVars->DisableGroupSelfShading) {
5939 0 : std::vector<int> DisabledZones = s_surf->SurfShadowDisabledZoneList(CurSurf);
5940 0 : bool isDisabledShadowSurf = false;
5941 0 : for (int i : DisabledZones) {
5942 0 : if (surface.Zone == i) {
5943 0 : isDisabledShadowSurf = true;
5944 0 : break;
5945 : }
5946 : }
5947 0 : if (isDisabledShadowSurf) continue; // Disable all shadowing surfaces in all disabled zones.
5948 0 : }
5949 :
5950 : // IF ((.NOT.Surface(GSSNR)%HeatTransSurf) .AND. &
5951 : // GetCurrentScheduleValue(state, Surface(GSSNR)%SchedShadowSurfIndex) == 1.0) CYCLE
5952 :
5953 : // Transform shadow casting surface from cartesian to homogeneous coordinates according to surface type.
5954 :
5955 11826 : if ((notHeatTransSurf) && (surface.BaseSurf != 0)) {
5956 :
5957 : // For shadowing subsurface coordinates of shadow casting surface are relative to the receiving surface
5958 : // project shadow to the receiving surface
5959 :
5960 0 : state.dataSolarShading->NVS = surface.Sides;
5961 0 : auto const &XV = s_surf->ShadeV(GSSNR).XV;
5962 0 : auto const &YV = s_surf->ShadeV(GSSNR).YV;
5963 0 : auto const &ZV = s_surf->ShadeV(GSSNR).ZV;
5964 0 : for (int N = 1; N <= state.dataSolarShading->NVS; ++N) {
5965 0 : state.dataSolarShading->XVS(N) = XV(N) - state.dataSolarShading->XShadowProjection * ZV(N);
5966 0 : state.dataSolarShading->YVS(N) = YV(N) - state.dataSolarShading->YShadowProjection * ZV(N);
5967 : }
5968 :
5969 0 : } else {
5970 : // Transform coordinates of shadow casting surface from general system to the system relative to the receiving surface
5971 : int NVT;
5972 11826 : CTRANS(state, GSSNR, NGRS, NVT, state.dataSolarShading->XVert, state.dataSolarShading->YVert, state.dataSolarShading->ZVert);
5973 11826 : CLIP(state,
5974 : NVT,
5975 11826 : state.dataSolarShading->XVert,
5976 11826 : state.dataSolarShading->YVert,
5977 11826 : state.dataSolarShading->ZVert); // Clip portions of the shadow casting surface which are behind the receiving surface
5978 :
5979 11826 : if (state.dataSolarShading->NumVertInShadowOrClippedSurface <= 2) continue;
5980 :
5981 : // Project shadow from shadow casting surface along sun's rays to receiving surface Shadow vertices
5982 : // become clockwise sequential
5983 :
5984 59098 : for (int N = 1; N <= state.dataSolarShading->NumVertInShadowOrClippedSurface; ++N) {
5985 47272 : state.dataSolarShading->XVS(N) =
5986 47272 : state.dataSolarShading->XVC(N) - state.dataSolarShading->XShadowProjection * state.dataSolarShading->ZVC(N);
5987 47272 : state.dataSolarShading->YVS(N) =
5988 47272 : state.dataSolarShading->YVC(N) - state.dataSolarShading->YShadowProjection * state.dataSolarShading->ZVC(N);
5989 : }
5990 : }
5991 :
5992 : // Transform to the homogeneous coordinate system.
5993 :
5994 11826 : NS3 = state.dataSolarShading->LOCHCA + 1;
5995 11826 : HTRANS1(state, NS3, state.dataSolarShading->NVS);
5996 :
5997 : // Adjust near-duplicate points.
5998 :
5999 11826 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
6000 11826 : assert(state.dataSolarShading->HCX.index(1, 1) == 0u);
6001 11826 : size_type j(state.dataSolarShading->HCX.index(NS3, 1));
6002 11826 : size_type NVR(state.dataSolarShading->HCNV(1));
6003 59098 : for (int N = 1; N <= state.dataSolarShading->NumVertInShadowOrClippedSurface;
6004 47272 : ++N, ++j) { // Tuned Logic change: break after 1st "close" point found
6005 47272 : Int64 const HCX_N(state.dataSolarShading->HCX[j]); // [ j ] == ( NS3, N )
6006 47272 : Int64 const HCY_N(state.dataSolarShading->HCY[j]);
6007 234767 : for (size_type l = 0; l < NVR; ++l) { // [ l ] == ( 1, l+1 )
6008 188150 : Real64 const delX = std::abs(state.dataSolarShading->HCX[l] - HCX_N);
6009 188150 : if (delX > 6) continue;
6010 3436 : Real64 const delY = std::abs(state.dataSolarShading->HCY[l] - HCY_N);
6011 3436 : if (delY > 6) continue;
6012 655 : if (delX > 0) state.dataSolarShading->HCX[j] = state.dataSolarShading->HCX[l]; // [ j ] == ( NS3, N )
6013 655 : if (delY > 0) state.dataSolarShading->HCY[j] = state.dataSolarShading->HCY[l];
6014 655 : break;
6015 : }
6016 : }
6017 11826 : HTRANS0(state, NS3, state.dataSolarShading->NumVertInShadowOrClippedSurface);
6018 11826 : if (!state.dataSolarShading->CalcSkyDifShading && surface.shadowSurfSched != nullptr) {
6019 3619 : if (iHour != 0) {
6020 3619 : SchValue = surface.shadowSurfSched->getHrTsVal(state, iHour, TS);
6021 : } else {
6022 0 : SchValue = surface.SchedMinValue;
6023 : }
6024 : } else {
6025 8207 : SchValue = surface.SchedMinValue;
6026 : }
6027 :
6028 11826 : state.dataSolarShading->HCT(NS3) = SchValue;
6029 :
6030 : // Determine overlap of shadow with receiving surface
6031 :
6032 11826 : state.dataSolarShading->CurrentShadowingSurface = I;
6033 11826 : state.dataSolarShading->CurrentSurfaceBeingShadowed = GSSNR;
6034 11826 : NS1 = 1;
6035 11826 : NS2 = NS3;
6036 11826 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
6037 : // Next statement is special to deal with transmitting shading devices
6038 11826 : if (state.dataSolarShading->OverlapStatus == FirstSurfWithinSecond && SchValue > 0.0)
6039 67 : state.dataSolarShading->OverlapStatus = PartialOverlap;
6040 11826 : MainOverlapStatus = state.dataSolarShading->OverlapStatus;
6041 11826 : ExitLoopStatus = MainOverlapStatus;
6042 :
6043 11826 : if (MainOverlapStatus == NoOverlap) { // No overlap of general surface shadow and receiving surface
6044 : // Continue
6045 7693 : } else if ((MainOverlapStatus == FirstSurfWithinSecond) || (MainOverlapStatus == TooManyVertices) ||
6046 : (MainOverlapStatus == TooManyFigures)) {
6047 957 : goto ShadowingSurfaces_exit;
6048 6736 : } else if ((MainOverlapStatus == SecondSurfWithinFirst) || (MainOverlapStatus == PartialOverlap)) {
6049 : // Determine overlaps with previous shadows.
6050 6736 : state.dataSolarShading->LOCHCA = NS3;
6051 6736 : state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
6052 7863 : if (state.dataSolarShading->NGSSHC > 1)
6053 1127 : MULTOL(state,
6054 1127 : state.dataSolarShading->LOCHCA,
6055 1127 : state.dataSolarShading->FGSSHC - 1,
6056 1127 : state.dataSolarShading->NGSSHC - 1); // HOYT - Remove this call
6057 : } else {
6058 0 : goto ShadowingSurfaces_exit;
6059 : }
6060 :
6061 10869 : ExitLoopStatus = -1;
6062 : }
6063 9872 : ShadowingSurfaces_exit:;
6064 :
6065 : // Compute sunlit area of surface (excluding effects of subsurfs).
6066 :
6067 10829 : if (ExitLoopStatus == FirstSurfWithinSecond) { // Surface fully shaded
6068 957 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
6069 957 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FGSSHC;
6070 :
6071 9872 : } else if ((ExitLoopStatus == TooManyVertices) || (ExitLoopStatus == TooManyFigures)) { // Array limits exceeded, estimate
6072 0 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.25 * state.dataSolarShading->HCAREA(1);
6073 :
6074 : } else {
6075 :
6076 : // Compute the sunlit area here.
6077 : // Call UnionShadow(FGSSHC,LOCHCA)
6078 :
6079 9872 : state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
6080 9872 : if (state.dataSolarShading->NGSSHC <= 0) {
6081 4263 : state.dataSolarShading->SurfSunlitArea(HTS) = state.dataSolarShading->HCAREA(1); // Surface fully sunlit
6082 : } else {
6083 5609 : Real64 A(state.dataSolarShading->HCAREA(1)); // Area
6084 12935 : for (int i = state.dataSolarShading->FGSSHC, e = state.dataSolarShading->FGSSHC + state.dataSolarShading->NGSSHC - 1; i <= e; ++i) {
6085 7326 : A += state.dataSolarShading->HCAREA(i) * (1.0 - state.dataSolarShading->HCT(i));
6086 : }
6087 5609 : state.dataSolarShading->SurfSunlitArea(HTS) = A;
6088 5609 : if (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0) { // Surface fully shaded
6089 25 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
6090 25 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FGSSHC;
6091 : }
6092 : }
6093 : }
6094 : }
6095 15787 : state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
6096 15787 : }
6097 :
6098 6982 : void CalcInteriorSolarOverlaps(EnergyPlusData &state,
6099 : int const iHour, // Hour Index
6100 : int const NBKS, // Number of back surfaces associated with this GRSNR (in general, only
6101 : int const HTSS, // Surface number of the subsurface (exterior window)
6102 : int const GRSNR, // General receiving surface number (base surface of the exterior window)
6103 : int const TS // Time step Index
6104 : )
6105 : {
6106 :
6107 : // SUBROUTINE INFORMATION:
6108 : // AUTHOR Fred Winkelmann
6109 : // DATE WRITTEN January 1999
6110 : // MODIFIED Nov 2001, FW: include beam radiation overlaps with
6111 : // back windows and doors; previously these subsurfaces ignored.
6112 : // May 2002, FW: fix problem where reveal was not being considered
6113 : // in calculating overlap areas if window is shaded only by reveal.
6114 : // June 2002, FW: fix problem that gave incorrect calculation when
6115 : // window is not shaded only by reveal
6116 : // June 2002, FW: remove incorrect multiplication of overlap areas
6117 : // by sunlit fraction when window is shaded only by reveal
6118 :
6119 : // PURPOSE OF THIS SUBROUTINE:
6120 : // For an exterior window with surface number HTSS, determines (1) the surface numbers of back
6121 : // surfaces receiving beam radiation from the window and (2) for each such back surface, the area
6122 : // of the portion of the window sending beam radiation to the back surface; this is called the
6123 : // "overlap area."
6124 :
6125 : // REFERENCES:
6126 : // BLAST/IBLAST code, original author George Walton
6127 :
6128 : // SUBROUTINE ARGUMENT DEFINITIONS:
6129 : // some of these will receive beam radiation from HTSS this hour)
6130 :
6131 : // SUBROUTINE PARAMETER DEFINITIONS:
6132 6982 : int constexpr WindowShadedOnlyByReveal(2); // for use with RevealStatus
6133 :
6134 : typedef Array2D<Int64>::size_type size_type;
6135 : int JBKS; // Counter of back surfaces with non-zero overlap with HTSS
6136 : int BackSurfNum; // Back surface number
6137 :
6138 : bool UseSimpleDistribution; // TRUE means simple interior solar distribution
6139 : // (all incoming beam assumed to strike floor),
6140 : // FALSE means exact interior solar distribution
6141 : // (track which back surfaces beam illuminates)
6142 :
6143 6982 : auto &s_surf = state.dataSurface;
6144 :
6145 : // Tuned Linear indexing
6146 :
6147 6982 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
6148 6982 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
6149 6982 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
6150 6982 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
6151 :
6152 6982 : if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
6153 :
6154 3822 : UseSimpleDistribution = false;
6155 :
6156 3822 : if ((NBKS <= 0) || (s_surf->Surface(GRSNR).ExtBoundCond > 0)) {
6157 :
6158 3117 : UseSimpleDistribution = true;
6159 :
6160 : } else {
6161 : // Using 'exact' distribution, replace subsurface HC entries with reveal HC entries
6162 : // so that the reveal HC is used in calculating interior solar overlap areas
6163 :
6164 : // Adding the following line fixes a problem where, if the window was shaded only
6165 : // by reveal, then the reveal was not considered in calculating interior solar
6166 : // overlap areas (FCW 5/3/02).
6167 : // IF(Surface(HTSS)%Reveal > 0.0) NRVLHC = 1
6168 : // Changing the line to the following avoids incorrect calculation when window is not shaded
6169 : // only by reveal (FCW 6/28/02).
6170 705 : if (state.dataSolarShading->SurfWinRevealStatus(iHour, TS, HTSS) == WindowShadedOnlyByReveal) state.dataSolarShading->NRVLHC = 1;
6171 705 : if (state.dataSolarShading->NRVLHC > 0) {
6172 0 : for (int I = 1; I <= state.dataSolarShading->NRVLHC; ++I) {
6173 0 : int const iS(state.dataSolarShading->FSBSHC - 1 + I);
6174 0 : int const iR(state.dataSolarShading->FRVLHC - 1 + I);
6175 0 : state.dataSolarShading->HCT(iS) = state.dataSolarShading->HCT(iR);
6176 0 : state.dataSolarShading->HCNV(iS) = state.dataSolarShading->HCNV(iR);
6177 0 : state.dataSolarShading->HCAREA(iS) = state.dataSolarShading->HCAREA(iR);
6178 0 : size_type lS(state.dataSolarShading->HCX.index(iS, 1));
6179 0 : size_type lR(state.dataSolarShading->HCX.index(iR, 1));
6180 0 : for (int J = 1; J <= state.dataSolarShading->MaxHCV; ++J, ++lS, ++lR) { // [ lS ] == ( iS, J ), [ lR ] == ( iR, J )
6181 0 : state.dataSolarShading->HCX[lS] = state.dataSolarShading->HCX[lR];
6182 0 : state.dataSolarShading->HCY[lS] = state.dataSolarShading->HCY[lR];
6183 0 : state.dataSolarShading->HCA[lS] = state.dataSolarShading->HCA[lR];
6184 0 : state.dataSolarShading->HCB[lS] = state.dataSolarShading->HCB[lR];
6185 0 : state.dataSolarShading->HCC[lS] = state.dataSolarShading->HCC[lR];
6186 : }
6187 : }
6188 0 : state.dataSolarShading->NSBSHC = state.dataSolarShading->NRVLHC;
6189 : }
6190 : }
6191 :
6192 : // Check for array space.
6193 3822 : if (state.dataSolarShading->FSBSHC + state.dataSolarShading->NBKSHC > state.dataSolarShading->MaxHCS) UseSimpleDistribution = true;
6194 :
6195 3822 : if (!UseSimpleDistribution) { // Compute overlaps
6196 :
6197 705 : std::unordered_map<unsigned, float> pssas;
6198 :
6199 : #ifndef EP_NO_OPENGL
6200 705 : if (state.dataSolarShading->penumbra) {
6201 : // Add back surfaces to array
6202 0 : std::vector<unsigned> pbBackSurfaces;
6203 0 : for (int bkSurfNum : state.dataShadowComb->ShadowComb(GRSNR).BackSurf) {
6204 0 : if (bkSurfNum == 0) continue;
6205 0 : if (state.dataSolarShading->SurfSunCosTheta(bkSurfNum) < DataEnvironment::SunIsUpValue) {
6206 0 : pbBackSurfaces.push_back(s_surf->SurfPenumbraID(bkSurfNum));
6207 : }
6208 : }
6209 0 : pssas = state.dataSolarShading->penumbra->calculate_interior_pssas({(unsigned)s_surf->SurfPenumbraID(HTSS)}, pbBackSurfaces);
6210 : // penumbra->render_interior_scene({(unsigned)Surface(HTSS).PenumbraID}, pbBackSurfaces);
6211 :
6212 0 : JBKS = 0;
6213 0 : for (int bkSurfNum : state.dataShadowComb->ShadowComb(GRSNR).BackSurf) {
6214 0 : if (bkSurfNum == 0) continue;
6215 0 : if (pssas[s_surf->SurfPenumbraID(bkSurfNum)] > 0) {
6216 0 : ++JBKS;
6217 0 : state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, JBKS, HTSS) = bkSurfNum;
6218 0 : Real64 OverlapArea = pssas[s_surf->SurfPenumbraID(bkSurfNum)] / state.dataSolarShading->SurfSunCosTheta(HTSS);
6219 0 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS) = OverlapArea * s_surf->SurfaceWindow(HTSS).glazedFrac;
6220 : }
6221 : }
6222 0 : }
6223 : #endif
6224 :
6225 705 : if (!state.dataSolarShading->penumbra) {
6226 :
6227 705 : state.dataSolarShading->FINSHC = state.dataSolarShading->FSBSHC + state.dataSolarShading->NSBSHC;
6228 :
6229 705 : JBKS = 0;
6230 :
6231 2151 : for (int IBKS = 1; IBKS <= state.dataSolarShading->NBKSHC;
6232 : ++IBKS) { // Loop over back surfaces to GRSNR this hour. NBKSHC is the number of
6233 : // back surfaces that would receive beam radiation from the base surface, GRSNR,
6234 : // if the base surface was transparent. In general, some (at least one) or all of these
6235 : // will receive beam radiation from the exterior window subsurface, HTSS, of GRSNR,
6236 : // depending on the size of HTSS and its location on GRSNR
6237 :
6238 1446 : BackSurfNum = state.dataSolarShading->HCNS(state.dataSolarShading->FBKSHC - 1 + IBKS);
6239 :
6240 : // Determine if this back surface number can receive beam radiation from the
6241 : // exterior window, HTSS, this hour, i.e., overlap area is positive
6242 :
6243 1446 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FINSHC - 1;
6244 :
6245 1446 : MULTOL(state, state.dataSolarShading->FBKSHC - 1 + IBKS, state.dataSolarShading->FSBSHC - 1, state.dataSolarShading->NSBSHC);
6246 :
6247 : // Compute overlap area for this back surface
6248 :
6249 1446 : state.dataSolarShading->NINSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FINSHC + 1;
6250 1446 : if (state.dataSolarShading->NINSHC <= 0) continue;
6251 1222 : Real64 OverlapArea = state.dataSolarShading->HCAREA(state.dataSolarShading->FINSHC);
6252 1222 : for (int J = 2; J <= state.dataSolarShading->NINSHC; ++J) {
6253 0 : OverlapArea += state.dataSolarShading->HCAREA(state.dataSolarShading->FINSHC - 1 + J) *
6254 0 : (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FINSHC - 1 + J));
6255 : }
6256 :
6257 1222 : if (OverlapArea > 0.001) {
6258 1222 : ++JBKS;
6259 1222 : if (JBKS <= state.dataBSDFWindow->MaxBkSurf) {
6260 1222 : state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, JBKS, HTSS) = BackSurfNum;
6261 1222 : int baseSurfaceNum = s_surf->Surface(BackSurfNum).BaseSurf;
6262 1222 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS) = OverlapArea * s_surf->SurfaceWindow(HTSS).glazedFrac;
6263 : // If this is a subsurface, subtract its overlap area from its base surface
6264 1222 : if (baseSurfaceNum != BackSurfNum) {
6265 0 : for (int iBaseBKS = 1; iBaseBKS <= JBKS; ++iBaseBKS) {
6266 0 : if (baseSurfaceNum == state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, iBaseBKS, HTSS)) {
6267 0 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, iBaseBKS, HTSS) =
6268 0 : max(0.0,
6269 0 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, iBaseBKS, HTSS) -
6270 0 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS));
6271 0 : break;
6272 : }
6273 : }
6274 : }
6275 : }
6276 : }
6277 : } // End of loop over back surfaces
6278 : }
6279 705 : }
6280 : } // End of check that sunlit area > 0.
6281 6982 : }
6282 :
6283 71220 : void CalcInteriorSolarDistribution(EnergyPlusData &state)
6284 : {
6285 :
6286 : // SUBROUTINE INFORMATION:
6287 : // AUTHOR Fred Winkelmann
6288 : // DATE WRITTEN January 1999
6289 : // MODIFIED Nov 1999, FW, for Window5 calculation method
6290 : // Oct 2000, FW: add transmitted solar variables for reporting
6291 : // Mar 2001, FW: add new calc of solar absorbed by window shades
6292 : // May 2001, FW: add calc of solar transmitted and absorbed by window blinds
6293 : // Oct 2001, LL: remove interpolation, solar now at time step
6294 : // Oct 2001, FW: add solar transmitted through interior windows
6295 : // Mar 24, 2001, FW: remove incorrect multiplication of Boverlap by sunlit fraction
6296 : // since effect of shadowing is already included in Aoverlap
6297 : // Apr 2001, FW: add effects of beam solar reflection from outside and inside reveals
6298 : // Jan 2003, FW: add between-glass shades and blinds
6299 : // Dec 2003, FW: report beam incident on inside of surface
6300 : // Jan 2004, FW: for blinds with horizontal slats, allow different diffuse/diffuse
6301 : // transmittance for ground and sky solar
6302 : // Apr 2004, FW: allow diffusing glazing
6303 : // May 2006, RR: allow external window screen
6304 : // Jan 2010, TH: add calculating and reporting of WinBmBmSolar, WinBmDifSolar,
6305 : // WinBmBmSolarEnergy, and WinBmDifSolarEnergy
6306 : // Jun 2013, SV: scheduled surface gains for walls and windows
6307 :
6308 : // PURPOSE OF THIS SUBROUTINE:
6309 : // For a time step, calculates solar radiation absorbed by exterior
6310 : // surfaces and interior solar radiation distribution
6311 :
6312 : using Dayltg::TransTDD;
6313 : using namespace DataWindowEquivalentLayer;
6314 :
6315 71220 : Array1D<Real64> CFBoverlap; // Sum of boverlap for each back surface
6316 71220 : Array2D<Real64> CFDirBoverlap; // Directional boverlap (Direction, IBack)
6317 :
6318 71220 : auto &s_mat = state.dataMaterial;
6319 71220 : auto &s_surf = state.dataSurface;
6320 :
6321 : #ifdef EP_Count_Calls
6322 : ++state.dataTimingsData->NumIntSolarDist_Calls;
6323 : #endif
6324 :
6325 170529 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
6326 212066 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
6327 112757 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
6328 112757 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
6329 112757 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
6330 143871 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
6331 248912 : for (int lay = 1; lay <= CFSMAXNL + 1; ++lay) {
6332 217798 : s_surf->SurfWinA(SurfNum, lay) = 0.0;
6333 : }
6334 31114 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfNum) = 0.0;
6335 31114 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = 0.0;
6336 : }
6337 112757 : int const firstSurfOpaque = thisSpace.OpaqOrIntMassSurfaceFirst;
6338 112757 : int const lastSurfOpaque = thisSpace.OpaqOrIntMassSurfaceLast;
6339 694821 : for (int SurfNum = firstSurfOpaque; SurfNum <= lastSurfOpaque; ++SurfNum) {
6340 582064 : s_surf->SurfOpaqAI(SurfNum) = 0.0;
6341 582064 : s_surf->SurfOpaqAO(SurfNum) = 0.0;
6342 : }
6343 : }
6344 : }
6345 :
6346 71220 : if ((int)state.dataDaylightingDevicesData->TDDPipe.size() > 0) {
6347 0 : for (auto &e : state.dataDaylightingDevicesData->TDDPipe) {
6348 0 : int SurfDome = e.Dome;
6349 0 : for (int lay = 1; lay <= CFSMAXNL + 1; ++lay) {
6350 0 : s_surf->SurfWinA(SurfDome, lay) = 0.0;
6351 : }
6352 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfDome) = 0.0;
6353 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfDome) = 0.0;
6354 : }
6355 : }
6356 :
6357 177272 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
6358 : // Solar entering a zone as beam or diffuse radiation, originating as beam solar incident on exterior windows)/(Beam normal solar) [W/(W/m2)]
6359 106052 : Real64 BTOTZone = 0.0;
6360 : // Beam radiation from exterior windows absorbed in a zone or transmitted through
6361 106052 : Real64 BABSZone = 0.0;
6362 106052 : state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
6363 106052 : state.dataHeatBal->EnclSolDBSSG(enclosureNum) = 0.0;
6364 106052 : state.dataHeatBal->EnclSolDBIntWin(enclosureNum) = 0.0;
6365 : // Loop over exterior surfaces in this zone
6366 106052 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
6367 : // delete values from previous timestep
6368 106052 : if (state.dataHeatBal->AnyBSDF) s_surf->SurfWinACFOverlap = 0.0;
6369 :
6370 : //-------------------------------------------------------------------------
6371 : // EXTERIOR BEAM SOLAR RADIATION ABSORBED ON THE OUTSIDE OF OPAQUE SURFACES
6372 : //-------------------------------------------------------------------------
6373 : // TODO: use opaq and window loop after airboundary is sorted
6374 : // TODO: It may be useful to sort SurfacePtr to group windows and domes together to reduce if conditions
6375 719225 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
6376 613173 : if (s_surf->Surface(SurfNum).Class != SurfaceClass::Window && s_surf->Surface(SurfNum).Class != SurfaceClass::TDD_Dome) {
6377 582057 : if (!s_surf->Surface(SurfNum).HeatTransSurf) continue;
6378 582057 : if (!s_surf->Surface(SurfNum).ExtSolar) continue;
6379 348126 : int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
6380 348126 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
6381 348126 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
6382 348126 : s_surf->SurfOpaqAO(SurfNum) = state.dataConstruction->Construct(ConstrNum).OutsideAbsorpSolar * CosInc * SunLitFract;
6383 : }
6384 : }
6385 :
6386 : //--------------------------------------------------------------------------------------------------------
6387 : // EXTERIOR WINDOWS OR TDD DOMES
6388 : //--------------------------------------------------------------------------------------------------------
6389 719225 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
6390 613173 : auto &surf = s_surf->Surface(SurfNum);
6391 613173 : if (surf.Class != SurfaceClass::Window && surf.Class != SurfaceClass::TDD_Dome) continue;
6392 31116 : if (!surf.ExtSolar && surf.OriginalClass != SurfaceClass::TDD_Diffuser) continue;
6393 :
6394 31116 : auto &surfWin = s_surf->SurfaceWindow(SurfNum);
6395 31116 : int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
6396 31116 : int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(SurfNum);
6397 31116 : auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
6398 31116 : int ScNum = surfWin.screenNum;
6399 31116 : WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum); // Set in subr. WindowShadingManager
6400 :
6401 31116 : auto &surfShade = s_surf->surfShades(SurfNum);
6402 :
6403 31116 : Real64 ProfAng = 0.0; // Window solar profile angle (radians)
6404 :
6405 31116 : Real64 SlatAng = surfShade.blind.slatAng;
6406 31116 : int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
6407 31116 : int SurfNum2 = SurfNum;
6408 31116 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
6409 0 : SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
6410 : }
6411 31116 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
6412 31116 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
6413 :
6414 : //-----------------------------------------
6415 : // BLOCK 1
6416 : // EXTERIOR BEAM AND DIFFUSE SOLAR RADIATION ABSORBED IN THE GLASS LAYERS OF (SurfWinA)
6417 : // EXTERIOR BEAM ABSORBED BY SHADING DEVICE (SurfWinExtBeamAbsByShadFac)
6418 : //-----------------------------------------
6419 : // Somewhat of a kludge
6420 31116 : if (surf.Class == SurfaceClass::TDD_Dome || surf.OriginalClass == SurfaceClass::TDD_Diffuser)
6421 0 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) =
6422 : SunLitFract; // Frames/dividers not allow
6423 31116 : int FenSolAbsPtr = 0;
6424 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
6425 0 : FenSolAbsPtr = WindowScheduledSolarAbs(state, SurfNum, ConstrNum);
6426 : }
6427 : bool SunlitFracWithoutReveal =
6428 31116 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) > 0;
6429 :
6430 : // Calculate interpolated blind properties
6431 : Real64 FrontDiffDiffTrans; // Bare-blind front diffuse-diffuse solar transmittance
6432 : Real64 FrontDiffDiffRefl;
6433 : Real64 FrontDiffAbs; // Bare-blind front diffuse solar reflectance
6434 : Real64 BackDiffDiffTrans; // Bare-blind back diffuse-diffuse solar transmittance
6435 : Real64 BackDiffDiffRefl;
6436 : Real64 BackDiffAbs; // Bare-blind back diffuse solar reflectance
6437 :
6438 : Real64 FrontBeamDiffTrans; // Blind ProfileAnglesolar front beam-diffuse transmittance
6439 : Real64 BackBeamDiffTrans; // Blind solar back beam-diffuse transmittance
6440 : Real64 FrontBeamDiffRefl; // Blind solar front beam-diffuse reflectance
6441 : Real64 BackBeamDiffRefl; // Blind solar back beam-diffuse reflectance
6442 : Real64 FrontBeamAbs; // Blind solar front beam absorptance
6443 : Real64 BackBeamAbs; // Blind solar back beam absorptance
6444 :
6445 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL && ANY_BLIND(ShadeFlag)) {
6446 0 : auto const &surfShade = s_surf->surfShades(SurfNum);
6447 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
6448 0 : assert(matBlind != nullptr);
6449 :
6450 0 : int profIdxLo = surfShade.blind.profAngIdxLo;
6451 0 : int profIdxHi = surfShade.blind.profAngIdxHi;
6452 0 : Real64 profInterpFac = surfShade.blind.profAngInterpFac;
6453 :
6454 0 : FrontDiffDiffTrans = surfShade.blind.TAR.Sol.Ft.Df.Tra;
6455 :
6456 0 : if (SunLitFract > 0.0 || SunlitFracWithoutReveal) {
6457 0 : auto const &btar1 = surfShade.blind.TAR;
6458 0 : auto const &btarFront1Lo = btar1.Sol.Ft.Bm[profIdxLo];
6459 0 : auto const &btarFront1Hi = btar1.Sol.Ft.Bm[profIdxHi];
6460 :
6461 0 : FrontBeamAbs = Interp(btarFront1Lo.Abs, btarFront1Hi.Abs, profInterpFac);
6462 0 : FrontBeamDiffTrans = Interp(btarFront1Lo.DfTra, btarFront1Hi.DfTra, profInterpFac);
6463 0 : if (ShadeFlag != WinShadingType::ExtBlind) { // FRONT: interior or bg blinds
6464 0 : FrontDiffDiffRefl = btar1.Sol.Ft.Df.Ref;
6465 0 : FrontDiffAbs = btar1.Sol.Ft.Df.Abs;
6466 0 : FrontBeamDiffRefl = Interp(btarFront1Lo.DfRef, btarFront1Hi.DfRef, profInterpFac);
6467 : }
6468 :
6469 0 : if (ShadeFlag != WinShadingType::IntBlind) { // BACK: exterior or bg blinds{
6470 0 : BackDiffDiffTrans = btar1.Sol.Bk.Df.Tra;
6471 0 : BackDiffDiffRefl = btar1.Sol.Bk.Df.Ref;
6472 0 : BackDiffAbs = btar1.Sol.Bk.Df.Abs;
6473 :
6474 0 : auto const &btarBack1Lo = btar1.Sol.Bk.Bm[profIdxLo];
6475 0 : auto const &btarBack1Hi = btar1.Sol.Bk.Bm[profIdxHi];
6476 :
6477 0 : BackBeamDiffTrans = Interp(btarBack1Lo.DfTra, btarBack1Hi.DfTra, profInterpFac);
6478 0 : BackBeamDiffRefl = Interp(btarBack1Lo.DfRef, btarBack1Hi.DfRef, profInterpFac);
6479 0 : BackBeamAbs = Interp(btarBack1Lo.Abs, btarBack1Hi.Abs, profInterpFac);
6480 : }
6481 : } // if (SunLitFrac > 0.0)
6482 : } // if (ANY_BLIND)
6483 :
6484 31116 : if (SunlitFracWithoutReveal) {
6485 :
6486 16090 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
6487 :
6488 : // For bare glazing or switchable glazing, the following includes the effects of
6489 : // (1) diffuse solar produced by beam solar incident on the outside and inside reveal
6490 : // surfaces, and (2) absorption of beam solar by outside and inside reveal surfaces.
6491 : // If there is an exterior shade/blind both of these effects are ignored. If there
6492 : // is an interior or between-glass shade/blind the effects of beam incident on
6493 : // inside reveal surfaces is ignored.
6494 15305 : int NGlass = thisConstruct.TotGlassLayers;
6495 15305 : Array1D<Real64> AbWin(NGlass); // Factor for front beam radiation absorbed in window glass layer
6496 33750 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6497 36890 : AbWin(Lay) = Window::POLYF(CosInc, thisConstruct.AbsBeamCoef(Lay)) * CosInc * SunLitFract *
6498 18445 : s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
6499 : }
6500 15305 : if (!IS_SHADED_NO_GLARE_CTRL(ShadeFlag)) {
6501 : // (ShadeFlag <= 0 || ShadeFlag >= 10) - Bare window (ShadeFlag = -1 or 0 or shading device of off)
6502 33750 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6503 : // Add contribution of beam reflected from outside and inside reveal
6504 36890 : s_surf->SurfWinA(SurfNum, Lay) = AbWin(Lay) +
6505 18445 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstruct.AbsDiff(Lay) +
6506 18445 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) * thisConstruct.AbsDiffBack(Lay);
6507 : }
6508 : } else {
6509 : // Shade, screen, blind or switchable glazing on (ShadeFlag > 0)
6510 : Real64 FracSunLit =
6511 0 : SunLitFract * s_surf->SurfaceWindow(SurfNum)
6512 0 : .OutProjSLFracMult[state.dataGlobal->HourOfDay]; // Effective fraction of window that is sunlit;
6513 0 : Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
6514 0 : Array1D<Real64> AbWinSh(NGlass); // Like AbWin, but for shaded window
6515 0 : Array1D<Real64> ADiffWinSh(NGlass); // Diffuse solar absorptance of glass layer, window with shading device
6516 0 : if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) FracSunLit = SunLitFract;
6517 :
6518 0 : if (ANY_SHADE(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
6519 0 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
6520 : // Shade or switchable glazing on
6521 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6522 0 : AbWinSh(Lay) = Window::POLYF(CosInc, thisConstructSh.AbsBeamCoef(Lay)) * CosInc * FracSunLit;
6523 0 : ADiffWinSh(Lay) = thisConstructSh.AbsDiff(Lay);
6524 : }
6525 0 : if (ShadeFlag == WinShadingType::IntShade) { // Exterior beam absorbed by INTERIOR SHADE
6526 : // Note that AbsBeamShadeCoef includes effect of shade/glazing inter-reflection
6527 0 : Real64 AbsShade = Window::POLYF(CosInc,
6528 0 : thisConstructSh.AbsBeamShadeCoef); // Interior shade or blind beam solar absorptance
6529 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6530 0 : (AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
6531 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstructSh.AbsDiffShade) *
6532 0 : surfWin.glazedFrac;
6533 : // In the above, GlazedFrac corrects for shadowing of divider onto interior shade
6534 0 : } else if (ShadeFlag == WinShadingType::ExtShade) { // Exterior beam absorbed by EXTERIOR SHADE
6535 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = thisConstructSh.AbsDiffShade * CosInc * SunLitFract;
6536 0 : } else if (ShadeFlag == WinShadingType::BGShade) { // Exterior beam absorbed by BETWEEN-GLASS SHADE
6537 0 : Real64 AbsShade = Window::POLYF(CosInc, thisConstructSh.AbsBeamShadeCoef);
6538 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6539 0 : AbsShade * CosInc * SunLitFract +
6540 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstructSh.AbsDiffShade;
6541 : }
6542 :
6543 : } else {
6544 : // Blind or screen on
6545 0 : ProfAng = surfShade.blind.profAng;
6546 0 : if (ShadeFlag == WinShadingType::IntBlind) {
6547 : // Interior blind on
6548 0 : Real64 TBmBm = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef);
6549 0 : Real64 RGlDiffBack = thisConstruct.ReflectSolDiffBack; // Glazing system back diffuse solar reflectance
6550 0 : Real64 RhoBlFront = FrontBeamDiffRefl; // Blind solar front beam reflectance
6551 0 : Real64 RhoBlDiffFront = FrontDiffDiffRefl; // Blind solar front diffuse reflectance
6552 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6553 0 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6554 0 : Real64 AGlDiffBack = thisConstruct.AbsDiffBack(Lay); // Glass layer back diffuse solar absorptance
6555 0 : AbWinSh(Lay) =
6556 0 : AbWin(Lay) + (TBmBm * AGlDiffBack * RhoBlFront / (1.0 - RhoBlFront * RGlDiffBack)) * CosInc * FracSunLit;
6557 0 : ADiffWinSh(Lay) =
6558 0 : ADiffWin + thisConstruct.TransDiff * AGlDiffBack * RhoBlDiffFront / (1.0 - RhoBlDiffFront * RGlDiffBack);
6559 : }
6560 : // Exterior beam absorbed by INTERIOR BLIND
6561 :
6562 0 : Real64 AbsBlFront = FrontBeamAbs; // Blind solar front beam absorptance
6563 0 : Real64 AbsBlDiffFront = FrontDiffAbs; // Blind solar front diffuse absorptance
6564 0 : Real64 AbsShade =
6565 0 : TBmBm * (AbsBlFront + RhoBlFront * RGlDiffBack * AbsBlDiffFront / (1.0 - RhoBlDiffFront * RGlDiffBack));
6566 0 : Real64 AbsShadeDiff =
6567 0 : thisConstruct.TransDiff *
6568 0 : (AbsBlDiffFront + RhoBlDiffFront * RGlDiffBack * AbsBlDiffFront /
6569 0 : (1.0 - RhoBlDiffFront * RGlDiffBack)); // Interior shade or blind diffuse solar absorptance
6570 :
6571 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6572 0 : (AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
6573 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * AbsShadeDiff) *
6574 0 : surfWin.glazedFrac;
6575 :
6576 : // In the above, GlazedFrac corrects for shadowing of divider onto interior blind
6577 0 : } else if (ShadeFlag == WinShadingType::ExtBlind) {
6578 : // Exterior blind on
6579 0 : Real64 TBlBmBm = surfShade.blind.bmBmTrans; // Blind solar front beam-beam transmittance
6580 0 : Real64 TBlDifDif = FrontDiffDiffTrans; // Diffuse-diffuse solar transmittance of blind
6581 0 : Real64 TBlBmDiff = FrontBeamDiffTrans; // Blind solar front beam-diffuse transmittance
6582 0 : Real64 RhoBlBack = BackBeamDiffRefl; // Blind solar back beam-diffuse reflectance
6583 0 : Real64 RhoBlDiffBack = BackDiffDiffRefl; // Blind solar back diffuse reflectance
6584 : Real64 RGlFront =
6585 0 : Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
6586 0 : Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
6587 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6588 0 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6589 0 : Real64 AGlDiffFront = thisConstruct.AbsDiff(Lay); // Glass layer front diffuse solar absorptance
6590 0 : AbWinSh(Lay) = TBlBmBm * AbWin(Lay) + ((TBlBmBm * RGlFront * RhoBlBack + TBlBmDiff) * AGlDiffFront /
6591 0 : (1 - RGlDiffFront * RhoBlDiffBack)) *
6592 0 : CosInc * FracSunLit;
6593 : // ADiffWinSh = 0.0 ! Assumes no contribution from reveal reflection when exterior blind in place
6594 : // Replaced above line with (FCW, 2/10/03):
6595 0 : ADiffWinSh(Lay) = ADiffWin * TBlDifDif / (1.0 - RGlDiffFront * RhoBlDiffBack);
6596 : }
6597 : // Exterior beam absorbed by EXTERIOR BLIND
6598 0 : Real64 AbsBlFront = FrontBeamAbs;
6599 0 : Real64 AbsBlBack = BackBeamAbs; // Blind solar back beam absorptance
6600 0 : Real64 AbsBlDiffBack = BackDiffAbs; // Blind solar back diffuse absorptance
6601 0 : Real64 AbsShade = AbsBlFront + AbsBlBack * RGlFront * TBlBmBm +
6602 0 : (AbsBlDiffBack * RGlDiffFront / (1.0 - RhoBlDiffBack * RGlDiffFront)) *
6603 0 : (RGlFront * TBlBmBm * RhoBlBack + TBlBmDiff);
6604 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsShade * CosInc * SunLitFract * InOutProjSLFracMult;
6605 0 : } else if (ShadeFlag == WinShadingType::ExtScreen) {
6606 : // Exterior screen on
6607 0 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
6608 0 : assert(screen != nullptr);
6609 :
6610 0 : auto &surf = s_surf->Surface(SurfNum);
6611 :
6612 0 : Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
6613 0 : Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
6614 0 : Real64 winPhi = surf.Tilt * Constant::DegToRad;
6615 0 : Real64 winTheta = surf.Azimuth * Constant::DegToRad;
6616 0 : Real64 phi = std::abs(solPhi - winPhi);
6617 0 : Real64 theta = std::abs(solTheta - winTheta);
6618 0 : Material::NormalizePhiTheta(phi, theta);
6619 : #ifdef PRECALC_INTERP_SCREEN
6620 : int ip1, ip2, it1, it2;
6621 : BilinearInterpCoeffs coeffs;
6622 0 : Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
6623 0 : GetBilinearInterpCoeffs(
6624 0 : phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
6625 0 : auto const &b11 = screen->btars[ip1][it1];
6626 0 : auto const &b12 = screen->btars[ip1][it2];
6627 0 : auto const &b21 = screen->btars[ip2][it1];
6628 0 : auto const &b22 = screen->btars[ip2][it2];
6629 :
6630 0 : Real64 TScDifDif = screen->DfTrans;
6631 0 : Real64 TScBmDif = BilinearInterp(b11.DfTrans, b12.DfTrans, b21.DfTrans, b22.DfTrans, coeffs);
6632 0 : Real64 TScBmBm = BilinearInterp(b11.BmTrans, b12.BmTrans, b21.BmTrans, b22.BmTrans, coeffs);
6633 0 : Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
6634 0 : Real64 RScDifBack = screen->DfRef;
6635 :
6636 : Real64 RGlFront =
6637 0 : Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
6638 0 : Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
6639 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
6640 : // Reduce the bare window absorbed beam by the screen beam transmittance and then account for
6641 : // interreflections
6642 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6643 0 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6644 0 : AbWinSh(Lay) = TScBmBm * AbWin(Lay) + (TScBmBm * RGlFront * RScBack + TScBmDif) * thisConstruct.AbsDiff(Lay) /
6645 0 : (1.0 - RGlDiffFront * RScDifBack) * CosInc * FracSunLit;
6646 0 : ADiffWinSh(Lay) = ADiffWin * TScDifDif / (1.0 - RGlDifFr * RScDifBack);
6647 : }
6648 : // Exterior beam absorbed by EXTERIOR SCREEN
6649 0 : Real64 AbsScBeam = BilinearInterp(b11.AbsSolFront, b12.AbsSolFront, b21.AbsSolFront, b22.AbsSolFront, coeffs);
6650 0 : Real64 AbsScDiffBack = screen->DfAbs;
6651 0 : Real64 AbsScreen = AbsScBeam * (1.0 + TScBmBm * RGlFront) +
6652 0 : (AbsScDiffBack * TScBmBm * RGlFront * RGlDiffFront * RScBack /
6653 0 : (1.0 - RScDifBack * RGlDiffFront)); // Exterior screen beam solar absorptance
6654 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsScreen * CosInc * SunLitFract * InOutProjSLFracMult;
6655 : #else // !PRECALC_INTERP_SCREEN
6656 : Material::ScreenBmTransAbsRef btar;
6657 : CalcScreenTransmittance(state, screen, phi, theta, btar);
6658 :
6659 : Real64 TScDifDif = screen->DfTrans;
6660 : Real64 TScBmDif = btar.DfTrans;
6661 : Real64 TScBmBm = btar.BmTrans;
6662 : Real64 RScBack = btar.RefSolFront;
6663 : Real64 RScDifBack = screen->DfRef;
6664 :
6665 : Real64 RGlFront =
6666 : Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
6667 : Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
6668 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
6669 : // Reduce the bare window absorbed beam by the screen beam transmittance and then account for
6670 : // interreflections
6671 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6672 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6673 : AbWinSh(Lay) = TScBmBm * AbWin(Lay) + (TScBmBm * RGlFront * RScBack + TScBmDif) * thisConstruct.AbsDiff(Lay) /
6674 : (1.0 - RGlDiffFront * RScDifBack) * CosInc * FracSunLit;
6675 : ADiffWinSh(Lay) = ADiffWin * TScDifDif / (1.0 - RGlDifFr * RScDifBack);
6676 : }
6677 : // Exterior beam absorbed by EXTERIOR SCREEN
6678 : Real64 AbsScBeam = btar.AbsSolFront;
6679 : Real64 AbsScDiffBack = screen->DfAbs;
6680 : Real64 AbsScreen = AbsScBeam * (1.0 + TScBmBm * RGlFront) +
6681 : (AbsScDiffBack * TScBmBm * RGlFront * RGlDiffFront * RScBack /
6682 : (1.0 - RScDifBack * RGlDiffFront)); // Exterior screen beam solar absorptance
6683 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsScreen * CosInc * SunLitFract * InOutProjSLFracMult;
6684 : #endif // PRECALC_INTERP_SCREEN
6685 0 : } else if (ShadeFlag == WinShadingType::BGBlind) {
6686 : // Between-glass blind o
6687 : // Isolated glass and blind properties at current incidence angle, profile angle and slat angle
6688 0 : Real64 t1 = Window::POLYF(CosInc,
6689 0 : thisConstruct.tBareSolCoef(1)); // Bare-glass beam solar trans for glass layers 1,2 and 3
6690 0 : Real64 t2 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(2));
6691 : Real64 af1 =
6692 0 : Window::POLYF(CosInc,
6693 0 : thisConstruct.afBareSolCoef(1)); // Bare-glass beam solar front abs for glass layers 1,2 and 3
6694 0 : Real64 af2 = Window::POLYF(CosInc, thisConstruct.afBareSolCoef(2));
6695 0 : Real64 ab1 = Window::POLYF(
6696 : CosInc,
6697 0 : thisConstruct.abBareSolCoef(1)); // Bare-glass beam solar back absorptance for glass layers 1,2 and 3
6698 0 : Real64 ab2 = Window::POLYF(CosInc, thisConstruct.abBareSolCoef(2));
6699 0 : Real64 rf2 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(2));
6700 0 : Real64 td1 = thisConstruct.tBareSolDiff(1); // Bare-glass diffuse solar transmittance for glass layers 1,2 and 3
6701 0 : Real64 td2 = thisConstruct.tBareSolDiff(2);
6702 0 : Real64 afd1 = thisConstruct.afBareSolDiff(1); // Bare-glass diffuse solar front absorptance for glass layers 1,2 and 3
6703 0 : Real64 afd2 = thisConstruct.afBareSolDiff(2);
6704 0 : Real64 abd1 = thisConstruct.abBareSolDiff(1); // Bare-glass diffuse solar back absorptance for glass layers 1,2 and 3
6705 0 : Real64 abd2 = thisConstruct.abBareSolDiff(2);
6706 0 : Real64 rfd2 = thisConstruct.rfBareSolDiff(2);
6707 0 : Real64 rbd1 = thisConstruct.rbBareSolDiff(1); // Bare-glass diffuse solar back reflectance for glass layers 1,2 and 3
6708 0 : Real64 rbd2 = thisConstruct.rbBareSolDiff(2);
6709 0 : Real64 tfshBB = surfShade.blind.bmBmTrans; // Bare-blind front and back beam-beam solar transmittance
6710 :
6711 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
6712 0 : assert(matBlind != nullptr);
6713 0 : Real64 tbshBB = matBlind->BeamBeamTrans(ProfAng, Constant::Pi - SlatAng);
6714 0 : Real64 tfshBd = FrontBeamDiffTrans; // Bare-blind front and back beam-diffuse solar transmittance
6715 0 : Real64 tbshBd = BackBeamDiffTrans;
6716 0 : Real64 rfshB = FrontBeamDiffRefl; // Bare-blind front and back beam solar reflectance
6717 0 : Real64 rbshB = BackBeamDiffRefl;
6718 0 : Real64 afshB = FrontBeamAbs;
6719 0 : Real64 abshB = BackBeamAbs;
6720 :
6721 0 : Real64 tfshd = FrontDiffDiffTrans; // Bare-blind front and back diffuse-diffuse solar transmittance
6722 0 : Real64 tbshd = BackDiffDiffTrans;
6723 0 : Real64 rfshd = FrontDiffDiffRefl; // Bare-blind front and back diffuse solar reflectance
6724 0 : Real64 rbshd = BackDiffDiffRefl;
6725 0 : Real64 afshd = FrontDiffAbs;
6726 0 : Real64 abshd = BackDiffAbs;
6727 :
6728 0 : Real64 AbsShade = 0.0;
6729 0 : Real64 AbsShadeDiff = 0.0;
6730 0 : if (NGlass == 2) {
6731 0 : AbWinSh(1) = CosInc * FracSunLit *
6732 0 : (af1 + t1 * tfshBB * rf2 * tbshBB * ab1 +
6733 0 : t1 * (rfshB + rfshB * rbd1 * rfshd + tfshBB * rf2 * tbshBd + tfshBd * rfd2 * tbshd) * abd1);
6734 0 : ADiffWinSh(1) = afd1 + td1 * (rfshd + rfshd * rbd1 * rfshd + tfshd * rfd2 * tbshd) * abd1;
6735 0 : AbWinSh(2) =
6736 0 : CosInc * FracSunLit *
6737 0 : (t1 * rfshB * af2 + t1 * (rfshB * rf2 * rbshd + tfshBd * (1 + rfd2 * rbshd) + rfshB * rbd1 * tfshd) * afd2);
6738 0 : ADiffWinSh(2) = td1 * (tfshd * (1 + rfd2 * rbshd) + rfshd * rbd1 * tfshd) * afd2;
6739 0 : AbsShade = t1 * (afshB + tfshBB * rf2 * abshB + tfshBd * rfd2 * abshd + rfshB * rbd1 * afshd);
6740 0 : AbsShadeDiff = td1 * (afshd * (1 + rfshd * rbd1) + tfshd * rfd2 * abshd);
6741 0 : } else if (NGlass == 3) {
6742 0 : Real64 t1t2 = t1 * t2; // t1*t2
6743 0 : Real64 td1td2 = td1 * td2;
6744 0 : Real64 af3 = Window::POLYF(CosInc, thisConstruct.afBareSolCoef(3));
6745 0 : Real64 rf3 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(3));
6746 0 : Real64 afd3 = thisConstruct.afBareSolDiff(3);
6747 0 : Real64 rfd3 = thisConstruct.rfBareSolDiff(3);
6748 0 : Real64 td2 = thisConstruct.tBareSolDiff(2);
6749 0 : AbWinSh(1) = CosInc * FracSunLit *
6750 0 : (af1 + t1 * rf2 * ab1 + t1t2 * tfshBB * rf3 * tbshBB * t2 * ab1 +
6751 0 : t1t2 * (rfshB * td2 + rfshB * rbd2 * rfshd * td2 + tfshBd * rfd3 * tbshd * td2) * abd1);
6752 0 : ADiffWinSh(1) = afd1 + td1 * rbd2 * abd1 +
6753 0 : td1td2 *
6754 0 : (rfshd * (1 + rbd2 * rfshd + td2 * rbd1 * td2 * rfshd) +
6755 0 : tfshd * (rfd3 * tbshd + rfd3 * rbshd * rfd3 * tbshd)) *
6756 0 : td2 * abd1;
6757 0 : AbWinSh(2) = CosInc * FracSunLit *
6758 0 : (t1 * af2 + t1t2 * (tfshBB * rf3 * tbshBB * ab2 + rfshB * td2 * rbd1 * afd2) +
6759 0 : t1t2 * (rfshB * (1 + rbd2 * rfshd) + tfshBB * rf3 * tbshBd + tfshBd * rfd3 * tbshd) * abd2);
6760 0 : ADiffWinSh(2) = td1 * afd2 + td1td2 * rfshd * td2 * rbd1 * afd2 +
6761 0 : td1td2 * (rfshd * (1 + rbd2 * rfshd) + tfshd * rfd3 * tbshd) * abd2;
6762 0 : AbWinSh(3) = CosInc * FracSunLit *
6763 0 : (t1t2 * tfshBB * af3 + t1t2 *
6764 0 : (tfshBB * rf3 * rbshB + tfshBd * (1 + rfd3 * rbshd) +
6765 0 : rfshB * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) *
6766 : afd3);
6767 0 : ADiffWinSh(3) = td1td2 * (tfshd * (1 + rfd3 * rbshd) + rfshd * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) * afd3;
6768 0 : AbsShade = t1t2 * (afshB * (1 + tfshBB * rf3) + afshd * (tfshBd * rfd3 + rfshB * (rbd2 + td2 * rbd1 * td2)));
6769 0 : AbsShadeDiff = td1td2 * (afshd + tfshd * rfd3 * abshd + rfshd * (rfd2 + td2 * rbd2 * td2) * afshd);
6770 : } // End of check if NGlass
6771 0 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6772 0 : AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
6773 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * AbsShadeDiff;
6774 : } // End of check if blind is interior, exterior or between-glass
6775 : } // End of check if a blind is on
6776 :
6777 0 : if (ShadeFlag != WinShadingType::SwitchableGlazing) {
6778 : // Interior or between glass shade or blind on
6779 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6780 0 : s_surf->SurfWinA(SurfNum, Lay) = AbWinSh(Lay);
6781 : // Add contribution of diffuse from beam on outside reveal
6782 0 : if (ANY_INTERIOR_SHADE_BLIND(ShadeFlag) || ANY_BETWEENGLASS_SHADE_BLIND(ShadeFlag))
6783 0 : s_surf->SurfWinA(SurfNum, Lay) += ADiffWinSh(Lay) * s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum);
6784 : }
6785 : } else {
6786 0 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
6787 : // Switchable glazing
6788 0 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6789 0 : Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum);
6790 0 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay);
6791 0 : s_surf->SurfWinA(SurfNum, Lay) = Window::InterpSw(SwitchFac, AbWin(Lay), AbWinSh(Lay));
6792 : // Add contribution of diffuse from beam on outside and inside reveal
6793 0 : s_surf->SurfWinA(SurfNum, Lay) +=
6794 0 : Window::InterpSw(SwitchFac, ADiffWin, ADiffWinSh(Lay)) * s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) +
6795 0 : Window::InterpSw(SwitchFac, thisConstruct.AbsDiffBack(Lay), thisConstructSh.AbsDiffBack(Lay)) *
6796 0 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum);
6797 : }
6798 : }
6799 0 : }
6800 :
6801 16090 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
6802 : // Do not read from schedule file here since this will be called only if direct beam is hitting the window and schedule
6803 : // will not be loaded in that case even if diffuse part of solar radiation is entering through the window
6804 0 : if (FenSolAbsPtr == 0) {
6805 : // Put in the equivalent layer absorptions
6806 : // Simon: This should not be multiplied with CosInc since Abs coefficient already includes angular
6807 : // factor
6808 0 : for (int Lay = 1;
6809 0 : Lay <= s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).NLayers;
6810 : ++Lay) {
6811 0 : Real64 absBeamWin = s_surf->SurfaceWindow(SurfNum)
6812 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6813 0 : .WinBmFtAbs(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, Lay);
6814 : Real64 AbWin =
6815 0 : absBeamWin * CosInc * SunLitFract * s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
6816 :
6817 : // Add contribution of beam reflected from outside and inside reveal
6818 0 : s_surf->SurfWinA(SurfNum, Lay) = AbWin +
6819 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) *
6820 0 : s_surf->SurfaceWindow(SurfNum)
6821 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6822 0 : .WinFtHemAbs(Lay) +
6823 0 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) *
6824 0 : s_surf->SurfaceWindow(SurfNum)
6825 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6826 0 : .WinBkHemAbs(Lay);
6827 : }
6828 : }
6829 :
6830 785 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
6831 : // call the ASHWAT fenestration model for optical properties
6832 : // determine the beam radiation absorptance and transmittance of the
6833 : // the equivalent layer window model
6834 785 : WindowEquivalentLayer::CalcEQLOpticalProperty(state, SurfNum, SolarArrays::BEAM, state.dataSolarShading->SurfWinAbsSolBeamEQL);
6835 785 : auto &CFS = state.dataWindowEquivLayer->CFS;
6836 : // recalculate the diffuse absorptance and transmittance of the
6837 : // the equivalent layer window model if there is shade control
6838 785 : int EQLNum = state.dataConstruction->Construct(surf.Construction).EQLConsPtr; // equivalent layer fenestration index
6839 785 : if (CFS(EQLNum).ISControlled) {
6840 320 : WindowEquivalentLayer::CalcEQLOpticalProperty(
6841 320 : state, SurfNum, SolarArrays::DIFF, state.dataSolarShading->SurfWinAbsSolDiffEQL);
6842 : } else {
6843 930 : state.dataSolarShading->SurfWinAbsSolDiffEQL(_, {1, CFS(EQLNum).NL + 1}) =
6844 1395 : state.dataWindowEquivalentLayer->CFSDiffAbsTrans(_, {1, CFS(EQLNum).NL + 1}, EQLNum);
6845 : }
6846 785 : thisConstruct.TransDiff = state.dataSolarShading->SurfWinAbsSolDiffEQL(1, CFS(EQLNum).NL + 1);
6847 :
6848 3628 : for (int Lay = 1; Lay <= CFS(EQLNum).NL + 1; ++Lay) {
6849 : // Factor for front beam radiation absorbed for equivalent layer window model
6850 2843 : Real64 AbWinEQL = state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay) * CosInc * SunLitFract *
6851 2843 : s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
6852 : ;
6853 2843 : if (CFS(EQLNum).L(1).LTYPE != LayerType::GLAZE) {
6854 : // if the first layer is not glazing (or it is a shade) do not
6855 0 : s_surf->SurfWinA(SurfNum, Lay) = AbWinEQL;
6856 : } else {
6857 : // the first layer is a glazing, include the outside reveal reflection
6858 : // and the inside reveal reflection until indoor shade layer is encountered.
6859 2843 : if (CFS(EQLNum).L(Lay).LTYPE == LayerType::GLAZE) {
6860 1570 : s_surf->SurfWinA(SurfNum, Lay) =
6861 1570 : AbWinEQL +
6862 1570 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay) +
6863 1570 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) * state.dataSolarShading->SurfWinAbsSolDiffEQL(2, Lay);
6864 : } else {
6865 2546 : s_surf->SurfWinA(SurfNum, Lay) = AbWinEQL + s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) *
6866 1273 : state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay);
6867 : }
6868 : }
6869 : }
6870 : }
6871 : } // End of SunlitFrac check
6872 :
6873 : //-----------------------------------------------------------------
6874 : // BLOCK 2
6875 : // SKY AND GROUND DIFFUSE SOLAR GAIN INTO ZONE FROM EXTERIOR WINDOW
6876 : //-----------------------------------------------------------------
6877 :
6878 : Real64 SkySolarInc =
6879 31116 : s_surf->SurfSkySolarInc(SurfNum); // Incident solar radiation on a window: sky diffuse plus beam reflected from obstruction (W/m2)
6880 31116 : Real64 DiffTrans = 0.0; // Glazing diffuse solar transmittance (including shade/blind/switching, if present)
6881 : Real64 DiffTransGnd; // Ground diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
6882 : Real64 DiffTransBmGnd; // Complex fen: diffuse solar transmittance for ground-reflected beam radiation
6883 : Real64 DiffTransSky; // Sky diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
6884 31116 : Real64 NomDiffTrans = 0.0;
6885 :
6886 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // complex fenestration
6887 0 : if (FenSolAbsPtr == 0) {
6888 : // Sky diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
6889 0 : DiffTransSky =
6890 0 : s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinSkyTrans;
6891 : // Ground diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
6892 0 : DiffTransGnd =
6893 0 : s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinSkyGndTrans;
6894 : // Complex fen: diffuse solar transmittance for ground-reflected beam radiation
6895 0 : DiffTransBmGnd = s_surf->SurfaceWindow(SurfNum)
6896 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6897 0 : .WinBmGndTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
6898 : // Define the effective transmittance for total sky and ground radiation
6899 0 : if ((SkySolarInc + s_surf->SurfWinBmGndSolarInc(SurfNum) + s_surf->SurfWinSkyGndSolarInc(SurfNum)) != 0.0) {
6900 0 : DiffTrans = (SkySolarInc * DiffTransSky + s_surf->SurfWinBmGndSolarInc(SurfNum) * DiffTransBmGnd +
6901 0 : s_surf->SurfWinSkyGndSolarInc(SurfNum) * DiffTransGnd) /
6902 0 : (SkySolarInc + s_surf->SurfWinBmGndSolarInc(SurfNum) + s_surf->SurfWinSkyGndSolarInc(SurfNum));
6903 : }
6904 : // Also update the nominal diffuse transmittance
6905 0 : NomDiffTrans =
6906 0 : s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinDiffTrans;
6907 : // Do not store in TransDiff because it is not used by BSDF and rest of the code uses it as flag for opaque
6908 : // surface incorrectly assuming wall heat transfer routines for windows.
6909 : // Construct( Surface( SurfNum ).Construction ).TransDiff = NomDiffTrans;
6910 : }
6911 31116 : } else if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
6912 0 : DiffTrans = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso);
6913 : } else {
6914 31116 : DiffTrans = thisConstruct.TransDiff;
6915 : }
6916 :
6917 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
6918 29742 : if (IS_SHADED_NO_GLARE_CTRL(s_surf->SurfWinShadingFlag(SurfNum))) {
6919 0 : auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
6920 0 : if (ShadeFlag != WinShadingType::SwitchableGlazing) {
6921 : // Shade or blind
6922 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
6923 : // Shade or screen
6924 0 : DiffTrans = constrSh.TransDiff;
6925 : } else {
6926 : // Blind
6927 0 : int slatIdxLo = surfShade.blind.slatAngIdxLo;
6928 0 : int slatIdxHi = surfShade.blind.slatAngIdxHi;
6929 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
6930 :
6931 0 : auto const &btarLo = constrSh.blindTARs[slatIdxLo];
6932 0 : auto const &btarHi = constrSh.blindTARs[slatIdxHi];
6933 :
6934 0 : DiffTrans = Interp(btarLo.Sol.Ft.Df.Tra, btarHi.Sol.Ft.Df.Tra, slatInterpFac);
6935 :
6936 : // For blinds with horizontal slats, allow different diffuse/diffuse transmittance for
6937 : // ground and sky solar
6938 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
6939 0 : assert(matBlind != nullptr);
6940 0 : if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
6941 0 : DiffTransGnd = Interp(btarLo.Sol.Ft.Df.TraGnd, btarHi.Sol.Ft.Df.TraGnd, slatInterpFac);
6942 0 : DiffTransSky = Interp(btarLo.Sol.Ft.Df.TraSky, btarHi.Sol.Ft.Df.TraSky, slatInterpFac);
6943 : }
6944 : }
6945 :
6946 : } else { // Switchable glazing
6947 :
6948 0 : Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum); // Switching factor for a window
6949 0 : DiffTrans = Window::InterpSw(SwitchFac, thisConstruct.TransDiff, constrSh.TransDiff);
6950 : }
6951 : }
6952 : }
6953 :
6954 : // Reporting variables
6955 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
6956 29742 : s_surf->SurfWinBlGlSysTsolDifDif(SurfNum) = DiffTrans;
6957 29742 : s_surf->SurfWinScGlSysTsolDifDif(SurfNum) = DiffTrans;
6958 29742 : if (ANY_BLIND(ShadeFlag) || ShadeFlag == WinShadingType::ExtScreen) {
6959 0 : s_surf->SurfWinBlGlSysTsolDifDif(SurfNum) = DiffTrans;
6960 0 : s_surf->SurfWinScGlSysTsolDifDif(SurfNum) = DiffTrans;
6961 0 : if (ShadeFlag == WinShadingType::ExtScreen) {
6962 0 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
6963 0 : assert(screen != nullptr);
6964 0 : s_surf->SurfWinScTsolDifDif(SurfNum) = screen->DfTrans;
6965 : } else {
6966 0 : s_surf->SurfWinBlTsolDifDif(SurfNum) = FrontDiffDiffTrans;
6967 : }
6968 : }
6969 : }
6970 :
6971 : //-----------------------------------------------------------------
6972 : // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
6973 : //-----------------------------------------------------------------
6974 31116 : Real64 TBmBm = 0.0; // Beam-beam solar transmittance for bare window or window with switchable glazing
6975 31116 : Real64 TBmDif = 0.0; // Beam-diffuse solar transmittance for bare window with diffusing glass
6976 31116 : Real64 TBmAllShBlSc = 0.0; // Beam-beam + beam-diffuse transmittance for window with shade, blind, screen, or switchable glazing
6977 31116 : Real64 TBmBmShBlSc = 0.0; // Beam-beam transmittance for window with shade, blind, screen, or switchable glazing
6978 31116 : Real64 TBmDifShBlSc = 0.0; // Beam-diffuse transmittance for window with shade, blind, screen, or switchable glazing
6979 : Real64 TBmBmBl; // Beam-beam transmittance for window with blind
6980 : Real64 TBmBmSc; // Beam-beam transmittance for window with screen
6981 : Real64 TDifBare; // Bare diffuse transmittance of exterior window
6982 : // Beam-beam transmittance for bare exterior window
6983 31116 : if (SunLitFract > 0.0) {
6984 16092 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
6985 0 : TBmDif = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarBeam);
6986 0 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolBeam = TBmDif; // Report variable
6987 16092 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) { // Regular window
6988 15307 : if (!s_surf->SurfWinSolarDiffusing(SurfNum)) { // Clear glazing
6989 15307 : TBmBm = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef); //[-]
6990 : } else { // Diffusing glazing
6991 0 : TBmDif = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef); //[-]
6992 : }
6993 785 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
6994 : // Need to check what effect, if any, defining these here has
6995 0 : TBmBm = s_surf->SurfaceWindow(SurfNum)
6996 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6997 0 : .WinDirSpecTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
6998 0 : TBmDif = s_surf->SurfaceWindow(SurfNum)
6999 0 : .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
7000 0 : .WinDirHemiTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep) -
7001 : TBmBm;
7002 785 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
7003 : // get ASHWAT fenestration model beam-beam and beam-diffuse properties
7004 785 : int EQLNum = state.dataConstruction->Construct(surf.Construction).EQLConsPtr; // equivalent layer fenestration index
7005 785 : Real64 TBmBmEQL = state.dataSolarShading->SurfWinAbsSolBeamEQL(1, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1);
7006 : // Beam-diffuse transmittance
7007 785 : Real64 TBmDiffEQL = max(0.0, state.dataSolarShading->SurfWinAbsSolBeamEQL(2, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1));
7008 : // Beam-beam transmittance: difference between beam-total and beam-diffuse transmittance
7009 785 : TBmBmEQL = max(0.0, (TBmBmEQL - TBmDiffEQL));
7010 785 : TBmBm = TBmBmEQL;
7011 785 : TBmDif = TBmDiffEQL;
7012 : }
7013 : }
7014 : // Diffuse-diffuse transmittance for bare exterior window
7015 31116 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
7016 0 : TDifBare = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso);
7017 : } else {
7018 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
7019 : // Complex Fenestration: use hemispherical ave of directional-hemispherical transmittance
7020 : // Note: this is not quite the same as the effective transmittance for total of sky and ground radiation
7021 0 : TDifBare = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinDiffTrans;
7022 : } else { // Regular window
7023 31116 : TDifBare = thisConstruct.TransDiff;
7024 : }
7025 : }
7026 :
7027 : //-----------------------------------------------------------------
7028 : // BLOCK 3 - SCREEN, BLINDS AND GLAZING SYSTEM BEAM SOLAR TRANSMITTANCE
7029 : //-----------------------------------------------------------------
7030 31116 : if (ConstrNumSh != 0 && SunLitFract > 0.0) {
7031 6440 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
7032 6440 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
7033 6440 : if (IS_SHADED_NO_GLARE_CTRL(ShadeFlag)) {
7034 : // Shade or screen or blind on, or switchable glazing
7035 : // (note in the following that diffusing glass is not oallowed in a window with shade, blind or switchable glazing)
7036 0 : if (ANY_SHADE(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
7037 : // Shade on or switchable glazing
7038 0 : TBmAllShBlSc = Window::POLYF(CosInc, thisConstructSh.TransSolBeamCoef);
7039 : } else {
7040 : // Blind or Screen on
7041 : Real64 TScBmDif; // Beam-diffuse solar transmittance of screen
7042 : Real64 TBlBmDif; // Beam-diffuse solar transmittance of blind
7043 : Real64 TBlDifDif; // Diffuse-diffuse solar transmittance of blind
7044 : Real64 TScBmBm;
7045 : Real64 TBlBmBm;
7046 0 : if (ShadeFlag == WinShadingType::ExtScreen) { // Exterior screen
7047 0 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
7048 0 : assert(screen != nullptr);
7049 :
7050 0 : auto &surf = s_surf->Surface(SurfNum);
7051 0 : Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
7052 0 : Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
7053 0 : Real64 winPhi = surf.Tilt * Constant::DegToRad;
7054 0 : Real64 winTheta = surf.Azimuth * Constant::DegToRad;
7055 0 : Real64 phi = std::abs(solPhi - winPhi);
7056 0 : Real64 theta = std::abs(solTheta - winTheta);
7057 0 : Material::NormalizePhiTheta(phi, theta);
7058 : #ifdef PRECALC_INTERP_SCREEN
7059 : int ip1, ip2, it1, it2;
7060 : BilinearInterpCoeffs coeffs;
7061 0 : Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
7062 0 : GetBilinearInterpCoeffs(
7063 0 : phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
7064 0 : auto const &b11 = screen->btars[ip1][it1];
7065 0 : auto const &b12 = screen->btars[ip1][it2];
7066 0 : auto const &b21 = screen->btars[ip2][it1];
7067 0 : auto const &b22 = screen->btars[ip2][it2];
7068 :
7069 0 : Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
7070 0 : Real64 RScDifBack = screen->DfRef;
7071 :
7072 0 : Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Beam front reflectance of glass
7073 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
7074 : // beam transmittance (written in subroutine CalcScreenTransmittance each time step)
7075 0 : TScBmBm = BilinearInterp(b11.BmTrans, b12.BmTrans, b21.BmTrans, b22.BmTrans, coeffs);
7076 0 : TBmBmSc = TBmBm * TScBmBm;
7077 0 : TScBmDif = BilinearInterp(b11.DfTrans, b12.DfTrans, b21.DfTrans, b22.DfTrans, coeffs);
7078 : // beam-beam and diffuse transmittance of exterior beam
7079 0 : TBmAllShBlSc = TScBmBm * (TBmBm + RGlBmFr * RScBack * TDifBare / (1 - RGlDifFr * RScDifBack)) +
7080 0 : TScBmDif * TDifBare / (1 - RGlDifFr * RScDifBack);
7081 0 : TBmBmShBlSc = TBmBmSc;
7082 0 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7083 : // Report variable for Beam-to-Diffuse transmittance (scattered transmittance)
7084 0 : s_surf->SurfWinScGlSysTsolBmBm(SurfNum) = TBmBmSc;
7085 0 : s_surf->SurfWinScTsolBmBm(SurfNum) = TScBmBm;
7086 0 : s_surf->SurfWinScTsolBmDif(SurfNum) = TScBmDif;
7087 : #else // !PRECALC_INTERP_SCREEN
7088 : Material::ScreenBmTransAbsRef btar;
7089 : CalcScreenTransmittance(state, screen, phi, theta, btar);
7090 :
7091 : Real64 RScBack = btar.RefSolFront;
7092 : Real64 RScDifBack = screen->DfRef;
7093 :
7094 : Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Beam front reflectance of glass
7095 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
7096 : // beam transmittance (written in subroutine CalcScreenTransmittance each time step)
7097 : TScBmBm = btar.BmTrans;
7098 : TBmBmSc = TBmBm * TScBmBm;
7099 : TScBmDif = btar.DfTrans;
7100 : // beam-beam and diffuse transmittance of exterior beam
7101 : TBmAllShBlSc = TScBmBm * (TBmBm + RGlBmFr * RScBack * TDifBare / (1 - RGlDifFr * RScDifBack)) +
7102 : TScBmDif * TDifBare / (1 - RGlDifFr * RScDifBack);
7103 : TBmBmShBlSc = TBmBmSc;
7104 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7105 : // Report variable for Beam-to-Diffuse transmittance (scattered transmittance)
7106 : s_surf->SurfWinScGlSysTsolBmBm(SurfNum) = TBmBmSc;
7107 : s_surf->SurfWinScTsolBmBm(SurfNum) = TScBmBm;
7108 : s_surf->SurfWinScTsolBmDif(SurfNum) = TScBmDif;
7109 : #endif // PRECALC_INTERP_SCREEN
7110 : } else {
7111 0 : TBlBmBm = surfShade.blind.bmBmTrans;
7112 0 : TBlBmDif = FrontBeamDiffTrans;
7113 0 : if (ShadeFlag == WinShadingType::IntBlind) {
7114 0 : Real64 RhoBlBmDifFr = FrontBeamDiffRefl; // Beam-diffuse front reflectance of blind
7115 0 : Real64 RGlDifBk = thisConstruct.ReflectSolDiffBack; // Diffuse front reflectance of glass
7116 0 : Real64 RhoBlDifDifFr = FrontDiffDiffRefl; // Diffuse-diffuse front reflectance of blind
7117 : // beam-beam and diffuse transmittance of exterior beam
7118 0 : TBmBmBl = TBmBm * TBlBmBm;
7119 0 : TBlDifDif = FrontDiffDiffTrans;
7120 0 : TBmAllShBlSc =
7121 0 : TBmBm * (TBlBmBm + TBlBmDif + TBlDifDif * RhoBlBmDifFr * RGlDifBk / (1 - RhoBlDifDifFr * RGlDifBk));
7122 0 : TBmBmShBlSc = TBmBmBl; // TBmBm * TBlBmBm
7123 0 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7124 0 : if (TBmDifShBlSc < 0.0) TBmDifShBlSc = 0.0;
7125 0 : } else if (ShadeFlag == WinShadingType::ExtBlind) {
7126 0 : Real64 RhoBlBmDifBk = BackBeamDiffRefl; // Beam-diffuse back reflectance of blind
7127 0 : Real64 RhoBlDifDifBk = BackDiffDiffRefl; // Diffuse-diffuse back reflectance of blind
7128 0 : Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef);
7129 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
7130 : // beam-beam and diffuse transmittance of exterior beam
7131 0 : TBmBmBl = TBmBm * TBlBmBm;
7132 0 : TBmAllShBlSc = TBlBmBm * (TBmBm + TDifBare * RGlBmFr * RhoBlBmDifBk / (1 - RGlDifFr * RhoBlDifDifBk)) +
7133 0 : TBlBmDif * TDifBare / (1 - RGlDifFr * RhoBlDifDifBk);
7134 0 : TBmBmShBlSc = TBmBmBl; // TBmBm * TBlBmBm
7135 0 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7136 : } else {
7137 : // Between-glass blind on
7138 0 : int NGlass = thisConstruct.TotGlassLayers;
7139 0 : Real64 td2 = thisConstruct.tBareSolDiff(2);
7140 0 : Real64 rbd1 = thisConstruct.rbBareSolDiff(1);
7141 0 : Real64 rbshB = BackBeamDiffRefl;
7142 0 : Real64 rfshd = FrontDiffDiffRefl;
7143 0 : Real64 rbshd = BackDiffDiffRefl;
7144 0 : Real64 tfshBd = FrontBeamDiffTrans;
7145 0 : Real64 t1 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(1));
7146 0 : Real64 t2 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(2));
7147 0 : Real64 tfshBB = surfShade.blind.bmBmTrans;
7148 0 : if (NGlass == 2) {
7149 0 : Real64 rf2 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(2));
7150 0 : Real64 rfshB = FrontBeamDiffRefl;
7151 0 : Real64 rfd2 = thisConstruct.rfBareSolDiff(2);
7152 0 : TBmBmBl = t1 * tfshBB * t2;
7153 0 : TBmAllShBlSc = t1 * tfshBB * t2 +
7154 0 : t1 * (tfshBB * rf2 * rbshB + tfshBd * (1.0 + rfd2 * rbshd) + rfshB * rbd1 * rfshd) * td2;
7155 : } else { // NGlass = 3
7156 0 : Real64 t1t2 = t1 * t2;
7157 0 : Real64 t3 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(3));
7158 0 : Real64 td3 = thisConstruct.tBareSolDiff(3);
7159 0 : Real64 rf3 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(3));
7160 0 : Real64 rbd2 = thisConstruct.rbBareSolDiff(2);
7161 0 : Real64 rfd3 = thisConstruct.rfBareSolDiff(3);
7162 0 : Real64 tfshd = FrontDiffDiffTrans;
7163 0 : TBmBmBl = t1 * t2 * tfshBB * t3;
7164 0 : TBmAllShBlSc = t1t2 * tfshBB * t3 + t1t2 *
7165 0 : (tfshBB * rf3 * rbshB + tfshBd * (1.0 + rfd3 * rbshd) +
7166 0 : rbshB * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) *
7167 : td3;
7168 : }
7169 : // added TH 12/9/2009
7170 0 : TBmBmShBlSc = TBmBmBl;
7171 0 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7172 : }
7173 0 : s_surf->SurfWinBlTsolBmBm(SurfNum) = TBlBmBm;
7174 0 : s_surf->SurfWinBlTsolBmDif(SurfNum) = TBlBmDif;
7175 0 : s_surf->SurfWinBlGlSysTsolBmBm(SurfNum) = TBmBmBl;
7176 : }
7177 : }
7178 : } // End of check if ShadeFlag > 0 and ShadeFlag < 10
7179 : } // end of checking if not eql window model
7180 : } // end of checking if sunlitfract > 0
7181 :
7182 31116 : if (ShadeFlag == WinShadingType::SwitchableGlazing) {
7183 : // Switchable glazing
7184 0 : Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum);
7185 0 : if (!s_surf->SurfWinSolarDiffusing(SurfNum)) {
7186 0 : TBmBm = Window::InterpSw(SwitchFac, TBmBm, TBmAllShBlSc);
7187 : } else {
7188 0 : TBmDif = Window::InterpSw(SwitchFac, TBmDif, TBmAllShBlSc);
7189 : }
7190 : }
7191 : // Report variables
7192 31116 : s_surf->SurfWinGlTsolBmBm(SurfNum) = TBmBm;
7193 31116 : s_surf->SurfWinGlTsolBmDif(SurfNum) = TBmDif;
7194 31116 : s_surf->SurfWinGlTsolDifDif(SurfNum) = TDifBare;
7195 :
7196 : //-----------------------------------------------------------------
7197 : // BLOCK 4 - REPORT WINDOW TRANSMITTANCE
7198 : //-----------------------------------------------------------------
7199 :
7200 : // The following SurfWinTransBmSolar and SurfWinTransDifSolar will be combined later to give
7201 : // WinTransSolar for reporting
7202 31116 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = 0.0;
7203 31116 : state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = 0.0;
7204 31116 : state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = 0.0;
7205 31116 : state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = 0.0;
7206 31116 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) =
7207 : 0.0; // Factor for exterior beam to beam solar transmitted through window, or window plus shade, into zone at current time (m2)
7208 31116 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) =
7209 : 0.0; // Factor for exterior beam to diffuse solar transmitted through window, or window plus shade, into zone at current time (m2)
7210 :
7211 31116 : Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
7212 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
7213 29742 : state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = DiffTrans * surf.Area;
7214 29742 : if (ANY_BLIND(ShadeFlag)) {
7215 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
7216 0 : assert(matBlind != nullptr);
7217 0 : if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
7218 0 : state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = DiffTransGnd * surf.Area;
7219 0 : state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = DiffTransSky * surf.Area;
7220 : }
7221 : }
7222 : } else {
7223 : // In equivalent layer window model system diffuse transmittance is based on unit
7224 : // diffuse radiation flux, and hence doesn't distinguish between sky and
7225 : // ground reflected diffuse radiations
7226 1374 : state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = DiffTrans * surf.Area;
7227 1374 : state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = DiffTrans * surf.Area;
7228 1374 : state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = DiffTrans * surf.Area;
7229 : }
7230 :
7231 31116 : if (!IS_SHADED_NO_GLARE_CTRL(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
7232 : // Unshaded or switchable glazing
7233 : // Note: with previous defs of TBmBm & TBmDif, these come out right for Complex Fenestration
7234 : // SurfWinTransBmSolar uses the directional-hemispherical transmittance
7235 31116 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = (TBmBm + TBmDif) * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7236 31116 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBm * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7237 31116 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDif * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7238 :
7239 : } else {
7240 0 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = TBmAllShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7241 0 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBmShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7242 0 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDifShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7243 : }
7244 :
7245 : // Add diffuse transmitted by window from beam reflected from outside reveal
7246 31116 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // Complex Fenestration
7247 0 : if (FenSolAbsPtr == 0) {
7248 0 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = (TBmBm + TBmDif) * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7249 0 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBm * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7250 0 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDif * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7251 0 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) +=
7252 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
7253 0 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) +=
7254 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
7255 : } else {
7256 0 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = 0.0;
7257 0 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = 0.0;
7258 : }
7259 : } else { // Regular window
7260 : // this is also valid for equivalent layer window
7261 31116 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) += s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
7262 31116 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) += s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
7263 : }
7264 :
7265 : //-----------------------------------------------------------------
7266 : // BLOCK 5 - UPDATE SOLAR ENTERING A ZONE AS BEAM OR DIFFUSE RADIATION
7267 : //-----------------------------------------------------------------
7268 : // Increment factor for total exterior beam solar entering zone through window as beam or diffuse
7269 31116 : if (SunLitFract > 0.0 && surf.Class != SurfaceClass::TDD_Dome) {
7270 : // Window is schedule surface gained. Do not make addition to what enters into zone since that information is not available
7271 16092 : if (FenSolAbsPtr == 0) {
7272 : Real64 TBmAll; // Window beam-to-(beam+diffuse) transmittance
7273 16092 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::BSDF && (ANY_BLIND(ShadeFlag) || ANY_SHADE_SCREEN(ShadeFlag))) {
7274 0 : TBmAll = TBmAllShBlSc;
7275 : } else {
7276 16092 : TBmAll = TBmBm + TBmDif;
7277 : }
7278 16092 : BTOTZone += surf.IncSolMultiplier * TBmAll * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // [m2]
7279 : }
7280 : }
7281 :
7282 : // Correct for effect of (1) beam absorbed by inside reveal, (2) diffuse entering zone from beam
7283 : // reflected by inside reveal and (3) diffuse transmitted by window from beam reflected from outside reveal.
7284 31116 : if (CosInc > 0.0) {
7285 : // The BTOTZone is the solar into zone assuming no inside or outside reveals
7286 : // The inside reveals receive solar (reflected part + absorbed part) from the window, this amount should be deducted from the
7287 : // BTOTZone, then adds the InsRevealDiffIntoZone
7288 16820 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // Complex Fenestration
7289 : // Do not add total into zone from scheduled surface gains. That will be added later
7290 0 : if (SurfaceScheduledSolarInc(state, SurfNum, ConstrNum) == 0) {
7291 0 : BTOTZone = BTOTZone - s_surf->SurfWinBmSolRefldInsReveal(SurfNum) - s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +
7292 0 : s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) +
7293 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
7294 : }
7295 : } else { // Regular window
7296 16820 : BTOTZone = BTOTZone - s_surf->SurfWinBmSolRefldInsReveal(SurfNum) - s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +
7297 16820 : s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) +
7298 16820 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
7299 : }
7300 : // Add beam solar absorbed by outside reveal to outside of window's base surface. Add beam solar absorbed by inside reveal to inside
7301 : // of window's base surface. This ignores 2-D heat transfer effects.
7302 16820 : int BaseSurfNum = surf.BaseSurf;
7303 16820 : s_surf->SurfOpaqAI(BaseSurfNum) += s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / s_surf->Surface(BaseSurfNum).Area;
7304 16820 : s_surf->SurfOpaqAO(BaseSurfNum) += s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) / s_surf->Surface(BaseSurfNum).Area;
7305 : }
7306 :
7307 : //-----------------------------------------------------------------
7308 : // BLOCK 6 - INTERIOR BEAM FROM EXTERIOR WINDOW THAT IS ABSORBED/TRANSMITTED BY BACK SURFACES
7309 : //-----------------------------------------------------------------
7310 :
7311 : // If shade is in place or there is a diffusing glass layer there is no interior beam
7312 : // from this exterior window since the beam-beam transmittance of shades and diffusing glass
7313 : // is assumed to be zero. The beam-beam transmittance of tubular daylighting devices is also
7314 : // assumed to be zero.
7315 31116 : if (SunLitFract > 0.0) {
7316 16092 : if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::BSDF)
7317 32184 : if (ANY_SHADE(ShadeFlag) || s_surf->SurfWinSolarDiffusing(SurfNum) || surf.OriginalClass == SurfaceClass::TDD_Diffuser ||
7318 16092 : surf.Class == SurfaceClass::TDD_Dome)
7319 0 : continue;
7320 :
7321 : // Find interior beam radiation that is:
7322 : // (1) absorbed by opaque back surfaces;
7323 : // (2) absorbed by glass layers of back surfaces that are interior or exterior windows;
7324 : // (3) absorbed by interior, exterior or between-glass shades or blinds of back surfaces
7325 : // that are exterior windows; and
7326 : // (4) transmitted through back surfaces that are interior or exterior windows.
7327 : // Beam-beam transmittance of exterior window
7328 : Real64 TBm; // Window beam-beam transmittance
7329 : Real64 TBmDenom; // TBmDenominator
7330 16092 : Real64 TBmBmSc = s_surf->SurfWinScGlSysTsolBmBm(SurfNum);
7331 16092 : Real64 TBmBmBl = s_surf->SurfWinBlGlSysTsolBmBm(SurfNum);
7332 16092 : Real64 TBmBm = s_surf->SurfWinGlTsolBmBm(SurfNum);
7333 :
7334 16092 : Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
7335 16092 : int InShelfSurf = 0; // Inside daylighting shelf surface number
7336 16092 : int ShelfNum = s_surf->SurfDaylightingShelfInd(SurfNum);
7337 16092 : if (ShelfNum > 0) { // Daylighting shelf
7338 0 : InShelfSurf = state.dataDaylightingDevicesData->Shelf(ShelfNum).InSurf;
7339 : }
7340 16092 : if (ANY_BLIND(ShadeFlag)) {
7341 0 : TBm = TBmBmBl; // Interior, exterior or between-glass blind on
7342 16092 : } else if (ShadeFlag == WinShadingType::ExtScreen) {
7343 0 : TBm = TBmBmSc; // Exterior screen on
7344 : } else {
7345 16092 : TBm = TBmBm; // Bare glass or switchable glazing
7346 : // Correction for beam absorbed by inside reveal
7347 16092 : TBmDenom = (SunLitFract * CosInc * surf.Area * InOutProjSLFracMult);
7348 16092 : if (TBmDenom != 0.0) { // when =0.0, no correction
7349 16081 : TBm -= s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / TBmDenom;
7350 : }
7351 16092 : TBm = max(0.0, TBm);
7352 : // this multiplier doesn't work with other shading, so no need to apply in other branches
7353 16092 : TBm *= surf.IncSolMultiplier;
7354 : }
7355 :
7356 16092 : if (TBm == 0.0) continue;
7357 15783 : if (InShelfSurf > 0) { // Inside daylighting shelf
7358 : // Inside daylighting shelves assume that no beam will pass the end of the shelf.
7359 : // Since all beam is absorbed on the shelf, this might cause them to get unrealistically hot at times.
7360 : // BTOTWinZone - Transmitted beam solar factor for a window [m2]
7361 0 : Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * InOutProjSLFracMult;
7362 : // Shelf surface area is divided by 2 because only one side sees beam (Area was multiplied by 2 during init)
7363 0 : s_surf->SurfOpaqAI(InShelfSurf) += BTOTWinZone / (0.5 * s_surf->Surface(InShelfSurf).Area); //[-]
7364 0 : BABSZone += BTOTWinZone; //[m2]
7365 0 : continue;
7366 0 : }
7367 :
7368 15783 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) { // Full interior solar distribution
7369 2997 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
7370 : // Loop over back surfaces irradiated by beam from this exterior window
7371 8220 : for (int IBack = 1; IBack <= state.dataBSDFWindow->MaxBkSurf; ++IBack) {
7372 : int BackSurfNum =
7373 8220 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
7374 8220 : if (BackSurfNum == 0) break; // No more irradiated back surfaces for this exterior window
7375 :
7376 5223 : auto &surfShadeBack = s_surf->surfShades(BackSurfNum);
7377 5223 : int ConstrNumBack = s_surf->SurfActiveConstruction(BackSurfNum);
7378 5223 : auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
7379 :
7380 5223 : int NBackGlass = constrBack.TotGlassLayers;
7381 : // Irradiated (overlap) area for this back surface, projected onto window plane
7382 : // (includes effect of shadowing on exterior window)
7383 : Real64 AOverlap =
7384 5223 : state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
7385 : // Back surface area irradiated by beam solar from an exterior window, projected onto window plane
7386 5223 : Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
7387 : // AOverlap multiplied by exterior window beam transmittance and cosine of incidence angle
7388 5223 : if (constrBack.TransDiff <= 0.0) {
7389 :
7390 : // Back surface is opaque interior or exterior wall
7391 : // Interior solar absorptance of opaque surface
7392 5222 : Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
7393 5222 : s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
7394 5222 : BABSZone += BOverlap * AbsIntSurf; //[m2]
7395 :
7396 : } else {
7397 :
7398 : // Back surface is an interior or exterior window
7399 : // Note that exterior back windows can have a shading device but interior back windows
7400 : // are assumed to be bare, i.e., they have no shading device and are non-switchable.
7401 : // The layer order for interior windows is "outside" to "inside," where "outside" refers to
7402 : // the adjacent zone and "inside" refers to the current zone.
7403 1 : WinShadingType ShadeFlagBack = s_surf->SurfWinShadingFlag(BackSurfNum);
7404 1 : Real64 slatAngBack = surfShadeBack.blind.slatAng;
7405 : Real64 CosIncBack =
7406 1 : std::abs(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, BackSurfNum));
7407 1 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
7408 : // Transmitting window is complex fen, change the incident angle to one for ray joining
7409 : // transmitting and back window centers
7410 0 : CosIncBack = std::abs(state.dataBSDFWindow->ComplexWind(SurfNum).sdotN(IBack));
7411 : }
7412 1 : int ConstrNumBackShRaw = s_surf->SurfWinActiveShadedConstruction(BackSurfNum);
7413 1 : int const ConstrNumBackSh = ConstrNumBackShRaw == 0 ? ConstrNumBack : ConstrNumBackShRaw;
7414 1 : state.dataSolarShading->SurfWinAbsBeam.dimension(state.dataHeatBal->MaxSolidWinLayers, 0.0);
7415 1 : Real64 TransBeamWin = 0.0; // Beam solar transmittance of a window
7416 1 : Real64 AbsBeamTotWin = 0.0; // Sum of window glass layer beam solar absorptances
7417 1 : Real64 backSurfBeamSolInTrans = 0.0; // Fraction of BeamSolarRad transmitted out through window inside face [W]
7418 :
7419 : // Interior beam absorptance of glass layers and beam transmittance of back exterior &
7420 : // or interior window WITHOUT SHADING this timestep
7421 1 : if (NOT_SHADED(ShadeFlagBack)) {
7422 3 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7423 2 : state.dataSolarShading->SurfWinAbsBeam(Lay) = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
7424 : }
7425 1 : TransBeamWin = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
7426 : }
7427 :
7428 : // Interior beam absorptance of glass layers and beam transmittance
7429 : // of back exterior window with SHADE
7430 1 : if (ANY_SHADE(ShadeFlagBack)) {
7431 0 : for (int Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNumBackSh).TotGlassLayers; ++Lay) {
7432 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7433 0 : Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).AbsBeamBackCoef(Lay));
7434 : }
7435 0 : TransBeamWin = Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).TransSolBeamCoef);
7436 : }
7437 :
7438 : // Interior beam absorbed by INTERIOR SHADE of back exterior window
7439 1 : if (ShadeFlagBack == WinShadingType::IntShade) {
7440 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7441 0 : BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade /
7442 0 : (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7443 0 : BABSZone += BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade;
7444 0 : backSurfBeamSolInTrans += BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade;
7445 :
7446 : // Interior beam absorbed by EXTERIOR SHADE of back exterior window
7447 1 : } else if (ShadeFlagBack == WinShadingType::ExtShade) {
7448 0 : Real64 RGlFront = constrBack.ReflectSolDiffFront;
7449 0 : auto const *matSh = s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(1));
7450 0 : auto const *matFenSh = dynamic_cast<Material::MaterialFen const *>(matSh);
7451 0 : assert(matFenSh != nullptr);
7452 :
7453 0 : Real64 AbsSh = matFenSh->AbsorpSolar;
7454 0 : Real64 RhoSh = 1.0 - AbsSh - matFenSh->Trans;
7455 0 : Real64 AShBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef) * AbsSh / (1.0 - RGlFront * RhoSh);
7456 0 : BABSZone += BOverlap * AShBack;
7457 0 : backSurfBeamSolInTrans += BOverlap * AShBack;
7458 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7459 0 : BOverlap * AShBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7460 :
7461 : // Interior beam absorbed by BETWEEN-GLASS SHADE of back exterior window
7462 1 : } else if (ShadeFlagBack == WinShadingType::BGShade) {
7463 0 : Real64 rbd1k = constrBack.rbBareSolDiff(1);
7464 0 : Real64 rfd2k = constrBack.rfBareSolDiff(2);
7465 : Real64 AShBack; // System shade absorptance for interior beam solar
7466 0 : if (NBackGlass == 2) {
7467 0 : Real64 t2k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(2));
7468 0 : auto const *matShade = dynamic_cast<Material::MaterialShade const *>(
7469 0 : s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(3)));
7470 0 : assert(matShade != nullptr);
7471 0 : Real64 TrSh = matShade->Trans; // Shade material solar transmittance
7472 0 : Real64 RhoSh = matShade->ReflectShade; // Shade material solar absorptance
7473 0 : Real64 AbsSh = min(1.0, max(0.0, 1 - TrSh - RhoSh)); // Shade material solar absorptance
7474 0 : AShBack = t2k * (1 + RhoSh * rfd2k + TrSh * rbd1k) * AbsSh;
7475 : } else { // NBackGlass = 3
7476 0 : Real64 t3k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(3));
7477 0 : Real64 td2k = constrBack.tBareSolDiff(2);
7478 0 : Real64 rbd2k = constrBack.rbBareSolDiff(2);
7479 0 : Real64 rfd3k = constrBack.rfBareSolDiff(3);
7480 0 : auto const *matShade = dynamic_cast<Material::MaterialShade const *>(
7481 0 : s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(5)));
7482 0 : assert(matShade != nullptr);
7483 0 : Real64 TrSh = matShade->Trans;
7484 0 : Real64 RhoSh = matShade->ReflectShade;
7485 0 : Real64 AbsSh = min(1.0, max(0.0, 1 - TrSh - RhoSh));
7486 0 : AShBack = t3k * (1 + RhoSh * rfd3k + TrSh * (rbd2k + td2k * rbd1k * td2k)) * AbsSh;
7487 : }
7488 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7489 0 : BOverlap * AShBack / s_surf->Surface(BackSurfNum).Area;
7490 0 : BABSZone += BOverlap * AShBack;
7491 0 : backSurfBeamSolInTrans += BOverlap * AShBack;
7492 : }
7493 :
7494 : // Interior beam absorptance of glass layers and beam absorbed in blind
7495 : // of back exterior window with BLIND
7496 1 : if (ANY_BLIND(ShadeFlagBack)) {
7497 0 : auto const &btarBack = surfShadeBack.blind.TAR;
7498 : auto const *matBlindBack =
7499 0 : dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShadeBack.blind.matNum));
7500 0 : assert(matBlindBack != nullptr);
7501 :
7502 0 : auto const &btar = surfShade.blind.TAR;
7503 0 : Real64 profAngBack = surfShadeBack.blind.profAng;
7504 :
7505 0 : int profIdxLoBack = surfShadeBack.blind.profAngIdxLo;
7506 0 : int profIdxHiBack = surfShadeBack.blind.profAngIdxHi;
7507 0 : Real64 profInterpFacBack = surfShadeBack.blind.profAngInterpFac;
7508 :
7509 0 : Real64 TGlBmBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
7510 0 : Real64 TBlBmBmBack = matBlindBack->BeamBeamTrans(profAngBack, Constant::Pi - slatAngBack);
7511 :
7512 : // Blind solar back beam-diffuse transmittance
7513 : // Is this supposed to be blindBack?
7514 : Real64 TBlBmDiffBack =
7515 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfTra, btar.Sol.Bk.Bm[profIdxLoBack].DfTra, profInterpFacBack);
7516 :
7517 0 : if (ShadeFlagBack == WinShadingType::IntBlind) {
7518 : // Interior beam absorptance of GLASS LAYERS of exterior back window with INTERIOR BLIND
7519 0 : FrontDiffDiffRefl = btarBack.Sol.Ft.Df.Ref; // Blind solar front beam reflectance
7520 0 : FrontDiffAbs = btarBack.Sol.Ft.Df.Abs;
7521 : Real64 RhoBlFront =
7522 0 : Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfRef, btar.Sol.Ft.Bm[profIdxHiBack].DfRef, profInterpFacBack);
7523 : Real64 AbsBlFront =
7524 0 : Interp(btar.Sol.Ft.Bm[profIdxLoBack].Abs, btar.Sol.Ft.Bm[profIdxHiBack].Abs, profInterpFacBack);
7525 : Real64 AbsBlBack =
7526 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
7527 :
7528 0 : Real64 RhoBlDiffFront = FrontDiffDiffRefl; // Glazing system solar back beam-beam reflectance
7529 0 : Real64 RGlBack = Window::POLYF(
7530 0 : CosIncBack, constrBack.ReflSolBeamBackCoef); // Glazing system back diffuse solar reflectance
7531 0 : Real64 RGlDiffBack = constrBack.ReflectSolDiffBack;
7532 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7533 0 : Real64 AbWinBack = Window::POLYF(
7534 : CosIncBack,
7535 : constrBack.AbsBeamBackCoef(Lay)); // Factor for back beam radiation absorbed in window glass layer
7536 0 : Real64 AGlDiffBack = constrBack.AbsDiffBack(Lay); // Glass layer back diffuse solar absorptance
7537 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7538 0 : TBlBmBmBack * AbWinBack + ((TBlBmBmBack * RGlBack * RhoBlFront + TBlBmDiffBack) * AGlDiffBack /
7539 0 : (1.0 - RGlDiffBack * RhoBlDiffFront));
7540 : }
7541 :
7542 : // Interior beam transmitted by exterior back window with INTERIOR BLIND
7543 0 : Real64 TGlDif = constrBack.TransDiff; // Bare diffuse transmittance of back window
7544 0 : TransBeamWin =
7545 0 : TBlBmBmBack * (TGlBmBack + TGlDif * RGlBack * RhoBlFront / (1.0 - RGlDiffBack * RhoBlDiffFront)) +
7546 0 : TBlBmDiffBack * TGlDif / (1.0 - RGlDiffBack * RhoBlDiffFront);
7547 :
7548 : // Interior beam absorbed by BLIND on exterior back window with INTERIOR BLIND
7549 :
7550 0 : Real64 AbsBlDiffFront = FrontDiffAbs; // Blind solar front diffuse absorptance
7551 0 : Real64 ABlBack = AbsBlBack + TBlBmBmBack * RGlBack * AbsBlFront +
7552 0 : (AbsBlDiffFront * RGlDiffBack / (1 - RhoBlDiffFront * RGlDiffBack)) *
7553 0 : (RGlBack * TBlBmBmBack * RhoBlFront +
7554 : TBlBmDiffBack); // Blind solar back absorptance for interior solar
7555 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7556 0 : BOverlap * ABlBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7557 0 : BABSZone += BOverlap * ABlBack;
7558 0 : backSurfBeamSolInTrans += BOverlap * ABlBack;
7559 :
7560 0 : } else if (ShadeFlagBack == WinShadingType::ExtBlind) {
7561 :
7562 : // Interior beam absorptance of GLASS LAYERS of exterior back window with EXTERIOR BLIND
7563 :
7564 0 : Real64 RGlDiffFront = state.dataConstruction->Construct(ConstrNumBack)
7565 0 : .ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
7566 :
7567 : // Is this supposed to be beam-beam reflection?
7568 : Real64 RhoBlBack =
7569 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
7570 : Real64 RhoBlBmDifBk =
7571 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
7572 : Real64 AbsBlBack =
7573 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
7574 :
7575 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7576 0 : Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
7577 0 : Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
7578 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7579 0 : AbWinBack + (TGlBmBack * AGlDiffFront * RhoBlBack / (1.0 - RhoBlBack * RGlDiffFront));
7580 : }
7581 :
7582 : // Interior beam transmitted by exterior back window with EXTERIOR BLIND
7583 0 : Real64 TBlDifDif = BackDiffDiffTrans;
7584 0 : Real64 RhoBlDifDifBk = BackDiffDiffRefl;
7585 0 : Real64 AbsBlDiffBack = BackDiffAbs;
7586 0 : Real64 ABlBack =
7587 0 : TGlBmBack * (AbsBlBack + RhoBlBack * RGlDiffFront * AbsBlDiffBack / (1 - RhoBlDifDifBk * RGlDiffFront));
7588 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
7589 0 : TransBeamWin = TGlBmBack * (TBlBmBmBack + TBlBmDiffBack +
7590 0 : TBlDifDif * RhoBlBmDifBk * RGlDifFr / (1.0 - RhoBlDifDifBk * RGlDifFr));
7591 : // Interior beam absorbed by EXTERIOR BLIND on exterior back window
7592 0 : BABSZone += BOverlap * ABlBack;
7593 0 : backSurfBeamSolInTrans += BOverlap * ABlBack;
7594 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7595 0 : BOverlap * ABlBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7596 :
7597 : } else {
7598 : // ShadeFlagBack == BGBlindOn
7599 0 : Real64 t1k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(1));
7600 0 : Real64 t2k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(2));
7601 0 : Real64 af2k = Window::POLYF(CosIncBack, constrBack.afBareSolCoef(2));
7602 0 : Real64 ab1k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(1));
7603 0 : Real64 ab2k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(2));
7604 0 : Real64 rb1k = Window::POLYF(CosIncBack, constrBack.rbBareSolCoef(1));
7605 0 : Real64 rb2k = Window::POLYF(CosIncBack, constrBack.rbBareSolCoef(2));
7606 0 : Real64 td1k = constrBack.tBareSolDiff(1);
7607 0 : Real64 td2k = constrBack.tBareSolDiff(2);
7608 0 : Real64 afd2k = constrBack.afBareSolDiff(2);
7609 0 : Real64 abd1k = constrBack.abBareSolDiff(1);
7610 0 : Real64 abd2k = constrBack.abBareSolDiff(2);
7611 0 : Real64 rfd2k = constrBack.rfBareSolDiff(2);
7612 0 : Real64 rbd1k = constrBack.rbBareSolDiff(1);
7613 0 : Real64 rbd2k = constrBack.rbBareSolDiff(2);
7614 0 : Real64 tfshBBk = matBlindBack->BeamBeamTrans(profAngBack, slatAngBack);
7615 0 : Real64 tbshBBk = matBlindBack->BeamBeamTrans(profAngBack, Constant::Pi - slatAngBack);
7616 :
7617 : Real64 tfshBdk =
7618 0 : Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfTra, btar.Sol.Ft.Bm[profIdxHiBack].DfTra, profInterpFacBack);
7619 : Real64 tbshBdk =
7620 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfTra, btar.Sol.Bk.Bm[profIdxHiBack].DfTra, profInterpFacBack);
7621 : Real64 rfshBk =
7622 0 : Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfRef, btar.Sol.Ft.Bm[profIdxHiBack].DfRef, profInterpFacBack);
7623 : Real64 rbshBk =
7624 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
7625 : Real64 afshBk =
7626 0 : Interp(btar.Sol.Ft.Bm[profIdxLoBack].Abs, btar.Sol.Ft.Bm[profIdxHiBack].Abs, profInterpFacBack);
7627 : Real64 abshBk =
7628 0 : Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
7629 0 : Real64 tfshdk = btarBack.Sol.Ft.Df.Tra;
7630 0 : Real64 rfshdk = btarBack.Sol.Ft.Df.Ref;
7631 0 : Real64 afshdk = btarBack.Sol.Ft.Df.Abs;
7632 0 : Real64 tbshdk = btarBack.Sol.Bk.Df.Tra;
7633 0 : Real64 rbshdk = btarBack.Sol.Bk.Df.Ref;
7634 0 : Real64 abshdk = btarBack.Sol.Bk.Df.Abs;
7635 : Real64 ABlBack;
7636 :
7637 0 : if (NBackGlass == 2) {
7638 : // Interior beam absorptance of GLASS LAYERS of exterior back window with BETWEEN-GLASS BLIND
7639 0 : state.dataSolarShading->SurfWinAbsBeam(2) =
7640 0 : ab2k + t2k * tbshBBk * rb1k * tfshBBk * af2k +
7641 0 : t2k * (tbshBBk * rb1k * tfshBdk + tbshBdk * rbd1k * tfshdk + rbshBk * (1.0 + rfd2k * rbshdk)) * afd2k;
7642 0 : state.dataSolarShading->SurfWinAbsBeam(1) =
7643 0 : t2k * tbshBBk * ab1k + t2k * (rbshBk * rfd2k * tbshdk + tbshBdk * (1.0 + rbd1k * rfshdk)) * abd1k;
7644 : // Interior beam transmitted by exterior back window with BETWEEN-GLASS BLIND
7645 0 : TransBeamWin =
7646 0 : t2k * tbshBBk * t1k +
7647 0 : t2k * (tbshBBk * rb1k * rfshBk + rbshBk * rfd2k * tbshdk + tbshBdk * (1.0 + rbd1k * rfshdk)) * td1k;
7648 : // Interior beam absorbed by BLIND on exterior back window with BETWEEN-GLASS BLIND
7649 0 : ABlBack = t2k * (abshBk + tbshBBk * rb1k * afshBk + rbshBk * rfd2k * abshdk + tbshBdk * rbd1k * afshdk);
7650 : } else { // NBackGlass = 3
7651 0 : Real64 t3k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(3));
7652 0 : Real64 af3k = Window::POLYF(CosIncBack, constrBack.afBareSolCoef(3));
7653 0 : Real64 ab3k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(3));
7654 0 : Real64 afd3k = constrBack.afBareSolDiff(3);
7655 0 : Real64 rfd3k = constrBack.rfBareSolDiff(3);
7656 0 : state.dataSolarShading->SurfWinAbsBeam(3) =
7657 0 : ab3k + t3k * tbshBBk * (rb2k + t2k * rb1k * t2k) * tfshBBk * af3k +
7658 0 : t3k *
7659 0 : (tbshBdk * rbd2k * tfshdk + tbshBdk * td2k * rbd1k * td2k * tfshdk +
7660 0 : rbshBk * (1.0 + rfd3k * rbshdk)) *
7661 : afd3k;
7662 0 : state.dataSolarShading->SurfWinAbsBeam(2) =
7663 0 : t3k * tbshBBk * (ab2k + t2k * rb1k * (af2k + t2k * rfshBk * abd2k)) +
7664 0 : t3k * (tbshBdk + tbshBdk * (rbd2k + td2k * rbd1k * td2k) * rfshdk + rbshBk * rfd3k * tbshdk) * abd2k +
7665 0 : t3k * tbshBdk * td2k * rbd1k * afd2k;
7666 0 : state.dataSolarShading->SurfWinAbsBeam(1) =
7667 0 : t3k * tbshBBk * (t2k * ab1k + (rb2k + t2k * rb1k * t2k) * rfshBk * td2k * abd1k) +
7668 0 : t3k * (rbshBk * rfd3k * tbshdk + tbshBdk * (1.0 + rbd2k * rfshdk + td2k * rbd2k * td2k * rfshdk)) *
7669 0 : td2k * abd1k;
7670 0 : TransBeamWin = t3k * tbshBBk * t2k * t1k +
7671 0 : t3k *
7672 0 : (tbshBBk * (rb2k * rfshBk + t2k * rb1k * t2k * rfshBk) + rbshBk * rfd3k * tbshdk +
7673 0 : tbshBdk * (1.0 + rbd2k * rfshdk + td2k * rbd1k * td2k * rfshdk)) *
7674 0 : td2k * td1k;
7675 0 : ABlBack = t3k * abshBk + t3k * tbshBBk * (rb2k + t2k * rb1k * t2k) * afshBk +
7676 0 : t3k * rbshBk * rfd3k * abshdk + t3k * tbshBdk * (rbd2k + td2k * rbd1k * td2k) * afshdk;
7677 : }
7678 :
7679 0 : BABSZone += BOverlap * ABlBack;
7680 0 : backSurfBeamSolInTrans += BOverlap * ABlBack;
7681 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7682 0 : BOverlap * ABlBack / s_surf->Surface(BackSurfNum).Area;
7683 :
7684 : } // End of check if between-glass blind is on back window
7685 1 : } else if (ShadeFlagBack == WinShadingType::ExtScreen) {
7686 :
7687 : // Interior beam absorptance of GLASS LAYERS of exterior back window with EXTERIOR SCREEN
7688 0 : Real64 TGlBmBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
7689 0 : Real64 RGlDiffFront = constrBack.ReflectSolDiffFront;
7690 :
7691 0 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
7692 0 : assert(screen != nullptr);
7693 :
7694 0 : auto &surf = s_surf->Surface(SurfNum);
7695 0 : Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
7696 0 : Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
7697 0 : Real64 winPhi = surf.Tilt * Constant::DegToRad;
7698 0 : Real64 winTheta = surf.Azimuth * Constant::DegToRad;
7699 0 : Real64 phi = std::abs(solPhi - winPhi);
7700 0 : Real64 theta = std::abs(solTheta - winTheta);
7701 0 : Material::NormalizePhiTheta(phi, theta);
7702 : #ifdef PRECALC_INTERP_SCREEN
7703 : int ip1, ip2, it1, it2;
7704 : BilinearInterpCoeffs coeffs;
7705 0 : Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
7706 0 : GetBilinearInterpCoeffs(
7707 0 : phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
7708 0 : auto const &b11 = screen->btars[ip1][it1];
7709 0 : auto const &b12 = screen->btars[ip1][it2];
7710 0 : auto const &b21 = screen->btars[ip2][it1];
7711 0 : auto const &b22 = screen->btars[ip2][it2];
7712 :
7713 0 : Real64 TScBmBmBack = BilinearInterp(b11.BmTransBack, b12.BmTransBack, b21.BmTransBack, b22.BmTransBack, coeffs);
7714 0 : Real64 TScBmDiffBack = BilinearInterp(b11.DfTransBack, b12.DfTransBack, b21.DfTransBack, b22.DfTransBack, coeffs);
7715 0 : Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
7716 0 : Real64 RScDifBack = screen->DfRef;
7717 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7718 0 : Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
7719 0 : Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
7720 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7721 0 : AbWinBack + (TGlBmBack * AGlDiffFront * RScBack / (1.0 - RScDifBack * RGlDiffFront));
7722 : }
7723 :
7724 : // Interior beam transmitted by exterior back window with EXTERIOR SCREEN
7725 0 : Real64 TScDifDif = screen->DfTrans;
7726 0 : Real64 RScBmDifBk = BilinearInterp(b11.RefSolBack, b12.RefSolBack, b21.RefSolBack, b22.RefSolBack, coeffs);
7727 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
7728 0 : Real64 RScDifDifBk = screen->DfRef;
7729 0 : TransBeamWin = TGlBmBack *
7730 0 : (TScBmBmBack + TScBmDiffBack + TScDifDif * RScBmDifBk * RGlDifFr / (1.0 - RScDifDifBk * RGlDifFr));
7731 :
7732 : // Interior beam absorbed by EXTERIOR SCREEN on exterior back window
7733 0 : Real64 AbsScBack = BilinearInterp(b11.AbsSolBack, b12.AbsSolBack, b21.AbsSolBack, b22.AbsSolBack, coeffs);
7734 0 : Real64 AbsScDiffBack = screen->DfAbs;
7735 0 : Real64 RScDiffBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
7736 : // Screen solar back absorptance for interior solar
7737 0 : Real64 AScBack =
7738 0 : TGlBmBack * (AbsScBack + RScBack * RGlDiffFront * AbsScDiffBack / (1.0 - RScDiffBack * RGlDiffFront));
7739 :
7740 0 : BABSZone += BOverlap * AScBack;
7741 0 : backSurfBeamSolInTrans += BOverlap * AScBack;
7742 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7743 0 : BOverlap * AScBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7744 : #else // !PRECALC_INTERP_SCREEN
7745 : Material::ScreenBmTransAbsRef btar;
7746 : Material::CalcScreenTransmittance(state, screen, phi, theta, btar);
7747 :
7748 : Real64 TScBmBmBack = btar.BmTransBack;
7749 : Real64 TScBmDiffBack = btar.DfTransBack;
7750 : Real64 RScBack = btar.RefSolFront;
7751 : Real64 RScDifBack = screen->DfRef;
7752 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7753 : Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
7754 : Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
7755 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7756 : AbWinBack + (TGlBmBack * AGlDiffFront * RScBack / (1.0 - RScDifBack * RGlDiffFront));
7757 : }
7758 :
7759 : // Interior beam transmitted by exterior back window with EXTERIOR SCREEN
7760 : Real64 TScDifDif = screen->DfTrans;
7761 : Real64 RScBmDifBk = btar.RefSolBack;
7762 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
7763 : Real64 RScDifDifBk = screen->DfRef;
7764 : TransBeamWin = TGlBmBack *
7765 : (TScBmBmBack + TScBmDiffBack + TScDifDif * RScBmDifBk * RGlDifFr / (1.0 - RScDifDifBk * RGlDifFr));
7766 :
7767 : // Interior beam absorbed by EXTERIOR SCREEN on exterior back window
7768 : Real64 AbsScBack = btar.AbsSolBack;
7769 : Real64 AbsScDiffBack = screen->DfAbs;
7770 : Real64 RScDiffBack = btar.RefSolFront;
7771 : // Screen solar back absorptance for interior solar
7772 : Real64 AScBack =
7773 : TGlBmBack * (AbsScBack + RScBack * RGlDiffFront * AbsScDiffBack / (1.0 - RScDiffBack * RGlDiffFront));
7774 :
7775 : BABSZone += BOverlap * AScBack;
7776 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7777 : BOverlap * AScBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
7778 : #endif // PRECALC_INTERP_SCREEN
7779 :
7780 : } // End of check if exterior screen on back window
7781 :
7782 : // Interior beam absorptance of glass layers of back exterior window with SWITCHABLE GLAZING
7783 1 : if (ShadeFlagBack == WinShadingType::SwitchableGlazing && s_surf->Surface(BackSurfNum).ExtBoundCond == 0) {
7784 0 : Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum); // Switching factor for a window
7785 : Real64 AbsBeamWinSh; // Glass layer beam solar absorptance of a shaded window
7786 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7787 : AbsBeamWinSh =
7788 0 : Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).AbsBeamBackCoef(Lay));
7789 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7790 0 : Window::InterpSw(SwitchFac, state.dataSolarShading->SurfWinAbsBeam(Lay), AbsBeamWinSh);
7791 : }
7792 : // Beam solar transmittance of a shaded window
7793 : Real64 TransBeamWinSh =
7794 0 : Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).TransSolBeamCoef);
7795 0 : TransBeamWin = Window::InterpSw(SwitchFac, TransBeamWin, TransBeamWinSh);
7796 : }
7797 :
7798 : // Sum of interior beam absorbed by all glass layers of back window
7799 1 : AbsBeamTotWin = 0.0;
7800 3 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7801 2 : AbsBeamTotWin += state.dataSolarShading->SurfWinAbsBeam(Lay);
7802 2 : s_surf->SurfWinA(BackSurfNum, Lay) +=
7803 2 : BOverlap * state.dataSolarShading->SurfWinAbsBeam(Lay) /
7804 2 : (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum)); //[-]
7805 : }
7806 :
7807 : // To BABSZon, add interior beam glass absorption and overall beam transmission for this back window
7808 1 : BABSZone += BOverlap * (AbsBeamTotWin + TransBeamWin);
7809 1 : backSurfBeamSolInTrans += BOverlap * (AbsBeamTotWin + TransBeamWin);
7810 1 : state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfNum) +=
7811 1 : backSurfBeamSolInTrans * state.dataEnvrn->BeamSolarRad; //[W]
7812 : // Interior beam transmitted to adjacent zone through an interior back window (assumed unshaded);
7813 : // this beam radiation is categorized as diffuse radiation in the adjacent zone.
7814 1 : int AdjSurfNum = s_surf->Surface(BackSurfNum).ExtBoundCond;
7815 1 : if (AdjSurfNum > 0) {
7816 0 : int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
7817 0 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BOverlap * TransBeamWin; //[m2]
7818 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) +=
7819 0 : BOverlap * TransBeamWin * state.dataEnvrn->BeamSolarRad; //[W]
7820 0 : s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfNum) =
7821 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
7822 : }
7823 : } // End of check if back surface is opaque or window
7824 5223 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) += BOverlap;
7825 5223 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(BackSurfNum) =
7826 5223 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
7827 : } // End of loop over back surfaces
7828 0 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
7829 : // For complex window calculation goes over outgoing basis directions for current state
7830 0 : int CurCplxFenState = s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState; // Current state for complex fenestration
7831 : // Get construction number which keeps transmittance properties
7832 0 : int IConst = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(CurCplxFenState).Konst; // Current surface construction number
7833 : // (it depends of state too)
7834 : // Solar radiation from this window will be calculated only in case when this window is not scheduled surface gained
7835 0 : if (WindowScheduledSolarAbs(state, SurfNum, IConst) == 0) {
7836 : // Current incoming direction number (Sun direction)
7837 0 : int IBm = state.dataBSDFWindow->ComplexWind(SurfNum)
7838 0 : .Geom(CurCplxFenState)
7839 0 : .SolBmIndex(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
7840 : // Report variables for complex fenestration here
7841 0 : state.dataHeatBal->SurfWinBSDFBeamDirectionRep(SurfNum) = IBm;
7842 0 : state.dataHeatBal->SurfWinBSDFBeamThetaRep(SurfNum) =
7843 0 : state.dataBSDFWindow->ComplexWind(SurfNum)
7844 0 : .Geom(CurCplxFenState)
7845 0 : .ThetaBm(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
7846 0 : state.dataHeatBal->SurfWinBSDFBeamPhiRep(SurfNum) = state.dataBSDFWindow->ComplexWind(SurfNum)
7847 0 : .Geom(CurCplxFenState)
7848 0 : .PhiBm(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
7849 :
7850 0 : int BaseSurf = surf.BaseSurf; // Base surface number for current complex window
7851 : // Get total number of back surfaces for current window (surface)
7852 : // Note that it is organized by base surface
7853 0 : int NBkSurf = state.dataShadowComb->ShadowComb(BaseSurf).NumBackSurf;
7854 0 : if (!allocated(CFBoverlap)) {
7855 0 : CFBoverlap.allocate(NBkSurf);
7856 : }
7857 0 : if (!allocated(CFDirBoverlap)) {
7858 0 : CFDirBoverlap.allocate(NBkSurf, state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis);
7859 : }
7860 :
7861 0 : CFBoverlap = 0.0;
7862 : // Calculate effects on all back surfaces for each of basis directions. Each of basis directions from the back of the
7863 : // window has to be considered as beam and therefore calculate CFBoverlap for each of them
7864 0 : for (int CurTrnDir = 1; CurTrnDir <= state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis;
7865 : ++CurTrnDir) {
7866 0 : Real64 CurLambda = state.dataBSDFWindow->ComplexWind(SurfNum)
7867 0 : .Geom(CurCplxFenState)
7868 0 : .Trn.Lamda(CurTrnDir); // Current lambda value in BSDF outgoing directions
7869 0 : Real64 DirTrans = state.dataConstruction->Construct(IConst).BSDFInput.SolFrtTrans(
7870 0 : IBm, CurTrnDir); // Current BSDF directional transmittance
7871 : // Now calculate effect of this direction on all back surfaces
7872 0 : for (int IBack = 1; IBack <= NBkSurf; ++IBack) {
7873 0 : CFDirBoverlap(IBack, CurTrnDir) =
7874 0 : state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).AOverlap(IBack, CurTrnDir) * DirTrans *
7875 0 : CurLambda * CosInc;
7876 0 : CFBoverlap(IBack) += CFDirBoverlap(IBack, CurTrnDir);
7877 : } // DO IBack = 1,MaxBkSurf
7878 : }
7879 :
7880 : // Summarizing results
7881 0 : for (int IBack = 1; IBack <= NBkSurf; ++IBack) {
7882 0 : int BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(IBack);
7883 0 : int ConstrNumBack = s_surf->Surface(BackSurfaceNumber).Construction;
7884 0 : auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
7885 : // Do not perform any calculation if surface is scheduled for incoming solar radiation
7886 0 : int SurfSolIncPtr = SurfaceScheduledSolarInc(state, BackSurfaceNumber, ConstrNumBack);
7887 :
7888 0 : if (SurfSolIncPtr == 0) {
7889 : // Surface hit is another complex fenestration
7890 0 : if (s_surf->SurfWinWindowModelType(BackSurfaceNumber) == WindowModel::BSDF) {
7891 : int CurBackState =
7892 0 : s_surf->SurfaceWindow(BackSurfaceNumber)
7893 0 : .ComplexFen.CurrentState; // Current state for back surface if that surface is complex fenestration
7894 : // Do not take into account this window if it is scheduled for surface gains
7895 0 : if (WindowScheduledSolarAbs(state, BackSurfaceNumber, ConstrNumBack) == 0) {
7896 : // Calculate energy loss per each outgoing orientation
7897 0 : for (int CurTrnDir = 1;
7898 0 : CurTrnDir <= state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis;
7899 : ++CurTrnDir) {
7900 : Real64 bestDot; // complex fenestration hits other complex fenestration, it is important to find
7901 : // matching beam directions. Beam leaving one window will have certain number for it's basis
7902 : // while same beam reaching back surface will have different beam number. This value is used
7903 : // to keep best matching dot product for those directions
7904 : Real64 curDot; // temporary variable for current dot product
7905 : int bestBackTrn; // Direction corresponding best dot product for back surface window
7906 0 : for (int CurBackDir = 1;
7907 0 : CurBackDir <= state.dataBSDFWindow->ComplexWind(BackSurfaceNumber).Geom(CurBackState).Trn.NBasis;
7908 : ++CurBackDir) {
7909 : // Purpose of this part is to find best match for outgoing beam number of window back surface
7910 : // and incoming beam number of complex fenestration which this beam will hit on (back surface
7911 : // again)
7912 : curDot =
7913 0 : dot(state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).sTrn(CurTrnDir),
7914 0 : state.dataBSDFWindow->ComplexWind(BackSurfaceNumber).Geom(CurBackState).sTrn(CurBackDir));
7915 0 : if (CurBackDir == 1) {
7916 0 : bestDot = curDot;
7917 0 : bestBackTrn = CurBackDir;
7918 : } else {
7919 0 : if (curDot < bestDot) {
7920 0 : bestDot = curDot;
7921 0 : bestBackTrn = CurBackDir;
7922 : }
7923 : }
7924 : }
7925 : // CurLambda = ComplexWind(BackSurfaceNumber)%Geom(CurBackState)%Trn%Lamda(CurTrnDir)
7926 : // Add influence of this exact direction to what stays in the zone. It is important to note that
7927 : // this needs to be done for each outgoing direction
7928 0 : Real64 babs = CFDirBoverlap(IBack, CurTrnDir) * (1 - s_surf->SurfaceWindow(BackSurfaceNumber)
7929 0 : .ComplexFen.State(CurBackState)
7930 0 : .IntegratedBkRefl(bestBackTrn));
7931 0 : BABSZone += babs;
7932 0 : state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfaceNumber) +=
7933 0 : babs * state.dataEnvrn->BeamSolarRad; //[W]
7934 :
7935 : // Absorptance from current back direction
7936 0 : int TotSolidLay = constrBack.TotSolidLayers;
7937 0 : for (int Lay = 1; Lay <= TotSolidLay; ++Lay) {
7938 : // IF (ALLOCATED(Construct(ConstrNumBack)%BSDFInput)) THEN
7939 : // CFDirBoverlap is energy transmitted for current basis beam. It is important to note that
7940 : // AWinOverlap array needs to contain flux and not absorbed energy because later in the code
7941 : // this will be multiplied with window area
7942 0 : s_surf->SurfWinACFOverlap(BackSurfaceNumber, Lay) +=
7943 0 : constrBack.BSDFInput.Layer(Lay).BkAbs(bestBackTrn, 1) * CFDirBoverlap(IBack, CurTrnDir) /
7944 0 : s_surf->Surface(BackSurfaceNumber).Area;
7945 : // END IF
7946 : }
7947 :
7948 : // Interior beam transmitted to adjacent zone through an interior back window;
7949 : // This beam radiation is categorized as diffuse radiation in the adjacent zone.
7950 : // Note that this is done for each outgoing direction of exterior window
7951 0 : int AdjSurfNum = s_surf->Surface(BackSurfaceNumber).ExtBoundCond;
7952 0 : if (AdjSurfNum > 0) {
7953 0 : int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
7954 0 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) +=
7955 0 : CFDirBoverlap(IBack, CurTrnDir) * s_surf->SurfaceWindow(BackSurfaceNumber)
7956 0 : .ComplexFen.State(CurBackState)
7957 0 : .IntegratedBkTrans(bestBackTrn);
7958 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfaceNumber) +=
7959 0 : CFDirBoverlap(IBack, CurTrnDir) *
7960 0 : s_surf->SurfaceWindow(BackSurfaceNumber)
7961 0 : .ComplexFen.State(CurBackState)
7962 0 : .IntegratedBkTrans(bestBackTrn) *
7963 0 : state.dataEnvrn->BeamSolarRad; //[W]
7964 0 : s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfaceNumber) =
7965 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfaceNumber) * state.dataGlobal->TimeStepZoneSec;
7966 : }
7967 : }
7968 : }
7969 : } else {
7970 0 : if (constrBack.TransDiff <= 0.0) {
7971 : // Do not take into account this window if it is scheduled for surface gains
7972 0 : Real64 AbsIntSurf = constrBack.InsideAbsorpSolar;
7973 0 : s_surf->SurfOpaqAI(BackSurfaceNumber) +=
7974 0 : CFBoverlap(IBack) * AbsIntSurf / s_surf->Surface(BackSurfaceNumber).Area;
7975 0 : BABSZone += CFBoverlap(IBack) * AbsIntSurf;
7976 : } else {
7977 : // Code for mixed windows goes here. It is same as above code for "ordinary" windows.
7978 : // Try to do something which will not produce duplicate code.
7979 : }
7980 : }
7981 : }
7982 : }
7983 :
7984 0 : if (allocated(CFBoverlap)) CFBoverlap.deallocate();
7985 0 : if (allocated(CFDirBoverlap)) CFDirBoverlap.deallocate();
7986 : }
7987 :
7988 0 : } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
7989 :
7990 0 : for (int IBack = 1; IBack <= state.dataBSDFWindow->MaxBkSurf; ++IBack) {
7991 : int BackSurfNum =
7992 0 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
7993 0 : if (BackSurfNum == 0) break; // No more irradiated back surfaces for this exterior window
7994 0 : if (s_surf->SurfWinWindowModelType(IBack) != WindowModel::EQL) continue; // only EQL back window is allowed
7995 :
7996 0 : int ConstrNumBack = s_surf->Surface(BackSurfNum).Construction;
7997 0 : auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
7998 0 : int NBackGlass = constrBack.TotGlassLayers;
7999 : // Irradiated (overlap) area for this back surface, projected onto window plane
8000 : // (includes effect of shadowing on exterior window)
8001 :
8002 : Real64 AOverlap =
8003 0 : state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
8004 0 : Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
8005 :
8006 0 : if (constrBack.TransDiff <= 0.0) {
8007 :
8008 : // Back surface is opaque interior or exterior wall
8009 0 : Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
8010 0 : s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
8011 0 : BABSZone += BOverlap * AbsIntSurf; //[m2]
8012 :
8013 : } else {
8014 :
8015 : // Back surface is an interior or exterior window
8016 : // Note that exterior back windows with and without shades are treated as defined.
8017 : // Equivalent Layer window model has no distinction when treating windows with and
8018 : // without shades (interior, inbetween and exterior shades)
8019 : // Note in equivalent layer window model if storm window exists it is defined as part of
8020 : // window construction, hence it does not require a separate treatment
8021 0 : state.dataSolarShading->SurfWinAbsBeamEQL = 0.0;
8022 0 : Real64 TransBeamWin = 0.0; // Beam solar transmittance of a window
8023 0 : Real64 backSurfBeamSolInTrans = 0.0; // Fraction of BeamSolarRad transmitted out through window inside face [W]
8024 :
8025 : // Interior beam absorptance of glass layers and beam transmittance of back exterior &
8026 : // or interior window (treats windows with/without shades as defined) for this timestep
8027 :
8028 : // call the ASHWAT fenestration model for beam radiation here
8029 0 : WindowEquivalentLayer::CalcEQLOpticalProperty(
8030 0 : state, BackSurfNum, SolarArrays::BEAM, state.dataSolarShading->SurfWinAbsSolBeamBackEQL);
8031 0 : auto &CFS = state.dataWindowEquivLayer->CFS;
8032 0 : int EQLNum = constrBack.EQLConsPtr;
8033 0 : state.dataSolarShading->SurfWinAbsBeamEQL({1, CFS(EQLNum).NL}) =
8034 0 : state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, {1, CFS(EQLNum).NL});
8035 : // get the interior beam transmitted through back exterior or interior EQL window
8036 0 : TransBeamWin = state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL + 1);
8037 : // Absorbed by the interior shade layer of back exterior window
8038 0 : if (CFS(EQLNum).L(CFS(EQLNum).NL).LTYPE != LayerType::GLAZE) {
8039 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
8040 0 : BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL) /
8041 0 : (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
8042 0 : BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL);
8043 0 : backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL);
8044 : }
8045 : // Absorbed by the exterior shade layer of back exterior window
8046 0 : if (CFS(EQLNum).L(1).LTYPE != LayerType::GLAZE) {
8047 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
8048 0 : BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1) /
8049 0 : (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
8050 0 : BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1);
8051 0 : backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1);
8052 : }
8053 :
8054 : // determine the number of glass layers
8055 0 : NBackGlass = 0;
8056 0 : for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
8057 0 : if (CFS(EQLNum).L(Lay).LTYPE != LayerType::GLAZE) continue;
8058 0 : ++NBackGlass;
8059 : }
8060 0 : if (NBackGlass >= 2) {
8061 : // If the number of glass is greater than 2, in between glass shade can be present
8062 0 : for (int Lay = 2; Lay <= CFS(EQLNum).NL - 1; ++Lay) {
8063 0 : if (CFS(EQLNum).L(CFS(EQLNum).NL).LTYPE != LayerType::GLAZE) {
8064 : // if there is in between shade glass determine the shade absorptance
8065 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) +=
8066 0 : BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay) /
8067 0 : s_surf->Surface(BackSurfNum).Area;
8068 0 : BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay);
8069 0 : backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay);
8070 : }
8071 : }
8072 : }
8073 : // Sum of interior beam absorbed by all glass layers of back window
8074 0 : Real64 AbsBeamTotWin = 0.0; // Glass layer beam solar absorptance of a shaded window
8075 0 : for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
8076 0 : AbsBeamTotWin += state.dataSolarShading->SurfWinAbsBeamEQL(Lay);
8077 0 : s_surf->SurfWinA(BackSurfNum, Lay) +=
8078 0 : BOverlap * state.dataSolarShading->SurfWinAbsBeamEQL(Lay) /
8079 0 : (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum)); //[-]
8080 : }
8081 :
8082 : // To BABSZon, add interior beam glass absorption and overall beam transmission for this back window
8083 :
8084 0 : BABSZone += BOverlap * (AbsBeamTotWin + TransBeamWin);
8085 0 : backSurfBeamSolInTrans += BOverlap * (AbsBeamTotWin + TransBeamWin);
8086 0 : state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfNum) +=
8087 0 : backSurfBeamSolInTrans * state.dataEnvrn->BeamSolarRad; //[W]
8088 :
8089 : // Interior beam transmitted to adjacent zone through an interior back window (assumed unshaded);
8090 : // this beam radiation is categorized as diffuse radiation in the adjacent zone.
8091 :
8092 0 : int AdjSurfNum = s_surf->Surface(BackSurfNum).ExtBoundCond;
8093 0 : if (AdjSurfNum > 0) {
8094 0 : int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
8095 0 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BOverlap * TransBeamWin; //[m2]
8096 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) +=
8097 0 : BOverlap * TransBeamWin * state.dataEnvrn->BeamSolarRad; //[W]
8098 0 : s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfNum) =
8099 0 : s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
8100 : }
8101 : } // End of check if back surface is opaque or window
8102 0 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) += BOverlap;
8103 0 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(BackSurfNum) =
8104 0 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
8105 : } // End of loop over back surfaces
8106 :
8107 : // *****************************
8108 :
8109 : } // IF (SurfaceWindow(SurfNum)%WindowModelType /= WindowModel:: BSDF) THEN
8110 : } else { // Simple interior solar distribution. All beam from exterior windows falls on floor;
8111 : // some of this is absorbed/transmitted, rest is reflected to other surfaces.
8112 :
8113 187294 : for (int const FloorNum : thisEnclosure.SurfacePtr) {
8114 : // In following, ISABSF is zero except for nominal floor surfaces
8115 174508 : if (state.dataSolarShading->SurfIntAbsFac(FloorNum) <= 0.0 || FloorNum == SurfNum) continue; // Keep only floor surfaces
8116 19225 : int const FlConstrNum = s_surf->SurfActiveConstruction(FloorNum);
8117 :
8118 19225 : Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * InOutProjSLFracMult; //[m2]
8119 19225 : Real64 AbsBeamTotWin = 0.0;
8120 :
8121 19225 : if (state.dataConstruction->Construct(FlConstrNum).TransDiff <= 0.0) {
8122 : // Opaque surface
8123 19224 : s_surf->SurfOpaqAI(FloorNum) +=
8124 19224 : BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) / s_surf->Surface(FloorNum).Area; //[-]
8125 : } else {
8126 : // Window
8127 :
8128 : // Note that diffuse solar absorptance is used here for floor windows even though we're
8129 : // dealing with incident beam radiation. This is because, for this simple interior distribution,
8130 : // the beam radiation from exterior windows is assumed to be uniformly distributed over the
8131 : // floor and so it makes no sense to use directional absorptances. Note also that floor windows
8132 : // are assumed to not have blinds or shades in this calculation.
8133 : // For the case of the floor window a complex fenestration (strange situation) the correct back
8134 : // diffuse layer absorptions have already been put into the construction
8135 :
8136 3 : for (int Lay = 1; Lay <= state.dataConstruction->Construct(FlConstrNum).TotGlassLayers; ++Lay) {
8137 2 : AbsBeamTotWin += state.dataConstruction->Construct(FlConstrNum).AbsDiffBack(Lay);
8138 : }
8139 : // In the following we have to multiply by the AbsDiffBack(Lay)/AbsBeamTotWin ratio to get the
8140 : // layer by layer absorbed beam since ISABSF(FloorNum) is proportional to AbsBeamTotWin
8141 : // (see ComputeIntSolarAbsorpFactors).
8142 :
8143 3 : for (int Lay = 1; Lay <= state.dataConstruction->Construct(FlConstrNum).TotGlassLayers; ++Lay) {
8144 4 : s_surf->SurfWinA(FloorNum, Lay) += state.dataConstruction->Construct(FlConstrNum).AbsDiffBack(Lay) / AbsBeamTotWin *
8145 2 : BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) /
8146 2 : s_surf->Surface(FloorNum).Area; //[-]
8147 : }
8148 : }
8149 :
8150 19225 : BABSZone += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum); //[m2]
8151 :
8152 19225 : int AdjSurfNum = s_surf->Surface(FloorNum).ExtBoundCond;
8153 19225 : if (state.dataConstruction->Construct(FlConstrNum).TransDiff > 0.0 && AdjSurfNum > 0) {
8154 :
8155 : // Window in an interior floor
8156 :
8157 0 : int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
8158 :
8159 : // Contribution (assumed diffuse) to adjacent zone of beam radiation passing
8160 : // through this window
8161 0 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) *
8162 0 : state.dataConstruction->Construct(FlConstrNum).TransDiff /
8163 : AbsBeamTotWin;
8164 :
8165 0 : BABSZone += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) *
8166 0 : state.dataConstruction->Construct(FlConstrNum).TransDiff / AbsBeamTotWin;
8167 : }
8168 :
8169 : } // End of loop over floor sections
8170 : } // End of check on complex vs. simple interior solar distribution
8171 :
8172 : } // End of sunlit fraction > 0 test
8173 : } // End of first loop over surfaces in zone
8174 :
8175 106052 : Real64 BABSZoneSSG = 0.0; // Beam radiation from exterior windows absorbed in a zone (only for scheduled surface gains)
8176 106052 : Real64 BTOTZoneSSG = 0.0; // Solar entering a zone in case of scheduled surface gains
8177 106052 : for (int iSSG = 1; iSSG <= s_surf->TotSurfIncSolSSG; ++iSSG) {
8178 0 : int SurfNum = s_surf->SurfIncSolSSG(iSSG).SurfPtr;
8179 0 : auto &surf = s_surf->Surface(SurfNum);
8180 : // do calculation only if construction number match.
8181 0 : if (s_surf->SurfIncSolSSG(iSSG).ConstrPtr == surf.Construction) {
8182 0 : if (surf.SolarEnclIndex == enclosureNum) {
8183 0 : Real64 AbsIntSurf = state.dataConstruction->Construct(surf.Construction).InsideAbsorpSolar;
8184 : // SolarIntoZone = GetCurrentScheduleValue(SurfIncSolSSG(iSSG)%SchedPtr) * Surface(SurfNum)%Area
8185 0 : Real64 SolarIntoZone = s_surf->SurfIncSolSSG(iSSG).sched->getCurrentVal(); // Solar radiation into zone to current surface
8186 0 : s_surf->SurfOpaqAI(SurfNum) = SolarIntoZone * AbsIntSurf;
8187 0 : BABSZoneSSG += s_surf->SurfOpaqAI(SurfNum) * surf.Area;
8188 0 : BTOTZoneSSG += SolarIntoZone * surf.Area;
8189 : }
8190 : }
8191 : }
8192 106052 : state.dataHeatBal->EnclSolDBSSG(enclosureNum) = BTOTZoneSSG - BABSZoneSSG;
8193 106052 : state.dataHeatBal->EnclSolDB(enclosureNum) = BTOTZone - BABSZone;
8194 :
8195 106052 : if (state.dataHeatBal->EnclSolDB(enclosureNum) < 0.0) {
8196 0 : state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
8197 : }
8198 :
8199 : // Variables for reporting
8200 719225 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
8201 613173 : auto &surf = s_surf->Surface(SurfNum);
8202 :
8203 613173 : Real64 SurfIncSolarMultiplier = surf.IncSolMultiplier;
8204 613173 : Real64 currBeamSolarRad = state.dataEnvrn->BeamSolarRad * SurfIncSolarMultiplier;
8205 613173 : Real64 currDifSolarRad = state.dataEnvrn->DifSolarRad * SurfIncSolarMultiplier;
8206 613173 : Real64 currGndSolarRad = state.dataEnvrn->GndSolarRad * SurfIncSolarMultiplier;
8207 613173 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
8208 78961 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) *= currBeamSolarRad;
8209 78961 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) =
8210 78961 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8211 78961 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) =
8212 78961 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) / (surf.Area + s_surf->SurfWinDividerArea(SurfNum));
8213 : } else { // Simple interior solar distribution. All beam falls on floor.
8214 534212 : if (state.dataSolarShading->SurfIntAbsFac(SurfNum) > 0.0 && surf.HeatTransSurf) {
8215 105174 : if (thisEnclosure.FloorArea > 0.0) {
8216 : // spread onto all floor surfaces, these may or may not be called "floor"
8217 105174 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = currBeamSolarRad * BTOTZone / thisEnclosure.FloorArea;
8218 0 : } else if (thisEnclosure.TotalSurfArea > 0.0) {
8219 : // spread onto all interior surfaces
8220 0 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = currBeamSolarRad * BTOTZone / thisEnclosure.TotalSurfArea;
8221 : } else { // divide be zero otherwise
8222 0 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = 0.0;
8223 : }
8224 : }
8225 534212 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) = surf.Area * state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum);
8226 534212 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) =
8227 534212 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8228 : }
8229 613173 : if (surf.Class == SurfaceClass::Window || surf.Class == SurfaceClass::TDD_Dome) {
8230 :
8231 31116 : s_surf->SurfWinIntBeamAbsByShade(SurfNum) = state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfNum);
8232 31116 : s_surf->SurfWinExtBeamAbsByShade(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum);
8233 :
8234 31116 : if ((surf.ExtBoundCond == ExternalEnvironment) || (surf.ExtBoundCond == OtherSideCondModeledExt)) {
8235 :
8236 31116 : WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum);
8237 31116 : int ShelfNum = s_surf->SurfDaylightingShelfInd(SurfNum);
8238 31116 : int OutShelfSurf = 0;
8239 31116 : if (ShelfNum > 0) { // Outside daylighting shelf
8240 0 : OutShelfSurf = state.dataDaylightingDevicesData->Shelf(ShelfNum).OutSurf;
8241 : }
8242 :
8243 : // This lookup may be avoid if this 2nd surf loop can be combined with the 1st
8244 31116 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
8245 0 : int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
8246 0 : int SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
8247 0 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8248 : // Exterior diffuse solar incident on window (W/m2)
8249 0 : Real64 DifSolarInc = currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(SurfNum2) +
8250 0 : currGndSolarRad * s_surf->Surface(SurfNum2).ViewFactorGround;
8251 : // Exterior diffuse sky solar transmitted by TDD (W/m2)
8252 0 : Real64 SkySolarTrans = currDifSolarRad * TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso) *
8253 0 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum2);
8254 : // Exterior diffuse ground solar transmitted by TDD (W/m2)
8255 0 : Real64 GndSolarTrans = currGndSolarRad * state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolIso *
8256 0 : s_surf->Surface(SurfNum2).ViewFactorGround;
8257 :
8258 0 : s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
8259 0 : s_surf->SurfWinDifSolar(SurfNum) = SkySolarTrans * surf.Area + GndSolarTrans * surf.Area;
8260 0 : s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8261 0 : s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8262 :
8263 0 : s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
8264 0 : s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8265 :
8266 0 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransmittedSolar = s_surf->SurfWinTransSolar(SurfNum);
8267 : // TDDPipe(PipeNum)%TransSolBeam = TBmBm ! Reported above
8268 0 : if (DifSolarInc > 0) {
8269 0 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolDiff = (SkySolarTrans + GndSolarTrans) / DifSolarInc;
8270 : } else {
8271 0 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolDiff = 0.0;
8272 : }
8273 :
8274 31116 : } else if (OutShelfSurf > 0) { // Outside daylighting shelf
8275 : Real64 ShelfSolarRad =
8276 0 : (currBeamSolarRad *
8277 0 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, OutShelfSurf) *
8278 0 : state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, OutShelfSurf) +
8279 0 : currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(OutShelfSurf)) *
8280 0 : state.dataDaylightingDevicesData->Shelf(ShelfNum).OutReflectSol;
8281 :
8282 0 : Real64 DifSolarInc = currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(SurfNum) +
8283 0 : currGndSolarRad * surf.ViewFactorGround +
8284 0 : ShelfSolarRad * state.dataDaylightingDevicesData->Shelf(ShelfNum).ViewFactor;
8285 :
8286 0 : s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
8287 0 : s_surf->SurfWinDifSolar(SurfNum) = DifSolarInc * state.dataSolarShading->SurfWinTransDifSolar(SurfNum);
8288 0 : s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8289 0 : s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8290 :
8291 0 : s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
8292 0 : s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8293 :
8294 : } else { // Regular window
8295 31116 : Real64 SkySolarInc = s_surf->SurfSkySolarInc(SurfNum);
8296 31116 : Real64 GndSolarInc = s_surf->SurfGndSolarInc(SurfNum);
8297 31116 : Real64 DifSolarInc = SkySolarInc + GndSolarInc;
8298 31116 : s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
8299 : // Note: for complex fenestration, SurfWinTransDifSolar has previously been defined using the effective
8300 : // transmittance for sky and ground diffuse radiation (including beam radiation reflected from the ground)
8301 : // so these calculations should be correct
8302 31116 : s_surf->SurfWinDifSolar(SurfNum) = DifSolarInc * state.dataSolarShading->SurfWinTransDifSolar(SurfNum);
8303 31116 : s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8304 31116 : s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8305 31116 : if (ANY_BLIND(ShadeFlag)) {
8306 0 : auto const &surfShade = s_surf->surfShades(SurfNum);
8307 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
8308 0 : assert(matBlind != nullptr);
8309 0 : if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
8310 0 : s_surf->SurfWinDifSolar(SurfNum) = SkySolarInc * state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) +
8311 0 : GndSolarInc * state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum);
8312 0 : s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8313 : }
8314 : }
8315 :
8316 31116 : s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
8317 31116 : s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8318 : }
8319 :
8320 : // added TH 12/9/2009, CR 7907 & 7809
8321 31116 : s_surf->SurfWinBmBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum);
8322 :
8323 31116 : s_surf->SurfWinBmDifSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum);
8324 31116 : s_surf->SurfWinBmBmSolarEnergy(SurfNum) = s_surf->SurfWinBmBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8325 31116 : s_surf->SurfWinBmDifSolarEnergy(SurfNum) = s_surf->SurfWinBmDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8326 :
8327 : // Solar not added by TDD:DOME; added to zone via TDD:DIFFUSER
8328 31116 : if (surf.Class != SurfaceClass::TDD_Dome) {
8329 31116 : state.dataHeatBal->ZoneTransSolar(enclosureNum) += s_surf->SurfWinTransSolar(SurfNum); //[W]
8330 31116 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) =
8331 31116 : state.dataHeatBal->ZoneTransSolar(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8332 31116 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinBmSolar(SurfNum);
8333 31116 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinDifSolar(SurfNum);
8334 31116 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) =
8335 31116 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8336 31116 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) =
8337 31116 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8338 : }
8339 : }
8340 : }
8341 : } // End of second loop over surfaces in zone
8342 :
8343 : } // End of first zone loop
8344 :
8345 : // Add interior window contribution to EnclSolDB
8346 :
8347 177272 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
8348 106052 : state.dataHeatBal->EnclSolDB(enclosureNum) += state.dataHeatBal->EnclSolDBIntWin(enclosureNum);
8349 106052 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum) = state.dataHeatBal->EnclSolDBIntWin(enclosureNum) * state.dataEnvrn->BeamSolarRad;
8350 106052 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclosureNum) =
8351 106052 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8352 : }
8353 :
8354 : // RJH - Calculate initial distribution of diffuse solar transmitted by exterior windows into each zone
8355 : // to all interior surfaces in the zone
8356 : // Includes subsequent transmittance of diffuse solar to adjacent zones through interior windows
8357 71220 : CalcWinTransDifSolInitialDistribution(state);
8358 71220 : }
8359 0 : void CalcAbsorbedOnExteriorOpaqueSurfaces(EnergyPlusData &state)
8360 : {
8361 : // SUBROUTINE INFORMATION:
8362 : // AUTHOR Simon Vidanovic
8363 : // DATE WRITTEN May 2017
8364 : // MODIFIED na
8365 : // RE-ENGINEERED na
8366 :
8367 : // PURPOSE OF THIS SUBROUTINE:
8368 : // Calculates solar energy absorbed on exterior opaque surfaces
8369 :
8370 0 : auto &s_surf = state.dataSurface;
8371 :
8372 0 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
8373 0 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
8374 0 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
8375 0 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
8376 0 : auto &surf = s_surf->Surface(SurfNum);
8377 : // TH added 3/24/2010 while debugging CR 7872
8378 0 : if (!surf.ExtSolar && surf.OriginalClass != SurfaceClass::TDD_Diffuser) continue;
8379 0 : int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
8380 0 : int SurfNum2 = SurfNum;
8381 0 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
8382 0 : int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
8383 0 : SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
8384 : }
8385 0 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8386 0 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8387 :
8388 : //-------------------------------------------------------------------------
8389 : // EXTERIOR BEAM SOLAR RADIATION ABSORBED ON THE OUTSIDE OF OPAQUE SURFACES
8390 : //-------------------------------------------------------------------------
8391 :
8392 0 : if (SunLitFract > 0.0 && state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) {
8393 0 : s_surf->SurfOpaqAO(SurfNum) = state.dataConstruction->Construct(ConstrNum).OutsideAbsorpSolar * CosInc * SunLitFract;
8394 :
8395 : // Note: movable insulation, if present, is accounted for in subr. InitIntSolarDistribution,
8396 : // where SurfQRadSWOutMvIns is calculated from SurfOpaqQRadSWOutAbs and insulation solar absorptance
8397 : }
8398 : }
8399 : }
8400 : }
8401 0 : }
8402 :
8403 0 : void CalcInteriorSolarDistributionWCESimple(EnergyPlusData &state)
8404 : {
8405 :
8406 : // SUBROUTINE INFORMATION:
8407 : // AUTHOR Simon Vidanovic
8408 : // DATE WRITTEN May 2017
8409 :
8410 : // PURPOSE OF THIS SUBROUTINE:
8411 : // For a time step, calculates solar radiation absorbed by window layers, sky and diffuse solar
8412 : // gain into zone from exterior window, beam solar on exterior window transmitted as beam and/or diffuse
8413 : // and interior beam from exterior window that is absorbed/transmitted by back surfaces
8414 :
8415 : using namespace MultiLayerOptics;
8416 :
8417 0 : auto &s_surf = state.dataSurface;
8418 :
8419 0 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
8420 0 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
8421 0 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
8422 0 : int const firstSurf = thisSpace.HTSurfaceFirst;
8423 0 : int const lastSurf = thisSpace.HTSurfaceLast;
8424 0 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
8425 0 : s_surf->SurfOpaqAI(surfNum) = 0.0;
8426 0 : s_surf->SurfOpaqAO(surfNum) = 0.0;
8427 : }
8428 : }
8429 : }
8430 :
8431 0 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
8432 :
8433 0 : Real64 BABSZone = 0;
8434 0 : Real64 BTOTZone = 0;
8435 0 : state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
8436 0 : state.dataHeatBal->EnclSolDBIntWin(enclosureNum) = 0.0;
8437 0 : state.dataHeatBal->ZoneTransSolar(enclosureNum) = 0;
8438 0 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) = 0;
8439 0 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) = 0;
8440 0 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) = 0;
8441 0 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) = 0;
8442 0 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) = 0;
8443 0 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
8444 :
8445 0 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
8446 0 : auto &surf = s_surf->Surface(SurfNum);
8447 0 : if (surf.Class != SurfaceClass::Window) continue;
8448 0 : int SurfNum2 = 0;
8449 0 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
8450 0 : int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
8451 0 : SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
8452 : } else {
8453 0 : SurfNum2 = SurfNum;
8454 : }
8455 0 : auto &window = s_surf->SurfaceWindow(SurfNum2);
8456 0 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2); // Note: surfnum 2
8457 0 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8458 :
8459 0 : std::pair<Real64, Real64> incomingAngle = getSunWCEAngles(state, SurfNum2, BSDFDirection::Incoming);
8460 0 : Real64 Theta = incomingAngle.first;
8461 0 : Real64 Phi = incomingAngle.second;
8462 :
8463 0 : int ConstrNum = s_surf->Surface(SurfNum2).Construction;
8464 0 : if (s_surf->Surface(SurfNum2).activeShadedConstruction > 0) ConstrNum = s_surf->Surface(SurfNum2).activeShadedConstruction;
8465 : auto aLayer = // (AUTO_OK_OBJ)
8466 0 : CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, WavelengthRange::Solar, ConstrNum);
8467 :
8468 : ///////////////////////////////////////////////
8469 : // Solar absorbed in window layers
8470 : ///////////////////////////////////////////////
8471 0 : if (state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2) > 0.0) {
8472 0 : size_t numOfLayers = aLayer->getNumOfLayers();
8473 0 : if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
8474 0 : int CurrentState = s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState;
8475 0 : auto &cplxState = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(CurrentState);
8476 0 : for (size_t Lay = 1; Lay <= numOfLayers; ++Lay) {
8477 : // Simon: Important note about this equation is to use BeamSolarRad and not SurfQRadSWOutIncident
8478 : // is because BeamSolarRad is direct normal radiation (looking at the Sun) while SurfRadSWOutIncident
8479 : // is normal to window incidence. Since BSDF coefficients are taking into account angle of incidence,
8480 : // BeamSolarRad should be used in this case
8481 0 : state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) =
8482 0 : cplxState.WinSkyFtAbs(Lay) * s_surf->SurfSkySolarInc(SurfNum2) +
8483 0 : cplxState.WinSkyGndAbs(Lay) * s_surf->SurfGndSolarInc(SurfNum2) +
8484 0 : s_surf->SurfWinA(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad +
8485 0 : s_surf->SurfWinACFOverlap(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad;
8486 0 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfNum, Lay) = state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) * surf.Area;
8487 0 : s_surf->SurfWinADiffFront(SurfNum, Lay) = cplxState.WinSkyGndAbs(Lay);
8488 : }
8489 : } else {
8490 0 : for (size_t Lay = 1; Lay <= numOfLayers; ++Lay) {
8491 0 : Real64 AbWinBeam = aLayer->getAbsorptanceLayer(Lay, Side::Front, ScatteringSimple::Direct, Theta, Phi) *
8492 0 : window.OutProjSLFracMult[state.dataGlobal->HourOfDay];
8493 0 : Real64 AbWinDiffFront = aLayer->getAbsorptanceLayer(Lay, Side::Front, ScatteringSimple::Diffuse, Theta, Phi);
8494 : // Real64 AbWinDiffBack = aLayer->getAbsorptanceLayer(Lay, Side::Back, ScatteringSimple::Diffuse,
8495 : // Theta, Phi);
8496 :
8497 : // Simon: This should not be multiplied with cosine of incident angle. This however gives same
8498 : // results as BSDF and Winkelmann models.
8499 0 : s_surf->SurfWinA(SurfNum, Lay) =
8500 0 : AbWinBeam * CosInc * SunLitFract * s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
8501 0 : s_surf->SurfWinADiffFront(SurfNum, Lay) = AbWinDiffFront;
8502 :
8503 : // Simon: Same not as for BSDF. Normal solar radiation should be taken here because angle of
8504 : // incidence is already taken into account
8505 0 : Real64 absBeam = s_surf->SurfWinA(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad;
8506 : Real64 absDiff =
8507 0 : s_surf->SurfWinADiffFront(SurfNum, Lay) * (s_surf->SurfSkySolarInc(SurfNum2) + s_surf->SurfGndSolarInc(SurfNum2));
8508 0 : state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) = (absBeam + absDiff);
8509 0 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfNum, Lay) = state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) * surf.Area;
8510 : }
8511 : }
8512 : }
8513 :
8514 : ////////////////////////////////////////////////////////////////////
8515 : // SKY AND GROUND DIFFUSE SOLAR GAIN INTO ZONE FROM EXTERIOR WINDOW
8516 : ////////////////////////////////////////////////////////////////////
8517 0 : constexpr Real64 minLambda{0.3};
8518 0 : constexpr Real64 maxLambda{2.5};
8519 : const Real64 Tdiff =
8520 0 : aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DiffuseDiffuse, Theta, Phi);
8521 0 : state.dataConstruction->Construct(ConstrNum).TransDiff = Tdiff;
8522 0 : Real64 EnclSolDSWin = s_surf->SurfSkySolarInc(SurfNum2) * Tdiff * s_surf->Surface(SurfNum2).Area;
8523 0 : if ((state.dataEnvrn->DifSolarRad != 0)) {
8524 0 : EnclSolDSWin /= state.dataEnvrn->DifSolarRad;
8525 : } else {
8526 0 : EnclSolDSWin /= 1e-8;
8527 : }
8528 :
8529 0 : Real64 EnclSolDGWin = s_surf->SurfGndSolarInc(SurfNum2) * Tdiff * s_surf->Surface(SurfNum2).Area;
8530 0 : (state.dataEnvrn->GndSolarRad != 0) ? EnclSolDGWin /= state.dataEnvrn->GndSolarRad : EnclSolDGWin /= 1e-8;
8531 :
8532 : ////////////////////////////////////////////////////////////////////
8533 : // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
8534 : ////////////////////////////////////////////////////////////////////
8535 0 : Real64 TBmBm = aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DirectDirect, Theta, Phi);
8536 0 : Real64 TBmDif = aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DirectDiffuse, Theta, Phi);
8537 0 : Real64 SurfWinTransBmBmSolar = TBmBm * SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
8538 0 : Real64 SurfWinTransBmDifSolar = TBmDif * SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
8539 0 : BTOTZone += SurfWinTransBmBmSolar + SurfWinTransBmDifSolar;
8540 :
8541 0 : Real64 DifSolarRadiation = s_surf->SurfSkySolarInc(SurfNum2) + s_surf->SurfGndSolarInc(SurfNum2);
8542 0 : s_surf->SurfWinBmSolar(SurfNum) = state.dataEnvrn->BeamSolarRad * (TBmBm + TBmDif) * surf.Area * CosInc;
8543 0 : s_surf->SurfWinDifSolar(SurfNum) = DifSolarRadiation * Tdiff * surf.Area;
8544 0 : s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8545 0 : s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8546 0 : s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum);
8547 0 : s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8548 :
8549 : // Add beam solar absorbed by outside reveal to outside of window's base surface.
8550 : // Add beam solar absorbed by inside reveal to inside of window's base surface.
8551 : // This ignores 2-D heat transfer effects.
8552 0 : int BaseSurfNum = surf.BaseSurf;
8553 0 : s_surf->SurfOpaqAI(BaseSurfNum) = s_surf->SurfWinBmSolAbsdInsReveal(SurfNum2) / s_surf->Surface(BaseSurfNum).Area;
8554 0 : s_surf->SurfOpaqAO(BaseSurfNum) = s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum2) / s_surf->Surface(BaseSurfNum).Area;
8555 :
8556 : ////////////////////////////////////////////////////////////////////
8557 : // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
8558 : ////////////////////////////////////////////////////////////////////
8559 0 : Real64 TBm = TBmBm;
8560 : // Correction for beam absorbed by inside reveal
8561 0 : Real64 TBmDenom = SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
8562 0 : if (TBmDenom != 0.0) { // when =0.0, no correction
8563 0 : TBm -= s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / TBmDenom;
8564 : }
8565 :
8566 0 : TBm = max(0.0, TBm);
8567 0 : TBm *= surf.IncSolMultiplier;
8568 :
8569 0 : int NumOfBackSurf = state.dataShadowComb->ShadowComb(BaseSurfNum).NumBackSurf;
8570 :
8571 0 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
8572 0 : for (int IBack = 1; IBack <= NumOfBackSurf; ++IBack) {
8573 :
8574 : int const BackSurfNum =
8575 0 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
8576 :
8577 0 : if (BackSurfNum == 0) break; // No more irradiated back surfaces for this exterior window
8578 0 : int ConstrNumBack = s_surf->Surface(BackSurfNum).Construction;
8579 0 : auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
8580 : // NBackGlass = Construct( ConstrNumBack ).TotGlassLayers;
8581 : // Irradiated (overlap) area for this back surface, projected onto window plane
8582 : // (includes effect of shadowing on exterior window)
8583 0 : Real64 AOverlap = state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
8584 0 : Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
8585 :
8586 0 : if (constrBack.TransDiff <= 0.0) {
8587 : // Back surface is opaque interior or exterior wall
8588 :
8589 0 : Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
8590 0 : s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
8591 0 : BABSZone += BOverlap * AbsIntSurf; //[m2]
8592 : }
8593 : }
8594 : } else {
8595 0 : for (int const FloorNum : thisEnclosure.SurfacePtr) {
8596 : // In following, ISABSF is zero except for nominal floor surfaces
8597 0 : if (!s_surf->Surface(FloorNum).HeatTransSurf) continue;
8598 0 : if (state.dataSolarShading->SurfIntAbsFac(FloorNum) <= 0.0 || FloorNum == SurfNum) continue; // Keep only floor surfaces
8599 :
8600 0 : Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay]; //[m2]
8601 :
8602 0 : if (state.dataConstruction->Construct(s_surf->Surface(FloorNum).Construction).TransDiff <= 0.0) {
8603 : // Opaque surface
8604 0 : s_surf->SurfOpaqAI(FloorNum) +=
8605 0 : BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) / s_surf->Surface(FloorNum).Area; //[-]
8606 : }
8607 : }
8608 : }
8609 0 : state.dataHeatBal->ZoneTransSolar(enclosureNum) += s_surf->SurfWinTransSolar(SurfNum); //[W]
8610 0 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) =
8611 0 : state.dataHeatBal->ZoneTransSolar(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8612 0 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinBmSolar(SurfNum);
8613 0 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinDifSolar(SurfNum);
8614 0 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) =
8615 0 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8616 0 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) =
8617 0 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8618 0 : }
8619 0 : state.dataHeatBal->EnclSolDB(enclosureNum) = BTOTZone - BABSZone;
8620 : }
8621 0 : }
8622 :
8623 0 : int WindowScheduledSolarAbs(EnergyPlusData &state,
8624 : int const SurfNum, // Surface number
8625 : int const ConstNum // Construction number
8626 : )
8627 : {
8628 : // SUBROUTINE INFORMATION:
8629 : // AUTHOR Simon Vidanovic
8630 : // DATE WRITTEN June 2013
8631 :
8632 : // PURPOSE OF THIS SUBROUTINE:
8633 : // Returns scheduled surface gain object for given surface-construction combination
8634 0 : auto &s_surf = state.dataSurface;
8635 :
8636 0 : for (int i = 1; i <= s_surf->TotFenLayAbsSSG; ++i) {
8637 0 : if ((s_surf->FenLayAbsSSG(i).SurfPtr == SurfNum) && (s_surf->FenLayAbsSSG(i).ConstrPtr == ConstNum)) {
8638 0 : return i;
8639 : }
8640 : }
8641 :
8642 0 : return 0;
8643 : }
8644 :
8645 582049 : int SurfaceScheduledSolarInc(EnergyPlusData &state,
8646 : int const SurfNum, // Surface number
8647 : int const ConstNum // Construction number
8648 : )
8649 : {
8650 : // SUBROUTINE INFORMATION:
8651 : // AUTHOR Simon Vidanovic
8652 : // DATE WRITTEN June 2013
8653 :
8654 : // PURPOSE OF THIS SUBROUTINE:
8655 : // Returns scheduled surface gain pointer for given surface-construction combination
8656 :
8657 582049 : auto &s_surf = state.dataSurface;
8658 :
8659 582061 : for (int i = 1; i <= s_surf->TotSurfIncSolSSG; ++i) {
8660 15 : if ((s_surf->SurfIncSolSSG(i).SurfPtr == SurfNum) && (s_surf->SurfIncSolSSG(i).ConstrPtr == ConstNum)) {
8661 3 : return i;
8662 : }
8663 : }
8664 :
8665 582046 : return 0;
8666 : }
8667 :
8668 3643 : void PerformSolarCalculations(EnergyPlusData &state)
8669 : {
8670 :
8671 : // SUBROUTINE INFORMATION:
8672 : // AUTHOR Linda K. Lawrie
8673 : // DATE WRITTEN July 1999
8674 : // MODIFIED Sept 2003, FCW: add calls to CalcBeamSolDiffuseReflFactors and
8675 : // CalcBeamSolSpecularReflFactors
8676 : // Jan 2004, FCW: call CalcDayltgCoefficients if storm window status on
8677 : // any window has changed
8678 : // RE-ENGINEERED na
8679 :
8680 : // PURPOSE OF THIS SUBROUTINE:
8681 : // This subroutine determines if new solar/shading calculations need
8682 : // to be performed and calls the proper routines to do the job.
8683 :
8684 : // METHODOLOGY EMPLOYED:
8685 : // Users are allowed to enter a value for number of days in each period that
8686 : // will be used for calculating solar. (Later, this could be more complicated as
8687 : // in allowing a number of days in a month or something). Using this value or the
8688 : // default (20 days) if nothing is entered by the user, the routine will use the
8689 : // number of days left to determine if a new set of calculations should be done.
8690 : // The calculations use the average of "equation of time" and "solar declination"
8691 : // to perform the calculations.
8692 :
8693 : // REFERENCES:
8694 : // na
8695 :
8696 : // Using/Aliasing
8697 : using Dayltg::CalcDayltgCoefficients;
8698 : // Locals
8699 : // SUBROUTINE ARGUMENT DEFINITIONS:
8700 : // na
8701 :
8702 : // SUBROUTINE PARAMETER DEFINITIONS:
8703 : // na
8704 :
8705 : // INTERFACE BLOCK SPECIFICATIONS
8706 : // na
8707 :
8708 : // DERIVED TYPE DEFINITIONS
8709 : // na
8710 :
8711 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
8712 : Real64 SumDec;
8713 : Real64 SumET;
8714 : Real64 AvgEqOfTime;
8715 : Real64 AvgSinSolarDeclin;
8716 : Real64 AvgCosSolarDeclin;
8717 : int PerDayOfYear;
8718 : int Count;
8719 : Real64 SinDec;
8720 : Real64 EqTime;
8721 : // not used INTEGER SurfNum
8722 :
8723 3643 : auto &s_surf = state.dataSurface;
8724 : // Calculate sky diffuse shading
8725 :
8726 3643 : if (state.dataGlobal->BeginSimFlag) {
8727 104 : state.dataSolarShading->CalcSkyDifShading = true;
8728 104 : SkyDifSolarShading(state); // Calculate factors for shading of sky diffuse solar
8729 104 : state.dataSolarShading->CalcSkyDifShading = false;
8730 : }
8731 :
8732 3643 : if (state.dataGlobal->BeginEnvrnFlag) {
8733 481 : state.dataSolarShading->ShadowingDaysLeft = 0;
8734 : }
8735 :
8736 3643 : if (state.dataSolarShading->ShadowingDaysLeft <= 0 || state.dataSysVars->DetailedSolarTimestepIntegration) {
8737 :
8738 1836 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
8739 : // Perform calculations.
8740 478 : state.dataSolarShading->ShadowingDaysLeft = state.dataSolarShading->ShadowingCalcFrequency;
8741 478 : if (state.dataGlobal->DayOfSim + state.dataSolarShading->ShadowingDaysLeft > state.dataGlobal->NumOfDayInEnvrn) {
8742 458 : state.dataSolarShading->ShadowingDaysLeft = state.dataGlobal->NumOfDayInEnvrn - state.dataGlobal->DayOfSim + 1;
8743 : }
8744 :
8745 : // Calculate average Equation of Time, Declination Angle for this period
8746 :
8747 478 : if (!state.dataGlobal->WarmupFlag) {
8748 1 : if (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather) {
8749 1 : DisplayString(state, "Updating Shadowing Calculations, Start Date=" + state.dataEnvrn->CurMnDyYr);
8750 : } else {
8751 0 : DisplayString(state, "Updating Shadowing Calculations, Start Date=" + state.dataEnvrn->CurMnDy);
8752 : }
8753 1 : state.dataReportFlag->DisplayPerfSimulationFlag = true;
8754 : }
8755 :
8756 478 : PerDayOfYear = state.dataEnvrn->DayOfYear;
8757 478 : SumDec = 0.0;
8758 478 : SumET = 0.0;
8759 1336 : for (Count = 1; Count <= state.dataSolarShading->ShadowingDaysLeft; ++Count) {
8760 858 : SUN3(PerDayOfYear, SinDec, EqTime);
8761 858 : SumDec += SinDec;
8762 858 : SumET += EqTime;
8763 858 : ++PerDayOfYear;
8764 : }
8765 :
8766 : // Compute Period Values
8767 478 : AvgSinSolarDeclin = SumDec / double(state.dataSolarShading->ShadowingDaysLeft);
8768 478 : AvgCosSolarDeclin = std::sqrt(1.0 - pow_2(AvgSinSolarDeclin));
8769 478 : AvgEqOfTime = SumET / double(state.dataSolarShading->ShadowingDaysLeft);
8770 : } else {
8771 1358 : SUN3(state.dataEnvrn->DayOfYear, AvgSinSolarDeclin, AvgEqOfTime);
8772 1358 : AvgCosSolarDeclin = std::sqrt(1.0 - pow_2(AvgSinSolarDeclin));
8773 : // trigger display of progress in the simulation every two weeks
8774 1358 : if (!state.dataGlobal->WarmupFlag && state.dataGlobal->BeginDayFlag && (state.dataGlobal->DayOfSim % 14 == 0)) {
8775 0 : state.dataReportFlag->DisplayPerfSimulationFlag = true;
8776 : }
8777 : }
8778 :
8779 1836 : CalcPerSolarBeam(state, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
8780 :
8781 : // Calculate factors for solar reflection
8782 1836 : if (s_surf->CalcSolRefl) {
8783 0 : CalcBeamSolDiffuseReflFactors(state);
8784 0 : CalcBeamSolSpecularReflFactors(state);
8785 0 : if (state.dataGlobal->BeginSimFlag) CalcSkySolDiffuseReflFactors(state);
8786 : }
8787 : // Calculate daylighting coefficients
8788 1836 : CalcDayltgCoefficients(state);
8789 : }
8790 :
8791 3643 : if (!state.dataGlobal->WarmupFlag) {
8792 417 : --state.dataSolarShading->ShadowingDaysLeft;
8793 : }
8794 :
8795 : // Recalculate daylighting coefficients if storm window has been added
8796 : // or removed from one or more windows at beginning of day
8797 5005 : if (state.dataDayltg->TotWindowsWithDayl > 0 && !state.dataGlobal->BeginSimFlag && !state.dataGlobal->BeginEnvrnFlag &&
8798 5005 : !state.dataGlobal->WarmupFlag && s_surf->TotStormWin > 0 && state.dataHeatBal->StormWinChangeThisDay) {
8799 0 : CalcDayltgCoefficients(state);
8800 : }
8801 3643 : }
8802 :
8803 8010 : void SHDRVL(EnergyPlusData &state,
8804 : int const HTSS, // Heat transfer surface number of the subsurface
8805 : int const SBSNR, // Subsurface number
8806 : int const Hour,
8807 : int const TS)
8808 : {
8809 :
8810 : // SUBROUTINE INFORMATION:
8811 : // AUTHOR Legacy Code
8812 : // DATE WRITTEN
8813 : // MODIFIED May 2002 (FCW): allow triangular windows to have reveal.
8814 : // RE-ENGINEERED Lawrie, Oct 2000
8815 :
8816 : // PURPOSE OF THIS SUBROUTINE:
8817 : // This subroutine computes the shadowing from a reveal onto a subsurface.
8818 :
8819 : // REFERENCES:
8820 : // BLAST/IBLAST code, original author George Walton
8821 :
8822 : int NVS; // Number of vertices
8823 :
8824 8010 : int constexpr None(0); // for use with RevealStatus
8825 8010 : int constexpr EntireWindowShadedByReveal(1); // for use with RevealStatus
8826 8010 : int constexpr WindowShadedOnlyByReveal(2); // for use with RevealStatus
8827 :
8828 : Real64 A; // Area
8829 : Real64 R; // Depth of the reveal (m)
8830 : int I; // Loop control
8831 : int N; // Vertex number
8832 : int NS1; // Locations in homogeneous coordinate array
8833 : int NS2;
8834 : // note, below dimensions not changed because subsurface still max 4
8835 8010 : Array1D<Real64> XVT(5); // Projected X coordinates of vertices
8836 8010 : Array1D<Real64> YVT(5); // Projected Y coordinates of vertices
8837 : bool RevealStatusSet; // Used to control flow through this subroutine.
8838 : // Certain operations performed only if reveal status not yet set.
8839 : int RevealStatus; // Status of the reveal, takes the parameter values above
8840 :
8841 8010 : auto &s_surf = state.dataSurface;
8842 :
8843 8010 : RevealStatus = None;
8844 8010 : RevealStatusSet = false;
8845 :
8846 8010 : if (!state.dataSolarShading->CalcSkyDifShading) {
8847 4994 : state.dataSolarShading->SurfWinRevealStatus(Hour, TS, SBSNR) = None;
8848 : }
8849 :
8850 8010 : R = s_surf->Surface(SBSNR).Reveal;
8851 8010 : if (R <= 0.0) {
8852 8010 : RevealStatus = None;
8853 8010 : RevealStatusSet = true;
8854 : }
8855 :
8856 8010 : if (!RevealStatusSet) {
8857 :
8858 0 : state.dataSolarShading->FRVLHC = state.dataSolarShading->LOCHCA + 1;
8859 0 : ++state.dataSolarShading->LOCHCA;
8860 0 : NVS = s_surf->Surface(SBSNR).Sides;
8861 :
8862 : // Currently (06May02) windows are either rectangles (NVS=4) or triangles (NVS=3)
8863 :
8864 0 : if (NVS == 4) { // Rectangular subsurface
8865 :
8866 : // Determine vertices of reveal.
8867 : // Project the subsurface up to the plane of the wall.
8868 :
8869 0 : XVT(1) = s_surf->ShadeV(SBSNR).XV(1) + R * max(state.dataSolarShading->XShadowProjection, 0.0);
8870 0 : XVT(2) = s_surf->ShadeV(SBSNR).XV(2) + R * max(state.dataSolarShading->XShadowProjection, 0.0);
8871 0 : XVT(3) = s_surf->ShadeV(SBSNR).XV(3) + R * min(state.dataSolarShading->XShadowProjection, 0.0);
8872 0 : XVT(4) = s_surf->ShadeV(SBSNR).XV(4) + R * min(state.dataSolarShading->XShadowProjection, 0.0);
8873 0 : YVT(1) = s_surf->ShadeV(SBSNR).YV(1) + R * min(state.dataSolarShading->YShadowProjection, 0.0);
8874 0 : YVT(2) = s_surf->ShadeV(SBSNR).YV(2) + R * max(state.dataSolarShading->YShadowProjection, 0.0);
8875 0 : YVT(3) = s_surf->ShadeV(SBSNR).YV(3) + R * max(state.dataSolarShading->YShadowProjection, 0.0);
8876 0 : YVT(4) = s_surf->ShadeV(SBSNR).YV(4) + R * min(state.dataSolarShading->YShadowProjection, 0.0);
8877 :
8878 : // Check for complete shadowing.
8879 :
8880 0 : if ((XVT(2) >= XVT(3)) || (YVT(2) >= YVT(1))) {
8881 :
8882 0 : RevealStatus = EntireWindowShadedByReveal;
8883 0 : RevealStatusSet = true;
8884 :
8885 : } else {
8886 : // Re-order vertices to clockwise.
8887 :
8888 0 : for (N = 1; N <= NVS; ++N) {
8889 0 : state.dataSolarShading->XVS(N) = XVT(NVS + 1 - N);
8890 0 : state.dataSolarShading->YVS(N) = YVT(NVS + 1 - N);
8891 : }
8892 :
8893 : // Transform to homogeneous coordinates
8894 :
8895 0 : HTRANS1(state, state.dataSolarShading->FRVLHC, NVS);
8896 0 : state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC) = -state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC);
8897 0 : state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC) = 1.0;
8898 :
8899 0 : if (state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC) <= 0.0) {
8900 0 : RevealStatus = EntireWindowShadedByReveal;
8901 0 : RevealStatusSet = true;
8902 : }
8903 : }
8904 :
8905 0 : } else if (NVS == 3) { // Triangular window
8906 :
8907 : // Project window to outside plane of parent surface
8908 :
8909 0 : for (N = 1; N <= 3; ++N) {
8910 0 : XVT(N) = s_surf->ShadeV(SBSNR).XV(N) + R * state.dataSolarShading->XShadowProjection;
8911 0 : YVT(N) = s_surf->ShadeV(SBSNR).YV(N) + R * state.dataSolarShading->YShadowProjection;
8912 : }
8913 :
8914 : // Find the overlap between the original window and the projected window
8915 : // Put XVT,YVT in clockwise order
8916 :
8917 0 : for (N = 1; N <= NVS; ++N) {
8918 0 : state.dataSolarShading->XVS(N) = XVT(NVS + 1 - N);
8919 0 : state.dataSolarShading->YVS(N) = YVT(NVS + 1 - N);
8920 : }
8921 :
8922 : // Transform to homogeneous coordinates
8923 :
8924 0 : NS1 = state.dataSolarShading->LOCHCA + 1;
8925 0 : state.dataSolarShading->LOCHCA = NS1;
8926 0 : HTRANS1(state, NS1, NVS);
8927 :
8928 : // Put XV,YV in clockwise order
8929 :
8930 0 : for (N = 1; N <= NVS; ++N) {
8931 0 : state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(NVS + 1 - N);
8932 0 : state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(NVS + 1 - N);
8933 : }
8934 :
8935 : // Transform to homogeneous coordinates
8936 :
8937 0 : NS2 = state.dataSolarShading->LOCHCA + 1;
8938 0 : state.dataSolarShading->LOCHCA = NS2;
8939 0 : HTRANS1(state, NS2, NVS);
8940 0 : state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC) = 1.0;
8941 :
8942 : // Find overlap
8943 :
8944 0 : DeterminePolygonOverlap(state, NS1, NS2, state.dataSolarShading->FRVLHC);
8945 0 : if (state.dataSolarShading->OverlapStatus == NoOverlap) {
8946 0 : RevealStatus = EntireWindowShadedByReveal;
8947 0 : RevealStatusSet = true;
8948 : }
8949 : }
8950 : }
8951 :
8952 8010 : if (!RevealStatusSet) {
8953 :
8954 : // Check for no shadows on window.
8955 :
8956 0 : if (state.dataSolarShading->NSBSHC <= 1) {
8957 0 : RevealStatus = WindowShadedOnlyByReveal;
8958 0 : RevealStatusSet = true;
8959 : } else {
8960 : // Reduce all previous shadows to size of reveal opening.
8961 0 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FRVLHC;
8962 0 : MULTOL(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->FSBSHC, state.dataSolarShading->NSBSHC - 1);
8963 0 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
8964 0 : RevealStatus = None;
8965 0 : RevealStatusSet = true;
8966 : } else {
8967 0 : state.dataSolarShading->NRVLHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FRVLHC + 1;
8968 0 : if (state.dataSolarShading->NRVLHC <= 1) {
8969 0 : RevealStatus = WindowShadedOnlyByReveal;
8970 0 : RevealStatusSet = true;
8971 : }
8972 : }
8973 : }
8974 : }
8975 :
8976 8010 : if (!RevealStatusSet) {
8977 : // Compute sunlit area.
8978 0 : A = state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC);
8979 0 : for (I = 2; I <= state.dataSolarShading->NRVLHC; ++I) {
8980 0 : A += state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC - 1 + I) *
8981 0 : (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC - 1 + I));
8982 : }
8983 0 : state.dataSolarShading->SurfSunlitArea(HTSS) = A;
8984 : }
8985 :
8986 8010 : if ((RevealStatus == EntireWindowShadedByReveal) || (state.dataSolarShading->SurfSunlitArea(HTSS) < 0.0)) {
8987 0 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0; // Window entirely shaded by reveal.
8988 8010 : } else if (RevealStatus == WindowShadedOnlyByReveal) {
8989 0 : state.dataSolarShading->SurfSunlitArea(HTSS) =
8990 0 : state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC); // Window shaded only by reveal.
8991 : }
8992 :
8993 8010 : if (!state.dataSolarShading->CalcSkyDifShading) {
8994 4994 : state.dataSolarShading->SurfWinRevealStatus(Hour, TS, SBSNR) = RevealStatus;
8995 : }
8996 8010 : }
8997 :
8998 90268 : void SHDSBS(EnergyPlusData &state,
8999 : int const iHour, // Hour Index
9000 : int const CurSurf,
9001 : int const NBKS, // Number of back surfaces
9002 : int const NSBS, // Number of subsurfaces
9003 : int const HTS, // Heat transfer surface number of the general receiving surf
9004 : int const TS // Time step Index
9005 : )
9006 : {
9007 :
9008 : // SUBROUTINE INFORMATION:
9009 : // AUTHOR Legacy Code
9010 : // DATE WRITTEN
9011 : // MODIFIED FCW, Oct 2002: Surface%Area --> Surface%Area + SurfaceWindow%DividerArea
9012 : // in calculation of SunlitFracWithoutReveal (i.e., use full window area, not
9013 : // just glass area.
9014 : // TH, May 2009: Bug fixed to address part of CR 7596 - inside reveals
9015 : // causing high cooling loads
9016 : // RE-ENGINEERED Lawrie, Oct 2000
9017 :
9018 : // PURPOSE OF THIS SUBROUTINE:
9019 : // This subroutine determines the shadowing on subsurfaces and
9020 : // revises the base surface area accordingly. It also computes
9021 : // the effect of transparent subsurfaces.
9022 :
9023 : // REFERENCES:
9024 : // BLAST/IBLAST code, original author George Walton
9025 :
9026 : Real64 A; // Area
9027 : int I; // Loop control
9028 : int J; // Loop control
9029 : int K; // Window construction number
9030 : int N; // Vertex number
9031 : Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
9032 : // For windows, includes divider area
9033 : // REAL(r64) FrameAreaAdd ! Additional frame area sunlit
9034 : // REAL(r64) DividerAreaAdd ! Additional frame area sunlit
9035 : int HTSS; // Heat transfer surface number of the subsurface
9036 : int SBSNR; // Subsurface number
9037 :
9038 90268 : auto &s_surf = state.dataSurface;
9039 :
9040 90268 : if (NSBS > 0) { // Action taken only if subsurfaces present
9041 :
9042 15470 : state.dataSolarShading->FSBSHC = state.dataSolarShading->LOCHCA + 1;
9043 :
9044 32628 : for (I = 1; I <= NSBS; ++I) { // Do for all subsurfaces (sbs).
9045 :
9046 17158 : SBSNR = state.dataShadowComb->ShadowComb(CurSurf).SubSurf(I);
9047 :
9048 17158 : HTSS = SBSNR;
9049 :
9050 17158 : K = s_surf->Surface(SBSNR).Construction;
9051 :
9052 17158 : if (!state.dataSolarShading->penumbra) {
9053 34316 : if ((state.dataSolarShading->OverlapStatus != TooManyVertices) && (state.dataSolarShading->OverlapStatus != TooManyFigures) &&
9054 17158 : (state.dataSolarShading->SurfSunlitArea(HTS) > 0.0)) {
9055 :
9056 : // Re-order vertices to clockwise sequential; compute homogeneous coordinates.
9057 8329 : state.dataSolarShading->NVS = s_surf->Surface(SBSNR).Sides;
9058 41645 : for (N = 1; N <= state.dataSolarShading->NVS; ++N) {
9059 33316 : state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(state.dataSolarShading->NVS + 1 - N);
9060 33316 : state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(state.dataSolarShading->NVS + 1 - N);
9061 : }
9062 8329 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FSBSHC;
9063 8329 : HTRANS1(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->NVS);
9064 8329 : state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
9065 8329 : state.dataSolarShading->HCT(state.dataSolarShading->LOCHCA) = 1.0;
9066 8329 : state.dataSolarShading->NSBSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FSBSHC + 1;
9067 :
9068 : // Determine sunlit area of subsurface due to shadows on general receiving surface.
9069 8329 : if (state.dataSolarShading->NGSSHC > 0) {
9070 2773 : MULTOL(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->FGSSHC - 1, state.dataSolarShading->NGSSHC);
9071 2773 : if ((state.dataSolarShading->OverlapStatus != TooManyVertices) && (state.dataSolarShading->OverlapStatus != TooManyFigures))
9072 2773 : state.dataSolarShading->NSBSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FSBSHC + 1;
9073 : }
9074 : }
9075 :
9076 34316 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures) ||
9077 17158 : (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0)) { // General receiving surface totally shaded.
9078 :
9079 8829 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9080 :
9081 8829 : if (iHour > 0 && TS > 0) state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) = 0.0;
9082 :
9083 8329 : } else if ((state.dataSolarShading->NGSSHC <= 0) || (state.dataSolarShading->NSBSHC == 1)) { // No shadows.
9084 :
9085 5608 : state.dataSolarShading->SurfSunlitArea(HTSS) = state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC);
9086 5608 : state.dataSolarShading->SurfSunlitArea(HTS) -=
9087 5608 : state.dataSolarShading->SurfSunlitArea(HTSS); // Revise sunlit area of general receiving surface.
9088 :
9089 : // TH. This is a bug. SunLitFracWithoutReveal should be a ratio of area
9090 : // IF(IHour > 0 .AND. TS > 0) SunLitFracWithoutReveal(HTSS,IHour,TS) = &
9091 : // Surface(HTSS)%NetAreaShadowCalc
9092 :
9093 : // new code fixed part of CR 7596. TH 5/29/2009
9094 5608 : if (iHour > 0 && TS > 0)
9095 3452 : state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
9096 3452 : state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).NetAreaShadowCalc;
9097 :
9098 5608 : SHDRVL(state, HTSS, SBSNR, iHour, TS); // Determine shadowing from reveal.
9099 :
9100 5608 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
9101 0 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9102 :
9103 : } else { // Compute area.
9104 :
9105 2721 : A = state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC);
9106 6211 : for (J = 2; J <= state.dataSolarShading->NSBSHC; ++J) {
9107 3490 : A += state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC - 1 + J) *
9108 3490 : (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FSBSHC - 1 + J));
9109 : }
9110 2721 : state.dataSolarShading->SurfSunlitArea(HTSS) = A;
9111 2721 : if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
9112 :
9113 2402 : state.dataSolarShading->SurfSunlitArea(HTS) -=
9114 2402 : state.dataSolarShading->SurfSunlitArea(HTSS); // Revise sunlit area of general receiving surface.
9115 :
9116 2402 : if (iHour > 0 && TS > 0)
9117 1542 : state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
9118 1542 : state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).Area;
9119 :
9120 2402 : SHDRVL(state, HTSS, SBSNR, iHour, TS); // Determine shadowing from reveal.
9121 :
9122 2402 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
9123 0 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9124 :
9125 : } else { // General receiving surface totally shaded.
9126 :
9127 319 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9128 : }
9129 : }
9130 : }
9131 :
9132 : // Determine transmittance and absorptances of sunlit window.
9133 17158 : if (state.dataConstruction->Construct(K).TransDiff > 0.0) {
9134 :
9135 11878 : if (!state.dataSolarShading->CalcSkyDifShading) { // Overlaps calculation is only done for beam solar
9136 : // shading, not for sky diffuse solar shading
9137 :
9138 6982 : CalcInteriorSolarOverlaps(state, iHour, NBKS, HTSS, CurSurf, TS);
9139 : }
9140 : }
9141 :
9142 : // Error checking.
9143 17158 : SurfArea = s_surf->Surface(SBSNR).NetAreaShadowCalc;
9144 17158 : state.dataSolarShading->SurfSunlitArea(HTSS) = max(0.0, state.dataSolarShading->SurfSunlitArea(HTSS));
9145 :
9146 17158 : state.dataSolarShading->SurfSunlitArea(HTSS) = min(state.dataSolarShading->SurfSunlitArea(HTSS), SurfArea);
9147 :
9148 : } // End of subsurface loop
9149 : }
9150 90268 : }
9151 :
9152 2216 : void SUN3(int const JulianDayOfYear, // Julian Day Of Year
9153 : Real64 &SineOfSolarDeclination, // Sine of Solar Declination
9154 : Real64 &EquationOfTime // Equation of Time (Degrees)
9155 : )
9156 : {
9157 :
9158 : // SUBROUTINE INFORMATION:
9159 : // AUTHOR Legacy Code
9160 : // DATE WRITTEN
9161 : // MODIFIED na
9162 : // RE-ENGINEERED Linda K. Lawrie
9163 :
9164 : // PURPOSE OF THIS SUBROUTINE:
9165 : // This subroutine computes the coefficients for determining
9166 : // the solar position.
9167 :
9168 : // METHODOLOGY EMPLOYED:
9169 : // The expressions are based on least-squares fits of data on p.316 of 'Thermal
9170 : // Environmental Engineering' by Threlkeld and on p.387 of the ASHRAE Handbook
9171 : // of Fundamentals (need date of ASHRAE HOF).
9172 :
9173 : // REFERENCES:
9174 : // BLAST/IBLAST code, original author George Walton
9175 :
9176 : // Fitted coefficients of Fourier series | Sine of declination coefficients
9177 : static constexpr std::array<Real64, 9> SineSolDeclCoef = {
9178 : 0.00561800, 0.0657911, -0.392779, 0.00064440, -0.00618495, -0.00010101, -0.00007951, -0.00011691, 0.00002096};
9179 : // Fitted coefficients of Fourier Series | Equation of Time coefficients
9180 : static constexpr std::array<Real64, 9> EqOfTimeCoef = {
9181 : 0.00021971, -0.122649, 0.00762856, -0.156308, -0.0530028, -0.00388702, -0.00123978, -0.00270502, -0.00167992};
9182 :
9183 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
9184 : Real64 X; // Day of Year in Radians (Computed from Input JulianDayOfYear)
9185 : Real64 CosX; // COS(X)
9186 : Real64 SineX; // SIN(X)
9187 :
9188 2216 : X = 0.017167 * JulianDayOfYear; // Convert julian date to angle X
9189 :
9190 : // Calculate sines and cosines of X
9191 2216 : SineX = std::sin(X);
9192 2216 : CosX = std::cos(X);
9193 :
9194 2216 : SineOfSolarDeclination = SineSolDeclCoef[0] + SineSolDeclCoef[1] * SineX + SineSolDeclCoef[2] * CosX + SineSolDeclCoef[3] * (SineX * CosX * 2.0) +
9195 2216 : SineSolDeclCoef[4] * (pow_2(CosX) - pow_2(SineX)) +
9196 2216 : SineSolDeclCoef[5] * (SineX * (pow_2(CosX) - pow_2(SineX)) + CosX * (SineX * CosX * 2.0)) +
9197 2216 : SineSolDeclCoef[6] * (CosX * (pow_2(CosX) - pow_2(SineX)) - SineX * (SineX * CosX * 2.0)) +
9198 2216 : SineSolDeclCoef[7] * (2.0 * (SineX * CosX * 2.0) * (pow_2(CosX) - pow_2(SineX))) +
9199 2216 : SineSolDeclCoef[8] * (pow_2(pow_2(CosX) - pow_2(SineX)) - pow_2(SineX * CosX * 2.0));
9200 :
9201 2216 : EquationOfTime = EqOfTimeCoef[0] + EqOfTimeCoef[1] * SineX + EqOfTimeCoef[2] * CosX + EqOfTimeCoef[3] * (SineX * CosX * 2.0) +
9202 2216 : EqOfTimeCoef[4] * (pow_2(CosX) - pow_2(SineX)) +
9203 2216 : EqOfTimeCoef[5] * (SineX * (pow_2(CosX) - pow_2(SineX)) + CosX * (SineX * CosX * 2.0)) +
9204 2216 : EqOfTimeCoef[6] * (CosX * (pow_2(CosX) - pow_2(SineX)) - SineX * (SineX * CosX * 2.0)) +
9205 2216 : EqOfTimeCoef[7] * (2.0 * (SineX * CosX * 2.0) * (pow_2(CosX) - pow_2(SineX))) +
9206 2216 : EqOfTimeCoef[8] * (pow_2(pow_2(CosX) - pow_2(SineX)) - pow_2(SineX * CosX * 2.0));
9207 2216 : }
9208 :
9209 30561 : void SUN4(EnergyPlusData &state,
9210 : Real64 const CurrentTime, // Time to use in shadowing calculations
9211 : Real64 const EqOfTime, // Equation of time for current day
9212 : Real64 const SinSolarDeclin, // Sine of the Solar declination (current day)
9213 : Real64 const CosSolarDeclin // Cosine of the Solar declination (current day)
9214 : )
9215 : {
9216 :
9217 : // SUBROUTINE INFORMATION:
9218 : // AUTHOR Legacy Code
9219 : // DATE WRITTEN
9220 : // MODIFIED na
9221 : // RE-ENGINEERED Lawrie, Oct 2000
9222 :
9223 : // PURPOSE OF THIS SUBROUTINE:
9224 : // This subroutine computes solar direction cosines for a given hour. These
9225 : // cosines are used in the shadowing calculations.
9226 : // REFERENCES:
9227 : // BLAST/IBLAST code, original author George Walton
9228 :
9229 : Real64 H; // Hour angle (before noon = +) (in radians)
9230 : Real64 HrAngle; // Basic hour angle
9231 :
9232 : // Compute the hour angle
9233 30561 : HrAngle = (15.0 * (12.0 - (CurrentTime + EqOfTime)) + (state.dataEnvrn->TimeZoneMeridian - state.dataEnvrn->Longitude));
9234 30561 : H = HrAngle * Constant::DegToRad;
9235 :
9236 : // Compute the cosine of the solar zenith angle.
9237 30561 : state.dataSolarShading->SUNCOS(3) = SinSolarDeclin * state.dataEnvrn->SinLatitude + CosSolarDeclin * state.dataEnvrn->CosLatitude * std::cos(H);
9238 30561 : state.dataSolarShading->SUNCOS(2) = 0.0;
9239 30561 : state.dataSolarShading->SUNCOS(1) = 0.0;
9240 :
9241 30561 : if (state.dataSolarShading->SUNCOS(3) < DataEnvironment::SunIsUpValue) return; // Return if sun not above horizon.
9242 :
9243 : // Compute other direction cosines.
9244 15058 : state.dataSolarShading->SUNCOS(2) = SinSolarDeclin * state.dataEnvrn->CosLatitude - CosSolarDeclin * state.dataEnvrn->SinLatitude * std::cos(H);
9245 15058 : state.dataSolarShading->SUNCOS(1) = CosSolarDeclin * std::sin(H);
9246 : }
9247 :
9248 249958 : void WindowShadingManager(EnergyPlusData &state)
9249 : {
9250 :
9251 : // SUBROUTINE INFORMATION:
9252 : // AUTHOR Fred Winkelmann
9253 : // DATE WRITTEN December 1998
9254 : // MODIFIED November 1999 (FW)
9255 : // Aug 2001 (FW): change shading control names, change approach
9256 : // to scheduling and glare control, add movable
9257 : // insulation controls (mainly for heating reduction)
9258 : // Dec 2001 (FW): add slat angle control for blinds
9259 : // Aug 2002 (FW): add four new control types:
9260 : // OnIfHighOutsideAirTempAndHighSolarOnWindow
9261 : // OnIfHighOutsideAirTempAndHighHorizontalSolar
9262 : // OnIfHighZoneAirTempAndHighSolarOnWindow
9263 : // OnIfHighZoneAirTempAndHighHorizontalSolar
9264 : // Dec 2002 (FW): add between-glass shade/blind
9265 : // Mar 2003 (FW): allow GlareControlIsActive = .TRUE. only for daylit zones
9266 : // Apr 2003 (FW): use SNLoadCoolRate or SNLoadHeatRate only if not first time step
9267 : // (fixes problem when used first time thru and not allocated)
9268 : // May 2006 (RR): add exterior window screen
9269 : // May 2009 (BG): add EMS actuator override for shade flag and slat angle
9270 : // RE-ENGINEERED na
9271 :
9272 : // PURPOSE OF THIS SUBROUTINE:
9273 : // For windows with shading, selects the shaded construction
9274 : // that is used in the heat balance calculation, and sets
9275 : // the window shading flag, which is:
9276 : // -1: if window has no shading device
9277 : // 0: if shading device is off
9278 : // 1: if interior shade is on
9279 : // 2: if glazing is switched to darker state
9280 : // 3: if exterior shade is on
9281 : // 6: if interior blind is on
9282 : // 7: if exterior blind is on
9283 : // 8: if between-glass shade is on
9284 : // 9: if between-glass blind is on
9285 : // 10: window has interior shade that is off but may be triggered on later
9286 : // to control daylight glare
9287 : // 20: window has switchable glazing that is unswitched but may be switched later
9288 : // to control daylight glare or daylight illuminance
9289 : // 30: window has exterior shade that is off but may be triggered on later
9290 : // to control daylight glare or daylight illuminance
9291 : // 60: window has interior blind that is off but may be triggered on later
9292 : // to control daylight glare or daylight illuminance
9293 : // 70: window has exterior blind that is off but may be triggered on later
9294 : // to control daylight glare or daylight illuminance
9295 : // 80: window has between-glass shade that is off but may be triggered on later
9296 : // to control daylight glare or daylight illuminance
9297 : // 90: window has between-glass blind that is off but may be triggered on later
9298 : // to control daylight glare or daylight illuminance
9299 : // A "shading device" may be an exterior, interior or between-glass shade or blind,
9300 : // or the lower-transmitting (dark) state of switchable glazing (e.g., electrochromic).
9301 : // In all cases, the unshaded condition is represented
9302 : // by the construction given by window's Surface()%Construction and
9303 : // the shaded condition is represented by the construction given by
9304 : // the window's Surface()%ShadedConstruction
9305 : // REFERENCES:
9306 : // na
9307 :
9308 : int IConst; // Construction
9309 :
9310 249958 : auto &s_mat = state.dataMaterial;
9311 249958 : auto &s_surf = state.dataSurface;
9312 :
9313 586610 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
9314 709607 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
9315 372955 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
9316 372955 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
9317 372955 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
9318 461523 : for (int ISurf = firstSurfWin; ISurf <= lastSurfWin; ++ISurf) {
9319 88568 : auto &surfWin = s_surf->SurfaceWindow(ISurf);
9320 88568 : s_surf->SurfWinExtIntShadePrevTS(ISurf) = s_surf->SurfWinShadingFlag(ISurf);
9321 :
9322 88568 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::NoShade;
9323 88568 : s_surf->SurfWinFracTimeShadingDeviceOn(ISurf) = 0.0;
9324 88568 : if (s_surf->SurfWinWindowModelType(ISurf) == WindowModel::EQL) {
9325 2369 : int EQLNum = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction).EQLConsPtr;
9326 2369 : if (state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr > 0) {
9327 1473 : auto &surfShade = s_surf->surfShades(ISurf);
9328 1473 : if (state.dataWindowEquivLayer->CFS(EQLNum).L(state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr).CNTRL ==
9329 1473 : state.dataWindowEquivalentLayer->lscNONE) {
9330 507 : surfShade.blind.slatAngDeg =
9331 507 : state.dataWindowEquivLayer->CFS(EQLNum).L(state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr).PHI_DEG;
9332 : } else {
9333 966 : surfShade.blind.slatAngDeg = 0.0;
9334 : }
9335 : }
9336 : }
9337 :
9338 : // Initialization of complex fenestration shading device
9339 88568 : if (s_surf->SurfWinWindowModelType(ISurf) == WindowModel::BSDF) {
9340 0 : auto &construction = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction);
9341 0 : int TotLayers = construction.TotLayers;
9342 0 : for (int Lay = 1; Lay <= TotLayers; ++Lay) {
9343 0 : const int LayPtr = construction.LayerPoint(Lay);
9344 0 : auto const *material = s_mat->materials(LayPtr);
9345 0 : const bool isShading = material->group == Material::Group::ComplexShade;
9346 0 : if (isShading && Lay == 1) {
9347 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtShade;
9348 : }
9349 0 : if (isShading && Lay == TotLayers) {
9350 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntShade;
9351 : }
9352 : }
9353 :
9354 0 : if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::IntShade) {
9355 0 : auto &surfShade = s_surf->surfShades(ISurf);
9356 0 : auto &construction = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction);
9357 0 : const int TotLay = construction.TotLayers;
9358 0 : int ShadingLayerPtr = construction.LayerPoint(TotLay);
9359 :
9360 0 : auto const *matComplexShade = dynamic_cast<Material::MaterialComplexShade *>(s_mat->materials(ShadingLayerPtr));
9361 0 : Real64 TauShadeIR = matComplexShade->TransThermal;
9362 0 : Real64 EpsShadeIR = matComplexShade->BackEmissivity;
9363 0 : Real64 RhoShadeIR = max(0.0, 1.0 - TauShadeIR - EpsShadeIR);
9364 : // Get properties of glass next to inside shading layer
9365 0 : int GlassLayPtr = construction.LayerPoint(TotLay - 2);
9366 0 : Real64 EpsGlassIR = s_mat->materials(GlassLayPtr)->AbsorpThermalBack;
9367 0 : Real64 RhoGlassIR = 1 - EpsGlassIR;
9368 :
9369 0 : surfShade.effShadeEmi = EpsShadeIR * (1.0 + RhoGlassIR * TauShadeIR / (1.0 - RhoGlassIR * RhoShadeIR));
9370 0 : surfShade.effGlassEmi = EpsGlassIR * TauShadeIR / (1.0 - RhoGlassIR * RhoShadeIR);
9371 : }
9372 : }
9373 :
9374 88568 : if (s_surf->Surface(ISurf).ExtBoundCond != ExternalEnvironment) continue;
9375 88568 : if (!s_surf->Surface(ISurf).HasShadeControl) {
9376 56212 : continue;
9377 : } else {
9378 : //
9379 : }
9380 :
9381 : // Initialize switching factor (applicable only to switchable glazing) to unswitched
9382 32356 : s_surf->SurfWinSwitchingFactor(ISurf) = 0.0;
9383 :
9384 32356 : IConst = s_surf->Surface(ISurf).Construction;
9385 : // Vis trans at normal incidence of unswitched glass. Counting the GlazedFrac
9386 32356 : if (IConst > 0)
9387 32352 : s_surf->SurfWinVisTransSelected(ISurf) =
9388 32352 : Window::POLYF(1.0, state.dataConstruction->Construct(IConst).TransVisBeamCoef) * surfWin.glazedFrac;
9389 :
9390 : // Window has shading control
9391 : // select the active window shading control and corresponding constructions
9392 32356 : size_t indexWindowShadingControl = selectActiveWindowShadingControlIndex(state, ISurf);
9393 64712 : if (!s_surf->Surface(ISurf).windowShadingControlList.empty() &&
9394 32356 : indexWindowShadingControl <= s_surf->Surface(ISurf).windowShadingControlList.size() - 1) {
9395 32356 : s_surf->Surface(ISurf).activeWindowShadingControl = s_surf->Surface(ISurf).windowShadingControlList[indexWindowShadingControl];
9396 : }
9397 32356 : s_surf->Surface(ISurf).activeShadedConstructionPrev = s_surf->Surface(ISurf).activeShadedConstruction;
9398 64708 : if (!s_surf->Surface(ISurf).shadedConstructionList.empty() &&
9399 32352 : indexWindowShadingControl <= s_surf->Surface(ISurf).shadedConstructionList.size() - 1) {
9400 32352 : s_surf->Surface(ISurf).activeShadedConstruction = s_surf->Surface(ISurf).shadedConstructionList[indexWindowShadingControl];
9401 : }
9402 32356 : s_surf->SurfWinActiveShadedConstruction(ISurf) = s_surf->Surface(ISurf).activeShadedConstruction;
9403 32356 : if (!s_surf->Surface(ISurf).shadedStormWinConstructionList.empty() &&
9404 0 : indexWindowShadingControl <= s_surf->Surface(ISurf).shadedStormWinConstructionList.size() - 1) {
9405 0 : if (s_surf->SurfWinStormWinFlag(ISurf) == 1) {
9406 0 : s_surf->SurfWinActiveShadedConstruction(ISurf) =
9407 0 : s_surf->Surface(ISurf).shadedStormWinConstructionList[indexWindowShadingControl];
9408 : }
9409 : }
9410 :
9411 32356 : int IShadingCtrl = s_surf->Surface(ISurf).activeWindowShadingControl;
9412 32356 : int IZone = s_surf->Surface(ISurf).Zone;
9413 : // Setpoint for shading
9414 32356 : Real64 SetPoint = s_surf->WindowShadingControl(IShadingCtrl).SetPoint; // Control setpoint
9415 32356 : Real64 SetPoint2 = s_surf->WindowShadingControl(IShadingCtrl).SetPoint2; // Second control setpoint
9416 :
9417 32356 : bool SchedAllowsControl = true; // True if control schedule is not specified or is specified and schedule value = 1
9418 32356 : auto const *sched = s_surf->WindowShadingControl(IShadingCtrl).sched;
9419 32356 : if (sched != nullptr) {
9420 32352 : if (s_surf->WindowShadingControl(IShadingCtrl).ShadingControlIsScheduled && sched->getCurrentVal() <= 0.0)
9421 32352 : SchedAllowsControl = false;
9422 : }
9423 :
9424 32356 : Real64 GlareControlIsActive = (state.dataDayltg->ZoneDaylight(IZone).totRefPts > 0 && state.dataEnvrn->SunIsUp &&
9425 0 : s_surf->WindowShadingControl(IShadingCtrl).GlareControlIsActive); // True if glare control is active
9426 :
9427 32356 : Real64 SolarOnWindow = 0.0; // Direct plus diffuse solar intensity on window (W/m2)
9428 32356 : Real64 BeamSolarOnWindow = 0.0; // Direct solar intensity on window (W/m2)
9429 32356 : Real64 HorizSolar = 0.0; // Horizontal direct plus diffuse solar intensity
9430 32356 : if (state.dataEnvrn->SunIsUp) {
9431 16354 : Real64 SkySolarOnWindow = state.dataSolarShading->SurfAnisoSkyMult(ISurf) *
9432 16354 : state.dataEnvrn->DifSolarRad; // Sky diffuse solar intensity on window (W/m2)
9433 16354 : BeamSolarOnWindow = state.dataEnvrn->BeamSolarRad *
9434 16354 : state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, ISurf) *
9435 16354 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, ISurf);
9436 16354 : SolarOnWindow = BeamSolarOnWindow + SkySolarOnWindow + state.dataEnvrn->GndSolarRad * s_surf->Surface(ISurf).ViewFactorGround;
9437 16354 : HorizSolar = state.dataEnvrn->BeamSolarRad * state.dataEnvrn->SOLCOS(3) + state.dataEnvrn->DifSolarRad;
9438 : }
9439 :
9440 : // Determine whether to deploy shading depending on type of control
9441 32356 : auto &thisIZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(IZone);
9442 :
9443 32356 : bool shadingOn = false;
9444 32356 : bool shadingOffButGlareControlOn = false;
9445 32356 : switch (s_surf->WindowShadingControl(IShadingCtrl).shadingControlType) {
9446 0 : case WindowShadingControlType::AlwaysOn: // 'ALWAYSON'
9447 0 : shadingOn = true;
9448 0 : break;
9449 0 : case WindowShadingControlType::AlwaysOff: // 'ALWAYSOFF'
9450 0 : break;
9451 32352 : case WindowShadingControlType::OnIfScheduled: // 'ONIFSCHEDULEALLOWS'
9452 32352 : if (SchedAllowsControl) shadingOn = true;
9453 32352 : break;
9454 0 : case WindowShadingControlType::HiSolar: // 'ONIFHIGHSOLARONWINDOW'
9455 : // ! Direct plus diffuse solar intensity on window
9456 0 : if (state.dataEnvrn->SunIsUp) {
9457 0 : if (SolarOnWindow > SetPoint && SchedAllowsControl) {
9458 0 : shadingOn = true;
9459 0 : } else if (GlareControlIsActive) {
9460 0 : shadingOffButGlareControlOn = true;
9461 : }
9462 : }
9463 0 : break;
9464 :
9465 0 : case WindowShadingControlType::HiHorzSolar: // 'ONIFHIGHHORIZONTALSOLAR' ! Direct plus diffuse exterior horizontal solar intensity
9466 0 : if (state.dataEnvrn->SunIsUp) {
9467 0 : if (HorizSolar > SetPoint && SchedAllowsControl) {
9468 0 : shadingOn = true;
9469 0 : } else if (GlareControlIsActive) {
9470 0 : shadingOffButGlareControlOn = true;
9471 : }
9472 : }
9473 0 : break;
9474 :
9475 0 : case WindowShadingControlType::HiOutAirTemp: // 'OnIfHighOutdoorAirTemperature'
9476 0 : if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && SchedAllowsControl) {
9477 0 : shadingOn = true;
9478 0 : } else if (GlareControlIsActive) {
9479 0 : shadingOffButGlareControlOn = true;
9480 : }
9481 0 : break;
9482 :
9483 0 : case WindowShadingControlType::HiZoneAirTemp: // 'OnIfHighZoneAirTemperature' ! Previous time step zone air temperature
9484 0 : if (thisIZoneHB.MAT > SetPoint && SchedAllowsControl) {
9485 0 : shadingOn = true;
9486 0 : } else if (GlareControlIsActive) {
9487 0 : shadingOffButGlareControlOn = true;
9488 : }
9489 0 : break;
9490 :
9491 0 : case WindowShadingControlType::OnHiOutTemp_HiSolarWindow: // 'OnIfHighOutdoorAirTempAndHighSolarOnWindow' ! Outside air temp and
9492 : // solar on window
9493 0 : if (state.dataEnvrn->SunIsUp) {
9494 0 : if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && SolarOnWindow > SetPoint2 && SchedAllowsControl) {
9495 0 : shadingOn = true;
9496 0 : } else if (GlareControlIsActive) {
9497 0 : shadingOffButGlareControlOn = true;
9498 : }
9499 : }
9500 0 : break;
9501 :
9502 0 : case WindowShadingControlType::OnHiOutTemp_HiHorzSolar: // 'OnIfHighOutdoorAirTempAndHighHorizontalSolar' ! Outside air temp and
9503 : // horizontal solar
9504 0 : if (state.dataEnvrn->SunIsUp) {
9505 0 : if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && HorizSolar > SetPoint2 && SchedAllowsControl) {
9506 0 : shadingOn = true;
9507 0 : } else if (GlareControlIsActive) {
9508 0 : shadingOffButGlareControlOn = true;
9509 : }
9510 : }
9511 0 : break;
9512 :
9513 0 : case WindowShadingControlType::OnHiZoneTemp_HiSolarWindow: // 'ONIFHIGHZONEAIRTEMPANDHIGHSOLARONWINDOW' ! Zone air temp and solar on
9514 : // window
9515 0 : if (state.dataEnvrn->SunIsUp) {
9516 0 : if (thisIZoneHB.MAT > SetPoint && SolarOnWindow > SetPoint2 && SchedAllowsControl) {
9517 0 : shadingOn = true;
9518 0 : } else if (GlareControlIsActive) {
9519 0 : shadingOffButGlareControlOn = true;
9520 : }
9521 : }
9522 0 : break;
9523 :
9524 0 : case WindowShadingControlType::OnHiZoneTemp_HiHorzSolar: // 'ONIFHIGHZONEAIRTEMPANDHIGHHORIZONTALSOLAR' ! Zone air temp and
9525 : // horizontal solar
9526 0 : if (state.dataEnvrn->SunIsUp) {
9527 0 : if (thisIZoneHB.MAT > SetPoint && HorizSolar > SetPoint2 && SchedAllowsControl) {
9528 0 : shadingOn = true;
9529 0 : } else if (GlareControlIsActive) {
9530 0 : shadingOffButGlareControlOn = true;
9531 : }
9532 : }
9533 0 : break;
9534 :
9535 0 : case WindowShadingControlType::HiZoneCooling:
9536 : // 'ONIFHIGHZONECOOLING' ! Previous time step zone sensible cooling rate [W]
9537 : // In the following, the check on BeginSimFlag is needed since SNLoadCoolRate (and SNLoadHeatRate,
9538 : // used in other CASEs) are not allocated at this point for the first time step of the simulation.
9539 0 : if (!state.dataGlobal->BeginSimFlag) {
9540 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > SetPoint && SchedAllowsControl) {
9541 0 : shadingOn = true;
9542 0 : } else if (GlareControlIsActive) {
9543 0 : shadingOffButGlareControlOn = true;
9544 : }
9545 : }
9546 0 : break;
9547 :
9548 0 : case WindowShadingControlType::HiGlare:
9549 : // 'ONIFHIGHGLARE' ! Daylight glare index at first reference point in the zone.
9550 : // This type of shading control is done in DayltgInteriorIllum. Glare control is not affected
9551 : // by control schedule.
9552 0 : if (state.dataEnvrn->SunIsUp) {
9553 0 : shadingOffButGlareControlOn = true;
9554 : }
9555 0 : break;
9556 :
9557 0 : case WindowShadingControlType::MeetDaylIlumSetp:
9558 : // 'MEETDAYLIGHTILLUMINANCESETPOINT') ! Daylight illuminance test is done in DayltgInteriorIllum
9559 : // Only switchable glazing does daylight illuminance control
9560 0 : if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9561 0 : shadingOffButGlareControlOn = true;
9562 : }
9563 0 : break;
9564 :
9565 1 : case WindowShadingControlType::HiSolar_HiLumin_OffMidNight:
9566 : // 'OnIfHighSolarOrHighLuminanceTillMidnight'
9567 : // if shade is already on, then keep it on until midnight, otherwise check thresholds
9568 1 : if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
9569 0 : shadingOn = true;
9570 1 : } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9571 1 : if (SolarOnWindow > SetPoint) {
9572 0 : shadingOn = true;
9573 : } else {
9574 : // pass to DayltgInteriorIllum to check for luminance
9575 1 : shadingOn = false;
9576 1 : shadingOffButGlareControlOn = true;
9577 : }
9578 : }
9579 : // if it is the beginning of the day, then shades off
9580 1 : if (state.dataGlobal->BeginDayFlag) {
9581 0 : shadingOn = false;
9582 0 : shadingOffButGlareControlOn = false;
9583 : }
9584 1 : break;
9585 :
9586 0 : case WindowShadingControlType::HiSolar_HiLumin_OffSunset:
9587 : // 'OnIfHighSolarOrHighLuminanceTillSunset'
9588 : // if shade is already on, then keep it on until sunset, otherwise check thresholds
9589 0 : if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
9590 0 : shadingOn = true;
9591 0 : } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9592 0 : if (SolarOnWindow > SetPoint) {
9593 0 : shadingOn = true;
9594 : } else {
9595 : // pass to DayltgInteriorIllum to check for luminance
9596 0 : shadingOn = false;
9597 0 : shadingOffButGlareControlOn = true;
9598 : }
9599 : }
9600 : // if sunset, then shades off
9601 0 : if (!state.dataEnvrn->SunIsUp) {
9602 0 : shadingOn = false;
9603 0 : shadingOffButGlareControlOn = false;
9604 : }
9605 0 : break;
9606 :
9607 1 : case WindowShadingControlType::HiSolar_HiLumin_OffNextMorning:
9608 : // 'OnIfHighSolarOrHighLuminanceTillNextMorning'
9609 : // if shade is already on, then keep it on until next day when sun is up, otherwise check thresholds
9610 1 : if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
9611 0 : shadingOn = true;
9612 1 : } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9613 1 : if (SolarOnWindow > SetPoint) {
9614 1 : shadingOn = true;
9615 : } else {
9616 : // pass to DayltgInteriorIllum to check for luminance
9617 0 : shadingOn = false;
9618 0 : shadingOffButGlareControlOn = true;
9619 : }
9620 : }
9621 : // if next morning (identified by sun is not up in previous time step and is up now), then shades off
9622 1 : if (!state.dataEnvrn->SunIsUpPrevTS && state.dataEnvrn->SunIsUp) {
9623 0 : shadingOn = false;
9624 0 : shadingOffButGlareControlOn = false;
9625 : }
9626 1 : break;
9627 :
9628 0 : case WindowShadingControlType::OnNightLoOutTemp_OffDay: // 'OnNightIfLowOutdoorTempAndOffDay'
9629 0 : if (!state.dataEnvrn->SunIsUp && s_surf->SurfOutDryBulbTemp(ISurf) < SetPoint && SchedAllowsControl) {
9630 0 : shadingOn = true;
9631 0 : } else if (GlareControlIsActive) {
9632 0 : shadingOffButGlareControlOn = true;
9633 : }
9634 0 : break;
9635 :
9636 0 : case WindowShadingControlType::OnNightLoInTemp_OffDay: // 'OnNightIfLowInsideTempAndOffDay')
9637 0 : if (!state.dataEnvrn->SunIsUp && thisIZoneHB.MAT < SetPoint && SchedAllowsControl) {
9638 0 : shadingOn = true;
9639 0 : } else if (GlareControlIsActive) {
9640 0 : shadingOffButGlareControlOn = true;
9641 : }
9642 0 : break;
9643 :
9644 0 : case WindowShadingControlType::OnNightIfHeating_OffDay: // 'OnNightIfHeatingAndOffDay'
9645 0 : if (!state.dataGlobal->BeginSimFlag) {
9646 0 : if (!state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysHeatRate > SetPoint &&
9647 : SchedAllowsControl) {
9648 0 : shadingOn = true;
9649 0 : } else if (GlareControlIsActive) {
9650 0 : shadingOffButGlareControlOn = true;
9651 : }
9652 : }
9653 0 : break;
9654 :
9655 0 : case WindowShadingControlType::OnNightLoOutTemp_OnDayCooling: // 'OnNightIfLowOutdoorTempAndOnDayIfCooling'
9656 0 : if (!state.dataGlobal->BeginSimFlag) {
9657 0 : if (!state.dataEnvrn->SunIsUp) { // Night
9658 0 : if (s_surf->SurfOutDryBulbTemp(ISurf) < SetPoint && SchedAllowsControl) shadingOn = true;
9659 : } else { // Day
9660 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 && SchedAllowsControl) {
9661 0 : shadingOn = true;
9662 0 : } else if (GlareControlIsActive) {
9663 0 : shadingOffButGlareControlOn = true;
9664 : }
9665 : }
9666 : }
9667 0 : break;
9668 :
9669 0 : case WindowShadingControlType::OnNightIfHeating_OnDayCooling: // 'OnNightIfHeatingAndOnDayIfCooling'
9670 0 : if (!state.dataGlobal->BeginSimFlag) {
9671 0 : if (!state.dataEnvrn->SunIsUp) { // Night
9672 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysHeatRate > SetPoint && SchedAllowsControl)
9673 0 : shadingOn = true;
9674 : } else { // Day
9675 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 && SchedAllowsControl) {
9676 0 : shadingOn = true;
9677 0 : } else if (GlareControlIsActive) {
9678 0 : shadingOffButGlareControlOn = true;
9679 : }
9680 : }
9681 : }
9682 0 : break;
9683 :
9684 0 : case WindowShadingControlType::OffNight_OnDay_HiSolarWindow: // 'OffNightAndOnDayIfCoolingAndHighSolarOnWindow'
9685 0 : if (!state.dataGlobal->BeginSimFlag) {
9686 0 : if (state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 &&
9687 : SchedAllowsControl) {
9688 0 : if (SolarOnWindow > SetPoint) shadingOn = true;
9689 0 : } else if (GlareControlIsActive) {
9690 0 : shadingOffButGlareControlOn = true;
9691 : }
9692 : }
9693 0 : break;
9694 :
9695 0 : case WindowShadingControlType::OnNight_OnDay_HiSolarWindow: // 'OnNightAndOnDayIfCoolingAndHighSolarOnWindow'
9696 0 : if (!state.dataGlobal->BeginSimFlag) {
9697 0 : if (state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 &&
9698 : SchedAllowsControl) {
9699 0 : if (SolarOnWindow > SetPoint) shadingOn = true;
9700 0 : } else if (!state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9701 0 : shadingOn = true;
9702 0 : } else if (GlareControlIsActive) {
9703 0 : shadingOffButGlareControlOn = true;
9704 : }
9705 : }
9706 0 : break;
9707 2 : default:
9708 2 : ShowWarningError(state, format("Invalid Selection of Window Shading Control Type for Surface {}", s_surf->Surface(ISurf).Name));
9709 : }
9710 :
9711 32356 : WinShadingType ShType = s_surf->WindowShadingControl(IShadingCtrl).ShadingType;
9712 :
9713 32356 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ShadeOff; // Initialize shading flag to off
9714 :
9715 32356 : if (IS_SHADED(ShType)) {
9716 32355 : if (shadingOn) {
9717 1 : s_surf->SurfWinShadingFlag(ISurf) = ShType;
9718 32354 : } else if (shadingOffButGlareControlOn) {
9719 1 : if (ShType == WinShadingType::SwitchableGlazing)
9720 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::GlassConditionallyLightened;
9721 1 : else if (ShType == WinShadingType::IntShade)
9722 1 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntShadeConditionallyOff;
9723 0 : else if (ShType == WinShadingType::ExtShade)
9724 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtShadeConditionallyOff;
9725 0 : else if (ShType == WinShadingType::IntBlind)
9726 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntBlindConditionallyOff;
9727 0 : else if (ShType == WinShadingType::ExtBlind)
9728 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtBlindConditionallyOff;
9729 0 : else if (ShType == WinShadingType::BGShade)
9730 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::BGShadeConditionallyOff;
9731 0 : else if (ShType == WinShadingType::BGBlind)
9732 0 : s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::BGBlindConditionallyOff;
9733 : }
9734 : }
9735 :
9736 : // Set switching factor to fully switched if ShadingFlag = 2
9737 32356 : if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::SwitchableGlazing) {
9738 0 : s_surf->SurfWinSwitchingFactor(ISurf) = 1.0;
9739 :
9740 : // Added TH 1/20/2010
9741 : // Vis trans at normal incidence of fully switched glass
9742 0 : IConst = s_surf->Surface(ISurf).activeShadedConstruction;
9743 0 : s_surf->SurfWinVisTransSelected(ISurf) =
9744 0 : Window::POLYF(1.0, state.dataConstruction->Construct(IConst).TransVisBeamCoef) * surfWin.glazedFrac;
9745 : }
9746 :
9747 : // Slat angle control for blinds
9748 32356 : auto &surfShade = s_surf->surfShades(ISurf);
9749 32356 : surfShade.blind.slatAng = 0.0;
9750 32356 : surfShade.blind.slatAngDeg = 0.0;
9751 32356 : surfShade.blind.slatBlockBeam = false;
9752 64712 : if (ANY_BLIND(s_surf->SurfWinShadingFlag(ISurf)) || s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::IntBlindConditionallyOff ||
9753 97068 : s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::ExtBlindConditionallyOff ||
9754 32356 : s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::BGBlindConditionallyOff) {
9755 : // Blind in place or may be in place due to glare control
9756 0 : if (surfShade.blind.matNum > 0) {
9757 0 : auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
9758 0 : assert(matBlind != nullptr);
9759 0 : Real64 InputSlatAngle = matBlind->SlatAngle * Constant::DegToRad; // Slat angle of associated Material:WindowBlind (rad)
9760 : Real64 ThetaBase; // Intermediate slat angle variable (rad)
9761 : Real64 ThetaBlock1; // Slat angles that just block beam solar (rad)
9762 : Real64 ThetaBlock2;
9763 :
9764 0 : Real64 ProfAng = surfShade.blind.profAng =
9765 0 : Dayltg::ProfileAngle(state, ISurf, state.dataEnvrn->SOLCOS, matBlind->SlatOrientation);
9766 :
9767 0 : if (ProfAng > Constant::PiOvr2 || ProfAng < -Constant::PiOvr2) {
9768 0 : ProfAng = min(max(ProfAng, -Constant::PiOvr2), Constant::PiOvr2);
9769 : }
9770 0 : surfShade.blind.profAngIdxLo = int((ProfAng + Constant::PiOvr2) / Material::dProfAng) + 1;
9771 0 : surfShade.blind.profAngIdxHi = std::min(Material::MaxProfAngs, surfShade.blind.profAngIdxLo + 1);
9772 :
9773 0 : surfShade.blind.profAngInterpFac =
9774 0 : (ProfAng + Constant::PiOvr2 - (surfShade.blind.profAngIdxLo - 1) * Material::dProfAng) / Material::dProfAng;
9775 :
9776 0 : if (matBlind->SlatWidth > matBlind->SlatSeparation && BeamSolarOnWindow > 0.0) {
9777 0 : ProfAng = surfShade.blind.profAng;
9778 0 : Real64 ThetaBase = std::acos(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth);
9779 : // There are two solutions for the slat angle that just blocks beam radiation
9780 0 : ThetaBlock1 = ProfAng + ThetaBase;
9781 0 : ThetaBlock2 = ProfAng + Constant::Pi - ThetaBase;
9782 0 : state.dataSolarShading->ThetaSmall = min(ThetaBlock1, ThetaBlock2);
9783 0 : state.dataSolarShading->ThetaBig = max(ThetaBlock1, ThetaBlock2);
9784 0 : state.dataSolarShading->ThetaMin = matBlind->MinSlatAngle * Constant::DegToRad;
9785 0 : state.dataSolarShading->ThetaMax = matBlind->MaxSlatAngle * Constant::DegToRad;
9786 : }
9787 :
9788 : // TH 5/20/2010, CR 8064: Slat Width <= Slat Separation
9789 0 : if (matBlind->SlatWidth <= matBlind->SlatSeparation && BeamSolarOnWindow > 0.0) {
9790 0 : if (s_surf->WindowShadingControl(IShadingCtrl).slatAngleControl == SlatAngleControl::BlockBeamSolar) {
9791 0 : ProfAng = surfShade.blind.profAng;
9792 0 : if (std::abs(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth) <= 1.0) {
9793 : // set to block 100% of beam solar, not necessarily to block maximum solar (beam + diffuse)
9794 0 : ThetaBase = std::acos(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth);
9795 0 : surfShade.blind.slatBlockBeam = true;
9796 : } else {
9797 : // cannot block 100% of beam solar, turn slats to be perpendicular to sun beam to block maximal beam solar
9798 0 : ThetaBase = 0.0;
9799 : }
9800 :
9801 : // There are two solutions for the slat angle that just blocks beam radiation
9802 0 : ThetaBlock1 = ProfAng + ThetaBase;
9803 0 : ThetaBlock2 = ProfAng - ThetaBase + Constant::Pi;
9804 :
9805 0 : state.dataSolarShading->ThetaSmall = min(ThetaBlock1, ThetaBlock2);
9806 0 : state.dataSolarShading->ThetaBig = max(ThetaBlock1, ThetaBlock2);
9807 0 : state.dataSolarShading->ThetaMin = matBlind->MinSlatAngle * Constant::DegToRad;
9808 0 : state.dataSolarShading->ThetaMax = matBlind->MaxSlatAngle * Constant::DegToRad;
9809 : }
9810 : }
9811 :
9812 : //
9813 0 : Real64 slatAng = 0.0;
9814 0 : bool slatBlockBeam = false;
9815 0 : switch (s_surf->WindowShadingControl(IShadingCtrl).slatAngleControl) {
9816 :
9817 0 : case SlatAngleControl::Fixed: { // 'FIXEDSLATANGLE'
9818 0 : slatAng = InputSlatAngle;
9819 :
9820 0 : if ((slatAng <= state.dataSolarShading->ThetaSmall || slatAng >= state.dataSolarShading->ThetaBig) &&
9821 0 : (matBlind->SlatWidth > matBlind->SlatSeparation) && (BeamSolarOnWindow > 0.0))
9822 0 : slatBlockBeam = true;
9823 0 : } break;
9824 :
9825 0 : case SlatAngleControl::Scheduled: { // 'SCHEDULEDSLATANGLE'
9826 0 : slatAng = s_surf->WindowShadingControl(IShadingCtrl).slatAngleSched->getCurrentVal();
9827 0 : slatAng = max(matBlind->MinSlatAngle, min(slatAng, matBlind->MaxSlatAngle)) * Constant::DegToRad;
9828 :
9829 0 : if ((slatAng <= state.dataSolarShading->ThetaSmall || slatAng >= state.dataSolarShading->ThetaBig) &&
9830 0 : (matBlind->SlatWidth > matBlind->SlatSeparation) && (BeamSolarOnWindow > 0.0))
9831 0 : slatBlockBeam = true;
9832 0 : } break;
9833 :
9834 0 : case SlatAngleControl::BlockBeamSolar: { // 'BLOCKBEAMSOLAR'
9835 0 : if (BeamSolarOnWindow > 0.0) {
9836 0 : if (matBlind->SlatSeparation >= matBlind->SlatWidth) {
9837 : // TH 5/20/2010. CR 8064.
9838 : // The following line of code assumes slats are always vertical/closed to minimize solar penetration
9839 : // The slat angle can however change if the only goal is to block maximum amount of direct beam solar
9840 : // SurfaceWindow(ISurf)%SlatAngThisTS = 0.0 ! Allows beam penetration but minimizes it
9841 :
9842 0 : if (state.dataSolarShading->ThetaSmall >= state.dataSolarShading->ThetaMin &&
9843 0 : state.dataSolarShading->ThetaSmall <= state.dataSolarShading->ThetaMax) {
9844 0 : slatAng = state.dataSolarShading->ThetaSmall;
9845 0 : } else if (state.dataSolarShading->ThetaBig >= state.dataSolarShading->ThetaMin &&
9846 0 : state.dataSolarShading->ThetaBig <= state.dataSolarShading->ThetaMax) {
9847 0 : slatAng = state.dataSolarShading->ThetaBig;
9848 0 : } else if (state.dataSolarShading->ThetaSmall < state.dataSolarShading->ThetaMin &&
9849 0 : state.dataSolarShading->ThetaBig < state.dataSolarShading->ThetaMin) {
9850 0 : slatAng = state.dataSolarShading->ThetaMin;
9851 0 : } else if (state.dataSolarShading->ThetaSmall > state.dataSolarShading->ThetaMax &&
9852 0 : state.dataSolarShading->ThetaBig > state.dataSolarShading->ThetaMax) {
9853 0 : slatAng = state.dataSolarShading->ThetaMax;
9854 : } else { // ThetaBig > ThetaMax and ThetaSmall < ThetaMin (no-block condition)
9855 0 : slatAng = state.dataSolarShading->ThetaMin;
9856 : }
9857 :
9858 : } else { // Usual case -- slat width greater than slat separation
9859 0 : if (state.dataSolarShading->ThetaSmall >= state.dataSolarShading->ThetaMin &&
9860 0 : state.dataSolarShading->ThetaSmall <= state.dataSolarShading->ThetaMax) {
9861 0 : slatAng = state.dataSolarShading->ThetaSmall;
9862 0 : slatBlockBeam = true;
9863 0 : } else if (state.dataSolarShading->ThetaBig >= state.dataSolarShading->ThetaMin &&
9864 0 : state.dataSolarShading->ThetaBig <= state.dataSolarShading->ThetaMax) {
9865 0 : slatAng = state.dataSolarShading->ThetaBig;
9866 0 : slatBlockBeam = true;
9867 0 : } else if (state.dataSolarShading->ThetaSmall < state.dataSolarShading->ThetaMin &&
9868 0 : state.dataSolarShading->ThetaBig < state.dataSolarShading->ThetaMin) {
9869 0 : slatAng = state.dataSolarShading->ThetaMin;
9870 0 : slatBlockBeam = true;
9871 0 : } else if (state.dataSolarShading->ThetaSmall > state.dataSolarShading->ThetaMax &&
9872 0 : state.dataSolarShading->ThetaBig > state.dataSolarShading->ThetaMax) {
9873 0 : slatAng = state.dataSolarShading->ThetaMax;
9874 0 : slatBlockBeam = true;
9875 : } else { // ThetaBig > ThetaMax and ThetaSmall < ThetaMin (no-block condition)
9876 0 : slatAng = state.dataSolarShading->ThetaMin;
9877 : }
9878 : }
9879 : } else {
9880 0 : slatAng = InputSlatAngle;
9881 : }
9882 0 : } break;
9883 0 : default:
9884 0 : break;
9885 : } // switch (slatAngControl)
9886 :
9887 0 : if (surfShade.blind.slatAngDegEMSon) {
9888 0 : slatAng = Constant::DegToRad * surfShade.blind.slatAngDegEMSValue;
9889 : }
9890 :
9891 : // Slat angle is changing, need to recalculate stored values
9892 0 : if (slatAng != surfShade.blind.slatAng) {
9893 0 : surfShade.blind.slatAng = slatAng;
9894 0 : surfShade.blind.slatAngDeg = surfShade.blind.slatAng * Constant::RadToDeg;
9895 :
9896 0 : Material::GetSlatIndicesInterpFac(surfShade.blind.slatAng,
9897 0 : surfShade.blind.slatAngIdxLo,
9898 0 : surfShade.blind.slatAngIdxHi,
9899 0 : surfShade.blind.slatAngInterpFac);
9900 0 : surfShade.blind.TAR.interpSlatAng(matBlind->TARs[surfShade.blind.slatAngIdxLo],
9901 0 : matBlind->TARs[surfShade.blind.slatAngIdxHi],
9902 : surfShade.blind.slatAngInterpFac);
9903 :
9904 0 : Real64 TauShIR = surfShade.blind.TAR.IR.Ft.Tra;
9905 0 : Real64 EpsShIR = surfShade.blind.TAR.IR.Bk.Emi;
9906 0 : Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
9907 :
9908 0 : surfShade.effShadeEmi = EpsShIR * (1.0 + surfShade.glass.rhoIR * TauShIR / (1.0 - surfShade.glass.rhoIR * RhoShIR));
9909 0 : surfShade.effGlassEmi = surfShade.glass.epsIR * TauShIR / (1.0 - surfShade.glass.rhoIR * RhoShIR);
9910 : }
9911 :
9912 0 : surfShade.blind.slatBlockBeam = slatBlockBeam;
9913 :
9914 : // Air flow permeability for calculation of convective air flow between blind and glass
9915 0 : Real64 PermeabilityA = std::sin(surfShade.blind.slatAng) - matBlind->SlatThickness / matBlind->SlatSeparation;
9916 0 : Real64 PermeabilityB = 1.0 - (std::abs(matBlind->SlatWidth * std::cos(surfShade.blind.slatAng)) +
9917 0 : matBlind->SlatThickness * std::sin(surfShade.blind.slatAng)) /
9918 0 : matBlind->SlatSeparation;
9919 0 : surfShade.blind.airFlowPermeability = min(1.0, max(0.0, PermeabilityA, PermeabilityB));
9920 0 : surfShade.blind.bmBmTrans = matBlind->BeamBeamTrans(surfShade.blind.profAng, surfShade.blind.slatAng);
9921 : }
9922 : } // End of check if interior or exterior or between glass blind in place
9923 :
9924 : // AR: don't need to do this anymore I don't think
9925 : // CALL CalcScreenTransmittance to initialized all screens prior to HB calc's
9926 : // if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::ExtScreen && state.dataEnvrn->SunIsUp) {
9927 : // CalcScreenTransmittance(state, ISurf);
9928 : // }
9929 :
9930 : // EMS Actuator Point: override setting if ems flag on
9931 32356 : if (s_surf->SurfWinShadingFlagEMSOn(ISurf)) {
9932 1 : WinShadingType SurfWinShadingFlagEMS = findValueInEnumeration(s_surf->SurfWinShadingFlagEMSValue(ISurf));
9933 1 : if (SurfWinShadingFlagEMS != WinShadingType::Invalid) {
9934 1 : s_surf->SurfWinShadingFlag(ISurf) = SurfWinShadingFlagEMS;
9935 : } else {
9936 0 : ShowWarningError(state,
9937 0 : format("Invalid EMS value of Window Shading Control Type for Surface {}", s_surf->Surface(ISurf).Name));
9938 : }
9939 : }
9940 : } // End of surface loop
9941 : }
9942 : }
9943 249958 : }
9944 :
9945 249956 : void CheckGlazingShadingStatusChange(EnergyPlusData &state)
9946 : {
9947 249956 : auto &s_surf = state.dataSurface;
9948 249956 : if (state.dataGlobal->BeginSimFlag) {
9949 112 : if (state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() && state.dataWindowManager->winOpticalModel->isSimplifiedModel()) {
9950 0 : state.dataHeatBal->EnclRadAlwaysReCalc = true;
9951 : } else {
9952 244 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
9953 282 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
9954 150 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
9955 937 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
9956 793 : auto &surf = s_surf->Surface(SurfNum);
9957 1586 : if (state.dataConstruction->Construct(surf.Construction).isTCWindow ||
9958 793 : state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
9959 6 : state.dataHeatBal->EnclRadAlwaysReCalc = true;
9960 6 : break;
9961 : }
9962 : }
9963 : }
9964 : }
9965 : }
9966 112 : if (state.dataHeatBal->EnclRadAlwaysReCalc) {
9967 12 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
9968 6 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
9969 : }
9970 12 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
9971 6 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
9972 : }
9973 : }
9974 : }
9975 249956 : if (state.dataHeatBal->EnclRadAlwaysReCalc) return;
9976 :
9977 247588 : if (state.dataGlobal->BeginEnvrnFlag || state.dataGlobal->AnyConstrOverridesInModel || state.dataGlobal->AnySurfPropOverridesInModel) {
9978 15405 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
9979 7826 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
9980 : }
9981 15405 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
9982 7826 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
9983 : }
9984 7579 : return;
9985 : }
9986 585389 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
9987 345380 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = false;
9988 : }
9989 585389 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
9990 345380 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = false;
9991 : }
9992 240009 : if (!state.dataGlobal->AndShadingControlInModel) return;
9993 16144 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
9994 153368 : for (int const SurfNum : state.dataViewFactor->EnclRadInfo(enclosureNum).SurfacePtr) {
9995 141260 : auto &surf = s_surf->Surface(SurfNum);
9996 141260 : auto &surfShade = s_surf->surfShades(SurfNum);
9997 141260 : bool surfShadingStatusChange = s_surf->SurfWinExtIntShadePrevTS(SurfNum) != s_surf->SurfWinShadingFlag(SurfNum) ||
9998 141260 : surf.activeShadedConstruction != surf.activeShadedConstructionPrev || surfShade.blind.movableSlats;
9999 141260 : if (surfShadingStatusChange) {
10000 0 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
10001 0 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
10002 0 : break;
10003 : }
10004 : }
10005 : }
10006 : }
10007 :
10008 1 : DataSurfaces::WinShadingType findValueInEnumeration(Real64 controlValue)
10009 : {
10010 : // This is a workaround to translate EMS Shading control numerical values
10011 : // EMS control of window shading devices involves setting the control values for shading control actuators with
10012 : // one of these values. The variable names can be used or replaced, it is the whole number values that trigger
10013 : // changes in the modeling.
10014 : // Shades and Blinds are either fully on or fully off, partial positions require multiple windows.
10015 : // the window shading control flag values follow
10016 : // -1: if window has no shading device
10017 : // 0: if shading device is off
10018 : // 1: if interior shade is on
10019 : // 2: if glazing is switched to darker state
10020 : // 3: if exterior shade is on
10021 : // 4: if exterior screen is on
10022 : // 6: if interior blind is on
10023 : // 7: if exterior blind is on
10024 : // 8: if between-glass shade is on
10025 : // 9: if between-glass blind is on
10026 : // 10: window has interior shade that is off but may be triggered on later to control daylight glare
10027 : // 20: window has switchable glazing that is unswitched but may be switched later to control daylight glare or
10028 : // daylight illuminance 30: window has exterior shade that is off but may be triggered on later to control
10029 : // daylight glare or daylight illuminance 60: window has interior blind that is off but may be triggered on later
10030 : // to control daylight glare or daylight illuminance 70: window has exterior blind that is off but may be
10031 : // triggered on later to control daylight glare or daylight illuminance 80: window has between-glass shade that is
10032 : // off but may be triggered on later to control daylight glare or daylight illuminance 90: window has
10033 : // between-glass blind that is off but may be triggered on later to control daylight glare or daylight illuminance
10034 1 : if (controlValue == -1.0) return WinShadingType::NoShade;
10035 1 : if (controlValue == 0.0) return WinShadingType::ShadeOff;
10036 1 : if (controlValue == 1.0) return WinShadingType::IntShade;
10037 0 : if (controlValue == 2.0) return WinShadingType::SwitchableGlazing;
10038 0 : if (controlValue == 3.0) return WinShadingType::ExtShade;
10039 0 : if (controlValue == 4.0) return WinShadingType::ExtScreen;
10040 0 : if (controlValue == 6.0) return WinShadingType::IntBlind;
10041 0 : if (controlValue == 7.0) return WinShadingType::ExtBlind;
10042 0 : if (controlValue == 8.0) return WinShadingType::BGShade;
10043 0 : if (controlValue == 9.0) return WinShadingType::BGBlind;
10044 0 : if (controlValue == 10.0) return WinShadingType::IntShadeConditionallyOff;
10045 0 : if (controlValue == 20.0) return WinShadingType::GlassConditionallyLightened;
10046 0 : if (controlValue == 30.0) return WinShadingType::ExtShadeConditionallyOff;
10047 0 : if (controlValue == 60.0) return WinShadingType::IntBlindConditionallyOff;
10048 0 : if (controlValue == 70.0) return WinShadingType::ExtBlindConditionallyOff;
10049 0 : if (controlValue == 80.0) return WinShadingType::BGShadeConditionallyOff;
10050 0 : if (controlValue == 90.0) return WinShadingType::BGBlindConditionallyOff;
10051 0 : return WinShadingType::Invalid;
10052 : }
10053 :
10054 32364 : int selectActiveWindowShadingControlIndex(EnergyPlusData &state, int curSurface)
10055 : {
10056 32364 : auto &s_surf = state.dataSurface;
10057 : // For a given surface, determine based on the schedules which index to the window shading control list vector
10058 : // should be active
10059 : // presume it is the first shading control - even if it is not active it needs to be some
10060 : // shading control which is then turned off in the WindowShadingManager
10061 32364 : if (s_surf->Surface(curSurface).windowShadingControlList.size() > 1) {
10062 6 : for (std::size_t listIndex = 0; listIndex < s_surf->Surface(curSurface).windowShadingControlList.size(); ++listIndex) {
10063 6 : int wsc = s_surf->Surface(curSurface).windowShadingControlList[listIndex];
10064 : // pick the first WindowShadingControl that has a non-zero schedule value
10065 6 : if (s_surf->WindowShadingControl(wsc).sched->getCurrentVal() > 0.0) {
10066 3 : return listIndex;
10067 : }
10068 : }
10069 : }
10070 32361 : return 0;
10071 : }
10072 :
10073 0 : void WindowGapAirflowControl(EnergyPlusData &state)
10074 : {
10075 :
10076 : // SUBROUTINE INFORMATION:
10077 : // AUTHOR Fred Winkelmann
10078 : // DATE WRITTEN February 2003
10079 : // MODIFIED June 2003, FCW: add fatal error for illegal schedule value
10080 : // RE-ENGINEERED na
10081 :
10082 : // PURPOSE OF THIS SUBROUTINE:
10083 : // For airflow windows, determines the airflow in the gap of
10084 : // double glazing and in the inner gap of triple glazing.
10085 :
10086 : // REFERENCES:
10087 : // na
10088 :
10089 0 : auto &s_surf = state.dataSurface;
10090 0 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
10091 0 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
10092 0 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
10093 0 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
10094 0 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
10095 0 : for (int ISurf = firstSurfWin; ISurf <= lastSurfWin; ++ISurf) {
10096 :
10097 0 : s_surf->SurfWinAirflowThisTS(ISurf) = 0.0;
10098 0 : if (s_surf->SurfWinMaxAirflow(ISurf) == 0.0) continue;
10099 0 : if (s_surf->Surface(ISurf).ExtBoundCond != ExternalEnvironment) continue;
10100 0 : switch (s_surf->SurfWinAirflowControlType(ISurf)) {
10101 0 : case WindowAirFlowControlType::MaxFlow: {
10102 0 : s_surf->SurfWinAirflowThisTS(ISurf) = s_surf->SurfWinMaxAirflow(ISurf);
10103 0 : } break;
10104 0 : case WindowAirFlowControlType::AlwaysOff: {
10105 0 : s_surf->SurfWinAirflowThisTS(ISurf) = 0.0;
10106 0 : } break;
10107 0 : case WindowAirFlowControlType::Schedule: {
10108 0 : if (s_surf->SurfWinAirflowHasSchedule(ISurf)) {
10109 0 : auto const *sched = s_surf->SurfWinAirflowScheds(ISurf);
10110 0 : Real64 ScheduleMult = sched->getCurrentVal(); // Multiplier value from schedule
10111 0 : if (ScheduleMult < 0.0 || ScheduleMult > 1.0) {
10112 0 : ShowFatalError(
10113 : state,
10114 0 : format("Airflow schedule has a value outside the range 0.0 to 1.0 for window={}", s_surf->Surface(ISurf).Name));
10115 : }
10116 0 : s_surf->SurfWinAirflowThisTS(ISurf) = ScheduleMult * s_surf->SurfWinMaxAirflow(ISurf);
10117 : }
10118 0 : } break;
10119 0 : default:
10120 0 : break;
10121 : }
10122 : } // End of surface loop
10123 : } // End of space loop
10124 : } // End of zone loop
10125 0 : }
10126 :
10127 113 : void SkyDifSolarShading(EnergyPlusData &state)
10128 : {
10129 :
10130 : // SUBROUTINE INFORMATION:
10131 : // AUTHOR Fred Winkelmann
10132 : // DATE WRITTEN May 1999
10133 : // MODIFIED Sep 2000, FCW: add IR view factor calc
10134 : // Sep 2002, FCW: correct error in expression for ground IR view factor.
10135 : // Affects only non-vertical surfaces that are shadowed. For these surfaces
10136 : // error caused underestimate of IR from ground and shadowing surfaces.
10137 : // Dec 2002; LKL: Sky Radiance Distribution now only anisotropic
10138 : // Nov 2003: FCW: modify to do sky solar shading of shadowing surfaces
10139 : // RE-ENGINEERED na
10140 :
10141 : // PURPOSE OF THIS SUBROUTINE:
10142 : // Calculates factors that account for shading of sky diffuse
10143 : // solar radiation by shadowing surfaces such as overhangs and detached
10144 : // shades.
10145 : // Called by PerformSolarCalculations
10146 : // For each exterior heat transfer surface calculates the following
10147 : // ratio (called DifShdgRatioIsoSky in this subroutine):
10148 : // R1 = (Diffuse solar from sky dome on surface, with shading)/
10149 : // (Diffuse solar from sky dome on surface, without shading)
10150 : // To calculate the incident diffuse radiation on a surface the sky
10151 : // hemisphere is divided into source elements ("patches"). Each patch
10152 : // is assumed to have the same radiance, i.e. the sky radiance is isotropic.
10153 : // The irradiance from each patch on a surface is calculated. Then these
10154 : // irradiances are summed to get the net irradiance on a surface, which
10155 : // the denominator of R1.
10156 : // To get the numerator of R1 the same summation is done, but for each surface
10157 : // and each patch the Shadow subroutine is called to determine how much
10158 : // radiation from a patch is blocked by shading surfaces.
10159 : // Also calculated is the following ratio (called DifShdgRatioHoriz in this routine):
10160 : // R2 = (Diffuse solar from sky horizon band on surface, with shading)/
10161 : // (Diffuse solar from sky horizon band on surface, without shading)
10162 : // For this ratio only a band of sky just above the horizon is considered.
10163 : // R1 and R2 are used in SUBROUTINE AnisoSkyViewFactors, which determines the
10164 : // sky diffuse solar irradiance on each exterior heat transfer surface each
10165 : // time step. In that routine the sky radiance distribution is a superposition
10166 : // of an isotropic distribution,
10167 : // a horizon brightening distribution and a circumsolar brightening distribution,
10168 : // where the proportion of each distribution depends
10169 : // on cloud cover, sun position and other factors. R1 multiplies the irradiance
10170 : // due to the isotropic component and R2 multiplies the irradiance due to the
10171 : // horizon brightening component.
10172 : // Calculates sky and ground IR view factors assuming sky IR is isotropic and
10173 : // shadowing surfaces are opaque to IR.
10174 :
10175 : // Using/Aliasing
10176 :
10177 : Real64 Fac1WoShdg; // Intermediate calculation factor, without shading
10178 : Real64 FracIlluminated; // Fraction of surface area illuminated by a sky patch
10179 : Real64 Fac1WithShdg; // Intermediate calculation factor, with shading
10180 : Real64 SurfArea; // Surface area (m2)
10181 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WithShdgIsoSky ! Diffuse solar irradiance from isotropic
10182 : // ! sky on surface, with shading
10183 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WoShdgIsoSky ! Diffuse solar from isotropic
10184 : // ! sky on surface, without shading
10185 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WithShdgHoriz ! Diffuse solar irradiance from horizon portion
10186 : // of
10187 : // ! sky on surface, with shading
10188 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WoShdgHoriz ! Diffuse solar irradiance from horizon portion
10189 : // of
10190 : // ! sky on surface, without shading
10191 : // INTEGER iHour,iTS
10192 :
10193 : // Initialize Surfaces Arrays
10194 113 : auto &s_surf = state.dataSurface;
10195 :
10196 122 : bool detailedShading = state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
10197 9 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal;
10198 113 : state.dataSolarShading->SurfSunlitArea = 0.0;
10199 113 : state.dataSolarShading->SurfWithShdgIsoSky.dimension(s_surf->TotSurfaces, 0.0);
10200 113 : state.dataSolarShading->SurfWoShdgIsoSky.dimension(s_surf->TotSurfaces, 0.0);
10201 113 : state.dataSolarShading->SurfWithShdgHoriz.dimension(s_surf->TotSurfaces, 0.0);
10202 113 : state.dataSolarShading->SurfWoShdgHoriz.dimension(s_surf->TotSurfaces, 0.0);
10203 113 : state.dataSolarShading->SurfDifShdgRatioIsoSky.allocate(s_surf->TotSurfaces);
10204 113 : state.dataSolarShading->SurfDifShdgRatioHoriz.allocate(s_surf->TotSurfaces);
10205 : // initialized as no shading
10206 113 : state.dataSolarShading->SurfDifShdgRatioIsoSky = 1.0;
10207 113 : state.dataSolarShading->SurfDifShdgRatioHoriz = 1.0;
10208 113 : if (detailedShading) {
10209 9 : state.dataSolarShading->SurfCurDifShdgRatioIsoSky.dimension(s_surf->TotSurfaces, 1.0);
10210 9 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS.allocate(state.dataGlobal->TimeStepsInHour, 24, s_surf->TotSurfaces);
10211 9 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS = 1.0;
10212 9 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS.allocate(state.dataGlobal->TimeStepsInHour, 24, s_surf->TotSurfaces);
10213 9 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS = 1.0;
10214 : }
10215 :
10216 659 : for (int SurfNum : s_surf->AllExtSolarSurfaceList) {
10217 546 : auto &surf = s_surf->Surface(SurfNum);
10218 :
10219 : // CurrentModuleObject='Surfaces'
10220 546 : if (detailedShading) {
10221 162 : SetupOutputVariable(state,
10222 : "Debug Surface Solar Shading Model DifShdgRatioIsoSky",
10223 : Constant::Units::None,
10224 81 : state.dataSolarShading->SurfCurDifShdgRatioIsoSky(SurfNum),
10225 : OutputProcessor::TimeStepType::Zone,
10226 : OutputProcessor::StoreType::Average,
10227 81 : surf.Name);
10228 : } else {
10229 930 : SetupOutputVariable(state,
10230 : "Debug Surface Solar Shading Model DifShdgRatioIsoSky",
10231 : Constant::Units::None,
10232 465 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum),
10233 : OutputProcessor::TimeStepType::Zone,
10234 : OutputProcessor::StoreType::Average,
10235 465 : surf.Name);
10236 : }
10237 1092 : SetupOutputVariable(state,
10238 : "Debug Surface Solar Shading Model DifShdgRatioHoriz",
10239 : Constant::Units::None,
10240 546 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum),
10241 : OutputProcessor::TimeStepType::Zone,
10242 : OutputProcessor::StoreType::Average,
10243 546 : surf.Name);
10244 1092 : SetupOutputVariable(state,
10245 : "Debug Surface Solar Shading Model WithShdgIsoSky",
10246 : Constant::Units::None,
10247 546 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum),
10248 : OutputProcessor::TimeStepType::Zone,
10249 : OutputProcessor::StoreType::Average,
10250 546 : surf.Name);
10251 1092 : SetupOutputVariable(state,
10252 : "Debug Surface Solar Shading Model WoShdgIsoSky",
10253 : Constant::Units::None,
10254 546 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum),
10255 : OutputProcessor::TimeStepType::Zone,
10256 : OutputProcessor::StoreType::Average,
10257 546 : surf.Name);
10258 : }
10259 :
10260 791 : for (int IPhi = 0; IPhi < NPhi; ++IPhi) { // Loop over patch altitude values
10261 678 : state.dataSolarShading->SUNCOS(3) = state.dataSolarShading->sin_Phi[IPhi];
10262 :
10263 16950 : for (int ITheta = 0; ITheta < NTheta; ++ITheta) { // Loop over patch azimuth values
10264 16272 : state.dataSolarShading->SUNCOS(1) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->cos_Theta[ITheta];
10265 16272 : state.dataSolarShading->SUNCOS(2) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->sin_Theta[ITheta];
10266 :
10267 94896 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
10268 78624 : auto &surf = s_surf->Surface(SurfNum);
10269 :
10270 : // Cosine of angle of incidence on surface of solar radiation from patch
10271 157248 : state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS.x * surf.OutNormVec.x +
10272 78624 : state.dataSolarShading->SUNCOS.y * surf.OutNormVec.y +
10273 78624 : state.dataSolarShading->SUNCOS.z * surf.OutNormVec.z;
10274 : }
10275 :
10276 16272 : SHADOW(state, 24, 0);
10277 :
10278 94896 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
10279 78624 : auto &surf = s_surf->Surface(SurfNum);
10280 :
10281 78624 : if (state.dataSolarShading->SurfSunCosTheta(SurfNum) < 0.0) continue;
10282 :
10283 42372 : Fac1WoShdg = state.dataSolarShading->cos_Phi[IPhi] * DThetaDPhi * state.dataSolarShading->SurfSunCosTheta(SurfNum);
10284 42372 : SurfArea = surf.NetAreaShadowCalc;
10285 42372 : if (SurfArea > Eps) {
10286 42372 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
10287 : } else {
10288 0 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / (SurfArea + Eps);
10289 : }
10290 42372 : Fac1WithShdg = Fac1WoShdg * FracIlluminated;
10291 42372 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) += Fac1WithShdg;
10292 42372 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) += Fac1WoShdg;
10293 :
10294 : // Horizon region
10295 42372 : if (IPhi == 0) {
10296 7047 : state.dataSolarShading->SurfWithShdgHoriz(SurfNum) += Fac1WithShdg;
10297 7047 : state.dataSolarShading->SurfWoShdgHoriz(SurfNum) += Fac1WoShdg;
10298 : }
10299 : } // End of surface loop
10300 : } // End of Theta loop
10301 : } // End of Phi loop
10302 :
10303 659 : for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
10304 :
10305 546 : if (std::abs(state.dataSolarShading->SurfWoShdgIsoSky(SurfNum)) > Eps) {
10306 494 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) =
10307 494 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum));
10308 : } else {
10309 52 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) =
10310 52 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) + Eps);
10311 : }
10312 546 : if (std::abs(state.dataSolarShading->SurfWoShdgHoriz(SurfNum)) > Eps) {
10313 494 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum) =
10314 494 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum));
10315 : } else {
10316 52 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum) =
10317 52 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum) + Eps);
10318 : }
10319 : }
10320 :
10321 : // Get IR view factors. An exterior surface can receive IR radiation from
10322 : // sky, ground or shadowing surfaces. Assume shadowing surfaces have same
10323 : // temperature as outside air (and therefore same temperature as ground),
10324 : // so that the view factor to these shadowing surfaces can be included in
10325 : // the ground view factor. Sky IR is assumed to be isotropic and shadowing
10326 : // surfaces are assumed to be opaque to IR so they totally "shade" IR from
10327 : // sky or ground.
10328 :
10329 945 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
10330 832 : auto &surface = s_surf->Surface(SurfNum);
10331 913 : if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm || !s_surf->ShadingTransmittanceVaries ||
10332 81 : state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
10333 751 : surface.ViewFactorSkyIR *= state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum);
10334 : } else {
10335 81 : surface.ViewFactorSkyIR *= state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(1, 1, SurfNum);
10336 : }
10337 832 : surface.ViewFactorGroundIR = 1.0 - surface.ViewFactorSkyIR;
10338 :
10339 832 : if (surface.SurfHasSurroundingSurfProperty) {
10340 1 : surface.ViewFactorGroundIR = 1.0 - surface.ViewFactorSkyIR - surface.ViewFactorSrdSurfs;
10341 : }
10342 : }
10343 :
10344 : // DEALLOCATE(WithShdgIsoSky)
10345 : // DEALLOCATE(WoShdgIsoSky)
10346 : // DEALLOCATE(WithShdgHoriz)
10347 : // DEALLOCATE(WoShdgHoriz)
10348 :
10349 122 : if (state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
10350 9 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
10351 90 : for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
10352 162 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS({1, state.dataGlobal->TimeStepsInHour}, {1, 24}, SurfNum) =
10353 162 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum);
10354 162 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS({1, state.dataGlobal->TimeStepsInHour}, {1, 24}, SurfNum) =
10355 162 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum);
10356 : }
10357 : }
10358 113 : }
10359 :
10360 71216 : void CalcWindowProfileAngles(EnergyPlusData &state)
10361 : {
10362 :
10363 : // SUBROUTINE INFORMATION:
10364 : // AUTHOR Fred Winkelmann
10365 : // DATE WRITTEN April 2002
10366 : // MODIFIED na
10367 : // RE-ENGINEERED na
10368 : // PURPOSE OF THIS SUBROUTINE:
10369 : // Called by CalcPerSolarBeam for wholly or partially sunlit exterior windows
10370 : // Calculates horizontal and vertical beam solar profile angles
10371 :
10372 : Real64 ElevSun; // Sun elevation; angle between sun and horizontal
10373 : Real64 ElevWin; // Window elevation: angle between window outward normal and horizontal
10374 : Real64 AzimWin; // Window azimuth (radians)
10375 : Real64 AzimSun; // Sun azimuth (radians)
10376 : Real64 ProfileAngHor; // Solar profile angle (radians) for horizontally oriented window elements
10377 : // such as the top and bottom of a frame.
10378 : // This is the incidence angle in a plane that is normal to the window
10379 : // and parallel to the Y-axis of the window (the axis along
10380 : // which the height of the window is measured).
10381 : Real64 ProfileAngVert; // Solar profile angle (radians) for vertically oriented elements
10382 : // such as the sides of a frame.
10383 : // This is the incidence angle in a plane that is normal to the window
10384 : // and parallel to the X-axis of the window (the axis along
10385 : // which the width of the window is measured).
10386 71216 : Vector3<Real64> WinNorm; // Unit vector normal to window
10387 71216 : Vector3<Real64> WinNormCrossBase; // Cross product of WinNorm and vector along window baseline
10388 71216 : Vector3<Real64> SunPrime; // Projection of sun vector onto plane (perpendicular to
10389 71216 : Vector3<Real64> const SolCosVec(state.dataEnvrn->SOLCOS); // Local Vector3 copy for speed (until SOLCOS mig to Vector3)
10390 : // window plane) determined by WinNorm and vector along
10391 : // baseline of window
10392 : Real64 ThWin; // Azimuth angle of WinNorm (radians)
10393 : Real64 dot1;
10394 : Real64 dot2;
10395 : Real64 dot3;
10396 :
10397 71216 : auto &s_surf = state.dataSurface;
10398 :
10399 71216 : ElevSun = Constant::PiOvr2 - std::acos(SolCosVec.z);
10400 71216 : AzimSun = std::atan2(SolCosVec.x, SolCosVec.y);
10401 :
10402 71216 : Real64 const cos_ElevSun = std::cos(ElevSun);
10403 71216 : Real64 const sin_ElevSun = std::sin(ElevSun);
10404 :
10405 170521 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
10406 212058 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
10407 112753 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
10408 112753 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
10409 112753 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
10410 143857 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
10411 31104 : auto &surf = s_surf->Surface(SurfNum);
10412 31104 : if (surf.ExtBoundCond != ExternalEnvironment && surf.ExtBoundCond != OtherSideCondModeledExt) continue;
10413 :
10414 31104 : s_surf->SurfWinProfileAngHor(SurfNum) = 0.0;
10415 31104 : s_surf->SurfWinProfileAngVert(SurfNum) = 0.0;
10416 31104 : if (state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) <= 0.0) continue;
10417 :
10418 16810 : ElevWin = Constant::PiOvr2 - surf.Tilt * Constant::DegToRad;
10419 16810 : AzimWin = surf.Azimuth * Constant::DegToRad;
10420 :
10421 16810 : ProfileAngHor = std::atan(sin_ElevSun / std::abs(cos_ElevSun * std::cos(AzimWin - AzimSun))) - ElevWin;
10422 :
10423 : // CR9280 - were having negative profile angles on west sides. commenting out previous code
10424 : // (original code) for vertical windows
10425 : // IF(ABS(ElevWin) < 0.1d0) THEN ! Near-vertical window
10426 : // ProfileAngVert = ABS(AzimWin-AzimSun)
10427 : // ELSE
10428 16810 : WinNorm = surf.OutNormVec;
10429 16810 : ThWin = AzimWin - Constant::PiOvr2;
10430 16810 : Real64 const sin_Elevwin(std::sin(ElevWin));
10431 16810 : WinNormCrossBase.x = -(sin_Elevwin * std::cos(ThWin));
10432 16810 : WinNormCrossBase.y = sin_Elevwin * std::sin(ThWin);
10433 16810 : WinNormCrossBase.z = std::cos(ElevWin);
10434 16810 : SunPrime = SolCosVec - WinNormCrossBase * dot(SolCosVec, WinNormCrossBase);
10435 16810 : dot1 = dot(WinNorm, SunPrime);
10436 16810 : dot2 = SunPrime.magnitude();
10437 16810 : dot3 = dot1 / dot2;
10438 16810 : if (dot3 > 1.0) {
10439 0 : dot3 = 1.0;
10440 16810 : } else if (dot3 < -1.0) {
10441 0 : dot3 = -1.0;
10442 : }
10443 : // ProfileAngVert =
10444 : // ABS(ACOS(DOT_PRODUCT(WinNorm,SunPrime)/SQRT(DOT_PRODUCT(SunPrime,SunPrime))))
10445 16810 : ProfileAngVert = std::abs(std::acos(dot3));
10446 : // END IF
10447 : // Constrain to 0 to pi
10448 16810 : if (ProfileAngVert > Constant::Pi) ProfileAngVert = Constant::TwoPi - ProfileAngVert;
10449 :
10450 16810 : s_surf->SurfWinProfileAngHor(SurfNum) = ProfileAngHor / Constant::DegToRad;
10451 16810 : s_surf->SurfWinProfileAngVert(SurfNum) = ProfileAngVert / Constant::DegToRad;
10452 16810 : s_surf->SurfWinTanProfileAngHor(SurfNum) = std::abs(std::tan(ProfileAngHor));
10453 16810 : s_surf->SurfWinTanProfileAngVert(SurfNum) = std::abs(std::tan(ProfileAngVert));
10454 : }
10455 : }
10456 : }
10457 71216 : }
10458 :
10459 17 : void CalcFrameDividerShadow(EnergyPlusData &state,
10460 : int const SurfNum, // Surface number
10461 : int const FrDivNum, // Frame/divider number
10462 : int const HourNum // Hour number
10463 : )
10464 : {
10465 :
10466 : // SUBROUTINE INFORMATION:
10467 : // AUTHOR Fred Winkelmann
10468 : // DATE WRITTEN June 2000
10469 : // MODIFIED Aug 2000, FW: add effective shadowing by inside
10470 : // projections
10471 : // RE-ENGINEERED na
10472 :
10473 : // PURPOSE OF THIS SUBROUTINE:
10474 : // Called by CalcPerSolarBeam for wholly or partially sunlit exterior windows
10475 : // with a frame and/or divider. Using beam solar profile angles,
10476 : // calculates fraction of glass shaded by exterior frame and divider projections,
10477 : // The frame and divider profiles are assumed to be rectangular.
10478 : // A similar shadowing approach is used to calculate the fraction of glass area
10479 : // that produces beam solar illumination on interior frame and divider projections.
10480 : // This fraction is used in CalcWinFrameAndDividerTemps to determine the
10481 : // beam solar absorbed by inside projections. Beam solar reflected by inside projections
10482 : // is assumed to stay in the zone (as beam solar) although in actuality roughly
10483 : // half of this is reflected back onto the glass and the half that is reflected
10484 : // into the zone is diffuse.
10485 : // For multipane glazing the effect of solar absorbed by the exposed portion of
10486 : // frame or divider between the panes is not calculated. Beam solar incident on
10487 : // these portions is assumed to be transmitted into the zone unchanged.
10488 : // The shadowing of diffuse solar radiation by projections is not considered.
10489 :
10490 : Real64 ElevSun; // Sun elevation; angle between sun and horizontal
10491 : Real64 ElevWin; // Window elevation: angle between window outward normal and horizontal
10492 : Real64 AzimWin; // Window azimuth (radians)
10493 : Real64 AzimSun; // Sun azimuth (radians)
10494 : Real64 ProfileAngHor; // Solar profile angle (radians) for horizontally oriented projections
10495 : // such as the top and bottom of a frame or horizontal dividers.
10496 : // This is the incidence angle in a plane that is normal to the window
10497 : // and parallel to the Y-axis of the window (the axis along
10498 : // which the height of the window is measured).
10499 : Real64 ProfileAngVert; // Solar profile angle (radians) for vertically oriented projections
10500 : // such as the top and bottom of a frame or horizontal dividers.
10501 : // This is the incidence angle in a plane that is normal to the window
10502 : // and parallel to the X-axis of the window (the axis along
10503 : // which the width of the window is measured).
10504 : Real64 TanProfileAngHor; // Tangent of ProfileAngHor
10505 : Real64 TanProfileAngVert; // Tangent of ProfileAngVert
10506 : Real64 FrWidth; // Frame width (m)
10507 : Real64 DivWidth; // Divider width (m)
10508 : Real64 FrProjOut; // Outside frame projection (m)
10509 : Real64 DivProjOut; // Outside divider projection (m)
10510 : Real64 FrProjIn; // Inside frame projection (m)
10511 : Real64 DivProjIn; // Inside divider projection (m)
10512 : int NHorDiv; // Number of horizontal dividers
10513 : int NVertDiv; // Number of vertical dividers
10514 : Real64 GlArea; // Glazed area (m2)
10515 : Real64 Arealite; // Area of a single lite of glass (m2); glazed area, GlArea,
10516 : // if there is no divider (in which case there is only one lite).
10517 : Real64 ArealiteCol; // Area of a vertical column of lites (m2)
10518 : Real64 ArealiteRow; // Area of a horizontal row of lites (m2)
10519 : Real64 AshVDout; // Shaded area from all vertical divider outside projections (m2)
10520 : Real64 AshVDin; // Shaded area from all vertical divider inside projections (m2)
10521 : Real64 AshHDout; // Shaded area from all horizontal divider outside projections (m2)
10522 : Real64 AshHDin; // Shaded area from all horizontal divider inside projections (m2)
10523 : Real64 AshVFout; // Shaded area from outside projection of vertical sides of frame (m2)
10524 : Real64 AshVFin; // Shaded area from inside projection of vertical sides of frame (m2)
10525 : Real64 AshHFout; // Shaded area from outside projection of horizontal sides
10526 : // (top) of frame (m2)
10527 : Real64 AshHFin; // Shaded area from inside projection of horizontal sides
10528 : // (top) of frame (m2)
10529 : Real64 AshDDover; // Divider/divider shadow overlap area (m2)
10530 : Real64 AshFFover; // Frame/frame shadow overlap area (m2)
10531 : Real64 AshFVDover; // Frame/vertical divider overlap area (m2)
10532 : Real64 AshFHDover; // Frame/horizontal divider overlap area (m2)
10533 : Real64 AshFDtotOut; // Total outside projection shadow area (m2)
10534 : Real64 AshFDtotIn; // Total inside projection shadow area (m2)
10535 : Real64 FracShFDOut; // Fraction of glazing shadowed by frame and divider
10536 : // outside projections
10537 : Real64 FracShFDin; // Fraction of glazing that illuminates frame and divider
10538 : // inside projections with beam radiation
10539 :
10540 17 : Vector3<Real64> WinNorm(3); // Window outward normal unit vector // Why the (3)?
10541 : Real64 ThWin; // Azimuth angle of WinNorm
10542 17 : Vector3<Real64> SunPrime(3); // Projection of sun vector onto plane (perpendicular to // Why the (3)?
10543 : // window plane) determined by WinNorm and vector along
10544 : // baseline of window
10545 17 : Vector3<Real64> WinNormCrossBase(3); // Cross product of WinNorm and vector along window baseline // Why the (3)?
10546 :
10547 17 : auto &s_surf = state.dataSurface;
10548 :
10549 17 : if (s_surf->FrameDivider(FrDivNum).FrameProjectionOut == 0.0 && s_surf->FrameDivider(FrDivNum).FrameProjectionIn == 0.0 &&
10550 17 : s_surf->FrameDivider(FrDivNum).DividerProjectionOut == 0.0 && s_surf->FrameDivider(FrDivNum).DividerProjectionIn == 0.0)
10551 0 : return;
10552 :
10553 17 : FrProjOut = s_surf->FrameDivider(FrDivNum).FrameProjectionOut;
10554 17 : FrProjIn = s_surf->FrameDivider(FrDivNum).FrameProjectionIn;
10555 17 : DivProjOut = s_surf->FrameDivider(FrDivNum).DividerProjectionOut;
10556 17 : DivProjIn = s_surf->FrameDivider(FrDivNum).DividerProjectionIn;
10557 :
10558 17 : auto &surf = s_surf->Surface(SurfNum);
10559 17 : GlArea = surf.Area;
10560 17 : ElevWin = Constant::PiOvr2 - surf.Tilt * Constant::DegToRad;
10561 17 : ElevSun = Constant::PiOvr2 - std::acos(state.dataSolarShading->SUNCOS(3));
10562 17 : AzimWin = surf.Azimuth * Constant::DegToRad;
10563 17 : AzimSun = std::atan2(state.dataSolarShading->SUNCOS(1), state.dataSolarShading->SUNCOS(2));
10564 :
10565 17 : ProfileAngHor = std::atan(std::sin(ElevSun) / std::abs(std::cos(ElevSun) * std::cos(AzimWin - AzimSun))) - ElevWin;
10566 17 : if (std::abs(ElevWin) < 0.1) { // Near-vertical window
10567 17 : ProfileAngVert = std::abs(AzimWin - AzimSun);
10568 : } else {
10569 0 : WinNorm = surf.OutNormVec;
10570 0 : ThWin = AzimWin - Constant::PiOvr2;
10571 0 : WinNormCrossBase(1) = -std::sin(ElevWin) * std::cos(ThWin);
10572 0 : WinNormCrossBase(2) = std::sin(ElevWin) * std::sin(ThWin);
10573 0 : WinNormCrossBase(3) = std::cos(ElevWin);
10574 0 : SunPrime = state.dataSolarShading->SUNCOS - WinNormCrossBase * dot(state.dataSolarShading->SUNCOS, WinNormCrossBase);
10575 0 : ProfileAngVert = std::abs(std::acos(dot(WinNorm, SunPrime) / magnitude(SunPrime)));
10576 : }
10577 : // Constrain to 0 to pi
10578 17 : if (ProfileAngVert > Constant::Pi) ProfileAngVert = 2 * Constant::Pi - ProfileAngVert;
10579 17 : TanProfileAngHor = std::abs(std::tan(ProfileAngHor));
10580 17 : TanProfileAngVert = std::abs(std::tan(ProfileAngVert));
10581 :
10582 17 : NHorDiv = s_surf->FrameDivider(FrDivNum).HorDividers;
10583 17 : NVertDiv = s_surf->FrameDivider(FrDivNum).VertDividers;
10584 17 : FrWidth = s_surf->FrameDivider(FrDivNum).FrameWidth;
10585 17 : DivWidth = s_surf->FrameDivider(FrDivNum).DividerWidth;
10586 :
10587 17 : Arealite = (surf.Height / (NHorDiv + 1.0) - DivWidth / 2.0) * (surf.Width / (NVertDiv + 1.0) - DivWidth / 2.0);
10588 17 : if (DivProjOut > 0.0 || DivProjIn > 0.0) {
10589 17 : ArealiteCol = (NHorDiv + 1) * Arealite;
10590 17 : ArealiteRow = (NVertDiv + 1) * Arealite;
10591 : } else {
10592 0 : ArealiteCol = GlArea;
10593 0 : ArealiteRow = GlArea;
10594 : }
10595 17 : AshVDout = 0.0;
10596 17 : AshVDin = 0.0;
10597 17 : AshHDout = 0.0;
10598 17 : AshHDin = 0.0;
10599 17 : AshVFout = 0.0;
10600 17 : AshVFin = 0.0;
10601 17 : AshHFout = 0.0;
10602 17 : AshHFin = 0.0;
10603 17 : AshDDover = 0.0;
10604 17 : AshFFover = 0.0;
10605 17 : AshFVDover = 0.0;
10606 17 : AshFHDover = 0.0;
10607 :
10608 17 : if (DivProjOut > 0.0 || DivProjIn > 0.0) {
10609 :
10610 : // Shaded area from all vertical dividers
10611 17 : AshVDout = NVertDiv * min((surf.Height - NHorDiv * DivWidth) * DivProjOut * TanProfileAngVert, ArealiteCol);
10612 17 : AshVDin = NVertDiv * min((surf.Height - NHorDiv * DivWidth) * DivProjIn * TanProfileAngVert, ArealiteCol);
10613 :
10614 : // Shaded area from all horizontal dividers
10615 17 : AshHDout = NHorDiv * min((surf.Width - NVertDiv * DivWidth) * DivProjOut * TanProfileAngHor, ArealiteRow);
10616 17 : AshHDin = NHorDiv * min((surf.Width - NVertDiv * DivWidth) * DivProjIn * TanProfileAngHor, ArealiteRow);
10617 :
10618 : // Horizontal divider/vertical divider shadow overlap
10619 17 : AshDDover = min(DivProjOut * TanProfileAngHor * DivProjOut * TanProfileAngVert, Arealite) * NHorDiv * NVertDiv;
10620 : }
10621 :
10622 17 : if (FrProjOut > 0.0 || FrProjIn > 0.0) {
10623 :
10624 : // Shaded area from sides of frame; to avoid complications from possible overlaps between
10625 : // shadow from side of frame and shadow from vertical divider the shaded area from side of
10626 : // frame is restricted to the area of one column of lites.
10627 17 : AshVFout = min((surf.Height - NHorDiv * DivWidth) * FrProjOut * TanProfileAngVert, ArealiteCol);
10628 17 : AshVFin = min((surf.Height - NHorDiv * DivWidth) * FrProjIn * TanProfileAngVert, ArealiteCol);
10629 :
10630 : // Shaded area from top or bottom of frame; to avoid complications from possible overlaps
10631 : // between shadow from top or bottom of frame and shadow from horizontal divider, the shaded
10632 : // area from the top or bottom of frame is restricted to the area of one row of lites.
10633 17 : AshHFout = min((surf.Width - NVertDiv * DivWidth) * FrProjOut * TanProfileAngHor, ArealiteRow);
10634 17 : AshHFin = min((surf.Width - NVertDiv * DivWidth) * FrProjIn * TanProfileAngHor, ArealiteRow);
10635 :
10636 : // Top/bottom of frame/side of frame shadow overlap
10637 17 : AshFFover = min(FrProjOut * TanProfileAngHor * FrProjOut * TanProfileAngVert, Arealite);
10638 17 : if (DivProjOut > 0.0) {
10639 : // Frame/vertical divider shadow overlap
10640 17 : AshFVDover = min(FrProjOut * DivProjOut * TanProfileAngHor * TanProfileAngVert, Arealite) * NVertDiv;
10641 : // Frame/horizontal divider shadow overlap
10642 17 : AshFHDover = min(FrProjOut * DivProjOut * TanProfileAngHor * TanProfileAngVert, Arealite) * NHorDiv;
10643 : }
10644 : }
10645 :
10646 17 : AshFDtotOut = AshVDout + AshHDout + AshVFout + AshHFout - (AshDDover + AshFFover + AshFVDover + AshFHDover);
10647 17 : AshFDtotIn =
10648 17 : (AshVDin + AshHDin) * s_surf->FrameDivider(FrDivNum).DividerSolAbsorp + (AshVFin + AshHFin) * s_surf->FrameDivider(FrDivNum).FrameSolAbsorp;
10649 :
10650 : // Divide by the glazed area of the window
10651 17 : FracShFDOut = AshFDtotOut / GlArea;
10652 17 : FracShFDin = AshFDtotIn / GlArea;
10653 17 : s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[HourNum] = 1.0 - FracShFDOut;
10654 17 : s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[HourNum] = 1.0 - (FracShFDin + FracShFDOut);
10655 17 : }
10656 :
10657 3 : void CalcBeamSolarOnWinRevealSurface(EnergyPlusData &state)
10658 : {
10659 :
10660 : // SUBROUTINE INFORMATION:
10661 : // AUTHOR F. Winkelmann
10662 : // DATE WRITTEN April 2002
10663 : // MODIFIED:na
10664 : // RE-ENGINEERED:na
10665 :
10666 : // PURPOSE OF THIS SUBROUTINE
10667 : // Called by InitHeatGains when the sun is up.
10668 : // Calculates beam solar radiation absorbed and reflected by top, bottom,
10669 : // right and left sides of outside and inside window reveal surfaces.
10670 : // In doing this calculation, the shadowing on a reveal surface by other reveal surfaces
10671 : // is determined using the orientation of the reveal surfaces and the sun position.
10672 : // It is assumed that:
10673 : // (1) The window is an exterior window and is rectangular.
10674 : // (2) The reveal surfaces are perpendicular to the window plane.
10675 : // (3) If an exterior shade or blind is in place, there is no beam solar on
10676 : // on exterior or interior reveal surfaces.
10677 : // (3) If an interior shade or blind is in place, there is no beam solar on
10678 : // interior reveal surfaces.
10679 : // (4) The effect of window divider, if present, is ignored, including shadowing
10680 : // of divider on inside reveal surfaces.
10681 :
10682 : // In the variable names, the "subscript" 1 = outside reveal, 2 = inside reveal
10683 : // The outside reveal surfaces (top, bottom, left, right) are assumed to have the same depth
10684 : // (given by Surface%Reveal and determined from vertices of window and vertices of parent
10685 : // wall) and the same solar absorptance. The inside reveal surfaces are divided into
10686 : // two categories: (1) the bottom reveal surface, called here the "inside sill;" and
10687 : // the other reveal surfaces (left, right and top). The left, right and top inside reveal
10688 : // surfaces are assumed to have the same depth and solar absorptance.
10689 : // The depth of the outside reveal is measured from the outside surface of the glazing;
10690 : // The depth of the inside sill and the other reveal surfaces is measured from the inside
10691 : // surface of the glazing. The inside sill is
10692 : // allowed to have depth and solar absorptance values that are different from the corresponding
10693 : // values for the other inside reveal surfaces. The inside sill depth is required to be
10694 : // greater than or equal to the depth of the other inside reveal surfaces. If the inside sill
10695 : // depth is greater than zero the depth of the other inside reveal surfaces is required to
10696 : // to be greater than zero.
10697 : // The reflection of beam solar radiation from all reveal surfaces is assumed to be isotropic
10698 : // diffuse; there is no specular component. Half of the beam solar reflected from outside
10699 : // reveal surfaces is assumed to go towards the window; the other half is assumed to go back
10700 : // to the exterior environment (i.e., reflection of this outward-going component from
10701 : // other outside reveal surfaces is not considered). The half that goes towards the window
10702 : // is added to the other radiation incident on the window.
10703 : // Correspondingly, half of the beam solar reflected from inside reveal surfaces is assumed
10704 : // to go towards the window, with the other half going into the zone (this half, and the portion
10705 : // going towards the window that is reflected) is added in CalcInteriorSolarDistribution
10706 : // to the variable BTOTzone, which is the total beam solar entering the zone as beam or diffuse.
10707 : // The portion going towards the window that is not reflected is absorbed in the glazing or
10708 : // transmitted back out into the exterior environment.
10709 : // The beam solar that is absorbed by outside reveal surfaces is added to the solar absorbed
10710 : // by the outside surface of the window's parent wall; similarly, the beam solar absorbed
10711 : // by the inside reveal surfaces is added to the solar absorbed by the inside surface of the
10712 : // parent wall (and is subtracted from BTOTzone).
10713 : // The net effect of beam solar reflected from outside reveal surfaces is to INCREASE the
10714 : // the heat gain to the zone, whereas the effect of beam solar reflected from interior reveal
10715 : // surfaces is to DECREASE the heat gain to the zone since part of this reflected solar is
10716 : // transmitted back out the window.
10717 : // If the window has a frame, the absorption of reflected beam solar by the inside and outside
10718 : // surfaces of the frame is considered. The shadowing of the frame onto interior reveal
10719 : // surfaces is also considered.
10720 :
10721 : // The total glazing thickness is taken to be the sum of the thickness of the glass layers
10722 : // and between-glass gas layers. If the window has an exterior, movable, storm window glass layer
10723 : // the presence of this layer and its adjacent air gap is considered in calculating the glazing
10724 : // properties (solar transmittance, etc.). But the storm window glass is assumed to be close
10725 : // enough to the rest of the glazing that its effect on total glazing thickness and outside
10726 : // reveal depth can be ignored.
10727 :
10728 : // METHODOLOGY EMPLOYED
10729 : // na
10730 :
10731 : // REFERENCES
10732 : // na
10733 :
10734 : // Locals
10735 : // SUBROUTINE ARGUMENT DEFINITIONS:na
10736 :
10737 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS
10738 :
10739 : int ConstrNum; // Construction number
10740 : int ConstrNumSh; // Shaded construction number
10741 : Real64 CosBetaBottom; // Cosine of beam solar angle of incidence on bottom reveal
10742 : Real64 CosBetaLeft; // Cosine of beam solar angle of incidence on left reveal
10743 : Real64 CosBeta; // ABS of CosBetaBottom or CosBetaLeft
10744 : Real64 d1; // Depth of outside reveal + half of glazing thickness (m)
10745 : Real64 d2; // Depth of inside sill or of inside reveal plus half of glazing thickness (m)
10746 : Real64 d2prime; // Depth of shadow cast on a reveal surface by opposite reveal (m)
10747 : Real64 d2prime2; // Depth of shadow cast by frame onto inside reveal (m)
10748 : Real64 d12; // d12 = d1 + d2 - d2prime (m)
10749 : Real64 TanAlpha; // Tangent of horizontal or vertical profile angle
10750 : Real64 TanGamma; // Tangent of vertical or horizontal profile angle
10751 : Real64 H; // Window height, width (m)
10752 : Real64 W;
10753 : Real64 L; // Window height or width (m)
10754 : Real64 A1sh; // Shadowed area of outside horizontal or vertical reveal (m2)
10755 : Real64 A2sh; // Shadowed area of inside horizontal or vertical reveal (m2)
10756 : Real64 A1ill; // Illuminated area of outside horizontal or vertical reveal (m2)
10757 : Real64 A2ill; // Illuminated area of inside horizontal or vertical reveal (m2)
10758 : Real64 SolTransGlass; // Beam solar transmittance of glazing
10759 : Real64 SolTransGlassSh; // For switchable glazing, beam solar trans in switched state
10760 : Real64 DiffReflGlass; // Diffuse back reflectance of glazing
10761 : Real64 DiffReflGlassSh; // For switchable glazing, diffuse back refl in switched state
10762 : int HorVertReveal; // Index: 1 = horizontal reveal, 2 = vertical reveal
10763 : Real64 OutsReveal; // Depth of outside reveal (from outside glazing plane to outside wall plane) (m)
10764 : Real64 InsReveal; // Depth of inside reveal (from inside glazing plane to inside wall plane (m)
10765 : Real64 InsSillDepth; // Depth of inside sill, measured from innermost face of glazing (m)
10766 : Real64 GlazingThickness; // Thickness of glazing, measured from innermost face to outermost face (m)
10767 : Real64 InsideRevealSolAbs; // Solar absorptance of inside reveal or inside sill
10768 : Real64 BmSolRefldOutsReveal; // Multiplied by beam solar gives beam solar reflected by horiz or vertical
10769 : // outside reveal surface (m2)
10770 : Real64 BmSolRefldInsReveal; // Multiplied by beam solar gives beam solar reflected by horiz or vertical
10771 : // inside reveal surface (m2)
10772 : WinShadingType ShadeFlag; // Shading flag
10773 : int FrameDivNum; // Frame/Divider number
10774 : Real64 FrameWidth; // Frame width (m)
10775 : Real64 P1; // Frame outside/inside projection plus half of glazing thickness (m)
10776 : Real64 P2;
10777 : Real64 f1; // f1=d1-P1, f2=d2-P2 (m)
10778 : Real64 f2;
10779 : Real64 L1; // Average distance of outside/inside illuminated area to frame;
10780 : Real64 L2;
10781 : // used in calculating view factor to frame (m)
10782 : Real64 FracToGlassOuts; // View factor from outside horizontal or vertical reveal to glass
10783 : Real64 FracToGlassIns; // View factor from inside horizontal or vertical reveal to glass
10784 : Real64 TanProfileAngVert; // Tangent of vertical profile angle (the profile angle appropriate for
10785 : // vertical reveal surfaces.
10786 : Real64 TanProfileAngHor; // Tangent of horizontal profile angle (the profile angle appropriate for
10787 : // horizontal reveal surfaces.
10788 :
10789 : Real64 tmp_SunlitFracWithoutReveal; // Temporary variable
10790 :
10791 3 : auto &s_surf = state.dataSurface;
10792 :
10793 6 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
10794 6 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
10795 3 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
10796 3 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
10797 3 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
10798 9 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
10799 : // Added TH for initialization. CR 7596 inside reveal causing high cooling loads
10800 : // for outside reveals
10801 6 : s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) = 0.0;
10802 6 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) = 0.0;
10803 6 : s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfNum) = 0.0;
10804 6 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) = 0.0;
10805 6 : s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) = 0.0;
10806 : // for inside reveals
10807 6 : s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) = 0.0;
10808 6 : s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) = 0.0;
10809 6 : s_surf->SurfWinBmSolRefldInsReveal(SurfNum) = 0.0;
10810 6 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) = 0.0;
10811 6 : s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfNum) = 0.0;
10812 6 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) = 0.0;
10813 6 : s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) = 0.0;
10814 6 : s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) = 0.0;
10815 6 : s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) = 0.0;
10816 6 : s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) = 0.0;
10817 6 : s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) = 0.0;
10818 :
10819 6 : auto &surf = s_surf->Surface(SurfNum);
10820 6 : if ((surf.ExtBoundCond != ExternalEnvironment && surf.ExtBoundCond != OtherSideCondModeledExt)) continue;
10821 6 : if (surf.Reveal == 0.0 && s_surf->SurfWinInsideReveal(SurfNum) == 0.0 && s_surf->SurfWinInsideSillDepth(SurfNum) == 0.0) continue;
10822 6 : if (surf.Sides != 4) continue;
10823 6 : if (s_surf->SurfWinInsideSillDepth(SurfNum) < s_surf->SurfWinInsideReveal(SurfNum)) continue;
10824 :
10825 6 : ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum);
10826 6 : if ((ShadeFlag == WinShadingType::ExtShade) || (ShadeFlag == WinShadingType::ExtBlind)) continue;
10827 :
10828 6 : if (state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) <= 0.0) continue;
10829 :
10830 6 : tmp_SunlitFracWithoutReveal =
10831 6 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
10832 :
10833 : // Calculate cosine of angle of incidence of beam solar on reveal surfaces,
10834 : // assumed to be perpendicular to window plane
10835 :
10836 6 : CosBetaBottom = -state.dataEnvrn->SOLCOS(1) * surf.SinAzim * surf.CosTilt - state.dataEnvrn->SOLCOS(2) * surf.CosAzim * surf.CosTilt +
10837 6 : state.dataEnvrn->SOLCOS(3) * surf.SinTilt;
10838 :
10839 6 : CosBetaLeft = -state.dataEnvrn->SOLCOS(1) * surf.CosAzim - state.dataEnvrn->SOLCOS(2) * surf.SinAzim;
10840 :
10841 : // Note: CosBetaTop = -CosBetaBottom, CosBetaRight = -CosBetaLeft
10842 :
10843 6 : OutsReveal = surf.Reveal;
10844 6 : InsReveal = s_surf->SurfWinInsideReveal(SurfNum);
10845 6 : InsideRevealSolAbs = 0.0;
10846 6 : GlazingThickness = s_surf->SurfWinTotGlazingThickness(SurfNum);
10847 6 : H = surf.Height;
10848 6 : W = surf.Width;
10849 6 : d1 = OutsReveal + 0.5 * GlazingThickness;
10850 6 : ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
10851 6 : ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(SurfNum);
10852 6 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
10853 :
10854 6 : SolTransGlass = Window::POLYF(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum),
10855 6 : thisConstruct.TransSolBeamCoef);
10856 6 : TanProfileAngVert = s_surf->SurfWinTanProfileAngVert(SurfNum);
10857 6 : TanProfileAngHor = s_surf->SurfWinTanProfileAngHor(SurfNum);
10858 6 : FrameDivNum = surf.FrameDivider;
10859 6 : FrameWidth = 0.0;
10860 6 : if (FrameDivNum != 0) {
10861 6 : FrameWidth = s_surf->FrameDivider(FrameDivNum).FrameWidth;
10862 6 : if (FrameWidth > 0.0) {
10863 6 : P1 = s_surf->FrameDivider(FrameDivNum).FrameProjectionOut + 0.5 * GlazingThickness;
10864 6 : P2 = s_surf->FrameDivider(FrameDivNum).FrameProjectionIn + 0.5 * GlazingThickness;
10865 6 : if (OutsReveal + 0.5 * GlazingThickness <= P1) d1 = P1 + 0.001;
10866 : }
10867 : }
10868 : // Loop over vertical and horizontal reveal surfaces
10869 18 : for (HorVertReveal = 1; HorVertReveal <= 2; ++HorVertReveal) {
10870 :
10871 12 : FracToGlassOuts = 0.5;
10872 12 : FracToGlassIns = 0.5;
10873 12 : BmSolRefldOutsReveal = 0.0;
10874 12 : BmSolRefldInsReveal = 0.0;
10875 12 : A1ill = 0.0;
10876 12 : A2ill = 0.0;
10877 :
10878 : // Added TH. 5/27/2009
10879 12 : A1sh = 0.0;
10880 12 : A2sh = 0.0;
10881 :
10882 12 : if (HorVertReveal == 1) { // Vertical reveal
10883 6 : TanAlpha = TanProfileAngHor;
10884 6 : TanGamma = TanProfileAngVert;
10885 6 : CosBeta = std::abs(CosBetaLeft);
10886 6 : L = surf.Height;
10887 6 : d2 = InsReveal + 0.5 * GlazingThickness;
10888 6 : d2prime = d1 + d2 - W / TanGamma;
10889 6 : InsideRevealSolAbs = s_surf->SurfWinInsideRevealSolAbs(SurfNum);
10890 : } else { // Horizontal reveal
10891 6 : InsSillDepth = s_surf->SurfWinInsideSillDepth(SurfNum);
10892 6 : TanAlpha = TanProfileAngVert;
10893 6 : TanGamma = TanProfileAngHor;
10894 6 : CosBeta = std::abs(CosBetaBottom);
10895 6 : L = surf.Width;
10896 6 : if (CosBetaBottom > 0.0) { // Bottom reveal surfaces may be illuminated
10897 6 : d2 = InsSillDepth + 0.5 * GlazingThickness;
10898 6 : InsideRevealSolAbs = s_surf->SurfWinInsideSillSolAbs(SurfNum);
10899 : } else { // Top reveal surfaces may be illuminated
10900 0 : d2 = InsReveal + 0.5 * GlazingThickness;
10901 0 : InsideRevealSolAbs = s_surf->SurfWinInsideRevealSolAbs(SurfNum);
10902 : }
10903 6 : d2prime = d1 + d2 - H / TanGamma;
10904 : }
10905 12 : if (d2prime < 0.0) d2prime = 0.0; // No shadow from opposing reveal
10906 12 : d12 = d1 + d2 - d2prime;
10907 :
10908 12 : if (FrameWidth <= 0.001) {
10909 : // Window without frame
10910 :
10911 : // Find inside and outside shadowed area of vertical or horizontal reveal surfaces
10912 : // that can be illuminated by beam solar; shadowing is by other reveal surfaces.
10913 :
10914 0 : if (d2prime <= d2) {
10915 0 : if (d12 * TanAlpha <= L) {
10916 0 : A1sh = 0.5 * TanAlpha * pow_2(d1);
10917 0 : A2sh = d2prime * L + 0.5 * TanAlpha * pow_2(d12) - A1sh;
10918 : } else { // d12*TanAlpha > L
10919 0 : if (d1 * TanAlpha <= L) {
10920 0 : A1sh = 0.5 * TanAlpha * pow_2(d1);
10921 0 : A2sh = d2 * L - 0.5 * TanAlpha * pow_2(L / TanAlpha - d1);
10922 : } else { // d1*TanAlpha > L
10923 0 : A1sh = d1 * L - (0.5 / TanAlpha) * pow_2(L);
10924 0 : A2sh = d2 * L;
10925 : }
10926 : }
10927 : } else { // d2prime > d2
10928 0 : A2sh = d2 * L;
10929 0 : if (d2prime < d1 + d2) {
10930 0 : if (d12 * TanAlpha <= L) {
10931 0 : A1sh = L * (d2prime - d2) + 0.5 * TanAlpha * pow_2(d12);
10932 : } else { // d12*TanAlpha > L
10933 0 : A1sh = d1 * L - 0.5 * pow_2(L) / TanAlpha;
10934 : }
10935 : } else { // d2prime >= d1+d2
10936 0 : A1sh = d1 * L;
10937 : }
10938 : }
10939 :
10940 : // Added TH. 5/27/2009
10941 0 : if (A1sh < 0.0) A1sh = 0.0;
10942 0 : if (A2sh < 0.0) A2sh = 0.0;
10943 :
10944 0 : if (OutsReveal >= 0.001) A1ill = d1 * L - A1sh; // A1ill = 0.0 if OutsReveal < 0.001
10945 0 : if (InsReveal >= 0.001) A2ill = d2 * L - A2sh; // A2ill = 0.0 if InsReveal < 0.001
10946 :
10947 : } else { // Window with frame; take into account shadowing
10948 : // of inside reveal surfaces by frame
10949 12 : f1 = d1 - P1;
10950 12 : f2 = d2 - P2;
10951 12 : d2prime2 = FrameWidth / TanGamma;
10952 12 : if (HorVertReveal == 1) { // Vertical reveal
10953 6 : if (InsReveal + 0.5 * GlazingThickness <= P2) d2 = P2 + 0.001;
10954 : } else { // Horizontal
10955 6 : if (CosBetaBottom > 0.0) { // Bottom reveal surfaces may be illuminated
10956 6 : if (InsSillDepth + 0.5 * GlazingThickness <= P2) d2 = P2 + 0.001;
10957 : } else { // Top reveal surfaces may be illuminated
10958 0 : if (InsReveal + 0.5 * GlazingThickness <= P2) d2 = P2 + 0.001;
10959 : }
10960 : }
10961 :
10962 12 : if (d2prime <= f2) { // Shadow from opposing reveal does not go beyond inside surface of frame
10963 :
10964 10 : if (d12 * TanAlpha <= L) {
10965 5 : A1sh = 0.5 * TanAlpha * pow_2(f1);
10966 5 : L1 = f1 * (f1 * TanAlpha / (6.0 * L) + 0.5);
10967 5 : if (d2 - (d2prime + d2prime2 + P2) >= 0.0) {
10968 5 : A2sh = (d2prime + d2prime2) * L + 0.5 * TanAlpha * (pow_2(d1 + d2 - d2prime) - pow_2(d1 + P2 + d2prime2));
10969 5 : L2 = d2prime2 + 0.5 * (d2 - (d2prime + d2prime2 + P2));
10970 : } else { // d2-(d2prime+d2prime2+P2) < 0. ! Inside reveal is fully shadowed by
10971 : // frame and/or opposing reveal
10972 0 : A2sh = f2 * L;
10973 0 : L2 = f2;
10974 : }
10975 : } else { // d12*TanAlpha >= L
10976 5 : if ((d1 + P2) * TanAlpha <= L) {
10977 5 : A1sh = 0.5 * TanAlpha * pow_2(f1);
10978 5 : L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
10979 5 : if ((d1 + P2 + d2prime2) * TanAlpha >= L) {
10980 0 : A2sh = f2 * L;
10981 0 : L2 = f2;
10982 : } else { // (d1+P2+d2prime2)*TanAlpha < L
10983 5 : A2sh = f2 * L - 0.5 * pow_2(L - (d1 + P2) * TanAlpha) / TanAlpha +
10984 5 : d2prime2 * (L - (d1 + P2 + d2prime2 / 2.0) * TanAlpha);
10985 5 : L2 = d2prime2 + (L / TanAlpha - (d1 + P2 + d2prime2)) / 3.0;
10986 : }
10987 : } else { // (d1+P2)*TanAlpha > L
10988 0 : L2 = f2;
10989 0 : A2sh = f2 * L;
10990 0 : if (f1 * TanAlpha <= L) {
10991 0 : A1sh = 0.5 * TanAlpha * pow_2(f1);
10992 0 : L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
10993 : } else { // f1*TanAlpha > L
10994 0 : A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
10995 0 : L1 = f1 - (L / TanAlpha) / 3.0;
10996 : }
10997 : }
10998 : }
10999 :
11000 : } else { // d2prime > f2 ! Shadow from opposing reveal goes beyond inside of frame
11001 :
11002 2 : A2sh = f2 * L;
11003 2 : L2 = f2;
11004 2 : if (d2prime >= d1 + d2) {
11005 0 : A1sh = 0.0;
11006 0 : L1 = f1;
11007 : } else { // d2prime < d1+d2
11008 2 : if (d2prime <= d2 + P1) {
11009 2 : if (f1 * TanAlpha <= L) {
11010 2 : A1sh = 0.5 * TanAlpha * pow_2(f1);
11011 2 : L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
11012 : } else { // f1*TanAlpha > L
11013 0 : A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
11014 0 : L1 = f1 - (L / TanAlpha) / 3.0;
11015 : }
11016 : } else { // d2prime > d2+P1
11017 0 : if (d12 * TanAlpha <= L) {
11018 0 : A1sh = L * (d2prime - (d2 + P1)) + 0.5 * TanAlpha * pow_2(d12);
11019 0 : L1 = (L * (f1 - d12 / 2.0) - d12 * TanAlpha * (f1 / 2 - d12 / 3.0)) / (L - d12 * TanAlpha / 2.0);
11020 : } else { // d12*TanAlpha > L
11021 0 : A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
11022 0 : L1 = f1 - (L / TanAlpha) / 3.0;
11023 : }
11024 : }
11025 : }
11026 : }
11027 :
11028 : // Added TH. 5/27/2009
11029 12 : if (A1sh < 0.0) A1sh = 0.0;
11030 12 : if (A2sh < 0.0) A2sh = 0.0;
11031 :
11032 12 : if (OutsReveal >= P1 + 0.5 * GlazingThickness + 0.001) A1ill = L * f1 - A1sh;
11033 12 : if (InsReveal >= P2 + 0.5 * GlazingThickness + 0.001) A2ill = L * f2 - A2sh;
11034 12 : if (L1 == 0.0) {
11035 0 : FracToGlassOuts = 0.0;
11036 : } else {
11037 12 : FracToGlassOuts = 0.5 * (1.0 - std::atan(FrameWidth / L1) / Constant::PiOvr2);
11038 : }
11039 12 : if (L2 == 0.0) {
11040 0 : FracToGlassIns = 0.0;
11041 : } else {
11042 12 : FracToGlassIns = 0.5 * (1.0 - std::atan(FrameWidth / L2) / Constant::PiOvr2);
11043 : }
11044 : } // End of check if window has frame
11045 :
11046 : // Added TH. 5/27/2009
11047 12 : if (A1ill < 0.0) A1ill = 0.0;
11048 12 : if (A2ill < 0.0) A2ill = 0.0;
11049 :
11050 : // Quantities related to outside reveal
11051 12 : if (A1ill > Constant::OneMillionth) {
11052 :
11053 0 : s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) +=
11054 0 : A1ill * s_surf->SurfWinOutsideRevealSolAbs(SurfNum) * CosBeta * tmp_SunlitFracWithoutReveal;
11055 :
11056 0 : BmSolRefldOutsReveal = A1ill * (1.0 - s_surf->SurfWinOutsideRevealSolAbs(SurfNum)) * CosBeta * tmp_SunlitFracWithoutReveal;
11057 :
11058 0 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) += state.dataEnvrn->BeamSolarRad * BmSolRefldOutsReveal;
11059 0 : s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfNum) =
11060 0 : s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) * state.dataGlobal->TimeStepZoneSec;
11061 :
11062 : // Reflected solar from outside horizontal and vertical reveal incident on glazing
11063 0 : s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) += FracToGlassOuts * BmSolRefldOutsReveal / surf.Area;
11064 :
11065 0 : if (FrameWidth > 0.0) {
11066 : // Reflected solar from outside horizontal and vertical reveal incident on frame
11067 0 : s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) +=
11068 0 : (0.5 - FracToGlassOuts) * BmSolRefldOutsReveal / s_surf->SurfWinFrameArea(SurfNum);
11069 : }
11070 :
11071 : } // End of check if A1ill > 0.0 (actually 10^-6)
11072 :
11073 : // Quantities related to inside reveal; inside reveal reflection/absorption is assumed
11074 : // to occur only if an interior shade or blind is not in place.
11075 :
11076 12 : if (NOT_SHADED(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
11077 :
11078 12 : if (A2ill > Constant::OneMillionth) {
11079 :
11080 10 : DiffReflGlass = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
11081 10 : if (ShadeFlag == WinShadingType::SwitchableGlazing) {
11082 0 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
11083 : SolTransGlassSh =
11084 0 : Window::POLYF(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum),
11085 0 : thisConstructSh.TransSolBeamCoef);
11086 0 : SolTransGlass = Window::InterpSw(s_surf->SurfWinSwitchingFactor(SurfNum), SolTransGlass, SolTransGlassSh);
11087 0 : DiffReflGlassSh = thisConstructSh.ReflectSolDiffBack;
11088 0 : DiffReflGlass = Window::InterpSw(s_surf->SurfWinSwitchingFactor(SurfNum), DiffReflGlass, DiffReflGlassSh);
11089 : }
11090 :
11091 : // Calc beam solar absorbed (m2)
11092 10 : s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +=
11093 10 : A2ill * SolTransGlass * InsideRevealSolAbs * CosBeta * tmp_SunlitFracWithoutReveal;
11094 :
11095 : // Added TH 5/26/2009 for reporting purpose - Beam solar absorbed by the inside reveal
11096 : // (W)
11097 10 : s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) +=
11098 10 : state.dataEnvrn->BeamSolarRad * A2ill * SolTransGlass * InsideRevealSolAbs * CosBeta * tmp_SunlitFracWithoutReveal;
11099 :
11100 : // in m2 = Area * solar transmitted fraction * inside reveal reflection fraction
11101 10 : BmSolRefldInsReveal = A2ill * SolTransGlass * (1.0 - InsideRevealSolAbs) * CosBeta * tmp_SunlitFracWithoutReveal;
11102 :
11103 10 : s_surf->SurfWinBmSolRefldInsReveal(SurfNum) += BmSolRefldInsReveal;
11104 :
11105 10 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) +=
11106 10 : state.dataEnvrn->BeamSolarRad * BmSolRefldInsReveal; // W, BeamSolarRad in W/m2
11107 10 : s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfNum) =
11108 10 : s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) * state.dataGlobal->TimeStepZoneSec;
11109 :
11110 : // Reflected solar from inside horizontal and vertical reveal incident on glazing
11111 10 : s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) += FracToGlassIns * BmSolRefldInsReveal / surf.Area;
11112 :
11113 : // Added TH 5/26/2009 for reporting purpose - diffuse on window glass from inside
11114 : // reveal (W)
11115 10 : s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) +=
11116 10 : state.dataEnvrn->BeamSolarRad * FracToGlassIns * BmSolRefldInsReveal;
11117 :
11118 : // Reflected solar from inside horizontal and vertical reveal incident on frame
11119 10 : if (FrameWidth > 0.0) {
11120 10 : s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) +=
11121 10 : (0.5 - FracToGlassIns) * BmSolRefldInsReveal / s_surf->SurfWinFrameArea(SurfNum);
11122 :
11123 : // Added TH 5/26/2009 for reporting purpose - diffuse on window frame from inside
11124 : // reveal (W)
11125 10 : s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) +=
11126 10 : state.dataEnvrn->BeamSolarRad * (0.5 - FracToGlassIns) * BmSolRefldInsReveal;
11127 : }
11128 :
11129 : // Reflected solar from inside reveal going directly into zone and reflected from
11130 : // glass. Assumes half of solar reflected from inside reveal goes as diffuse radiation
11131 : // into the zone and half goes as diffuse radiation towards window.
11132 10 : s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) += BmSolRefldInsReveal * (0.5 + DiffReflGlass * FracToGlassIns);
11133 :
11134 : // Added TH 5/26/2009 for reporting purpose - diffuse into zone from inside reveal (W)
11135 10 : s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) +=
11136 10 : state.dataEnvrn->BeamSolarRad * BmSolRefldInsReveal * (0.5 + DiffReflGlass * FracToGlassIns);
11137 :
11138 : } // End of check if A2ill > 0.0 (actually 10^-6)
11139 :
11140 : } // End of check if interior shade or blind is in place
11141 :
11142 : } // End of loop over vertical and horizontal reveal
11143 :
11144 : } // End of surface loop
11145 : }
11146 : }
11147 3 : }
11148 :
11149 249964 : void ReportSurfaceShading(EnergyPlusData &state)
11150 : {
11151 :
11152 : // SUBROUTINE INFORMATION:
11153 : // AUTHOR Linda Lawrie
11154 : // DATE WRITTEN April 2000
11155 : // MODIFIED na
11156 : // RE-ENGINEERED na
11157 :
11158 : // PURPOSE OF THIS SUBROUTINE:
11159 : // This subroutine uses the internal variables used in the Shading
11160 : // calculations and prepares them for reporting (at timestep level).
11161 :
11162 : // METHODOLOGY EMPLOYED:
11163 : // Because all of the calculations are done on a "daily" basis in this
11164 : // module, it is difficult to formulate the values that might be useful
11165 : // for reporting. SunlitFrac was the first of these two arrays to be
11166 : // made into "two dimensions". It is not clear that both have to be
11167 : // two dimensions.
11168 :
11169 : // REFERENCES:
11170 : // na
11171 :
11172 : // Using/Aliasing
11173 : using namespace OutputReportPredefined;
11174 :
11175 : // Locals
11176 : // SUBROUTINE ARGUMENT DEFINITIONS:
11177 : // na
11178 :
11179 : // SUBROUTINE PARAMETER DEFINITIONS:
11180 : // na
11181 :
11182 : // INTERFACE BLOCK SPECIFICATIONS
11183 : // na
11184 :
11185 : // DERIVED TYPE DEFINITIONS
11186 : // na
11187 :
11188 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
11189 : int SurfNum; // Loop Counter
11190 : int RepCol; // the column of the predefined report
11191 :
11192 249964 : auto &s_surf = state.dataSurface;
11193 2359397 : for (SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
11194 2109433 : auto &surf = s_surf->Surface(SurfNum);
11195 :
11196 2109433 : s_surf->SurfSunlitFrac(SurfNum) = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
11197 2109433 : s_surf->SurfSunlitArea(SurfNum) =
11198 2109433 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) * surf.Area;
11199 : }
11200 : // added for predefined reporting
11201 249964 : RepCol = 0;
11202 249964 : if (state.dataEnvrn->Month == 3 && state.dataEnvrn->DayOfMonth == 21) {
11203 0 : if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
11204 0 : RepCol = state.dataOutRptPredefined->pdchSlfMar21_9;
11205 0 : } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
11206 0 : RepCol = state.dataOutRptPredefined->pdchSlfMar21_12;
11207 0 : } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
11208 0 : RepCol = state.dataOutRptPredefined->pdchSlfMar21_15;
11209 : }
11210 249964 : } else if (state.dataEnvrn->Month == 6 && state.dataEnvrn->DayOfMonth == 21) {
11211 0 : if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
11212 0 : RepCol = state.dataOutRptPredefined->pdchSlfJun21_9;
11213 0 : } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
11214 0 : RepCol = state.dataOutRptPredefined->pdchSlfJun21_12;
11215 0 : } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
11216 0 : RepCol = state.dataOutRptPredefined->pdchSlfJun21_15;
11217 : }
11218 249964 : } else if (state.dataEnvrn->Month == 12 && state.dataEnvrn->DayOfMonth == 21) {
11219 73882 : if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
11220 472 : RepCol = state.dataOutRptPredefined->pdchSlfDec21_9;
11221 73410 : } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
11222 472 : RepCol = state.dataOutRptPredefined->pdchSlfDec21_12;
11223 72938 : } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
11224 472 : RepCol = state.dataOutRptPredefined->pdchSlfDec21_15;
11225 : }
11226 : }
11227 249964 : if (RepCol != 0) {
11228 9936 : for (SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
11229 8520 : auto &surf = s_surf->Surface(SurfNum);
11230 8520 : if (surf.Class == SurfaceClass::Window) {
11231 24 : PreDefTableEntry(state, RepCol, surf.Name, s_surf->SurfSunlitFrac(SurfNum));
11232 : }
11233 : }
11234 : }
11235 249964 : }
11236 :
11237 26 : void ReportSurfaceErrors(EnergyPlusData &state)
11238 : {
11239 :
11240 : // SUBROUTINE INFORMATION:
11241 : // AUTHOR Linda Lawrie
11242 : // DATE WRITTEN November 2004
11243 : // MODIFIED na
11244 : // RE-ENGINEERED na
11245 :
11246 : // PURPOSE OF THIS SUBROUTINE:
11247 : // This subroutine reports some recurring type errors that can get mixed up with more important
11248 : // errors in the error file.
11249 :
11250 : using namespace DataErrorTracking; // for error tracking
11251 :
11252 26 : static Array1D_string const MSG(4, {"misses", "", "within", "overlaps"});
11253 :
11254 : int Loop1;
11255 : int Loop2;
11256 : int Count;
11257 : int TotCount;
11258 26 : Array1D_bool SurfErrorReported;
11259 26 : Array1D_bool SurfErrorReported2;
11260 :
11261 26 : auto &s_surf = state.dataSurface;
11262 :
11263 26 : if (state.dataSolarShading->NumTooManyFigures + state.dataSolarShading->NumTooManyVertices + state.dataSolarShading->NumBaseSubSurround > 0) {
11264 0 : ShowMessage(state, "");
11265 0 : ShowMessage(state, "===== Recurring Surface Error Summary =====");
11266 0 : ShowMessage(state, "The following surface error messages occurred.");
11267 0 : ShowMessage(state, "");
11268 :
11269 0 : if (state.dataSolarShading->NumBaseSubSurround > 0) {
11270 0 : ShowMessage(state, "Base Surface does not surround subsurface errors occurring...");
11271 0 : ShowMessage(state,
11272 : "Check that the GlobalGeometryRules object is expressing the proper starting corner and "
11273 : "direction [CounterClockwise/Clockwise]");
11274 0 : ShowMessage(state, "");
11275 : }
11276 :
11277 0 : SurfErrorReported.dimension(s_surf->TotSurfaces, false);
11278 0 : TotCount = 0;
11279 0 : for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumBaseSubSurround; ++Loop1) {
11280 0 : Count = 0;
11281 0 : if (SurfErrorReported(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1)) continue;
11282 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumBaseSubSurround; ++Loop2) {
11283 0 : if (state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1 ==
11284 0 : state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex1 &&
11285 0 : state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex == state.dataSolarShading->TrackBaseSubSurround(Loop2).MiscIndex) {
11286 0 : ++Count;
11287 : }
11288 : }
11289 0 : TotCount += Count;
11290 0 : state.dataErrTracking->TotalWarningErrors += Count - 1;
11291 0 : ShowWarningError(state,
11292 0 : format("Base surface does not surround subsurface (CHKSBS), Overlap Status={}",
11293 0 : state.dataSolarShading->cOverLapStatus(state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex)));
11294 0 : ShowContinueError(state, format(" The base surround errors occurred {} times.", Count));
11295 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumBaseSubSurround; ++Loop2) {
11296 0 : if (state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1 ==
11297 0 : state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex1 &&
11298 0 : state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex == state.dataSolarShading->TrackBaseSubSurround(Loop2).MiscIndex) {
11299 0 : ShowContinueError(state,
11300 0 : format("Surface \"{}\" {} SubSurface \"{}\"",
11301 0 : s_surf->Surface(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1).Name,
11302 0 : MSG(state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex),
11303 0 : s_surf->Surface(state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex2).Name));
11304 : }
11305 : }
11306 0 : SurfErrorReported(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1) = true;
11307 : }
11308 0 : if (TotCount > 0) {
11309 0 : ShowMessage(state, "");
11310 0 : ShowContinueError(state, format(" The base surround errors occurred {} times (total).", TotCount));
11311 0 : ShowMessage(state, "");
11312 : }
11313 :
11314 0 : SurfErrorReported2.allocate(s_surf->TotSurfaces);
11315 0 : SurfErrorReported = false;
11316 0 : TotCount = 0;
11317 0 : if (state.dataSolarShading->NumTooManyVertices > 0) {
11318 0 : ShowMessage(state, format("Too many vertices [>={}] in shadow overlap errors occurring...", state.dataSolarShading->MaxHCV));
11319 0 : ShowMessage(state,
11320 : "These occur throughout the year and may occur several times for the same surfaces. You "
11321 : "may be able to reduce them by "
11322 : "adding Output:Diagnostics,DoNotMirrorDetachedShading;");
11323 : }
11324 0 : for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumTooManyVertices; ++Loop1) {
11325 0 : Count = 0;
11326 0 : SurfErrorReported2 = false;
11327 0 : if (SurfErrorReported(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1)) continue;
11328 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyVertices; ++Loop2) {
11329 0 : if (state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1 ==
11330 0 : state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex1) {
11331 0 : ++Count;
11332 : }
11333 : }
11334 0 : TotCount += Count;
11335 0 : state.dataErrTracking->TotalWarningErrors += Count - 1;
11336 0 : ShowMessage(state, "");
11337 0 : ShowWarningError(state, format("Too many vertices [>={}] in a shadow overlap", state.dataSolarShading->MaxHCV));
11338 0 : ShowContinueError(state,
11339 0 : format("Overlapping figure={}, Surface Class=[{}]",
11340 0 : s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1).Name,
11341 0 : cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1).Class)));
11342 0 : ShowContinueError(state, format(" This error occurred {} times.", Count));
11343 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyVertices; ++Loop2) {
11344 0 : if (state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1 ==
11345 0 : state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex1) {
11346 0 : if (SurfErrorReported2(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2)) continue;
11347 0 : ShowContinueError(state,
11348 0 : format("Figure being Overlapped={}, Surface Class=[{}]",
11349 0 : s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2).Name,
11350 0 : cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2).Class)));
11351 0 : SurfErrorReported2(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2) = true;
11352 : }
11353 : }
11354 0 : SurfErrorReported(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1) = true;
11355 : }
11356 0 : if (TotCount > 0) {
11357 0 : ShowMessage(state, "");
11358 0 : ShowContinueError(state, format(" The too many vertices errors occurred {} times (total).", TotCount));
11359 0 : ShowMessage(state, "");
11360 : }
11361 :
11362 0 : SurfErrorReported = false;
11363 0 : TotCount = 0;
11364 0 : if (state.dataSolarShading->NumTooManyFigures > 0) {
11365 0 : ShowMessage(state, format("Too many figures [>={}] in shadow overlap errors occurring...", state.dataSolarShading->MaxHCS));
11366 0 : ShowMessage(state,
11367 : "These occur throughout the year and may occur several times for the same surfaces. You "
11368 : "may be able to reduce them by "
11369 : "adding OutputDiagnostics,DoNotMirrorDetachedShading;");
11370 : }
11371 0 : for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumTooManyFigures; ++Loop1) {
11372 0 : Count = 0;
11373 0 : SurfErrorReported2 = false;
11374 0 : if (SurfErrorReported(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1)) continue;
11375 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyFigures; ++Loop2) {
11376 0 : if (state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1 == state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex1) {
11377 0 : ++Count;
11378 : }
11379 : }
11380 0 : TotCount += Count;
11381 0 : state.dataErrTracking->TotalWarningErrors += Count - 1;
11382 0 : ShowMessage(state, "");
11383 0 : ShowWarningError(state, format("Too many figures [>={}] in a shadow overlap", state.dataSolarShading->MaxHCS));
11384 0 : ShowContinueError(state,
11385 0 : format("Overlapping figure={}, Surface Class=[{}]",
11386 0 : s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1).Name,
11387 0 : cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1).Class)));
11388 0 : ShowContinueError(state, format(" This error occurred {} times.", Count));
11389 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyFigures; ++Loop2) {
11390 0 : if (state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1 == state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex1) {
11391 0 : if (SurfErrorReported2(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2)) continue;
11392 0 : ShowContinueError(state,
11393 0 : format("Figure being Overlapped={}, Surface Class=[{}]",
11394 0 : s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2).Name,
11395 0 : cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2).Class)));
11396 0 : SurfErrorReported2(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2) = true;
11397 : }
11398 : }
11399 0 : SurfErrorReported(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1) = true;
11400 : }
11401 0 : if (TotCount > 0) {
11402 0 : ShowMessage(state, "");
11403 0 : ShowContinueError(state, format(" The too many figures errors occurred {} times (total).", TotCount));
11404 0 : ShowMessage(state, "");
11405 : }
11406 0 : SurfErrorReported.deallocate();
11407 0 : SurfErrorReported2.deallocate();
11408 : }
11409 26 : }
11410 :
11411 114 : void ComputeWinShadeAbsorpFactors(EnergyPlusData &state)
11412 : {
11413 :
11414 : // SUBROUTINE INFORMATION:
11415 : // AUTHOR Fred Winkelmann
11416 : // DATE WRITTEN Mar 2001
11417 : // MODIFIED Oct 2002,FCW: change ConstrNumSh =
11418 : // WindowShadingControl(WinShadeCtrlNum)%ShadedConstruction
11419 : // to Surface(SurfNum)%ShadedConstruction
11420 : // RE-ENGINEERED na
11421 :
11422 : // PURPOSE OF THIS SUBROUTINE:
11423 : // Called by InitSolarCalculations. Finds fractions that apportion radiation absorbed by a
11424 : // window shade to the two faces of the shade. For radiation incident from the left,
11425 : // ShadeAbsFacFace(1) is the fraction of radiation absorbed in the left-hand half of the
11426 : // of the shade and ShadeAbsFacFace(2) is the fraction absorbed in the right-hand half.
11427 : // The shade is assumed to be homogeneous.
11428 :
11429 : // REFERENCES: See EnergyPlus engineering documentation
11430 : // USE STATEMENTS: na
11431 114 : auto &s_mat = state.dataMaterial;
11432 114 : auto &s_surf = state.dataSurface;
11433 :
11434 247 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
11435 284 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
11436 151 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
11437 151 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
11438 151 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
11439 207 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
11440 56 : auto &surf = s_surf->Surface(SurfNum);
11441 56 : if (surf.Class == SurfaceClass::Window && surf.HasShadeControl) {
11442 8 : int WinShadeCtrlNum = surf.activeWindowShadingControl; // Window shading control number
11443 :
11444 8 : int MatNumSh = 0; // Shade layer material number
11445 8 : Real64 AbsorpEff = 0.0; // Effective absorptance of isolated shade layer (fraction of
11446 : // of incident radiation remaining after reflected portion is
11447 : // removed that is absorbed
11448 8 : if (ANY_SHADE(s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType)) {
11449 0 : int const ConstrNumSh = surf.activeShadedConstruction; // Window construction number with shade
11450 0 : int TotLay = state.dataConstruction->Construct(ConstrNumSh).TotLayers; // Total layers in a construction
11451 :
11452 0 : if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::IntShade) {
11453 0 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay); // Interior shade
11454 0 : } else if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::ExtShade) {
11455 0 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(1); // Exterior shade
11456 0 : } else if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::BGShade) {
11457 0 : if (state.dataConstruction->Construct(ConstrNumSh).TotGlassLayers == 2) {
11458 : // Double pane with between-glass shade
11459 0 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(3);
11460 : } else {
11461 : // Triple pane with between-glass shade
11462 0 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(5);
11463 : }
11464 : }
11465 :
11466 0 : auto const *matSh = s_mat->materials(MatNumSh);
11467 0 : auto const *matFenSh = dynamic_cast<Material::MaterialFen const *>(matSh);
11468 0 : assert(matFenSh != nullptr);
11469 0 : AbsorpEff = matFenSh->AbsorpSolar / (matFenSh->AbsorpSolar + matFenSh->Trans + 0.0001);
11470 0 : AbsorpEff = min(max(AbsorpEff, 0.0001),
11471 : 0.999); // Constrain to avoid problems with following log eval
11472 0 : s_surf->SurfWinShadeAbsFacFace1(SurfNum) = (1.0 - std::exp(0.5 * std::log(1.0 - AbsorpEff))) / AbsorpEff;
11473 0 : s_surf->SurfWinShadeAbsFacFace2(SurfNum) = 1.0 - s_surf->SurfWinShadeAbsFacFace1(SurfNum);
11474 : }
11475 : }
11476 : }
11477 : }
11478 : }
11479 114 : }
11480 :
11481 71220 : void CalcWinTransDifSolInitialDistribution(EnergyPlusData &state)
11482 : {
11483 :
11484 : // SUBROUTINE INFORMATION:
11485 : // AUTHOR Rob Hitchcock
11486 : // DATE WRITTEN July 2007
11487 : // MODIFIED N/A
11488 : // RE-ENGINEERED N/A
11489 :
11490 : // PURPOSE OF THIS SUBROUTINE:
11491 : // This subroutine calculates the initial distribution
11492 : // of diffuse solar transmitted through exterior windows
11493 : // to individual heat transfer surfaces in each zone(or enclosure).
11494 :
11495 : // METHODOLOGY EMPLOYED:
11496 : // Apportions diffuse solar transmitted through each exterior window
11497 : // that is then absorbed, reflected, and/or transmitted
11498 : // by other heat transfer surfaces in the zone.
11499 : // Calculations use:
11500 : // 1. WinDifSolar calculated in SUBROUTINE CalcInteriorSolarDistribution,
11501 : // 2. view factors between each exterior window and
11502 : // other heat transfer surfaces in a zone
11503 : // calculated in SUBROUTINE CalcApproximateViewFactors, and
11504 : // 3. surface absorptances, reflectances, and transmittances
11505 : // determined here using revised code from SUBROUTINE InitIntSolarDistribution
11506 :
11507 : // Using/Aliasing
11508 : using namespace DataViewFactorInformation;
11509 : using namespace DataWindowEquivalentLayer;
11510 :
11511 : Real64 AbsInt; // Tmp var for Inside surface short-wave absorptance
11512 : Real64 InsideDifAbsorptance; // Inside diffuse solar absorptance of a surface
11513 : Real64 InsideDifReflectance; // Inside diffuse solar reflectance of a surface
11514 : int BlNum; // Blind number
11515 : Real64 BlAbsDiffBk; // Glass layer back diffuse solar absorptance when blind in place
11516 : Real64 AbsDiffBkBl; // Blind diffuse back solar absorptance as part of glazing system
11517 :
11518 : // REAL(r64) :: DividerSolAbs ! Window divider solar absorptance
11519 : // REAL(r64) :: DividerSolRefl ! Window divider solar reflectance
11520 : // INTEGER :: MatNumGl ! Glass layer material number
11521 : // INTEGER :: MatNumSh ! Shade layer material number
11522 : // REAL(r64) :: TransGl,ReflGl,AbsGl ! Glass layer solar transmittance, reflectance, absorptance
11523 :
11524 71220 : Real64 ViewFactor = 0.0; // temp var for view factor
11525 : // Real64 ViewFactorTotal; // debug var for view factor total
11526 71220 : Real64 WinDifSolarTrans = 0.0; // debug var for WinDifSolar() [W]
11527 : // Real64 WinDifSolarDistTotl; // debug var for window total
11528 : // distributed diffuse solar [W] Real64 WinDifSolarDistAbsorbedTotl; // debug
11529 : // var for individual exterior window total distributed
11530 : // diffuse solar absorbed [W]
11531 : // Real64 WinDifSolarDistReflectedTotl; // debug var for individual exterior window total distributed
11532 : // diffuse solar reflected [W]
11533 : // Real64 WinDifSolarDistTransmittedTotl; // debug var for individual exterior window total distributed
11534 : // diffuse solar transmitted [W]
11535 71220 : Real64 WinDifSolLayAbsW = 0.0; // temp var for diffuse solar absorbed by individual glass layer [W]
11536 : // Real64 ZoneDifSolarTrans; // debug var for WinDifSolar() [W]
11537 : // Real64 ZoneDifSolarDistTotl; // debug var for zone total
11538 : // distributed diffuse solar [W] Real64 ZoneDifSolarDistAbsorbedTotl; //
11539 : // debug var for zone total distributed diffuse solar absorbed [W] Real64
11540 : // ZoneDifSolarDistReflectedTotl; // debug var for zone total distributed
11541 : // diffuse solar reflected [W] Real64 ZoneDifSolarDistTransmittedTotl; //
11542 : // debug var for zone total distributed diffuse solar transmitted [W]
11543 :
11544 71220 : Real64 DifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by surface [W]
11545 71220 : Real64 DifSolarAbs = 0.0; // temp var for diffuse solar absorbed by surface [W/m2]
11546 71220 : Real64 DifSolarReflW = 0.0; // temp var for diffuse solar reflected by surface [W]
11547 71220 : Real64 ShBlDifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by shade/blind [W]
11548 :
11549 71220 : Array2D<Real64> SurfWinAbsSolBeamEQL(2, CFSMAXNL + 1); // absorbed exterior beam radiation by layers fraction
11550 : Array2D<Real64> SurfWinAbsSolDiffEQL(2,
11551 71220 : CFSMAXNL + 1); // absorbed exterior diffuse radiation by layers fraction
11552 71220 : Array2D<Real64> SurfWinAbsSolBeamBackEQL(2, CFSMAXNL + 1); // absorbed interior beam radiation by layers fraction from back
11553 71220 : Array2D<Real64> AbsSolDiffBackEQL(2, CFSMAXNL + 1); // absorbed exterior diffuse radiation by layers fraction from back
11554 : int EQLNum; // equivalent layer fenestration index
11555 : int Lay; // equivalent layer fenestration layer index
11556 :
11557 71220 : auto &s_surf = state.dataSurface;
11558 :
11559 : // Init accumulators for absorbed diffuse solar for all surfaces for later heat balance calcs
11560 71220 : state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs = 0.0;
11561 71220 : state.dataHeatBal->SurfWinInitialDifSolwinAbs = 0.0;
11562 :
11563 : // Init accumulator for total reflected diffuse solar within each zone for interreflection calcs
11564 71220 : state.dataHeatBal->EnclSolInitialDifSolReflW = 0.0;
11565 :
11566 : // Init accumulator for transmitted diffuse solar for all surfaces for reporting
11567 71220 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans = 0.0;
11568 :
11569 : // Loop over all zones doing initial distribution of diffuse solar to interior heat transfer surfaces
11570 177270 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
11571 106050 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
11572 : // Init Zone accumulators for debugging
11573 : // ZoneDifSolarTrans = 0.0;
11574 : // ZoneDifSolarDistAbsorbedTotl = 0.0;
11575 : // ZoneDifSolarDistReflectedTotl = 0.0;
11576 : // ZoneDifSolarDistTransmittedTotl = 0.0;
11577 : // Loop over all diffuse solar transmitting surfaces (i.e., exterior windows and TDDs) in the current zone
11578 719221 : for (int const DifTransSurfNum : thisEnclosure.SurfacePtr) {
11579 : // Skip surfaces that are not exterior, except for TDD_Diffusers
11580 613171 : auto &difTransSurf = s_surf->Surface(DifTransSurfNum);
11581 613171 : if ((difTransSurf.ExtBoundCond != ExternalEnvironment) && (difTransSurf.ExtBoundCond != OtherSideCondModeledExt) &&
11582 208431 : (difTransSurf.OriginalClass != SurfaceClass::TDD_Diffuser))
11583 208431 : continue;
11584 :
11585 : // Do I need to do anything special for TDDs?
11586 : // if ( SurfaceWindow( DifTransSurfNum ).OriginalClass == SurfaceClass::TDD_Diffuser )
11587 : // {
11588 : // }
11589 :
11590 : // Skip surfaces that are not exterior windows or TDD diffusers
11591 404740 : if (difTransSurf.Class != SurfaceClass::Window && difTransSurf.OriginalClass != SurfaceClass::TDD_Diffuser) continue;
11592 :
11593 : //----------------------------------------------------------------------------------------------------------
11594 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH EXTERIOR WINDOWS AND TDDS TO INTERIOR HEAT TRANSFER
11595 : // SURFACES
11596 : //----------------------------------------------------------------------------------------------------------
11597 :
11598 : // Init transmitted solar debug vars
11599 : // ViewFactorTotal = 0.0;
11600 31114 : WinDifSolarTrans = s_surf->SurfWinDifSolar(DifTransSurfNum);
11601 : // ZoneDifSolarTrans += WinDifSolarTrans;
11602 :
11603 : // Init Exterior Window accumulators for debugging
11604 : // WinDifSolarDistAbsorbedTotl = 0.0;
11605 : // WinDifSolarDistReflectedTotl = 0.0;
11606 : // WinDifSolarDistTransmittedTotl = 0.0;
11607 :
11608 : // Loop over all heat transfer surfaces in the current zone that might receive diffuse solar
11609 425000 : for (int const HeatTransSurfNum : thisEnclosure.SurfacePtr) {
11610 : // Skip surfaces that are not heat transfer surfaces
11611 : // Skip tubular daylighting device domes
11612 393886 : auto &surf = s_surf->Surface(HeatTransSurfNum);
11613 :
11614 393886 : if (surf.Class == SurfaceClass::TDD_Dome) continue;
11615 :
11616 : // View factor from current (sending) window DifTransSurfNum to current (receiving) surface
11617 : // HeatTransSurfNum
11618 393886 : int const HTenclosureSurfNum = surf.SolarEnclSurfIndex; // HT surface index for EnclSolInfo.SurfacePtr and F arrays
11619 393886 : int const enclosureNum = surf.SolarEnclIndex; // index for EnclSolInfo
11620 : int const DTenclSurfNum =
11621 393886 : s_surf->Surface(DifTransSurfNum).SolarEnclSurfIndex; // Window surface index for EnclSolInfo.SurfacePtr and F arrays
11622 :
11623 393886 : ViewFactor = state.dataViewFactor->EnclSolInfo(enclosureNum).F(HTenclosureSurfNum, DTenclSurfNum);
11624 : // debug ViewFactorTotal
11625 : // ViewFactorTotal += ViewFactor; // debug
11626 :
11627 : // Skip receiving surfaces with 0.0 view factor
11628 393886 : if (ViewFactor <= 0.0) continue;
11629 :
11630 297136 : Real64 const WinDifSolarTrans_Factor(WinDifSolarTrans * ViewFactor);
11631 297136 : Real64 const win_SwitchingFactor(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum));
11632 297136 : Real64 const per_HTSurfaceArea(1.0 / surf.Area);
11633 :
11634 : // Calculate diffuse solar from current exterior window absorbed and reflected by current heat
11635 : // transfer surface And calculate transmitted diffuse solar to adjacent zones through interior
11636 : // windows
11637 297136 : int const ConstrNum = s_surf->SurfActiveConstruction(HeatTransSurfNum);
11638 297136 : if (state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) { // Interior Opaque Surface
11639 :
11640 : // Determine the inside (back) diffuse solar absorptance
11641 : // and reflectance of the current heat transfer surface
11642 219812 : InsideDifAbsorptance = state.dataHeatBalSurf->SurfAbsSolarInt(HeatTransSurfNum);
11643 : // Inside (back) diffuse solar reflectance is assumed to be 1 - absorptance
11644 219812 : InsideDifReflectance = 1.0 - InsideDifAbsorptance;
11645 :
11646 : // Absorbed diffuse solar [W] = current window transmitted diffuse solar [W]
11647 : // * view factor from current (sending) window DifTransSurfNum to current (receiving)
11648 : // surface HeatTransSurfNum
11649 : // * current surface inside solar absorptance
11650 219812 : DifSolarAbsW = WinDifSolarTrans_Factor * InsideDifAbsorptance; // [W]
11651 :
11652 : // Absorbed diffuse solar [W/m2] = Absorbed diffuse solar [W]
11653 : // / current surface net area
11654 219812 : DifSolarAbs = DifSolarAbsW * per_HTSurfaceArea;
11655 :
11656 : // Accumulate absorbed diffuse solar [W/m2] on this surface for heat balance calcs
11657 219812 : state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs(HeatTransSurfNum) += DifSolarAbs;
11658 :
11659 : // Reflected diffuse solar [W] = current window transmitted diffuse solar
11660 : // * view factor from current (sending) window DifTransSurfNum to current (receiving)
11661 : // surface HeatTransSurfNum
11662 : // * current window inside solar reflectance
11663 219812 : DifSolarReflW = WinDifSolarTrans_Factor * InsideDifReflectance;
11664 :
11665 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
11666 : // interreflection calcs
11667 219812 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
11668 :
11669 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of
11670 : // energy For opaque surfaces all incident diffuse is either absorbed or reflected
11671 :
11672 : } else { // Exterior or Interior Window
11673 77324 : int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(HeatTransSurfNum);
11674 77324 : int TotGlassLayers = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
11675 77324 : WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(HeatTransSurfNum);
11676 :
11677 77324 : if (s_surf->SurfWinWindowModelType(HeatTransSurfNum) != WindowModel::EQL) {
11678 77322 : if (NOT_SHADED(ShadeFlag)) { // No window shading
11679 : // Init accumulator for transmittance calc below
11680 77322 : DifSolarAbsW = 0.0;
11681 :
11682 : // Calc diffuse solar absorbed by all window glass layers
11683 : // Note: I am assuming here that individual glass layer absorptances have been
11684 : // corrected
11685 : // to account for layer by layer transmittance and reflection effects.
11686 154686 : for (int IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
11687 : // Calc diffuse solar absorbed from the inside by each window glass layer [W]
11688 77364 : AbsInt = state.dataConstruction->Construct(ConstrNum).AbsDiffBack(IGlass);
11689 77364 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).AbsDiffBack(IGlass);
11690 :
11691 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
11692 : // transmittance calc below
11693 77364 : DifSolarAbsW += WinDifSolLayAbsW;
11694 :
11695 : // Accumulate diffuse solar absorbed from the inside by each window glass layer
11696 : // [W/m2] for heat balance calcs
11697 77364 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
11698 : }
11699 :
11700 : // Calc diffuse solar reflected back to zone
11701 : // I don't really care if this is a window or opaque surface since I am just
11702 : // accumulating all reflected diffuse solar in a zone bucket for "interreflected"
11703 : // distribution Reflected diffuse solar [W] = current window transmitted diffuse solar
11704 : // * view factor from current (sending) window DifTransSurfNum to current
11705 : // (receiving) surface HeatTransSurfNum
11706 : // * current window inside solar reflectance
11707 77322 : InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
11708 77322 : DifSolarReflW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
11709 :
11710 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
11711 : // interreflection calcs
11712 77322 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
11713 :
11714 : //------------------------------------------------------------------------------
11715 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
11716 : //------------------------------------------------------------------------------
11717 :
11718 : // If this receiving window surface (HeatTransSurfNum) is an interior window,
11719 : // calc distributed solar transmitted to adjacent zone [W]
11720 : // NOTE: This calc is here because interior windows are currently assumed to have no
11721 : // shading
11722 :
11723 : // Get the adjacent surface number for this receiving window surface
11724 77322 : int AdjSurfNum = surf.ExtBoundCond;
11725 : // If the adjacent surface number is > 0, this is an interior window
11726 77322 : if (AdjSurfNum > 0) { // this is an interior window surface
11727 :
11728 : // Calc diffuse solar from current exterior window
11729 : // transmitted through this interior window to adjacent zone [W]
11730 : // Transmitted diffuse solar [W] = current exterior window transmitted diffuse
11731 : // solar
11732 : // * view factor from current (sending) window DifTransSurfNum to current
11733 : // (receiving) surface HeatTransSurfNum
11734 : // - diffuse absorbed by this interior window
11735 : // - diffuse reflected by this interior window
11736 0 : Real64 DifSolarTransThroughW = WinDifSolarTrans_Factor - DifSolarAbsW - DifSolarReflW;
11737 : // HERE 8/15/07 Note Construct(AdjConstrNum)%TransDiff could be used here since
11738 : // the "front" transmittance for an interior window in the adjacent zone is the
11739 : // correct direction as long as I use the Construct() of the Surface in the
11740 : // adjacent zone. However, the above calculation better conserves energy, although
11741 : // possibly at the expense of less accurate transmittance calcs. Preliminary tests
11742 : // showed fairly good agreement between the two DifSolarTransW calculation
11743 : // methods, but for consistency I stuck with the above. int AdjConstrNum =
11744 : // Surface(AdjSurfNum).Construction;
11745 : // DifSolarTransW = WinDifSolar(DifTransSurfNum) &
11746 : // * ViewFactor &
11747 : // * Construct(AdjConstrNum)%TransDiff
11748 :
11749 : // Get the adjacent zone index
11750 0 : int const adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
11751 :
11752 : // Call routine to distribute diffuse solar transmitted through this interior
11753 : // window into adjacent zone
11754 0 : CalcInteriorWinTransDifSolInitialDistribution(state, adjEnclosureNum, AdjSurfNum, DifSolarTransThroughW);
11755 : }
11756 :
11757 : // Calc transmitted Window and Zone total distributed diffuse solar to check for
11758 : // conservation of energy This is not very effective since it assigns whatever
11759 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
11760 : // Should be just total less reflected
11761 77322 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
11762 :
11763 : // Accumulate transmitted diffuse solar for reporting
11764 77322 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
11765 :
11766 0 : } else if (ShadeFlag == WinShadingType::SwitchableGlazing) { // Switchable glazing
11767 : // Init accumulator for transmittance calc below
11768 0 : DifSolarAbsW = 0.0;
11769 :
11770 0 : auto const &construct = state.dataConstruction->Construct(ConstrNum);
11771 0 : auto const &construct_AbsDiffBack = construct.AbsDiffBack;
11772 0 : auto const &construct_sh = state.dataConstruction->Construct(ConstrNumSh);
11773 0 : auto const &construct_sh_AbsDiffBack = construct_sh.AbsDiffBack;
11774 0 : for (int IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
11775 : // Calc diffuse solar absorbed in each window glass layer
11776 0 : WinDifSolLayAbsW =
11777 : WinDifSolarTrans_Factor *
11778 0 : Window::InterpSw(win_SwitchingFactor, construct_AbsDiffBack(IGlass), construct_sh_AbsDiffBack(IGlass));
11779 :
11780 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
11781 : // transmittance calc below
11782 0 : DifSolarAbsW += WinDifSolLayAbsW;
11783 :
11784 : // Accumulate diffuse solar absorbed from the inside by each window glass layer
11785 : // [W/m2] for heat balance calcs
11786 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
11787 : }
11788 :
11789 : // Calc diffuse solar reflected back to zone
11790 0 : DifSolarReflW = WinDifSolarTrans_Factor *
11791 0 : Window::InterpSw(win_SwitchingFactor, construct.ReflectSolDiffBack, construct_sh.ReflectSolDiffBack);
11792 :
11793 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
11794 : // interreflection calcs
11795 0 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
11796 :
11797 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
11798 : // conservation of energy This is not very effective since it assigns whatever
11799 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
11800 : // Should be just total less reflected
11801 0 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
11802 :
11803 : // Accumulate transmitted diffuse solar for reporting
11804 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
11805 :
11806 0 : } else if (ConstrNumSh != 0) {
11807 : // Interior, exterior or between-glass shade, screen or blind in place
11808 :
11809 : // Init accumulator for transmittance calc below
11810 0 : DifSolarAbsW = 0.0;
11811 0 : WinDifSolLayAbsW = 0.0;
11812 :
11813 : // First calc diffuse solar absorbed by each glass layer in this window with
11814 : // shade/blind in place
11815 0 : auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
11816 0 : auto const &surfShade = s_surf->surfShades(HeatTransSurfNum);
11817 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
11818 :
11819 0 : for (int IGlass = 1; IGlass <= constrSh.TotGlassLayers; ++IGlass) {
11820 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
11821 : // Calc diffuse solar absorbed in each window glass layer and shade
11822 0 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * constrSh.AbsDiffBack(IGlass);
11823 0 : } else if (ANY_BLIND(ShadeFlag)) {
11824 0 : auto const &slatDfAbsLo = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxLo];
11825 0 : auto const &slatDfAbsHi = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxHi];
11826 0 : BlAbsDiffBk = Interp(slatDfAbsLo.Sol.Bk.Df.Abs, slatDfAbsHi.Sol.Bk.Df.Abs, slatInterpFac);
11827 : // Calc diffuse solar absorbed in each window glass layer and shade
11828 0 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * BlAbsDiffBk;
11829 : }
11830 :
11831 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
11832 : // transmittance calc below
11833 0 : DifSolarAbsW += WinDifSolLayAbsW;
11834 :
11835 : // Accumulate diffuse solar absorbed from the inside by each window glass layer
11836 : // [W/m2] for heat balance calcs
11837 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
11838 : }
11839 :
11840 : // Next calc diffuse solar reflected back to zone from window with shade or blind on
11841 : // Diffuse back solar reflectance, bare glass or shade on
11842 0 : InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
11843 0 : if ((ShadeFlag == WinShadingType::IntBlind) || (ShadeFlag == WinShadingType::ExtBlind)) {
11844 0 : auto const &constr = state.dataConstruction->Construct(ConstrNum);
11845 0 : auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
11846 0 : auto const &btarSlatLo = constr.blindTARs[surfShade.blind.slatAngIdxLo];
11847 0 : auto const &btarSlatHi = constr.blindTARs[surfShade.blind.slatAngIdxHi];
11848 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
11849 : // Diffuse back solar reflectance, blind present, vs. slat angle
11850 0 : InsideDifReflectance = Interp(btarSlatLo.Sol.Bk.Df.Ref, btarSlatHi.Sol.Bk.Df.Ref, slatInterpFac);
11851 : }
11852 0 : DifSolarReflW = WinDifSolarTrans_Factor * InsideDifReflectance;
11853 :
11854 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
11855 : // interreflection calcs
11856 0 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
11857 :
11858 : // Now calc diffuse solar absorbed by shade/blind itself
11859 0 : BlNum = surfShade.blind.matNum;
11860 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
11861 : // Calc diffuse solar absorbed by shade or screen [W]
11862 0 : ShBlDifSolarAbsW = WinDifSolarTrans_Factor * constrSh.AbsDiffBackShade;
11863 0 : } else if (ANY_BLIND(ShadeFlag)) {
11864 0 : auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
11865 0 : auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
11866 0 : auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
11867 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
11868 0 : AbsDiffBkBl = Interp(btarSlatLo.Sol.Bk.Df.Abs, btarSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
11869 0 : ShBlDifSolarAbsW = WinDifSolarTrans_Factor * AbsDiffBkBl;
11870 : }
11871 : // Correct for divider shadowing
11872 0 : if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
11873 0 : ShBlDifSolarAbsW *= s_surf->SurfaceWindow(HeatTransSurfNum).glazedFrac;
11874 : }
11875 :
11876 : // Accumulate diffuse solar absorbed by shade or screen [W/m2] for heat balance calcs
11877 0 : s_surf->SurfWinInitialDifSolAbsByShade(HeatTransSurfNum) += ShBlDifSolarAbsW * per_HTSurfaceArea;
11878 :
11879 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
11880 : // transmittance calc below
11881 0 : DifSolarAbsW += ShBlDifSolarAbsW;
11882 :
11883 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
11884 : // conservation of energy This is not very effective since it assigns whatever
11885 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
11886 : // Should be just total less reflected
11887 0 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
11888 :
11889 : // Accumulate transmitted diffuse solar for reporting
11890 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
11891 : } // End of shading flag check
11892 :
11893 : } else {
11894 : // SurfaceWindow(HeatTransSurfNum)%WindowModelType == WindowModel:: EQL
11895 : // ConstrNum=Surface(HeatTransSurfNum)%Construction
11896 : // call the ASHWAT fenestration model for diffuse radiation here
11897 2 : WindowEquivalentLayer::CalcEQLOpticalProperty(state, HeatTransSurfNum, SolarArrays::DIFF, AbsSolDiffBackEQL);
11898 :
11899 2 : EQLNum = state.dataConstruction->Construct(ConstrNum).EQLConsPtr;
11900 6 : for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(EQLNum).NL; ++Lay) {
11901 :
11902 : // Calc diffuse solar absorbed from the inside by each layer of EQL model [W]
11903 : // WinDifSolLayAbsW = WinDifSolar(DifTransSurfNum)* ViewFactor *
11904 : // Construct(ConstrNum)%AbsDiffBack(Lay)
11905 4 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * AbsSolDiffBackEQL(2, Lay);
11906 :
11907 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
11908 : // transmittance calc below
11909 4 : DifSolarAbsW += WinDifSolLayAbsW;
11910 :
11911 : // Accumulate diffuse solar absorbed from the inside by each window layer [W/m2] for
11912 : // heat balance calcs
11913 4 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, Lay) += WinDifSolLayAbsW * per_HTSurfaceArea;
11914 :
11915 : // ASHWAT equivalent layer model may require not the individual layer absorption but
11916 : // the flux InitialDifSolwinEQL(HeatTransSurfNum) = WinDifSolar(DifTransSurfNum)*
11917 : // ViewFactor
11918 : }
11919 :
11920 : // Calc diffuse solar reflected back to zone
11921 : // I don't really care if this is a window or opaque surface since I am just
11922 : // accumulating all reflected diffuse solar in a zone bucket for "interreflected"
11923 : // distribution Reflected diffuse solar [W] = current window transmitted diffuse solar
11924 : // * view factor from current (sending) window DifTransSurfNum to current (receiving)
11925 : // surface HeatTransSurfNum
11926 : // * current window inside solar reflectance
11927 2 : InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
11928 2 : DifSolarReflW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
11929 :
11930 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
11931 : // interreflection calcs
11932 2 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
11933 :
11934 : //------------------------------------------------------------------------------
11935 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
11936 : //------------------------------------------------------------------------------
11937 :
11938 : // If this receiving window surface (HeatTransSurfNum) is an interior window,
11939 : // calc distributed solar transmitted to adjacent zone [W]
11940 : // NOTE: This calc is here because interior windows are currently assumed to have no
11941 : // shading
11942 :
11943 : // Get the adjacent surface number for this receiving window surface
11944 2 : int const AdjSurfNum = s_surf->Surface(HeatTransSurfNum).ExtBoundCond;
11945 : // If the adjacent surface number is > 0, this is an interior window
11946 2 : if (AdjSurfNum > 0) { // this is an interior window surface
11947 :
11948 : // Calc diffuse solar from current exterior window
11949 : // transmitted through this interior window to adjacent zone [W]
11950 : // Transmitted diffuse solar [W] = current exterior window transmitted diffuse solar
11951 : // * view factor from current (sending) window DifTransSurfNum to current
11952 : // (receiving) surface HeatTransSurfNum
11953 0 : Real64 DifSolarTransW = AbsSolDiffBackEQL(2, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1) * ViewFactor;
11954 : // int AdjConstrNum = Surface(AdjSurfNum).Construction;
11955 : // Get the adjacent zone index
11956 0 : int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
11957 : // Call routine to distribute diffuse solar transmitted through this interior window
11958 : // into adjacent zone
11959 0 : CalcInteriorWinTransDifSolInitialDistribution(state, adjEnclosureNum, AdjSurfNum, DifSolarTransW);
11960 : }
11961 :
11962 : // Calc transmitted Window and Zone total distributed diffuse solar to check for
11963 : // conservation of energy This is not very effective since it assigns whatever
11964 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
11965 : // Should be just total less reflected
11966 2 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
11967 :
11968 : // Accumulate transmitted diffuse solar for reporting
11969 2 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
11970 :
11971 : } // IF (SurfaceWindow(HeatTransSurfNum)%WindowModelType /= WindowModel:: EQL) THEN
11972 :
11973 : // HERE 8/14/07 Ignore absorptance and reflectance of Frames and Dividers for now.
11974 : // I would need revised view factors that included these surface types.
11975 : // By ignoring them here, the diffuse solar is accounted for on the other surfaces
11976 :
11977 : // IF(SurfaceWindow(HeatTransSurfNum)%FrameArea > 0.0) THEN ! Window has a frame
11978 : // Note that FrameQRadInAbs is initially calculated in InitSolarHeatGains
11979 : // END IF
11980 :
11981 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerArea > 0.0) THEN ! Window has dividers
11982 : // DividerSolAbs = SurfaceWindow(HeatTransSurfNum)%DividerSolAbsorp
11983 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerType == Suspended) THEN ! Suspended
11984 : // divider; account for inside glass
11985 : // MatNumGl = Construct(ConstrNum)%LayerPoint(Construct(ConstrNum)%TotLayers)
11986 : // TransGl = dataMaterial.Material(MatNumGl)%Trans
11987 : // ReflGl = dataMaterial.Material(MatNumGl)%ReflectSolDiffBack
11988 : // AbsGl = 1.0d0-TransGl-ReflGl
11989 : // DividerSolRefl = 1.0d0-DividerSolAbs
11990 : // DividerSolAbs = AbsGl + TransGl*(DividerSolAbs +
11991 : // DividerSolRefl*AbsGl)/(1.0d0-DividerSolRefl*ReflGl)
11992 : // END IF
11993 : // Correct for interior shade transmittance
11994 : // IF(ShadeFlag == IntShadeOn) THEN
11995 : // MatNumSh = Construct(ConstrNumSh)%LayerPoint(Construct(ConstrNumSh)%TotLayers)
11996 : // DividerSolAbs = DividerSolAbs * dataMaterial.Material(MatNumSh)%Trans
11997 : // ELSE IF(ShadeFlag == WinShadingType::IntBlind) THEN
11998 : // DividerSolAbs = DividerSolAbs *
11999 : // InterpSlatAng(SurfaceWindow(HeatTransSurfNum)%SlatAngThisTS, &
12000 : // SurfaceWindow(HeatTransSurfNum)%MovableSlats,Blind(BlNum)%SolBackDiffDiffTrans)
12001 : // END IF
12002 : // Note that DividerQRadInAbs is initially calculated in InitSolarHeatGains
12003 :
12004 : // END IF ! Window has dividers
12005 :
12006 : } // opaque or window heat transfer surface
12007 :
12008 : } // HeatTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
12009 :
12010 : // Check debug var for view factors here
12011 : // ViewFactorTotal
12012 : // Check debug vars for individual transmitting surfaces here
12013 : // WinDifSolarDistTotl = WinDifSolarDistAbsorbedTotl + WinDifSolarDistReflectedTotl +
12014 : // WinDifSolarDistTransmittedTotl;
12015 : // WinDifSolarTrans
12016 :
12017 : } // DifTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
12018 :
12019 : // Check debug vars for zone totals here
12020 : // ZoneDifSolarDistTotl = ZoneDifSolarDistAbsorbedTotl + ZoneDifSolarDistReflectedTotl +
12021 : // ZoneDifSolarDistTransmittedTotl;
12022 : // ZoneDifSolarTrans
12023 : // ZoneDifSolarDistAbsorbedTotl
12024 : // ZoneDifSolarDistReflectedTotl
12025 : // ZoneDifSolarDistTransmittedTotl
12026 : // CALL DisplayString('Diffuse Solar Distribution Zone Totals')
12027 :
12028 : } // ZoneNum = 1, NumOfZones
12029 71220 : }
12030 0 : void CalcInteriorWinTransDifSolInitialDistribution(EnergyPlusData &state,
12031 : int const IntWinEnclosureNum, // Interior Window Enclosure index number
12032 : int const IntWinSurfNum, // Interior Window Surface number
12033 : Real64 const IntWinDifSolarTransW // Diffuse Solar transmitted through Interior Window
12034 : // IntWinSurfNum from adjacent enclosure [W]
12035 : )
12036 : {
12037 :
12038 : // SUBROUTINE INFORMATION:
12039 : // AUTHOR Rob Hitchcock
12040 : // DATE WRITTEN August 2007
12041 : // MODIFIED N/A
12042 : // RE-ENGINEERED N/A
12043 :
12044 : // PURPOSE OF THIS SUBROUTINE:
12045 : // This subroutine calculates the initial distribution
12046 : // of diffuse solar transmitted through the given interior window
12047 : // to individual heat transfer surfaces in the given enclosure.
12048 : // Diffuse solar transmitted through interior windows in this enclosure
12049 : // to adjacent enclosures, is added to the EnclSolInitialDifSolReflW
12050 : // of the adjacent enclosure for subsequent interreflection calcs
12051 :
12052 : // METHODOLOGY EMPLOYED:
12053 : // Similar to method used in CalcWinTransDifSolInitialDistribution.
12054 : // Apportions diffuse solar transmitted through an interior window
12055 : // that is then absorbed, reflected, and/or transmitted
12056 : // by other heat transfer surfaces in the given enclosure.
12057 : // Calculations use:
12058 : // 1. DifSolarTransW calculated in SUBROUTINE CalcWinTransDifSolInitialDistribution,
12059 : // 2. view factors between the interior window and
12060 : // other heat transfer surfaces in the given enclosure
12061 : // calculated in SUBROUTINE CalcApproximateViewFactors, and
12062 : // 3. surface absorptances, reflectances, and transmittances
12063 : // determined here using revised code from SUBROUTINE InitIntSolarDistribution
12064 :
12065 : // Using/Aliasing
12066 : using namespace DataViewFactorInformation;
12067 :
12068 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
12069 : int IGlass; // Glass layer counter
12070 : int TotGlassLayers; // Number of glass layers in a window construction
12071 : WinShadingType ShadeFlag; // Shading flag
12072 : Real64 AbsInt; // Tmp var for Inside surface short-wave absorptance
12073 : Real64 InsideDifAbsorptance; // Inside diffuse solar absorptance of a surface
12074 : Real64 InsideDifReflectance; // Inside diffuse solar reflectance of a surface
12075 : int BlNum; // Blind number
12076 : Real64 BlAbsDiffBk; // Glass layer back diffuse solar absorptance when blind in place
12077 : Real64 AbsDiffBkBl; // Blind diffuse back solar absorptance as part of glazing system
12078 :
12079 : // REAL(r64) :: DividerSolAbs ! Window divider solar absorptance
12080 : // REAL(r64) :: DividerSolRefl ! Window divider solar reflectance
12081 : // INTEGER :: MatNumGl ! Glass layer material number
12082 : // INTEGER :: MatNumSh ! Shade layer material number
12083 : // REAL(r64) :: TransGl,ReflGl,AbsGl ! Glass layer solar transmittance, reflectance, absorptance
12084 :
12085 : Real64 ViewFactor; // temp var for view factor
12086 : Real64 ViewFactorTotal; // debug var for view factor total
12087 : Real64 WinDifSolarTrans; // debug var for WinDifSolar() [W]
12088 : // Real64 WinDifSolarDistTotl; // debug var for window total distributed
12089 : // diffuse solar [W] Real64 WinDifSolarDistAbsorbedTotl( 0.0 ); // debug var
12090 : // for individual exterior window total
12091 : // distributed
12092 : // diffuse solar absorbed [W]
12093 : // Real64 WinDifSolarDistReflectedTotl( 0.0 ); // debug var for individual exterior window total
12094 : // distributed
12095 : // diffuse solar reflected [W]
12096 : // Real64 WinDifSolarDistTransmittedTotl( 0.0 ); // debug var for individual exterior window total
12097 : // distributed
12098 : // diffuse solar transmitted [W]
12099 : Real64 WinDifSolLayAbsW; // temp var for diffuse solar absorbed by individual glass layer [W]
12100 : // Real64 ZoneDifSolarTrans( 0.0 ); // debug var for WinDifSolar() [W]
12101 : // REAL(r64) :: ZoneDifSolarDistTotl ! debug var for zone total distributed diffuse solar [W]
12102 : // Real64 ZoneDifSolarDistAbsorbedTotl( 0.0 ); // debug var for zone total distributed diffuse solar
12103 : // absorbed [W] Real64 ZoneDifSolarDistReflectedTotl( 0.0 ); // debug var for zone total distributed
12104 : // diffuse solar reflected [W] Real64 ZoneDifSolarDistTransmittedTotl( 0.0 ); // debug var for zone
12105 : // total distributed diffuse solar transmitted [W]
12106 :
12107 0 : Real64 DifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by surface [W]
12108 0 : Real64 DifSolarAbs = 0.0; // temp var for diffuse solar absorbed by surface [W/m2]
12109 0 : Real64 DifSolarReflW = 0.0; // temp var for diffuse solar reflected by surface [W]
12110 0 : Real64 DifSolarTransW = 0.0; // temp var for diffuse solar transmitted through interior window surface [W]
12111 0 : Real64 ShBlDifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by shade/blind [W]
12112 :
12113 : //-------------------------------------------------------------------------------------------------
12114 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO INTERIOR HEAT TRANSFER SURFACES
12115 : //-------------------------------------------------------------------------------------------------
12116 :
12117 0 : auto &s_surf = state.dataSurface;
12118 :
12119 : // Init debug vars
12120 0 : ViewFactorTotal = 0.0;
12121 0 : WinDifSolarTrans = IntWinDifSolarTransW;
12122 :
12123 0 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(IntWinEnclosureNum);
12124 : // Loop over all heat transfer surfaces in the current zone that might receive diffuse solar
12125 0 : Real64 InitialZoneDifSolReflW_zone(0.0);
12126 0 : for (int const HeatTransSurfNum : thisEnclosure.SurfacePtr) {
12127 :
12128 0 : auto &surf = s_surf->Surface(HeatTransSurfNum);
12129 :
12130 : // Skip surfaces that are not heat transfer surfaces
12131 0 : if (!surf.HeatTransSurf) continue;
12132 : // Skip tubular daylighting device domes
12133 0 : if (surf.Class == SurfaceClass::TDD_Dome) continue;
12134 :
12135 : // View factor from current (sending) window IntWinSurfNum to current (receiving) surface HeatTransSurfNum
12136 0 : int HTenclosureSurfNum = surf.SolarEnclSurfIndex; // HT surface index for EnclSolInfo.SurfacePtr and F arrays
12137 0 : int enclosureNum = surf.SolarEnclIndex; // index for EnclSolInfo
12138 0 : int IntWinEnclSurfNum = s_surf->Surface(IntWinSurfNum).SolarEnclSurfIndex; // Window surface index for EnclSolInfo.SurfacePtr and F arrays
12139 :
12140 0 : ViewFactor = state.dataViewFactor->EnclSolInfo(enclosureNum).F(HTenclosureSurfNum, IntWinEnclSurfNum);
12141 : // debug ViewFactorTotal
12142 0 : ViewFactorTotal += ViewFactor; // debug
12143 :
12144 : // Skip receiving surfaces with 0.0 view factor
12145 0 : if (ViewFactor <= 0.0) continue;
12146 0 : Real64 const SolarTrans_ViewFactor(IntWinDifSolarTransW * ViewFactor);
12147 :
12148 : // Calculate diffuse solar from current interior window absorbed and reflected by current heat transfer
12149 : // surface And calculate transmitted diffuse solar to adjacent zones through interior windows
12150 0 : int const ConstrNum = s_surf->SurfActiveConstruction(HeatTransSurfNum);
12151 0 : if (state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) { // Interior Opaque Surface
12152 :
12153 : // Determine the inside (back) diffuse solar absorptance
12154 : // and reflectance of the current heat transfer surface
12155 0 : InsideDifAbsorptance = state.dataHeatBalSurf->SurfAbsSolarInt(HeatTransSurfNum);
12156 : // Inside (back) diffuse solar reflectance is assumed to be 1 - absorptance
12157 0 : InsideDifReflectance = 1.0 - InsideDifAbsorptance;
12158 :
12159 : // Absorbed diffuse solar [W] = current window transmitted diffuse solar [W]
12160 : // * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
12161 : // HeatTransSurfNum
12162 : // * current surface inside solar absorptance
12163 0 : DifSolarAbsW = SolarTrans_ViewFactor * InsideDifAbsorptance; // [W]
12164 :
12165 : // Absorbed diffuse solar [W/m2] = Absorbed diffuse solar [W]
12166 : // / current surface net area
12167 0 : DifSolarAbs = DifSolarAbsW / surf.Area;
12168 :
12169 : // Accumulate absorbed diffuse solar [W/m2] on this surface for heat balance calcs
12170 0 : state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs(HeatTransSurfNum) += DifSolarAbs;
12171 :
12172 : // Reflected diffuse solar [W] = current window transmitted diffuse solar
12173 : // * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
12174 : // HeatTransSurfNum
12175 : // * current window inside solar reflectance
12176 0 : DifSolarReflW = SolarTrans_ViewFactor * InsideDifReflectance;
12177 :
12178 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent interreflection
12179 : // calcs
12180 0 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12181 :
12182 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12183 : // For opaque surfaces all incident diffuse is either absorbed or reflected
12184 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug [W]
12185 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug [W]
12186 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug [W]
12187 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug [W]
12188 :
12189 : } else { // Exterior or Interior Window
12190 :
12191 0 : int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(HeatTransSurfNum);
12192 0 : auto const &construction = state.dataConstruction->Construct(ConstrNum);
12193 :
12194 0 : TotGlassLayers = construction.TotGlassLayers;
12195 0 : ShadeFlag = s_surf->SurfWinShadingFlag(HeatTransSurfNum);
12196 :
12197 0 : if (NOT_SHADED(ShadeFlag)) { // No window shading
12198 : // Init accumulator for transmittance calc below
12199 0 : DifSolarAbsW = 0.0;
12200 :
12201 : // Calc diffuse solar absorbed by all window glass layers
12202 : // Note: I am assuming here that individual glass layer absorptances have been corrected
12203 : // to account for layer by layer transmittance and reflection effects.
12204 0 : for (IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
12205 : // Calc diffuse solar absorbed from the inside by each window glass layer [W]
12206 0 : AbsInt = construction.AbsDiffBack(IGlass);
12207 0 : WinDifSolLayAbsW = SolarTrans_ViewFactor * construction.AbsDiffBack(IGlass);
12208 :
12209 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12210 : // below
12211 0 : DifSolarAbsW += WinDifSolLayAbsW;
12212 :
12213 : // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
12214 : // heat balance calcs
12215 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
12216 : }
12217 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12218 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12219 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12220 :
12221 : // Calc diffuse solar reflected back to zone
12222 : // I don't really care if this is a window or opaque surface since I am just
12223 : // accumulating all reflected diffuse solar in a zone bucket for "interreflected" distribution
12224 : // Reflected diffuse solar [W] = current window transmitted diffuse solar
12225 : // * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
12226 : // HeatTransSurfNum
12227 : // * current window inside solar reflectance
12228 0 : DifSolarReflW = SolarTrans_ViewFactor * construction.ReflectSolDiffBack;
12229 :
12230 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12231 : // interreflection calcs
12232 0 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12233 :
12234 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12235 :
12236 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
12237 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
12238 :
12239 : // Calc transmitted Window and Zone total distributed diffuse solar to check for conservation of
12240 : // energy This is not very effective since it assigns whatever distributed diffuse solar has not
12241 : // been absorbed or reflected to transmitted.
12242 0 : DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
12243 :
12244 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12245 : // conservation of energy
12246 : // WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12247 : // ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12248 :
12249 : // Accumulate transmitted diffuse solar for reporting
12250 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
12251 :
12252 : //-----------------------------------------------------------------------------------
12253 : // ADD TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
12254 : // TOTAL REFLECTED DIFFUSE SOLAR FOR SUBSEQUENT INTERREFLECTION CALCS
12255 : //-----------------------------------------------------------------------------------
12256 :
12257 : // If this receiving window surface (HeatTransSurfNum) is an interior window,
12258 : // add transmitted diffuse solar to adjacent zone total reflected distributed
12259 : // diffuse solar for subsequent interreflection calcs
12260 : // NOTE: This calc is here because interior windows are currently assumed to have no shading
12261 :
12262 : // Get the adjacent surface number for this receiving window surface
12263 0 : int const AdjSurfNum = surf.ExtBoundCond;
12264 : // If the adjacent surface number is > 0, this is an interior window
12265 0 : if (AdjSurfNum > 0) { // this is an interior window surface
12266 :
12267 : // Get the adjacent zone/enclosure index
12268 : // Add transmitted diffuse solar to total reflected distributed diffuse solar for each zone
12269 : // for subsequent interreflection calcs
12270 0 : state.dataHeatBal->EnclSolInitialDifSolReflW(s_surf->Surface(AdjSurfNum).SolarEnclIndex) += DifSolarTransW; // [W]
12271 : }
12272 :
12273 0 : } else if (ShadeFlag == WinShadingType::SwitchableGlazing) { // Switchable glazing
12274 : // Init accumulator for transmittance calc below
12275 0 : auto const &constructionSh = state.dataConstruction->Construct(ConstrNumSh);
12276 0 : DifSolarAbsW = 0.0;
12277 :
12278 0 : for (IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
12279 : // Calc diffuse solar absorbed in each window glass layer
12280 0 : WinDifSolLayAbsW = SolarTrans_ViewFactor * InterpSw(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum),
12281 0 : construction.AbsDiffBack(IGlass),
12282 0 : constructionSh.AbsDiffBack(IGlass));
12283 :
12284 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12285 : // below
12286 0 : DifSolarAbsW += WinDifSolLayAbsW;
12287 :
12288 : // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
12289 : // heat balance calcs
12290 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
12291 : }
12292 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12293 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12294 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12295 :
12296 : // Calc diffuse solar reflected back to zone
12297 0 : DifSolarReflW =
12298 : SolarTrans_ViewFactor *
12299 0 : InterpSw(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum), construction.ReflectSolDiffBack, constructionSh.ReflectSolDiffBack);
12300 :
12301 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12302 : // interreflection calcs
12303 0 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12304 :
12305 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12306 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
12307 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
12308 :
12309 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12310 : // conservation of energy This is not very effective since it assigns whatever distributed diffuse
12311 : // solar has not been absorbed or reflected to transmitted.
12312 0 : DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
12313 : // WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12314 : // ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug
12315 : //[W]
12316 :
12317 : // Accumulate transmitted diffuse solar for reporting
12318 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
12319 :
12320 : } else {
12321 0 : auto const &surfShade = s_surf->surfShades(HeatTransSurfNum);
12322 : // Interior, exterior or between-glass shade, screen or blind in place
12323 :
12324 : // Init accumulator for transmittance calc below
12325 0 : DifSolarAbsW = 0.0;
12326 0 : WinDifSolLayAbsW = 0.0;
12327 :
12328 : // First calc diffuse solar absorbed by each glass layer in this window with shade/blind in place
12329 0 : auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
12330 0 : for (IGlass = 1; IGlass <= constrSh.TotGlassLayers; ++IGlass) {
12331 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
12332 : // Calc diffuse solar absorbed in each window glass layer and shade
12333 0 : WinDifSolLayAbsW = SolarTrans_ViewFactor * constrSh.AbsDiffBack(IGlass);
12334 0 : } else if (ANY_BLIND(ShadeFlag)) {
12335 0 : auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
12336 0 : auto const &dfAbsSlatLo = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxLo];
12337 0 : auto const &dfAbsSlatHi = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxHi];
12338 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
12339 0 : BlAbsDiffBk = Interp(dfAbsSlatLo.Sol.Bk.Df.Abs, dfAbsSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
12340 : // Calc diffuse solar absorbed in each window glass layer and shade
12341 0 : WinDifSolLayAbsW = SolarTrans_ViewFactor * BlAbsDiffBk;
12342 : }
12343 :
12344 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12345 : // below
12346 0 : DifSolarAbsW += WinDifSolLayAbsW;
12347 :
12348 : // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
12349 : // heat balance calcs
12350 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
12351 : }
12352 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12353 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12354 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12355 :
12356 : // Next calc diffuse solar reflected back to zone from window with shade or blind on
12357 : // Diffuse back solar reflectance, bare glass or shade on
12358 0 : InsideDifReflectance = construction.ReflectSolDiffBack;
12359 0 : if ((ShadeFlag == WinShadingType::IntBlind) || (ShadeFlag == WinShadingType::ExtBlind)) {
12360 0 : auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
12361 0 : auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
12362 0 : auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
12363 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
12364 : // Diffuse back solar reflectance, blind present, vs. slat angle
12365 0 : InsideDifReflectance = Interp(btarSlatLo.Sol.Bk.Df.Ref, btarSlatHi.Sol.Bk.Df.Ref, slatInterpFac);
12366 : }
12367 0 : DifSolarReflW = SolarTrans_ViewFactor * InsideDifReflectance;
12368 :
12369 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12370 : // interreflection calcs
12371 0 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12372 :
12373 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12374 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
12375 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
12376 :
12377 : // Now calc diffuse solar absorbed by shade/blind itself
12378 0 : BlNum = surfShade.blind.matNum;
12379 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
12380 : // Calc diffuse solar absorbed by shade or screen [W]
12381 0 : ShBlDifSolarAbsW = SolarTrans_ViewFactor * constrSh.AbsDiffBackShade;
12382 0 : } else if (ANY_BLIND(ShadeFlag)) {
12383 0 : auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
12384 0 : auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
12385 0 : auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
12386 0 : Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
12387 : // Calc diffuse solar absorbed by blind [W]
12388 0 : AbsDiffBkBl = Interp(btarSlatLo.Sol.Bk.Df.Abs, btarSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
12389 0 : ShBlDifSolarAbsW = SolarTrans_ViewFactor * AbsDiffBkBl;
12390 : }
12391 : // Correct for divider shadowing
12392 0 : if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
12393 0 : ShBlDifSolarAbsW *= s_surf->SurfaceWindow(HeatTransSurfNum).glazedFrac;
12394 : }
12395 :
12396 : // Accumulate diffuse solar absorbed by shade or screen [W/m2] for heat balance calcs
12397 0 : s_surf->SurfWinInitialDifSolAbsByShade(HeatTransSurfNum) += (ShBlDifSolarAbsW / surf.Area);
12398 :
12399 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12400 : // below
12401 0 : DifSolarAbsW += ShBlDifSolarAbsW;
12402 :
12403 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12404 : // WinDifSolarDistAbsorbedTotl += ShBlDifSolarAbsW; // debug
12405 : // ZoneDifSolarDistAbsorbedTotl += ShBlDifSolarAbsW; // debug
12406 :
12407 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12408 : // conservation of energy This is not very effective since it assigns whatever distributed diffuse
12409 : // solar has not been absorbed or reflected to transmitted.
12410 0 : DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
12411 : // WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12412 : // ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12413 :
12414 : // Accumulate transmitted diffuse solar for reporting
12415 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
12416 :
12417 : } // End of shading flag check
12418 :
12419 : // HERE 8/14/07 Ignore absorptance and reflectance of Frames and Dividers for now.
12420 : // I would need revised view factors that included these surface types.
12421 : // By ignoring them here, the diffuse solar is accounted for on the other surfaces
12422 :
12423 : // IF(SurfaceWindow(HeatTransSurfNum)%FrameArea > 0.0) THEN ! Window has a frame
12424 : // Note that FrameQRadInAbs is initially calculated in InitSolarHeatGains
12425 : // END IF
12426 :
12427 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerArea > 0.0) THEN ! Window has dividers
12428 : // DividerSolAbs = SurfaceWindow(HeatTransSurfNum)%DividerSolAbsorp
12429 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerType == Suspended) THEN ! Suspended divider;
12430 : // account for inside glass
12431 : // MatNumGl = Construct(ConstrNum)%LayerPoint(Construct(ConstrNum)%TotLayers)
12432 : // TransGl = dataMaterial.Material(MatNumGl)%Trans
12433 : // ReflGl = dataMaterial.Material(MatNumGl)%ReflectSolDiffBack
12434 : // AbsGl = 1.0d0-TransGl-ReflGl
12435 : // DividerSolRefl = 1.0d0-DividerSolAbs
12436 : // DividerSolAbs = AbsGl + TransGl*(DividerSolAbs +
12437 : // DividerSolRefl*AbsGl)/(1.0d0-DividerSolRefl*ReflGl)
12438 : // END IF
12439 : // Correct for interior shade transmittance
12440 : // IF(ShadeFlag == IntShadeOn) THEN
12441 : // MatNumSh = Construct(ConstrNumSh)%LayerPoint(Construct(ConstrNumSh)%TotLayers)
12442 : // DividerSolAbs = DividerSolAbs * dataMaterial.Material(MatNumSh)%Trans
12443 : // ELSE IF(ShadeFlag == WinShadingType::IntBlind) THEN
12444 : // DividerSolAbs = DividerSolAbs *
12445 : // InterpSlatAng(SurfaceWindow(HeatTransSurfNum)%SlatAngThisTS, &
12446 : // SurfaceWindow(HeatTransSurfNum)%MovableSlats,Blind(BlNum)%SolBackDiffDiffTrans)
12447 : // END IF
12448 : // Note that DividerQRadInAbs is initially calculated in InitSolarHeatGains
12449 :
12450 : // END IF ! Window has dividers
12451 : } // opaque or window heat transfer surface
12452 :
12453 : } // HeatTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
12454 0 : state.dataHeatBal->EnclSolInitialDifSolReflW(IntWinEnclosureNum) += InitialZoneDifSolReflW_zone;
12455 :
12456 : // Check debug var for view factors here
12457 : // ViewFactorTotal
12458 : // Check debug vars for individual transmitting surfaces here
12459 : // WinDifSolarDistTotl = WinDifSolarDistAbsorbedTotl + WinDifSolarDistReflectedTotl +
12460 : // WinDifSolarDistTransmittedTotl; //Debug
12461 : // WinDifSolarTrans
12462 0 : }
12463 :
12464 0 : void CalcComplexWindowOverlap(EnergyPlusData &state,
12465 : BSDFGeomDescr &Geom, // State Geometry
12466 : BSDFWindowGeomDescr const &Window, // Window Geometry
12467 : int const ISurf // Surface number of the complex fenestration
12468 : )
12469 : {
12470 : // SUBROUTINE INFORMATION:
12471 : // AUTHOR Simon Vidanovic
12472 : // DATE WRITTEN May 2012
12473 : // MODIFIED Simon Vidanovic (May 2013) - added overlaps calculations for daylighting
12474 : // RE-ENGINEERED na
12475 :
12476 : // PURPOSE OF THIS SUBROUTINE:
12477 : // For each of basis directions on back surface of the window calculates
12478 : // overlap areas. It also calculates overlap areas and reflectances for daylighting calculations
12479 :
12480 : using namespace Vectors;
12481 :
12482 : Real64 XShadowProjection; // temporary buffer
12483 : Real64 YShadowProjection; // temporary buffer
12484 :
12485 : Real64 XSp; // for calc BSDF projection direction
12486 : Real64 YSp; // for calc BSDF projection direction
12487 : Real64 ZSp; // for calc BSDF projection direction
12488 : Real64 SdotX; // temporary variable for manipulating .dot. product
12489 : Real64 SdotY; // temporary variable for manipulating .dot. product
12490 : Real64 SdotZ; // temporary variable for manipulating .dot. product
12491 : int BackSurfaceNumber; // current back surface number
12492 : int NVT; // Number of vertices of back surface
12493 : int NS1; // Number of the figure being overlapped
12494 : int NS2; // Number of the figure doing overlapping
12495 : int NS3; // Location to place results of overlap
12496 : int IRay; // Current ray of BSDF direction
12497 : int KBkSurf; // Current back surface
12498 : int N;
12499 :
12500 : // Daylighting
12501 : int IConst; // Construction number of back surface
12502 : int InsideConLay; // Construction's inside material layer number
12503 : Real64 VisibleReflectance; // Visible reflectance for inside surface material
12504 : Real64 TotAOverlap; // Total overlap area for given outgoing direction
12505 : Real64 TotARhoVisOverlap; // Total overlap area time reflectance for given outgoing direction
12506 :
12507 0 : auto &s_surf = state.dataSurface;
12508 :
12509 0 : state.dataSolarShading->XVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
12510 0 : state.dataSolarShading->YVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
12511 0 : state.dataSolarShading->ZVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
12512 :
12513 0 : Geom.AOverlap.dimension(Window.NBkSurf, Geom.Trn.NBasis, 0.0);
12514 0 : Geom.ARhoVisOverlap.dimension(Window.NBkSurf, Geom.Trn.NBasis, 0.0);
12515 0 : Geom.AveRhoVisOverlap.dimension(Geom.Trn.NBasis, 0.0);
12516 :
12517 : // First to calculate and store coordinates of the window surface
12518 0 : state.dataSolarShading->LOCHCA = 1;
12519 0 : int BaseSurf = s_surf->Surface(ISurf).BaseSurf; // Base surface number
12520 :
12521 : // Base surface contains current window surface (ISurf).
12522 : // Since that is case, below transformation should always return ZVT = 0.0
12523 : // for every possible transformation
12524 0 : CTRANS(state, ISurf, BaseSurf, NVT, state.dataSolarShading->XVertex, state.dataSolarShading->YVertex, state.dataSolarShading->ZVertex);
12525 :
12526 : // HTRANS routine is using coordinates stored in XVS and YVS in order to calculate
12527 : // surface area. Since both projections are equal to zero, then simply
12528 : // copy these values into XVS and YVS arrays
12529 0 : for (N = 1; N <= NVT; ++N) {
12530 0 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVertex(N);
12531 0 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVertex(N);
12532 : }
12533 :
12534 : // This calculates the area stored in XVS and YVS
12535 0 : HTRANS1(state, state.dataSolarShading->LOCHCA, NVT);
12536 :
12537 : // Calculation of overlap areas for each outgoing basis direction
12538 0 : for (IRay = 1; IRay <= Geom.Trn.NBasis; ++IRay) { // basis directions loop (on back surface)
12539 : // For current basis direction calculate dot product between window surface
12540 : // and basis direction. This will be used to calculate projection of each
12541 : // of the back surfaces to window surface for given basis direction
12542 0 : SdotX = dot(s_surf->Surface(ISurf).lcsx, Geom.sTrn(IRay));
12543 0 : SdotY = dot(s_surf->Surface(ISurf).lcsy, Geom.sTrn(IRay));
12544 0 : SdotZ = dot(s_surf->Surface(ISurf).lcsz, Geom.sTrn(IRay));
12545 0 : XSp = -SdotX;
12546 0 : YSp = -SdotY;
12547 0 : ZSp = -SdotZ;
12548 :
12549 : // Projection of shadows for current basis direction
12550 0 : if (std::abs(ZSp) > Constant::SmallDistance) {
12551 0 : XShadowProjection = XSp / ZSp;
12552 0 : YShadowProjection = YSp / ZSp;
12553 0 : if (std::abs(XShadowProjection) < 1.e-8) XShadowProjection = 0.0;
12554 0 : if (std::abs(YShadowProjection) < 1.e-8) YShadowProjection = 0.0;
12555 : } else {
12556 0 : XShadowProjection = 0.0;
12557 0 : YShadowProjection = 0.0;
12558 : }
12559 :
12560 0 : for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
12561 : // BaseSurf = Surface(ISurf).BaseSurf
12562 0 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
12563 :
12564 : // Transform coordinates of back surface from general system to the
12565 : // plane of the receiving surface
12566 0 : CTRANS(state,
12567 : BackSurfaceNumber,
12568 : BaseSurf,
12569 : NVT,
12570 0 : state.dataSolarShading->XVertex,
12571 0 : state.dataSolarShading->YVertex,
12572 0 : state.dataSolarShading->ZVertex);
12573 :
12574 : // Project "shadow" from back surface along sun's rays to receiving surface. Back surface vertices
12575 : // become clockwise sequential.
12576 :
12577 0 : for (N = 1; N <= NVT; ++N) {
12578 0 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVertex(N) - YShadowProjection * state.dataSolarShading->ZVertex(N);
12579 0 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVertex(N) - XShadowProjection * state.dataSolarShading->ZVertex(N);
12580 : }
12581 :
12582 : // Transform to the homogeneous coordinate system.
12583 :
12584 0 : NS3 = state.dataSolarShading->LOCHCA + 1;
12585 0 : state.dataSolarShading->HCT(NS3) = 0.0;
12586 0 : HTRANS1(state, NS3, NVT);
12587 :
12588 : // Determine area of overlap of projected back surface and receiving surface.
12589 :
12590 0 : NS1 = 1;
12591 0 : NS2 = NS3;
12592 0 : state.dataSolarShading->HCT(NS3) = 1.0;
12593 0 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
12594 :
12595 0 : if (state.dataSolarShading->OverlapStatus == NoOverlap) continue; // to next back surface
12596 0 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
12597 0 : break; // back surfaces DO loop
12598 :
12599 0 : state.dataSolarShading->LOCHCA = NS3;
12600 0 : state.dataSolarShading->HCNS(state.dataSolarShading->LOCHCA) = BackSurfaceNumber;
12601 0 : state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
12602 :
12603 0 : Geom.AOverlap(KBkSurf, IRay) = state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
12604 : } // DO KBkSurf = 1 , NBkSurf
12605 :
12606 : // If some of back surfaces is contained in base surface, then need to subtract shadow of subsurface
12607 : // from shadow on base surface. Reason is that above shadowing algorithm is calculating shadow without
12608 : // influence of subsurfaces
12609 0 : for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
12610 0 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
12611 : // CurBaseSurf is Current base surface number for shadow overlap calculations
12612 0 : int CurBaseSurf = s_surf->Surface(BackSurfaceNumber).BaseSurf;
12613 0 : if (CurBaseSurf != BackSurfaceNumber) {
12614 : // Search if that base surface in list of back surfaces for current window
12615 : // CurBackSurface is Current back surface number for base surface
12616 0 : int CurBackSurface = 0;
12617 0 : for (N = 1; N <= Window.NBkSurf; ++N) {
12618 0 : if (state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(N) == CurBaseSurf) {
12619 0 : CurBackSurface = N;
12620 0 : break;
12621 : }
12622 : }
12623 0 : if (CurBackSurface != 0) {
12624 0 : Geom.AOverlap(CurBackSurface, IRay) -= Geom.AOverlap(KBkSurf, IRay);
12625 : }
12626 : }
12627 : }
12628 :
12629 0 : auto &s_mat = state.dataMaterial;
12630 :
12631 : // Calculate overlap area times reflectance. This is necessary for complex fenestration daylighting
12632 : // calculations
12633 0 : TotAOverlap = 0.0;
12634 0 : TotARhoVisOverlap = 0.0;
12635 0 : for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
12636 0 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
12637 0 : IConst = s_surf->Surface(BackSurfaceNumber).Construction;
12638 0 : InsideConLay = state.dataConstruction->Construct(IConst).TotLayers;
12639 0 : if (s_surf->SurfWinWindowModelType(BackSurfaceNumber) == WindowModel::BSDF) {
12640 0 : VisibleReflectance = state.dataConstruction->Construct(IConst).ReflectVisDiffBack;
12641 : } else {
12642 0 : VisibleReflectance = (1.0 - s_mat->materials(InsideConLay)->AbsorpVisible);
12643 : }
12644 0 : Geom.ARhoVisOverlap(KBkSurf, IRay) = Geom.AOverlap(KBkSurf, IRay) * VisibleReflectance;
12645 0 : TotAOverlap += Geom.AOverlap(KBkSurf, IRay);
12646 0 : TotARhoVisOverlap += Geom.ARhoVisOverlap(KBkSurf, IRay);
12647 : }
12648 :
12649 0 : if (TotAOverlap != 0.0) {
12650 0 : Geom.AveRhoVisOverlap(IRay) = TotARhoVisOverlap / TotAOverlap;
12651 : }
12652 :
12653 : } // DO IRay = 1, Geom%Trn%NBasis
12654 :
12655 : // Reset back shadowing counter since complex windows do not need it anymore
12656 0 : state.dataSolarShading->LOCHCA = 1;
12657 0 : }
12658 :
12659 249956 : void TimestepInitComplexFenestration(EnergyPlusData &state)
12660 : {
12661 : // SUBROUTINE INFORMATION:
12662 : // AUTHOR Simon Vidanovic
12663 : // DATE WRITTEN May 2012
12664 : // MODIFIED May 2012 (Initialize complex fenestration in case of EMS)
12665 : // RE-ENGINEERED na
12666 :
12667 : // PURPOSE OF THIS SUBROUTINE:
12668 : // Performs initialization of complex fenestration. It also performs check if current surface containing
12669 : // complex fenestration have construction changed (by EMS) in which case performs addition of current states
12670 : // into complex fenestration array
12671 :
12672 : using WindowComplexManager::CheckCFSStates;
12673 :
12674 : // Locals
12675 : int iSurf; // Current surface number
12676 : int iState; // current state number
12677 : int NumOfStates; // number of states for current window
12678 :
12679 249956 : auto &s_surf = state.dataSurface;
12680 :
12681 2359340 : for (iSurf = 1; iSurf <= s_surf->TotSurfaces; ++iSurf) {
12682 2109384 : if (s_surf->SurfWinWindowModelType(iSurf) == WindowModel::BSDF) {
12683 : // This will check complex fenestrations state and add new one if necessary (EMS case)
12684 0 : CheckCFSStates(state, iSurf);
12685 :
12686 0 : NumOfStates = state.dataBSDFWindow->ComplexWind(iSurf).NumStates;
12687 :
12688 : // Check for overlap areas and initialize if necessary
12689 0 : for (iState = 1; iState <= NumOfStates; ++iState) {
12690 : // do initialization only once
12691 0 : if (state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState).InitState) {
12692 0 : CalcComplexWindowOverlap(
12693 0 : state, state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState), state.dataBSDFWindow->ComplexWind(iSurf), iSurf);
12694 0 : state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState).InitState = false;
12695 : }
12696 : }
12697 : }
12698 : }
12699 249956 : }
12700 :
12701 : } // namespace EnergyPlus::SolarShading
|