Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <algorithm>
50 : #include <cassert>
51 : #include <cmath>
52 : #include <memory>
53 :
54 : // ObjexxFCL Headers
55 : #include <ObjexxFCL/Array.functions.hh>
56 : #include <ObjexxFCL/Fmath.hh>
57 : #include <ObjexxFCL/Vector3.hh>
58 : #include <ObjexxFCL/member.functions.hh>
59 :
60 : // EnergyPlus Headers
61 : #include <EnergyPlus/CommandLineInterface.hh>
62 : #include <EnergyPlus/Construction.hh>
63 : #include <EnergyPlus/Data/EnergyPlusData.hh>
64 : #include <EnergyPlus/DataDaylightingDevices.hh>
65 : #include <EnergyPlus/DataEnvironment.hh>
66 : #include <EnergyPlus/DataErrorTracking.hh>
67 : #include <EnergyPlus/DataHeatBalSurface.hh>
68 : #include <EnergyPlus/DataHeatBalance.hh>
69 : #include <EnergyPlus/DataIPShortCuts.hh>
70 : #include <EnergyPlus/DataReportingFlags.hh>
71 : #include <EnergyPlus/DataShadowingCombinations.hh>
72 : #include <EnergyPlus/DataStringGlobals.hh>
73 : #include <EnergyPlus/DataSurfaces.hh>
74 : #include <EnergyPlus/DataSystemVariables.hh>
75 : #include <EnergyPlus/DataViewFactorInformation.hh>
76 : #include <EnergyPlus/DataWindowEquivalentLayer.hh>
77 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
78 : #include <EnergyPlus/DaylightingDevices.hh>
79 : #include <EnergyPlus/DaylightingManager.hh>
80 : #include <EnergyPlus/DisplayRoutines.hh>
81 : #include <EnergyPlus/EMSManager.hh>
82 : #include <EnergyPlus/EnergyPlusLogger.hh>
83 : #include <EnergyPlus/General.hh>
84 : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
85 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
86 : #include <EnergyPlus/OutputProcessor.hh>
87 : #include <EnergyPlus/OutputReportPredefined.hh>
88 : #include <EnergyPlus/PluginManager.hh>
89 : #include <EnergyPlus/ScheduleManager.hh>
90 : #include <EnergyPlus/SolarReflectionManager.hh>
91 : #include <EnergyPlus/SolarShading.hh>
92 : #include <EnergyPlus/UtilityRoutines.hh>
93 : #include <EnergyPlus/Vectors.hh>
94 : #include <EnergyPlus/WindowComplexManager.hh>
95 : #include <EnergyPlus/WindowEquivalentLayer.hh>
96 : #include <EnergyPlus/WindowManager.hh>
97 : #include <EnergyPlus/WindowManagerExteriorData.hh>
98 : #include <EnergyPlus/WindowModel.hh>
99 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
100 : #include <WCEMultiLayerOptics.hpp>
101 :
102 : namespace EnergyPlus::SolarShading {
103 :
104 : // MODULE INFORMATION:
105 : // AUTHOR Rick Strand
106 : // DATE WRITTEN March 1997
107 : // MODIFIED December 1998, FCW
108 : // MODIFIED July 1999, Linda Lawrie, eliminate shadefl.scr,
109 : // do shadowing calculations during simulation
110 : // MODIFIED June 2001, FCW, handle window blinds
111 : // MODIFIED May 2004, LKL, Polygons > 4 sides (not subsurfaces)
112 : // MODIFIED January 2007, LKL, Taking parameters back to original integer (HC)
113 : // MODIFIED August 2011, JHK, Including Complex Fenestration optical calculations
114 : // MODIFIED November 2012, BG, Timestep solar and daylighting calculations
115 : // RE-ENGINEERED na
116 :
117 : // PURPOSE OF THIS MODULE:
118 : // The purpose of this module is to encompass the routines and data
119 : // which are need to perform the solar calculations in EnergyPlus.
120 : // This also requires that shading and geometry routines and data
121 : // which are used by the solar calculations be included in this module.
122 :
123 : // METHODOLOGY EMPLOYED:
124 : // Many of the methods used in this module have been carried over from the
125 : // (I)BLAST program. As such, there is not much documentation on the
126 : // methodology used. The original code was written mainly by George
127 : // Walton and requires coordinate transformations. It calculates
128 : // shading using an overlapping polygon approach.
129 :
130 : // REFERENCES:
131 : // TARP Manual, NIST Publication.
132 : // Passive Solar Extension of the BLAST Program, CERL/UIUC Publication.
133 :
134 : using namespace DataEnvironment;
135 : using namespace DataHeatBalance;
136 : using namespace DataSurfaces;
137 : using namespace DataShadowingCombinations;
138 : using namespace SolarReflectionManager;
139 : using namespace DataVectorTypes;
140 : using namespace Window;
141 : using namespace FenestrationCommon;
142 : using namespace SingleLayerOptics;
143 :
144 : int constexpr NPhi = 6; // Number of altitude angle steps for sky integration
145 : int constexpr NTheta = 24; // Number of azimuth angle steps for sky integration
146 : Real64 constexpr Eps = 1.e-10; // Small number
147 : Real64 constexpr DPhi = Constant::PiOvr2 / NPhi; // Altitude step size
148 : Real64 constexpr DTheta = 2.0 * Constant::Pi / NTheta; // Azimuth step size
149 : Real64 constexpr DThetaDPhi = DTheta * DPhi; // Product of DTheta and DPhi
150 : Real64 constexpr PhiMin = 0.5 * DPhi; // Minimum altitude
151 :
152 : Real64 constexpr HCMULT = 100000.0; // Multiplier used to change meters to .01 millimeters for homogeneous coordinates.
153 : // Homogeneous Coordinates are represented in integers (64 bit). This changes the surface coordinates from meters
154 : // to .01 millimeters -- making that the resolution for shadowing, polygon clipping, etc.
155 : Real64 constexpr sqHCMULT = (HCMULT * HCMULT); // Square of HCMult used in Homogeneous coordinates
156 : Real64 constexpr sqHCMULT_fac = (0.5 / sqHCMULT); // ( 0.5 / sqHCMULT ) factor
157 :
158 : // Parameters for use with the variable OverlapStatus...
159 : int constexpr NoOverlap = 1;
160 : int constexpr FirstSurfWithinSecond = 2;
161 : int constexpr SecondSurfWithinFirst = 3;
162 : int constexpr PartialOverlap = 4;
163 : int constexpr TooManyVertices = 5;
164 : int constexpr TooManyFigures = 6;
165 :
166 796 : void InitSolarCalculations(EnergyPlusData &state)
167 : {
168 :
169 : // SUBROUTINE INFORMATION:
170 : // AUTHOR George Walton
171 : // DATE WRITTEN September 1977
172 : // MODIFIED na
173 : // RE-ENGINEERED Mar97, RKS, Initial EnergyPlus Version
174 :
175 : // PURPOSE OF THIS SUBROUTINE:
176 : // This routine controls the computation of the solar flux multipliers.
177 :
178 : // METHODOLOGY EMPLOYED:
179 : // All shadowing calculations have been grouped under this routine to
180 : // allow segmentation separating it from the hourly loads calculation.
181 :
182 : #ifdef EP_Count_Calls
183 : ++state.dataTimingsData->NumInitSolar_Calls;
184 : #endif
185 796 : if (state.dataGlobal->BeginSimFlag) {
186 796 : if (state.files.outputControl.shd) {
187 795 : state.dataSolarShading->shd_stream =
188 1590 : std::make_unique<std::fstream>(state.dataStrGlobals->outputShdFilePath, std::ios_base::out | std::ios_base::trunc);
189 795 : 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 1 : state.dataSolarShading->shd_stream = std::make_unique<std::iostream>(nullptr);
195 : }
196 :
197 796 : if (state.dataSolarShading->GetInputFlag) {
198 796 : checkShadingSurfaceSchedules(state);
199 796 : processShadowingInput(state);
200 796 : state.dataSolarShading->GetInputFlag = false;
201 1592 : state.dataSolarShading->MaxHCV =
202 796 : (((max(15, state.dataSurface->MaxVerticesPerSurface) + 16) / 16) * 16) - 1; // Assure MaxHCV+1 is multiple of 16 for 128 B alignment
203 796 : assert((state.dataSolarShading->MaxHCV + 1) % 16 == 0);
204 : }
205 :
206 796 : if (state.dataSolarShading->firstTime) DisplayString(state, "Allocate Solar Module Arrays");
207 796 : AllocateModuleArrays(state);
208 :
209 796 : if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::FullInteriorExterior) {
210 346 : if (state.dataSolarShading->firstTime) DisplayString(state, "Computing Interior Solar Absorption Factors");
211 346 : ComputeIntSolarAbsorpFactors(state);
212 : }
213 :
214 796 : if (state.dataSolarShading->firstTime) DisplayString(state, "Determining Shadowing Combinations");
215 796 : DetermineShadowingCombinations(state);
216 796 : state.dataSolarShading->shd_stream.reset(); // Done writing to shd file
217 :
218 796 : if (state.dataSolarShading->firstTime) DisplayString(state, "Computing Window Shade Absorption Factors");
219 796 : ComputeWinShadeAbsorpFactors(state);
220 :
221 796 : if (state.dataSurface->CalcSolRefl) {
222 9 : DisplayString(state, "Initializing Solar Reflection Factors");
223 9 : InitSolReflRecSurf(state);
224 : }
225 :
226 796 : if (state.dataSolarShading->firstTime) DisplayString(state, "Proceeding with Initializing Solar Calculations");
227 : }
228 :
229 796 : if (state.dataGlobal->BeginEnvrnFlag) {
230 796 : state.dataSolarShading->SurfSunCosTheta = 0.0;
231 796 : state.dataSolarShading->SurfSunlitArea = 0.0;
232 796 : state.dataSurface->SurfSunlitArea = 0.0;
233 796 : state.dataSurface->SurfSunlitFrac = 0.0;
234 796 : state.dataHeatBal->SurfSunlitFracHR = 0.0;
235 796 : state.dataHeatBal->SurfSunlitFrac = 0.0;
236 796 : state.dataHeatBal->SurfSunlitFracWithoutReveal = 0.0;
237 796 : state.dataHeatBal->SurfWinBackSurfaces = 0;
238 796 : state.dataHeatBal->SurfWinOverlapAreas = 0.0;
239 796 : state.dataHeatBal->SurfCosIncAngHR = 0.0;
240 796 : state.dataHeatBal->SurfCosIncAng = 0.0;
241 796 : 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 796 : state.dataSolarShading->SurfMultIsoSky = 0.0;
249 796 : state.dataSolarShading->SurfMultCircumSolar = 0.0;
250 796 : state.dataSolarShading->SurfMultHorizonZenith = 0.0;
251 796 : state.dataSolarShading->SurfWinRevealStatus = 0;
252 :
253 5852 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
254 5056 : state.dataHeatBal->ZoneWinHeatGain(zoneNum) = 0.0;
255 5056 : state.dataHeatBal->ZoneWinHeatGainRep(zoneNum) = 0.0;
256 5056 : state.dataHeatBal->ZoneWinHeatLossRep(zoneNum) = 0.0;
257 5056 : state.dataHeatBal->ZoneWinHeatGainRepEnergy(zoneNum) = 0.0;
258 5056 : state.dataHeatBal->ZoneWinHeatLossRepEnergy(zoneNum) = 0.0;
259 5056 : state.dataHeatBal->ZoneOpaqSurfInsFaceCond(zoneNum) = 0.0;
260 5056 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep(zoneNum) = 0.0;
261 5056 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep(zoneNum) = 0.0;
262 5056 : state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg(zoneNum) = 0.0;
263 5056 : state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg(zoneNum) = 0.0;
264 : }
265 5851 : for (int enclNum = 1; enclNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclNum) {
266 5055 : state.dataHeatBal->ZoneTransSolar(enclNum) = 0.0;
267 5055 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclNum) = 0.0;
268 5055 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclNum) = 0.0;
269 5055 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclNum) = 0.0;
270 5055 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclNum) = 0.0;
271 5055 : state.dataHeatBal->ZoneDifSolFrIntWinsRep(enclNum) = 0.0;
272 5055 : state.dataHeatBal->ZoneTransSolarEnergy(enclNum) = 0.0;
273 5055 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclNum) = 0.0;
274 5055 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclNum) = 0.0;
275 5055 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclNum) = 0.0;
276 5055 : state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy(enclNum) = 0.0;
277 : }
278 46840 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
279 46044 : state.dataHeatBal->SurfQRadSWOutIncident(SurfNum) = 0.0;
280 46044 : state.dataHeatBal->SurfQRadSWOutIncidentBeam(SurfNum) = 0.0;
281 46044 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = 0.0;
282 46044 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) = 0.0;
283 46044 : state.dataHeatBal->SurfIntBmIncInsSurfIntensRep(SurfNum) = 0.0;
284 46044 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRep(SurfNum) = 0.0;
285 46044 : state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse(SurfNum) = 0.0;
286 46044 : state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse(SurfNum) = 0.0;
287 46044 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd(SurfNum) = 0.0;
288 46044 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd(SurfNum) = 0.0;
289 46044 : state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs(SurfNum) = 0.0;
290 46044 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs(SurfNum) = 0.0;
291 46044 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs(SurfNum) = 0.0;
292 46044 : state.dataHeatBal->SurfCosIncidenceAngle(SurfNum) = 0.0;
293 46044 : state.dataHeatBal->SurfSWInAbsTotalReport(SurfNum) = 0.0;
294 46044 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) = 0.0;
295 46044 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy(SurfNum) = 0.0;
296 46044 : state.dataHeatBal->SurfInitialDifSolInAbsReport(SurfNum) = 0.0;
297 : }
298 5852 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
299 10124 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
300 5068 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
301 5068 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
302 5068 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
303 11285 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
304 :
305 6217 : state.dataSurface->SurfWinTransSolar(SurfNum) = 0.0;
306 6217 : state.dataSurface->SurfWinBmSolar(SurfNum) = 0.0;
307 6217 : state.dataSurface->SurfWinBmBmSolar(SurfNum) = 0.0;
308 6217 : state.dataSurface->SurfWinBmDifSolar(SurfNum) = 0.0;
309 6217 : state.dataSurface->SurfWinDifSolar(SurfNum) = 0.0;
310 :
311 6217 : state.dataSurface->SurfWinTransSolarEnergy(SurfNum) = 0.0;
312 6217 : state.dataSurface->SurfWinBmSolarEnergy(SurfNum) = 0.0;
313 6217 : state.dataSurface->SurfWinBmBmSolarEnergy(SurfNum) = 0.0;
314 6217 : state.dataSurface->SurfWinBmDifSolarEnergy(SurfNum) = 0.0;
315 :
316 6217 : state.dataSurface->SurfWinHeatGain(SurfNum) = 0.0;
317 6217 : state.dataSurface->SurfWinHeatGainRep(SurfNum) = 0.0;
318 6217 : state.dataSurface->SurfWinHeatLossRep(SurfNum) = 0.0;
319 : }
320 11285 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
321 6217 : state.dataSurface->SurfWinGainConvGlazToZoneRep(SurfNum) = 0.0;
322 6217 : state.dataSurface->SurfWinGainIRGlazToZoneRep(SurfNum) = 0.0;
323 6217 : state.dataSurface->SurfWinLossSWZoneToOutWinRep(SurfNum) = 0.0;
324 6217 : state.dataSurface->SurfWinGainFrameDividerToZoneRep(SurfNum) = 0.0;
325 6217 : state.dataSurface->SurfWinGainConvShadeToZoneRep(SurfNum) = 0.0;
326 6217 : state.dataSurface->SurfWinGainIRShadeToZoneRep(SurfNum) = 0.0;
327 6217 : state.dataSurface->SurfWinGapConvHtFlowRep(SurfNum) = 0.0;
328 6217 : state.dataSurface->SurfWinShadingAbsorbedSolar(SurfNum) = 0.0;
329 :
330 6217 : state.dataSurface->SurfWinSysSolTransmittance(SurfNum) = 0.0;
331 6217 : state.dataSurface->SurfWinSysSolReflectance(SurfNum) = 0.0;
332 6217 : state.dataSurface->SurfWinSysSolAbsorptance(SurfNum) = 0.0;
333 : }
334 11285 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
335 6217 : state.dataSurface->SurfWinDifSolarEnergy(SurfNum) = 0.0;
336 6217 : state.dataSurface->SurfWinHeatGainRepEnergy(SurfNum) = 0.0;
337 6217 : state.dataSurface->SurfWinHeatLossRepEnergy(SurfNum) = 0.0;
338 6217 : state.dataSurface->SurfWinGapConvHtFlowRepEnergy(SurfNum) = 0.0;
339 6217 : state.dataSurface->SurfWinShadingAbsorbedSolarEnergy(SurfNum) = 0.0;
340 :
341 6217 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfNum) = 0.0;
342 6217 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfNum) = 0.0;
343 6217 : state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfNum) = 0.0;
344 6217 : state.dataHeatBal->SurfWinInitialDifSolInTransReport(SurfNum) = 0.0;
345 :
346 6217 : state.dataSurface->SurfWinInsideGlassCondensationFlag(SurfNum) = 0;
347 6217 : state.dataSurface->SurfWinInsideFrameCondensationFlag(SurfNum) = 0;
348 6217 : state.dataSurface->SurfWinInsideDividerCondensationFlag(SurfNum) = 0;
349 : }
350 5056 : }
351 : }
352 : }
353 :
354 : // Initialize these once
355 5572 : for (int IPhi = 1; IPhi <= NPhi; ++IPhi) { // Loop over patch altitude values
356 4776 : Real64 Phi = PhiMin + (IPhi - 1) * DPhi; // 7.5,22.5,37.5,52.5,67.5,82.5 for NPhi = 6
357 4776 : state.dataSolarShading->sin_Phi.push_back(std::sin(Phi));
358 4776 : state.dataSolarShading->cos_Phi.push_back(std::cos(Phi));
359 : }
360 :
361 19900 : for (int ITheta = 1; ITheta <= NTheta; ++ITheta) { // Loop over patch azimuth values
362 19104 : Real64 Theta = (ITheta - 1) * DTheta; // 0,15,30,....,330,345 for NTheta = 24
363 19104 : state.dataSolarShading->sin_Theta.push_back(std::sin(Theta));
364 19104 : state.dataSolarShading->cos_Theta.push_back(std::cos(Theta));
365 : }
366 :
367 796 : state.dataSolarShading->firstTime = false;
368 796 : }
369 :
370 796 : void checkShadingSurfaceSchedules(EnergyPlusData &state)
371 : {
372 : // Shading surfaces with a transmittance schedule that is always 1.0 are marked IsTransparent during shading surface input processing
373 : // Now that EMS (and other types) actuators are set up, check to see if the schedule has an actuator and reset if needed
374 2432 : for (int surfNum = state.dataSurface->ShadingSurfaceFirst; surfNum <= state.dataSurface->ShadingSurfaceLast; ++surfNum) {
375 1636 : auto &thisSurface = state.dataSurface->Surface(surfNum);
376 1636 : if (!thisSurface.IsTransparent) continue;
377 : // creating some dummy bools here on purpose -- we need to do some renaming and/or consolidate these into a meaningful new global sometime
378 : // for now I want the logic to be as readable as possible, so creating shorthand variables makes it very clear
379 0 : bool const anyPlugins = size(state.dataPluginManager->plugins) > 0;
380 0 : bool const runningByAPI = state.dataGlobal->eplusRunningViaAPI;
381 0 : bool const anyEMS = state.dataGlobal->AnyEnergyManagementSystemInModel;
382 0 : if ((anyEMS && EMSManager::isScheduleManaged(state, thisSurface.SchedShadowSurfIndex)) || runningByAPI || anyPlugins) {
383 : // Transmittance schedule definitely has an actuator or may have one via python plugin or API
384 : // Set not transparent so it won't be skipped during shading calcs
385 0 : thisSurface.IsTransparent = false;
386 : // Also set global flags
387 0 : state.dataSolarShading->anyScheduledShadingSurface = true;
388 0 : state.dataSurface->ShadingTransmittanceVaries = true;
389 0 : } else if (!thisSurface.MirroredSurf) {
390 : // Warning moved here from shading surface input processing (skip warning for mirrored surfaces)
391 0 : ShowWarningError(state,
392 0 : format(R"(Shading Surface="{}", Transmittance Schedule Name="{}", is always transparent.)",
393 0 : thisSurface.Name,
394 0 : state.dataScheduleMgr->Schedule(thisSurface.SchedShadowSurfIndex).Name));
395 0 : ShowContinueError(state, "This shading surface will be ignored.");
396 : }
397 : }
398 796 : }
399 :
400 796 : void GetShadowingInput(EnergyPlusData &state)
401 : {
402 : // SUBROUTINE INFORMATION:
403 : // AUTHOR Linda K. Lawrie
404 : // DATE WRITTEN July 1999
405 : // MODIFIED B. Griffith, Nov 2012, add calculation method
406 :
407 : // PURPOSE OF THIS SUBROUTINE:
408 : // This subroutine gets the Shadowing Calculation object.
409 :
410 : // Using/Aliasing
411 : using DataSystemVariables::ShadingMethod;
412 :
413 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
414 : int NumItems;
415 : int NumNumbers;
416 : int NumAlphas;
417 : int IOStat;
418 796 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
419 796 : state.dataIPShortCut->rNumericArgs({1, 4}) = 0.0; // so if nothing gotten, defaults will be maintained.
420 796 : state.dataIPShortCut->cAlphaArgs(1) = "";
421 796 : state.dataIPShortCut->cAlphaArgs(2) = "";
422 796 : cCurrentModuleObject = "ShadowCalculation";
423 796 : NumItems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
424 796 : NumAlphas = 0;
425 796 : NumNumbers = 0;
426 796 : if (NumItems > 1) {
427 0 : ShowWarningError(state, format("{}: More than 1 occurrence of this object found, only first will be used.", cCurrentModuleObject));
428 : }
429 :
430 796 : if (NumItems != 0) {
431 306 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
432 : cCurrentModuleObject,
433 : 1,
434 153 : state.dataIPShortCut->cAlphaArgs,
435 : NumAlphas,
436 153 : state.dataIPShortCut->rNumericArgs,
437 : NumNumbers,
438 : IOStat,
439 153 : state.dataIPShortCut->lNumericFieldBlanks,
440 153 : state.dataIPShortCut->lAlphaFieldBlanks,
441 153 : state.dataIPShortCut->cAlphaFieldNames,
442 153 : state.dataIPShortCut->cNumericFieldNames);
443 153 : state.dataSolarShading->ShadowingCalcFrequency = state.dataIPShortCut->rNumericArgs(1);
444 : }
445 :
446 796 : if (state.dataSolarShading->ShadowingCalcFrequency <= 0) {
447 : // Set to default value
448 643 : state.dataSolarShading->ShadowingCalcFrequency = 20;
449 : }
450 796 : if (state.dataSolarShading->ShadowingCalcFrequency > 31) {
451 0 : ShowWarningError(state, format("{}: suspect {}", cCurrentModuleObject, state.dataIPShortCut->cNumericFieldNames(1)));
452 0 : ShowContinueError(state, format("Value entered=[{:.0R}], Shadowing Calculations will be inaccurate.", state.dataIPShortCut->rNumericArgs(1)));
453 : }
454 :
455 796 : if (state.dataIPShortCut->rNumericArgs(2) > 199.0) {
456 153 : state.dataSolarShading->MaxHCS = state.dataIPShortCut->rNumericArgs(2);
457 : } else {
458 643 : state.dataSolarShading->MaxHCS = 15000;
459 : }
460 :
461 796 : int aNum = 1;
462 796 : unsigned pixelRes = 512u;
463 796 : if (NumAlphas >= aNum) {
464 153 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Scheduled")) {
465 1 : state.dataSysVars->shadingMethod = ShadingMethod::Scheduled;
466 1 : state.dataIPShortCut->cAlphaArgs(aNum) = "Scheduled";
467 1 : checkScheduledSurfacePresent(state);
468 152 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Imported")) {
469 1 : if (state.dataScheduleMgr->ScheduleFileShadingProcessed) {
470 1 : state.dataSysVars->shadingMethod = ShadingMethod::Imported;
471 1 : state.dataIPShortCut->cAlphaArgs(aNum) = "Imported";
472 : } else {
473 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
474 0 : ShowContinueError(state,
475 0 : format("Value entered=\"{}\" while no Schedule:File:Shading object is defined, InternalCalculation will be used.",
476 0 : state.dataIPShortCut->cAlphaArgs(aNum)));
477 : }
478 151 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "PolygonClipping")) {
479 150 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
480 150 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
481 1 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "PixelCounting")) {
482 1 : state.dataSysVars->shadingMethod = ShadingMethod::PixelCounting;
483 1 : state.dataIPShortCut->cAlphaArgs(aNum) = "PixelCounting";
484 1 : if (NumNumbers >= 3) {
485 1 : pixelRes = (unsigned)state.dataIPShortCut->rNumericArgs(3);
486 : }
487 : #ifdef EP_NO_OPENGL
488 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
489 : ShowContinueError(state, format("Value entered=\"{}\"", state.dataIPShortCut->cAlphaArgs(aNum)));
490 : ShowContinueError(state, "This version of EnergyPlus was not compiled to use OpenGL (required for PixelCounting)");
491 : ShowContinueError(state, "PolygonClipping will be used instead");
492 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
493 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
494 : #else
495 1 : if (Penumbra::Penumbra::is_valid_context()) {
496 1 : std::shared_ptr<EnergyPlusLogger> penumbra_logger = std::make_shared<EnergyPlusLogger>(EnergyPlusLogger::Log_level::Info);
497 1 : state.dataSolarShading->LoggerContext = std::make_pair<EnergyPlusData *, std::string>(&state, "");
498 1 : penumbra_logger->set_message_context(&state.dataSolarShading->LoggerContext);
499 1 : state.dataSolarShading->penumbra = std::make_unique<Penumbra::Penumbra>(pixelRes, penumbra_logger);
500 1 : } else {
501 0 : ShowWarningError(state, "No GPU found (required for PixelCounting)");
502 0 : ShowContinueError(state, "PolygonClipping will be used instead");
503 0 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
504 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
505 : }
506 : #endif
507 : } else {
508 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
509 0 : ShowContinueError(state, format("Value entered=\"{}\", PolygonClipping will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
510 : }
511 : } else {
512 643 : state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
513 643 : state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
514 : }
515 :
516 796 : aNum++;
517 796 : if (NumAlphas >= aNum) {
518 153 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Periodic")) {
519 151 : state.dataSysVars->DetailedSolarTimestepIntegration = false;
520 151 : state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
521 2 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Timestep")) {
522 2 : state.dataSysVars->DetailedSolarTimestepIntegration = true;
523 2 : state.dataIPShortCut->cAlphaArgs(aNum) = "Timestep";
524 : } else {
525 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
526 0 : ShowContinueError(state, format("Value entered=\"{}\", Periodic will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
527 0 : state.dataSysVars->DetailedSolarTimestepIntegration = false;
528 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
529 : }
530 : } else {
531 643 : state.dataSysVars->DetailedSolarTimestepIntegration = false;
532 643 : state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
533 : }
534 :
535 796 : aNum++;
536 796 : if (NumAlphas >= aNum) {
537 7 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SutherlandHodgman")) {
538 7 : state.dataSysVars->SutherlandHodgman = true;
539 7 : state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
540 0 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "ConvexWeilerAtherton")) {
541 0 : state.dataSysVars->SutherlandHodgman = false;
542 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
543 0 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SlaterBarskyandSutherlandHodgman")) {
544 0 : state.dataSysVars->SutherlandHodgman = true;
545 0 : state.dataSysVars->SlaterBarsky = true;
546 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
547 0 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(aNum)) {
548 0 : if (!state.dataSysVars->SutherlandHodgman) { // if already set.
549 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
550 : } else {
551 0 : if (!state.dataSysVars->SlaterBarsky) {
552 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
553 : } else {
554 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
555 : }
556 : }
557 : } else {
558 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
559 0 : if (!state.dataSysVars->SutherlandHodgman) {
560 0 : ShowContinueError(state, format("Value entered=\"{}\", ConvexWeilerAtherton will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
561 : } else {
562 0 : if (!state.dataSysVars->SlaterBarsky) {
563 0 : ShowContinueError(state, format("Value entered=\"{}\", SutherlandHodgman will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
564 : } else {
565 0 : ShowContinueError(
566 : state,
567 0 : format("Value entered=\"{}\", SlaterBarskyandSutherlandHodgman will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
568 : }
569 : }
570 : }
571 : } else {
572 789 : if (!state.dataSysVars->SutherlandHodgman) {
573 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
574 : } else {
575 789 : if (!state.dataSysVars->SlaterBarsky) {
576 789 : state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
577 : } else {
578 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
579 : }
580 : }
581 : }
582 :
583 796 : aNum++;
584 796 : if (NumAlphas >= aNum) {
585 5 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SimpleSkyDiffuseModeling")) {
586 5 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
587 5 : state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
588 0 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "DetailedSkyDiffuseModeling")) {
589 0 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = true;
590 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "DetailedSkyDiffuseModeling";
591 0 : } else if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
592 0 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
593 0 : state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
594 : } else {
595 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
596 0 : ShowContinueError(state, format("Value entered=\"{}\", SimpleSkyDiffuseModeling will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
597 : }
598 : } else {
599 791 : state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
600 791 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
601 : }
602 :
603 796 : aNum++;
604 796 : if (NumAlphas >= aNum) {
605 5 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
606 1 : state.dataSysVars->ReportExtShadingSunlitFrac = true;
607 1 : state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
608 4 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
609 4 : state.dataSysVars->ReportExtShadingSunlitFrac = false;
610 4 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
611 : } else {
612 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
613 0 : ShowContinueError(state, format("Value entered=\"{}\", InternalCalculation will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
614 : }
615 : } else {
616 791 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
617 791 : state.dataSysVars->ReportExtShadingSunlitFrac = false;
618 : }
619 :
620 796 : aNum++;
621 796 : if (NumAlphas >= aNum) {
622 3 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
623 2 : state.dataSysVars->DisableSelfShadingWithinGroup = true;
624 2 : state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
625 1 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
626 1 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
627 : } else {
628 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
629 0 : ShowContinueError(state,
630 0 : format("Value entered=\"{}\", all shading effects would be considered.", state.dataIPShortCut->cAlphaArgs(aNum)));
631 : }
632 : } else {
633 793 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
634 : }
635 :
636 796 : aNum++;
637 796 : if (NumAlphas >= aNum) {
638 3 : if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
639 1 : state.dataSysVars->DisableSelfShadingBetweenGroup = true;
640 1 : state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
641 2 : } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
642 2 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
643 : } else {
644 0 : ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
645 0 : ShowContinueError(state,
646 0 : format("Value entered=\"{}\", all shading effects would be considered.", state.dataIPShortCut->cAlphaArgs(aNum)));
647 : }
648 : } else {
649 793 : state.dataIPShortCut->cAlphaArgs(aNum) = "No";
650 : }
651 :
652 796 : if (state.dataSysVars->DisableSelfShadingBetweenGroup && state.dataSysVars->DisableSelfShadingWithinGroup) {
653 1 : state.dataSysVars->DisableAllSelfShading = true;
654 795 : } else if (state.dataSysVars->DisableSelfShadingBetweenGroup || state.dataSysVars->DisableSelfShadingWithinGroup) {
655 1 : state.dataSysVars->DisableGroupSelfShading = true;
656 : }
657 :
658 796 : aNum++;
659 796 : state.dataSysVars->shadingGroupsNum = NumAlphas - (aNum - 1);
660 796 : state.dataSysVars->shadingGroupZoneListNames.allocate(state.dataSysVars->shadingGroupsNum);
661 797 : for (int numZone = 1; numZone <= state.dataSysVars->shadingGroupsNum; ++numZone) {
662 1 : state.dataSysVars->shadingGroupZoneListNames(numZone) = state.dataIPShortCut->cAlphaArgs(aNum - 1 + numZone);
663 : }
664 :
665 796 : if (!state.dataSysVars->DetailedSolarTimestepIntegration && state.dataSurface->ShadingTransmittanceVaries &&
666 0 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
667 :
668 0 : ShowWarningError(state, "GetShadowingInput: The shading transmittance for shading devices may change throughout the year.");
669 0 : ShowContinueError(state,
670 0 : format("Choose Shading Calculation Update Frequency Method = Timestep in the {} object to capture all shading impacts.",
671 : cCurrentModuleObject));
672 : }
673 796 : if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm && state.dataSurface->ShadingTransmittanceVaries &&
674 0 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
675 :
676 0 : ShowWarningError(state, "GetShadowingInput: The shading transmittance for shading devices may change throughout the year.");
677 0 : ShowContinueError(state, "Simulation has been reset to use DetailedSkyDiffuseModeling. Simulation continues.");
678 0 : ShowContinueError(state, format("Choose DetailedSkyDiffuseModeling in the {} object to remove this warning.", cCurrentModuleObject));
679 0 : state.dataSysVars->DetailedSkyDiffuseAlgorithm = true;
680 0 : state.dataIPShortCut->cAlphaArgs(2) = "DetailedSkyDiffuseModeling";
681 0 : if (!state.dataSysVars->DetailedSolarTimestepIntegration && state.dataSolarShading->ShadowingCalcFrequency > 1) {
682 0 : ShowContinueError(state,
683 0 : format("Better accuracy may be gained by setting the {} to 1 in the {} object.",
684 0 : state.dataIPShortCut->cNumericFieldNames(1),
685 : cCurrentModuleObject));
686 : }
687 796 : } else if (state.dataSysVars->DetailedSkyDiffuseAlgorithm) {
688 0 : if (!state.dataSurface->ShadingTransmittanceVaries || state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
689 0 : ShowWarningError(state,
690 : "GetShadowingInput: DetailedSkyDiffuseModeling is chosen but not needed as either the shading transmittance for "
691 : "shading devices does not change throughout the year");
692 0 : ShowContinueError(state, " or MinimalShadowing has been chosen.");
693 0 : ShowContinueError(state, "Simulation should be set to use SimpleSkyDiffuseModeling, but is left at Detailed for simulation.");
694 0 : ShowContinueError(state, format("Choose SimpleSkyDiffuseModeling in the {} object to reduce computation time.", cCurrentModuleObject));
695 : }
696 : }
697 :
698 796 : print(state.files.eio,
699 : "{}",
700 : "! <Shadowing/Sun Position Calculations Annual Simulations>, Shading Calculation Method, "
701 : "Shading Calculation Update Frequency Method, Shading Calculation Update Frequency {days}, "
702 : "Maximum Figures in Shadow Overlap Calculations {}, Polygon Clipping Algorithm, Pixel Counting Resolution, Sky Diffuse Modeling "
703 : "Algorithm, Output External Shading Calculation Results, Disable "
704 : "Self-Shading Within Shading Zone Groups, Disable Self-Shading From Shading Zone Groups to Other Zones\n");
705 5572 : print(state.files.eio,
706 : "Shadowing/Sun Position Calculations Annual Simulations,{},{},{},{},{},{},{},{},{},{}\n",
707 796 : state.dataIPShortCut->cAlphaArgs(1),
708 796 : state.dataIPShortCut->cAlphaArgs(2),
709 796 : state.dataSolarShading->ShadowingCalcFrequency,
710 796 : state.dataSolarShading->MaxHCS,
711 796 : state.dataIPShortCut->cAlphaArgs(3),
712 : pixelRes,
713 796 : state.dataIPShortCut->cAlphaArgs(4),
714 796 : state.dataIPShortCut->cAlphaArgs(5),
715 796 : state.dataIPShortCut->cAlphaArgs(6),
716 796 : state.dataIPShortCut->cAlphaArgs(7));
717 796 : }
718 :
719 796 : void processShadowingInput(EnergyPlusData &state)
720 : {
721 : // all shadow input processing that needed zones and surfaces to already be read into data (part of fix for Defect #10299)
722 :
723 797 : if ((state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::PixelCounting) &&
724 1 : state.dataSolarShading->anyScheduledShadingSurface) {
725 1 : ShowSevereError(state, "The Shading Calculation Method of choice is \"PixelCounting\"; ");
726 1 : ShowContinueError(state, "and there is at least one shading surface of type ");
727 1 : ShowContinueError(state, "Shading:Site:Detailed, Shading:Building:Detailed, or Shading:Zone:Detailed, ");
728 1 : ShowContinueError(state, "that has an active transmittance schedule value greater than zero or may vary.");
729 1 : ShowContinueError(state, "With \"PixelCounting\" Shading Calculation Method, the shading surfaces will be treated as ");
730 1 : ShowContinueError(state, "completely opaque (transmittance = 0) during the shading calculation, ");
731 1 : ShowContinueError(state, "which may result in inaccurate or unexpected results.");
732 1 : ShowContinueError(state, "It is suggested switching to another Shading Calculation Method, such as \"PolygonClipping\".");
733 : }
734 :
735 796 : if (state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::Imported) {
736 : int ExtShadingSchedNum;
737 114 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
738 113 : ExtShadingSchedNum = ScheduleManager::GetScheduleIndex(state, state.dataSurface->Surface(SurfNum).Name + "_shading");
739 113 : if (ExtShadingSchedNum != 0) {
740 113 : state.dataSurface->Surface(SurfNum).SurfSchedExternalShadingFrac = true;
741 113 : state.dataSurface->Surface(SurfNum).SurfExternalShadingSchInd = ExtShadingSchedNum;
742 : } else {
743 0 : ShowWarningError(state,
744 0 : format("processShadowingInput: sunlit fraction schedule not found for {} when using ImportedShading.",
745 0 : state.dataSurface->Surface(SurfNum).Name));
746 0 : ShowContinueError(state, "These values are set to 1.0.");
747 : }
748 : }
749 : }
750 :
751 : int SurfZoneGroup, CurZoneGroup;
752 796 : int Found = 0;
753 796 : 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 114 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
765 113 : if (state.dataSurface->Surface(SurfNum).ExtBoundCond == 0) { // Loop through all exterior surfaces
766 89 : SurfZoneGroup = 0;
767 : // Check the shading zone group of each exterior surface
768 178 : for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups
769 89 : CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop);
770 425 : for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones;
771 : ZoneNum++) { // Loop through all zones in the zone list
772 375 : if (state.dataSurface->Surface(SurfNum).Zone == state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum)) {
773 39 : SurfZoneGroup = CurZoneGroup;
774 39 : break;
775 : }
776 : }
777 : }
778 : // if a surface is not in any zone group, no self shading is disabled for this surface
779 89 : 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 78 : for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups
783 39 : CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop);
784 39 : if (SurfZoneGroup == CurZoneGroup && state.dataSysVars->DisableSelfShadingWithinGroup) {
785 234 : for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones;
786 : ZoneNum++) { // Loop through all zones in the zone list
787 195 : state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back(
788 195 : 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 796 : }
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 1 : for (int surfNum = 1; surfNum <= surfData->TotSurfaces; ++surfNum) {
813 0 : auto &thisSurf = surfData->Surface(surfNum);
814 0 : if ((thisSurf.Class == SurfaceClass::Shading || thisSurf.Class == SurfaceClass::Detached_F || thisSurf.Class == SurfaceClass::Detached_B ||
815 0 : thisSurf.Class == SurfaceClass::Overhang || thisSurf.Class == SurfaceClass::Fin))
816 0 : continue; // skip shading surfaces
817 0 : if (!thisSurf.SurfSchedExternalShadingFrac) {
818 0 : numNotDef += 1;
819 0 : if (numNotDef == 1) {
820 0 : ShowWarningError(
821 : state,
822 0 : format("ShadowCalculation specified Schedule for the Shading Calculation Method but no schedule provided for {}", thisSurf.Name));
823 0 : ShowContinueError(
824 : state, "When Schedule is selected for the Shading Calculation Method and no schedule is provided for a particular surface,");
825 0 : ShowContinueError(
826 : state, "EnergyPlus will assume that the surface is not shaded. Use SurfaceProperty:LocalEnvironment to specify a schedule");
827 0 : 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 796 : 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 796 : int constexpr HoursInDay(24);
855 :
856 796 : state.dataSolarShading->SurfSunCosTheta.dimension(state.dataSurface->TotSurfaces, 0.0);
857 796 : state.dataSolarShading->SurfSunlitArea.dimension(state.dataSurface->TotSurfaces, 0.0);
858 796 : if (!state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() || !state.dataWindowManager->winOpticalModel->isSimplifiedModel()) {
859 794 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac.allocate(state.dataSurface->TotSurfaces);
860 794 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac.allocate(state.dataSurface->TotSurfaces);
861 794 : state.dataSolarShading->SurfWinTransBmSolar.allocate(state.dataSurface->TotSurfaces);
862 794 : state.dataSolarShading->SurfWinTransDifSolar.allocate(state.dataSurface->TotSurfaces);
863 794 : state.dataSolarShading->SurfWinTransDifSolarGnd.allocate(state.dataSurface->TotSurfaces);
864 794 : state.dataSolarShading->SurfWinTransDifSolarSky.allocate(state.dataSurface->TotSurfaces);
865 794 : state.dataSolarShading->SurfWinTransBmBmSolar.allocate(state.dataSurface->TotSurfaces);
866 794 : state.dataSolarShading->SurfWinTransBmDifSolar.allocate(state.dataSurface->TotSurfaces);
867 : }
868 796 : state.dataSolarShading->SurfAnisoSkyMult.dimension(state.dataSurface->TotSurfaces, 1.0);
869 796 : state.dataSolarShading->SurfIntAbsFac.dimension(state.dataSurface->TotSurfaces, 0.0);
870 : // For isotropic sky: recalculated in AnisoSkyViewFactors if anisotropic radiance
871 : // ALLOCATE(WithShdgIsoSky(TotSurfaces))
872 : // WithShdgIsoSky=0.0
873 : // ALLOCATE(WoShdgIsoSky(TotSurfaces))
874 : // WoShdgIsoSky=0.0
875 : // ALLOCATE(WithShdgHoriz(TotSurfaces))
876 : // WithShdgHoriz=0.0
877 : // ALLOCATE(WoShdgHoriz(TotSurfaces))
878 : // WoShdgHoriz=0.0
879 : // ALLOCATE(DifShdgRatioIsoSky(TotSurfaces))
880 : // DifShdgRatioIsoSky=0.0
881 : // ALLOCATE(DifShdgRatioHoriz(TotSurfaces))
882 : // DifShdgRatioHoriz=0.0
883 796 : state.dataSolarShading->SurfMultIsoSky.dimension(state.dataSurface->TotSurfaces, 0.0);
884 796 : state.dataSolarShading->SurfMultCircumSolar.dimension(state.dataSurface->TotSurfaces, 0.0);
885 796 : state.dataSolarShading->SurfMultHorizonZenith.dimension(state.dataSurface->TotSurfaces, 0.0);
886 796 : state.dataSolarShading->SurfWinRevealStatus.dimension(24, state.dataGlobal->NumOfTimeStepInHour, state.dataSurface->TotSurfaces, 0);
887 :
888 : // Weiler-Atherton
889 796 : state.dataSolarShading->MAXHCArrayBounds = 2 * (state.dataSurface->MaxVerticesPerSurface + 1);
890 796 : state.dataSolarShading->MAXHCArrayIncrement = state.dataSurface->MaxVerticesPerSurface + 1;
891 796 : state.dataSolarShading->XTEMP.dimension(2 * (state.dataSurface->MaxVerticesPerSurface + 1), 0.0);
892 796 : state.dataSolarShading->YTEMP.dimension(2 * (state.dataSurface->MaxVerticesPerSurface + 1), 0.0);
893 796 : state.dataSolarShading->XVC.dimension(state.dataSurface->MaxVerticesPerSurface + 1, 0.0);
894 796 : state.dataSolarShading->XVS.dimension(state.dataSurface->MaxVerticesPerSurface + 1, 0.0);
895 796 : state.dataSolarShading->YVC.dimension(state.dataSurface->MaxVerticesPerSurface + 1, 0.0);
896 796 : state.dataSolarShading->YVS.dimension(state.dataSurface->MaxVerticesPerSurface + 1, 0.0);
897 796 : state.dataSolarShading->ZVC.dimension(state.dataSurface->MaxVerticesPerSurface + 1, 0.0);
898 :
899 : // Sutherland-Hodgman
900 796 : state.dataSolarShading->ATEMP.dimension(2 * (state.dataSurface->MaxVerticesPerSurface + 1), 0.0);
901 796 : state.dataSolarShading->BTEMP.dimension(2 * (state.dataSurface->MaxVerticesPerSurface + 1), 0.0);
902 796 : state.dataSolarShading->CTEMP.dimension(2 * (state.dataSurface->MaxVerticesPerSurface + 1), 0.0);
903 796 : state.dataSolarShading->XTEMP1.dimension(2 * (state.dataSurface->MaxVerticesPerSurface + 1), 0.0);
904 796 : state.dataSolarShading->YTEMP1.dimension(2 * (state.dataSurface->MaxVerticesPerSurface + 1), 0.0);
905 :
906 796 : state.dataSurface->SurfSunCosHourly.allocate(HoursInDay);
907 19900 : for (int hour = 1; hour <= HoursInDay; hour++) {
908 19104 : state.dataSurface->SurfSunCosHourly(hour) = 0.0;
909 : }
910 796 : state.dataSurface->SurfSunlitArea.dimension(state.dataSurface->TotSurfaces, 0.0);
911 796 : state.dataSurface->SurfSunlitFrac.dimension(state.dataSurface->TotSurfaces, 0.0);
912 796 : state.dataSurface->SurfSkySolarInc.dimension(state.dataSurface->TotSurfaces, 0);
913 796 : state.dataSurface->SurfGndSolarInc.dimension(state.dataSurface->TotSurfaces, 0);
914 796 : state.dataSurface->SurfBmToBmReflFacObs.dimension(state.dataSurface->TotSurfaces, 0.0);
915 796 : state.dataSurface->SurfBmToDiffReflFacObs.dimension(state.dataSurface->TotSurfaces, 0.0);
916 796 : state.dataSurface->SurfBmToDiffReflFacGnd.dimension(state.dataSurface->TotSurfaces, 0.0);
917 796 : state.dataSurface->SurfSkyDiffReflFacGnd.dimension(state.dataSurface->TotSurfaces, 0.0);
918 796 : state.dataSurface->SurfOpaqAI.dimension(state.dataSurface->TotSurfaces, 0.0);
919 796 : state.dataSurface->SurfOpaqAO.dimension(state.dataSurface->TotSurfaces, 0.0);
920 796 : state.dataSurface->SurfWinTransSolar.dimension(state.dataSurface->TotSurfaces, 0.0);
921 796 : state.dataSurface->SurfWinBmSolar.dimension(state.dataSurface->TotSurfaces, 0.0);
922 796 : state.dataSurface->SurfWinBmBmSolar.dimension(state.dataSurface->TotSurfaces, 0.0);
923 796 : state.dataSurface->SurfWinBmDifSolar.dimension(state.dataSurface->TotSurfaces, 0.0);
924 796 : state.dataSurface->SurfWinDifSolar.dimension(state.dataSurface->TotSurfaces, 0.0);
925 796 : state.dataSurface->SurfWinHeatGain.dimension(state.dataSurface->TotSurfaces, 0.0);
926 796 : state.dataSurface->SurfWinHeatGainRep.dimension(state.dataSurface->TotSurfaces, 0.0);
927 796 : state.dataSurface->SurfWinHeatLossRep.dimension(state.dataSurface->TotSurfaces, 0.0);
928 796 : state.dataSurface->SurfWinGainConvGlazToZoneRep.dimension(state.dataSurface->TotSurfaces, 0.0);
929 796 : state.dataSurface->SurfWinGainIRGlazToZoneRep.dimension(state.dataSurface->TotSurfaces, 0.0);
930 796 : state.dataSurface->SurfWinLossSWZoneToOutWinRep.dimension(state.dataSurface->TotSurfaces, 0.0);
931 796 : state.dataSurface->SurfWinGainFrameDividerToZoneRep.dimension(state.dataSurface->TotSurfaces, 0.0);
932 796 : state.dataSurface->SurfWinGainConvShadeToZoneRep.dimension(state.dataSurface->TotSurfaces, 0.0);
933 796 : state.dataSurface->SurfWinGainIRShadeToZoneRep.dimension(state.dataSurface->TotSurfaces, 0.0);
934 796 : state.dataSurface->SurfWinGapConvHtFlowRep.dimension(state.dataSurface->TotSurfaces, 0.0);
935 796 : state.dataSurface->SurfWinShadingAbsorbedSolar.dimension(state.dataSurface->TotSurfaces, 0.0);
936 796 : state.dataSurface->SurfWinSysSolTransmittance.dimension(state.dataSurface->TotSurfaces, 0.0);
937 796 : state.dataSurface->SurfWinSysSolReflectance.dimension(state.dataSurface->TotSurfaces, 0.0);
938 796 : state.dataSurface->SurfWinSysSolAbsorptance.dimension(state.dataSurface->TotSurfaces, 0.0);
939 796 : state.dataSurface->SurfWinInsideGlassCondensationFlag.dimension(state.dataSurface->TotSurfaces, 0);
940 796 : state.dataSurface->SurfWinInsideFrameCondensationFlag.dimension(state.dataSurface->TotSurfaces, 0);
941 796 : state.dataSurface->SurfWinInsideDividerCondensationFlag.dimension(state.dataSurface->TotSurfaces, 0);
942 :
943 796 : state.dataHeatBal->SurfSunlitFracHR.dimension(HoursInDay, state.dataSurface->TotSurfaces, 0.0);
944 796 : state.dataHeatBal->SurfSunlitFrac.dimension(HoursInDay, state.dataGlobal->NumOfTimeStepInHour, state.dataSurface->TotSurfaces, 0.0);
945 796 : state.dataHeatBal->SurfSunlitFracWithoutReveal.dimension(HoursInDay, state.dataGlobal->NumOfTimeStepInHour, state.dataSurface->TotSurfaces, 0.0);
946 3184 : state.dataHeatBal->SurfWinBackSurfaces.dimension(
947 2388 : HoursInDay, state.dataGlobal->NumOfTimeStepInHour, state.dataBSDFWindow->MaxBkSurf, state.dataSurface->TotSurfaces, 0);
948 3184 : state.dataHeatBal->SurfWinOverlapAreas.dimension(
949 2388 : HoursInDay, state.dataGlobal->NumOfTimeStepInHour, state.dataBSDFWindow->MaxBkSurf, state.dataSurface->TotSurfaces, 0.0);
950 796 : state.dataHeatBal->SurfCosIncAngHR.dimension(HoursInDay, state.dataSurface->TotSurfaces, 0.0);
951 796 : state.dataHeatBal->SurfCosIncAng.dimension(HoursInDay, state.dataGlobal->NumOfTimeStepInHour, state.dataSurface->TotSurfaces, 0.0);
952 :
953 796 : state.dataHeatBal->ZoneTransSolar.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
954 796 : state.dataHeatBal->ZoneBmSolFrExtWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
955 796 : state.dataHeatBal->ZoneBmSolFrIntWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
956 796 : state.dataHeatBal->EnclSolInitialDifSolReflW.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
957 796 : state.dataHeatBal->ZoneDifSolFrExtWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
958 796 : state.dataHeatBal->ZoneDifSolFrIntWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
959 796 : state.dataHeatBal->ZoneWinHeatGain.dimension(state.dataGlobal->NumOfZones, 0.0);
960 796 : state.dataHeatBal->ZoneWinHeatGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
961 796 : state.dataHeatBal->ZoneWinHeatLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
962 796 : state.dataHeatBal->ZoneOpaqSurfInsFaceCond.dimension(state.dataGlobal->NumOfZones, 0.0);
963 796 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
964 796 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
965 796 : state.dataHeatBal->ZoneOpaqSurfExtFaceCond.dimension(state.dataGlobal->NumOfZones, 0.0);
966 796 : state.dataHeatBal->ZoneOpaqSurfExtFaceCondGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
967 796 : state.dataHeatBal->ZoneOpaqSurfExtFaceCondLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
968 :
969 796 : state.dataHeatBal->SurfQRadSWOutIncident.dimension(state.dataSurface->TotSurfaces, 0.0);
970 796 : state.dataHeatBal->SurfQRadSWOutIncidentBeam.dimension(state.dataSurface->TotSurfaces, 0.0);
971 796 : state.dataHeatBal->SurfBmIncInsSurfIntensRep.dimension(state.dataSurface->TotSurfaces, 0.0);
972 796 : state.dataHeatBal->SurfBmIncInsSurfAmountRep.dimension(state.dataSurface->TotSurfaces, 0.0);
973 : // ALLOCATE(DifIncInsSurfIntensRep(TotSurfaces))
974 : // DifIncInsSurfIntensRep=0.0
975 : // ALLOCATE(DifIncInsSurfAmountRep(TotSurfaces))
976 : // DifIncInsSurfAmountRep=0.0
977 796 : state.dataHeatBal->SurfIntBmIncInsSurfIntensRep.dimension(state.dataSurface->TotSurfaces, 0.0);
978 796 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRep.dimension(state.dataSurface->TotSurfaces, 0.0);
979 : // ALLOCATE(IntDifIncInsSurfIntensRep(TotSurfaces))
980 : // IntDifIncInsSurfIntensRep=0.0
981 : // ALLOCATE(IntDifIncInsSurfAmountRep(TotSurfaces))
982 : // IntDifIncInsSurfAmountRep=0.0
983 796 : state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse.dimension(state.dataSurface->TotSurfaces, 0.0);
984 796 : state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse.dimension(state.dataSurface->TotSurfaces, 0.0);
985 796 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd.dimension(state.dataSurface->TotSurfaces, 0.0);
986 796 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd.dimension(state.dataSurface->TotSurfaces, 0.0);
987 796 : state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs.dimension(state.dataSurface->TotSurfaces, 0.0);
988 796 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs.dimension(state.dataSurface->TotSurfaces, 0.0);
989 796 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs.dimension(state.dataSurface->TotSurfaces, 0.0);
990 796 : state.dataHeatBal->SurfCosIncidenceAngle.dimension(state.dataSurface->TotSurfaces, 0.0);
991 :
992 796 : state.dataHeatBal->SurfWinBSDFBeamDirectionRep.dimension(state.dataSurface->TotSurfaces, 0);
993 796 : state.dataHeatBal->SurfWinBSDFBeamThetaRep.dimension(state.dataSurface->TotSurfaces, 0.0);
994 796 : state.dataHeatBal->SurfWinBSDFBeamPhiRep.dimension(state.dataSurface->TotSurfaces, 0.0);
995 796 : state.dataHeatBal->SurfWinQRadSWwinAbsTot.dimension(state.dataSurface->TotSurfaces, 0.0);
996 796 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer.dimension(state.dataSurface->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
997 796 : state.dataHeatBal->SurfWinFenLaySurfTempFront.dimension(state.dataSurface->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
998 796 : state.dataHeatBal->SurfWinFenLaySurfTempBack.dimension(state.dataSurface->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
999 :
1000 796 : state.dataHeatBal->SurfWinSWwinAbsTotalReport.dimension(state.dataSurface->TotSurfaces, 0.0);
1001 796 : state.dataHeatBal->SurfInitialDifSolInAbsReport.dimension(state.dataSurface->TotSurfaces, 0.0);
1002 796 : state.dataHeatBal->SurfWinInitialDifSolInTransReport.dimension(state.dataSurface->TotSurfaces, 0.0);
1003 796 : state.dataHeatBal->SurfSWInAbsTotalReport.dimension(state.dataSurface->TotSurfaces, 0.0);
1004 :
1005 : // energy
1006 796 : state.dataSurface->SurfWinTransSolarEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1007 796 : state.dataSurface->SurfWinBmSolarEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1008 796 : state.dataSurface->SurfWinBmBmSolarEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1009 796 : state.dataSurface->SurfWinBmDifSolarEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1010 :
1011 796 : state.dataSurface->SurfWinDifSolarEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1012 796 : state.dataSurface->SurfWinHeatGainRepEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1013 796 : state.dataSurface->SurfWinHeatLossRepEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1014 796 : state.dataSurface->SurfWinGapConvHtFlowRepEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1015 796 : state.dataSurface->SurfWinHeatTransferRepEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1016 796 : state.dataSurface->SurfWinShadingAbsorbedSolarEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1017 :
1018 796 : state.dataHeatBal->ZoneTransSolarEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1019 796 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1020 796 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1021 796 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1022 796 : state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
1023 796 : state.dataHeatBal->ZoneWinHeatGainRepEnergy.dimension(state.dataGlobal->NumOfZones, 0.0);
1024 796 : state.dataHeatBal->ZoneWinHeatLossRepEnergy.dimension(state.dataGlobal->NumOfZones, 0.0);
1025 :
1026 796 : state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1027 796 : state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1028 796 : state.dataHeatBal->ZnOpqSurfExtFaceCondGnRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1029 796 : state.dataHeatBal->ZnOpqSurfExtFaceCondLsRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
1030 : // ALLOCATE(DifIncInsSurfAmountRepEnergy(TotSurfaces))
1031 : // DifIncInsSurfAmountRepEnergy=0.0
1032 796 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1033 796 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1034 : // ALLOCATE(IntDifIncInsSurfAmountRepEnergy(TotSurfaces))
1035 : // IntDifIncInsSurfAmountRepEnergy=0.0
1036 796 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy.dimension(state.dataSurface->TotSurfaces, 0.0);
1037 :
1038 46840 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
1039 46044 : state.dataSurface->SurfWinBmSolAbsdOutsReveal(SurfNum) = 0.0;
1040 46044 : state.dataSurface->SurfWinBmSolRefldOutsRevealReport(SurfNum) = 0.0;
1041 46044 : state.dataSurface->SurfWinBmSolAbsdInsReveal(SurfNum) = 0.0;
1042 46044 : state.dataSurface->SurfWinBmSolRefldInsReveal(SurfNum) = 0.0;
1043 46044 : state.dataSurface->SurfWinBmSolRefldInsRevealReport(SurfNum) = 0.0;
1044 46044 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) = 0.0;
1045 46044 : state.dataSurface->SurfWinInsRevealDiffOntoGlazing(SurfNum) = 0.0;
1046 46044 : state.dataSurface->SurfWinInsRevealDiffIntoZone(SurfNum) = 0.0;
1047 46044 : state.dataSurface->SurfWinOutsRevealDiffOntoFrame(SurfNum) = 0.0;
1048 46044 : state.dataSurface->SurfWinInsRevealDiffOntoFrame(SurfNum) = 0.0;
1049 : }
1050 :
1051 : // Added report variables for inside reveal to debug CR 7596. TH 5/26/2009
1052 46840 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
1053 46044 : state.dataSurface->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) = 0.0;
1054 46044 : state.dataSurface->SurfWinInsRevealDiffIntoZoneReport(SurfNum) = 0.0;
1055 46044 : state.dataSurface->SurfWinInsRevealDiffOntoFrameReport(SurfNum) = 0.0;
1056 46044 : state.dataSurface->SurfWinBmSolAbsdInsRevealReport(SurfNum) = 0.0;
1057 : }
1058 :
1059 796 : DisplayString(state, "Initializing Zone and Enclosure Report Variables");
1060 5851 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
1061 5055 : std::string &thisEnclosureName = state.dataViewFactor->EnclSolInfo(enclosureNum).Name;
1062 10110 : SetupOutputVariable(state,
1063 : "Enclosure Windows Total Transmitted Solar Radiation Rate",
1064 : Constant::Units::W,
1065 5055 : state.dataHeatBal->ZoneTransSolar(enclosureNum),
1066 : OutputProcessor::TimeStepType::Zone,
1067 : OutputProcessor::StoreType::Average,
1068 : thisEnclosureName);
1069 10110 : SetupOutputVariable(state,
1070 : "Enclosure Exterior Windows Total Transmitted Beam Solar Radiation Rate",
1071 : Constant::Units::W,
1072 5055 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum),
1073 : OutputProcessor::TimeStepType::Zone,
1074 : OutputProcessor::StoreType::Average,
1075 : thisEnclosureName);
1076 10110 : SetupOutputVariable(state,
1077 : "Enclosure Interior Windows Total Transmitted Beam Solar Radiation Rate",
1078 : Constant::Units::W,
1079 5055 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum),
1080 : OutputProcessor::TimeStepType::Zone,
1081 : OutputProcessor::StoreType::Average,
1082 : thisEnclosureName);
1083 10110 : SetupOutputVariable(state,
1084 : "Enclosure Exterior Windows Total Transmitted Diffuse Solar Radiation Rate",
1085 : Constant::Units::W,
1086 5055 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum),
1087 : OutputProcessor::TimeStepType::Zone,
1088 : OutputProcessor::StoreType::Average,
1089 : thisEnclosureName);
1090 10110 : SetupOutputVariable(state,
1091 : "Enclosure Interior Windows Total Transmitted Diffuse Solar Radiation Rate",
1092 : Constant::Units::W,
1093 5055 : state.dataHeatBal->ZoneDifSolFrIntWinsRep(enclosureNum),
1094 : OutputProcessor::TimeStepType::Zone,
1095 : OutputProcessor::StoreType::Average,
1096 : thisEnclosureName);
1097 : // Energy variables
1098 10110 : SetupOutputVariable(state,
1099 : "Enclosure Windows Total Transmitted Solar Radiation Energy",
1100 : Constant::Units::J,
1101 5055 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum),
1102 : OutputProcessor::TimeStepType::Zone,
1103 : OutputProcessor::StoreType::Sum,
1104 : thisEnclosureName);
1105 10110 : SetupOutputVariable(state,
1106 : "Enclosure Exterior Windows Total Transmitted Beam Solar Radiation Energy",
1107 : Constant::Units::J,
1108 5055 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum),
1109 : OutputProcessor::TimeStepType::Zone,
1110 : OutputProcessor::StoreType::Sum,
1111 : thisEnclosureName);
1112 10110 : SetupOutputVariable(state,
1113 : "Enclosure Interior Windows Total Transmitted Beam Solar Radiation Energy",
1114 : Constant::Units::J,
1115 5055 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclosureNum),
1116 : OutputProcessor::TimeStepType::Zone,
1117 : OutputProcessor::StoreType::Sum,
1118 : thisEnclosureName);
1119 10110 : SetupOutputVariable(state,
1120 : "Enclosure Exterior Windows Total Transmitted Diffuse Solar Radiation Energy",
1121 : Constant::Units::J,
1122 5055 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum),
1123 : OutputProcessor::TimeStepType::Zone,
1124 : OutputProcessor::StoreType::Sum,
1125 : thisEnclosureName);
1126 10110 : SetupOutputVariable(state,
1127 : "Enclosure Interior Windows Total Transmitted Diffuse Solar Radiation Energy",
1128 : Constant::Units::J,
1129 5055 : state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy(enclosureNum),
1130 : OutputProcessor::TimeStepType::Zone,
1131 : OutputProcessor::StoreType::Sum,
1132 : thisEnclosureName);
1133 : }
1134 5852 : for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) {
1135 10112 : SetupOutputVariable(state,
1136 : "Zone Windows Total Heat Gain Rate",
1137 : Constant::Units::W,
1138 5056 : state.dataHeatBal->ZoneWinHeatGainRep(ZoneLoop),
1139 : OutputProcessor::TimeStepType::Zone,
1140 : OutputProcessor::StoreType::Average,
1141 5056 : state.dataHeatBal->Zone(ZoneLoop).Name);
1142 10112 : SetupOutputVariable(state,
1143 : "Zone Windows Total Heat Loss Rate",
1144 : Constant::Units::W,
1145 5056 : state.dataHeatBal->ZoneWinHeatLossRep(ZoneLoop),
1146 : OutputProcessor::TimeStepType::Zone,
1147 : OutputProcessor::StoreType::Average,
1148 5056 : state.dataHeatBal->Zone(ZoneLoop).Name);
1149 10112 : SetupOutputVariable(state,
1150 : "Zone Windows Total Heat Gain Energy",
1151 : Constant::Units::J,
1152 5056 : state.dataHeatBal->ZoneWinHeatGainRepEnergy(ZoneLoop),
1153 : OutputProcessor::TimeStepType::Zone,
1154 : OutputProcessor::StoreType::Sum,
1155 5056 : state.dataHeatBal->Zone(ZoneLoop).Name);
1156 10112 : SetupOutputVariable(state,
1157 : "Zone Windows Total Heat Loss Energy",
1158 : Constant::Units::J,
1159 5056 : state.dataHeatBal->ZoneWinHeatLossRepEnergy(ZoneLoop),
1160 : OutputProcessor::TimeStepType::Zone,
1161 : OutputProcessor::StoreType::Sum,
1162 5056 : state.dataHeatBal->Zone(ZoneLoop).Name);
1163 5056 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
1164 : // CurrentModuleObject='Zone(Advanced)'
1165 120 : SetupOutputVariable(state,
1166 : "Zone Opaque Surface Inside Faces Total Conduction Heat Gain Rate",
1167 : Constant::Units::W,
1168 60 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep(ZoneLoop),
1169 : OutputProcessor::TimeStepType::Zone,
1170 : OutputProcessor::StoreType::Average,
1171 60 : state.dataHeatBal->Zone(ZoneLoop).Name);
1172 120 : SetupOutputVariable(state,
1173 : "Zone Opaque Surface Inside Faces Total Conduction Heat Loss Rate",
1174 : Constant::Units::W,
1175 60 : state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep(ZoneLoop),
1176 : OutputProcessor::TimeStepType::Zone,
1177 : OutputProcessor::StoreType::Average,
1178 60 : state.dataHeatBal->Zone(ZoneLoop).Name);
1179 : // Energy variables
1180 120 : SetupOutputVariable(state,
1181 : "Zone Opaque Surface Inside Faces Total Conduction Heat Gain Energy",
1182 : Constant::Units::J,
1183 60 : state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg(ZoneLoop),
1184 : OutputProcessor::TimeStepType::Zone,
1185 : OutputProcessor::StoreType::Sum,
1186 60 : state.dataHeatBal->Zone(ZoneLoop).Name);
1187 120 : SetupOutputVariable(state,
1188 : "Zone Opaque Surface Inside Faces Total Conduction Heat Loss Energy",
1189 : Constant::Units::J,
1190 60 : state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg(ZoneLoop),
1191 : OutputProcessor::TimeStepType::Zone,
1192 : OutputProcessor::StoreType::Sum,
1193 60 : state.dataHeatBal->Zone(ZoneLoop).Name);
1194 : }
1195 : }
1196 :
1197 796 : DisplayString(state, "Initializing Surface (Shading) Report Variables");
1198 : // CurrentModuleObject='Surfaces'
1199 46840 : for (int SurfLoop = 1; SurfLoop <= state.dataSurface->TotSurfaces; ++SurfLoop) {
1200 46044 : auto &surf = state.dataSurface->Surface(SurfLoop);
1201 92088 : SetupOutputVariable(state,
1202 : "Surface Outside Normal Azimuth Angle",
1203 : Constant::Units::deg,
1204 46044 : surf.Azimuth,
1205 : OutputProcessor::TimeStepType::Zone,
1206 : OutputProcessor::StoreType::Average,
1207 46044 : surf.Name);
1208 46044 : if (surf.ExtSolar) {
1209 38664 : SetupOutputVariable(state,
1210 : "Surface Outside Face Sunlit Area",
1211 : Constant::Units::m2,
1212 19332 : state.dataSurface->SurfSunlitArea(SurfLoop),
1213 : OutputProcessor::TimeStepType::Zone,
1214 : OutputProcessor::StoreType::Average,
1215 19332 : surf.Name);
1216 38664 : SetupOutputVariable(state,
1217 : "Surface Outside Face Sunlit Fraction",
1218 : Constant::Units::None,
1219 19332 : state.dataSurface->SurfSunlitFrac(SurfLoop),
1220 : OutputProcessor::TimeStepType::Zone,
1221 : OutputProcessor::StoreType::Average,
1222 19332 : surf.Name);
1223 38664 : SetupOutputVariable(state,
1224 : "Surface Outside Face Incident Solar Radiation Rate per Area",
1225 : Constant::Units::W_m2,
1226 19332 : state.dataHeatBal->SurfQRadSWOutIncident(SurfLoop),
1227 : OutputProcessor::TimeStepType::Zone,
1228 : OutputProcessor::StoreType::Average,
1229 19332 : surf.Name);
1230 38664 : SetupOutputVariable(state,
1231 : "Surface Outside Face Incident Beam Solar Radiation Rate per Area",
1232 : Constant::Units::W_m2,
1233 19332 : state.dataHeatBal->SurfQRadSWOutIncidentBeam(SurfLoop),
1234 : OutputProcessor::TimeStepType::Zone,
1235 : OutputProcessor::StoreType::Average,
1236 19332 : surf.Name);
1237 38664 : SetupOutputVariable(state,
1238 : "Surface Outside Face Incident Sky Diffuse Solar Radiation Rate per Area",
1239 : Constant::Units::W_m2,
1240 19332 : state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse(SurfLoop),
1241 : OutputProcessor::TimeStepType::Zone,
1242 : OutputProcessor::StoreType::Average,
1243 19332 : surf.Name);
1244 38664 : SetupOutputVariable(state,
1245 : "Surface Outside Face Incident Ground Diffuse Solar Radiation Rate per Area",
1246 : Constant::Units::W_m2,
1247 19332 : state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse(SurfLoop),
1248 : OutputProcessor::TimeStepType::Zone,
1249 : OutputProcessor::StoreType::Average,
1250 19332 : surf.Name);
1251 38664 : SetupOutputVariable(state,
1252 : "Surface Outside Face Beam Solar Incident Angle Cosine Value",
1253 : Constant::Units::None,
1254 19332 : state.dataHeatBal->SurfCosIncidenceAngle(SurfLoop),
1255 : OutputProcessor::TimeStepType::Zone,
1256 : OutputProcessor::StoreType::Average,
1257 19332 : surf.Name);
1258 38664 : SetupOutputVariable(state,
1259 : "Surface Outside Face Incident Sky Diffuse Ground Reflected Solar Radiation Rate per Area",
1260 : Constant::Units::W_m2,
1261 19332 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd(SurfLoop),
1262 : OutputProcessor::TimeStepType::Zone,
1263 : OutputProcessor::StoreType::Average,
1264 19332 : surf.Name);
1265 38664 : SetupOutputVariable(state,
1266 : "Surface Outside Face Incident Sky Diffuse Surface Reflected Solar Radiation Rate per Area",
1267 : Constant::Units::W_m2,
1268 19332 : state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs(SurfLoop),
1269 : OutputProcessor::TimeStepType::Zone,
1270 : OutputProcessor::StoreType::Average,
1271 19332 : surf.Name);
1272 38664 : SetupOutputVariable(state,
1273 : "Surface Outside Face Incident Beam To Beam Surface Reflected Solar Radiation Rate per Area",
1274 : Constant::Units::W_m2,
1275 19332 : state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs(SurfLoop),
1276 : OutputProcessor::TimeStepType::Zone,
1277 : OutputProcessor::StoreType::Average,
1278 19332 : surf.Name);
1279 38664 : SetupOutputVariable(state,
1280 : "Surface Outside Face Incident Beam To Diffuse Surface Reflected Solar Radiation Rate per Area",
1281 : Constant::Units::W_m2,
1282 19332 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs(SurfLoop),
1283 : OutputProcessor::TimeStepType::Zone,
1284 : OutputProcessor::StoreType::Average,
1285 19332 : surf.Name);
1286 38664 : SetupOutputVariable(state,
1287 : "Surface Outside Face Incident Beam To Diffuse Ground Reflected Solar Radiation Rate per Area",
1288 : Constant::Units::W_m2,
1289 19332 : state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd(SurfLoop),
1290 : OutputProcessor::TimeStepType::Zone,
1291 : OutputProcessor::StoreType::Average,
1292 19332 : surf.Name);
1293 38664 : SetupOutputVariable(state,
1294 : "Surface Anisotropic Sky Multiplier",
1295 : Constant::Units::None,
1296 19332 : state.dataSolarShading->SurfAnisoSkyMult(SurfLoop),
1297 : OutputProcessor::TimeStepType::Zone,
1298 : OutputProcessor::StoreType::Average,
1299 19332 : surf.Name);
1300 19332 : SetupOutputVariable(state,
1301 : "Surface Window BSDF Beam Direction Number",
1302 : Constant::Units::None,
1303 19332 : state.dataHeatBal->SurfWinBSDFBeamDirectionRep(SurfLoop),
1304 : OutputProcessor::TimeStepType::Zone,
1305 : OutputProcessor::StoreType::Average,
1306 19332 : surf.Name);
1307 38664 : SetupOutputVariable(state,
1308 : "Surface Window BSDF Beam Theta Angle",
1309 : Constant::Units::rad,
1310 19332 : state.dataHeatBal->SurfWinBSDFBeamThetaRep(SurfLoop),
1311 : OutputProcessor::TimeStepType::Zone,
1312 : OutputProcessor::StoreType::Average,
1313 19332 : surf.Name);
1314 38664 : SetupOutputVariable(state,
1315 : "Surface Window BSDF Beam Phi Angle",
1316 : Constant::Units::rad,
1317 19332 : state.dataHeatBal->SurfWinBSDFBeamPhiRep(SurfLoop),
1318 : OutputProcessor::TimeStepType::Zone,
1319 : OutputProcessor::StoreType::Average,
1320 19332 : surf.Name);
1321 : }
1322 46044 : if (!surf.HeatTransSurf) continue;
1323 :
1324 44391 : if (surf.Class == SurfaceClass::Window) {
1325 : // CurrentModuleObject='Windows/GlassDoors'
1326 6217 : if (surf.ExtSolar) {
1327 12402 : SetupOutputVariable(state,
1328 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
1329 : Constant::Units::W,
1330 6201 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
1331 : OutputProcessor::TimeStepType::Zone,
1332 : OutputProcessor::StoreType::Average,
1333 6201 : surf.Name);
1334 12402 : SetupOutputVariable(state,
1335 : "Surface Window Total Glazing Layers Absorbed Shortwave Radiation Rate",
1336 : Constant::Units::W,
1337 6201 : state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfLoop),
1338 : OutputProcessor::TimeStepType::Zone,
1339 : OutputProcessor::StoreType::Average,
1340 6201 : surf.Name);
1341 :
1342 6201 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF) {
1343 24 : NumOfLayers = state.dataConstruction->Construct(surf.Construction).TotSolidLayers;
1344 : } else {
1345 6177 : NumOfLayers = state.dataConstruction->Construct(surf.Construction).TotLayers;
1346 : }
1347 16476 : for (I = 1; I <= NumOfLayers; ++I) {
1348 10275 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF) {
1349 204 : SetupOutputVariable(state,
1350 136 : format("Surface Window Total Absorbed Shortwave Radiation Rate Layer {}", I),
1351 : Constant::Units::W,
1352 68 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfLoop, I),
1353 : OutputProcessor::TimeStepType::Zone,
1354 : OutputProcessor::StoreType::Average,
1355 68 : surf.Name);
1356 : }
1357 10275 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF || (I == 1)) {
1358 18735 : SetupOutputVariable(state,
1359 12490 : format("Surface Window Front Face Temperature Layer {}", I),
1360 : Constant::Units::C,
1361 6245 : state.dataHeatBal->SurfWinFenLaySurfTempFront(SurfLoop, I),
1362 : OutputProcessor::TimeStepType::Zone,
1363 : OutputProcessor::StoreType::Average,
1364 6245 : surf.Name);
1365 : }
1366 10275 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF || (I == NumOfLayers)) {
1367 18735 : SetupOutputVariable(state,
1368 12490 : format("Surface Window Back Face Temperature Layer {}", I),
1369 : Constant::Units::C,
1370 6245 : state.dataHeatBal->SurfWinFenLaySurfTempBack(SurfLoop, I),
1371 : OutputProcessor::TimeStepType::Zone,
1372 : OutputProcessor::StoreType::Average,
1373 6245 : surf.Name);
1374 : }
1375 : }
1376 :
1377 12402 : SetupOutputVariable(state,
1378 : "Surface Window Transmitted Solar Radiation Rate",
1379 : Constant::Units::W,
1380 6201 : state.dataSurface->SurfWinTransSolar(SurfLoop),
1381 : OutputProcessor::TimeStepType::Zone,
1382 : OutputProcessor::StoreType::Average,
1383 6201 : surf.Name);
1384 12402 : SetupOutputVariable(state,
1385 : "Surface Window Transmitted Beam Solar Radiation Rate",
1386 : Constant::Units::W,
1387 6201 : state.dataSurface->SurfWinBmSolar(SurfLoop),
1388 : OutputProcessor::TimeStepType::Zone,
1389 : OutputProcessor::StoreType::Average,
1390 6201 : surf.Name);
1391 :
1392 : // added TH 12/9/2009
1393 12402 : SetupOutputVariable(state,
1394 : "Surface Window Transmitted Beam To Beam Solar Radiation Rate",
1395 : Constant::Units::W,
1396 6201 : state.dataSurface->SurfWinBmBmSolar(SurfLoop),
1397 : OutputProcessor::TimeStepType::Zone,
1398 : OutputProcessor::StoreType::Average,
1399 6201 : surf.Name);
1400 12402 : SetupOutputVariable(state,
1401 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Rate",
1402 : Constant::Units::W,
1403 6201 : state.dataSurface->SurfWinBmDifSolar(SurfLoop),
1404 : OutputProcessor::TimeStepType::Zone,
1405 : OutputProcessor::StoreType::Average,
1406 6201 : surf.Name);
1407 :
1408 12402 : SetupOutputVariable(state,
1409 : "Surface Window Transmitted Diffuse Solar Radiation Rate",
1410 : Constant::Units::W,
1411 6201 : state.dataSurface->SurfWinDifSolar(SurfLoop),
1412 : OutputProcessor::TimeStepType::Zone,
1413 : OutputProcessor::StoreType::Average,
1414 6201 : surf.Name);
1415 12402 : SetupOutputVariable(state,
1416 : "Surface Window Heat Gain Rate",
1417 : Constant::Units::W,
1418 6201 : state.dataSurface->SurfWinHeatGainRep(SurfLoop),
1419 : OutputProcessor::TimeStepType::Zone,
1420 : OutputProcessor::StoreType::Average,
1421 6201 : surf.Name);
1422 12402 : SetupOutputVariable(state,
1423 : "Surface Window Heat Loss Rate",
1424 : Constant::Units::W,
1425 6201 : state.dataSurface->SurfWinHeatLossRep(SurfLoop),
1426 : OutputProcessor::TimeStepType::Zone,
1427 : OutputProcessor::StoreType::Average,
1428 6201 : surf.Name);
1429 12402 : SetupOutputVariable(state,
1430 : "Surface Window Gap Convective Heat Transfer Rate",
1431 : Constant::Units::W,
1432 6201 : state.dataSurface->SurfWinGapConvHtFlowRep(SurfLoop),
1433 : OutputProcessor::TimeStepType::Zone,
1434 : OutputProcessor::StoreType::Average,
1435 6201 : surf.Name);
1436 12402 : SetupOutputVariable(state,
1437 : "Surface Window Shading Device Absorbed Solar Radiation Rate",
1438 : Constant::Units::W,
1439 6201 : state.dataSurface->SurfWinShadingAbsorbedSolar(SurfLoop),
1440 : OutputProcessor::TimeStepType::Zone,
1441 : OutputProcessor::StoreType::Average,
1442 6201 : surf.Name);
1443 12402 : SetupOutputVariable(state,
1444 : "Surface Window Net Heat Transfer Rate",
1445 : Constant::Units::W,
1446 6201 : state.dataSurface->SurfWinHeatGain(SurfLoop),
1447 : OutputProcessor::TimeStepType::Zone,
1448 : OutputProcessor::StoreType::Average,
1449 6201 : surf.Name);
1450 :
1451 6201 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
1452 : // CurrentModuleObject='Windows/GlassDoors(Advanced)'
1453 268 : SetupOutputVariable(state,
1454 : "Surface Window Inside Face Glazing Zone Convection Heat Gain Rate",
1455 : Constant::Units::W,
1456 134 : state.dataSurface->SurfWinGainConvGlazToZoneRep(SurfLoop),
1457 : OutputProcessor::TimeStepType::Zone,
1458 : OutputProcessor::StoreType::Average,
1459 134 : surf.Name);
1460 268 : SetupOutputVariable(state,
1461 : "Surface Window Inside Face Glazing Net Infrared Heat Transfer Rate",
1462 : Constant::Units::W,
1463 134 : state.dataSurface->SurfWinGainIRGlazToZoneRep(SurfLoop),
1464 : OutputProcessor::TimeStepType::Zone,
1465 : OutputProcessor::StoreType::Average,
1466 134 : surf.Name);
1467 268 : SetupOutputVariable(state,
1468 : "Surface Window Shortwave from Zone Back Out Window Heat Transfer Rate",
1469 : Constant::Units::W,
1470 134 : state.dataSurface->SurfWinLossSWZoneToOutWinRep(SurfLoop),
1471 : OutputProcessor::TimeStepType::Zone,
1472 : OutputProcessor::StoreType::Average,
1473 134 : surf.Name);
1474 268 : SetupOutputVariable(state,
1475 : "Surface Window Inside Face Frame and Divider Zone Heat Gain Rate",
1476 : Constant::Units::W,
1477 134 : state.dataSurface->SurfWinGainFrameDividerToZoneRep(SurfLoop),
1478 : OutputProcessor::TimeStepType::Zone,
1479 : OutputProcessor::StoreType::Average,
1480 134 : surf.Name);
1481 268 : SetupOutputVariable(state,
1482 : "Surface Window Inside Face Gap between Shade and Glazing Zone Convection Heat Gain Rate",
1483 : Constant::Units::W,
1484 134 : state.dataSurface->SurfWinConvHeatFlowNatural(SurfLoop),
1485 : OutputProcessor::TimeStepType::Zone,
1486 : OutputProcessor::StoreType::Average,
1487 134 : surf.Name);
1488 268 : SetupOutputVariable(state,
1489 : "Surface Window Inside Face Shade Zone Convection Heat Gain Rate",
1490 : Constant::Units::W,
1491 134 : state.dataSurface->SurfWinGainConvShadeToZoneRep(SurfLoop),
1492 : OutputProcessor::TimeStepType::Zone,
1493 : OutputProcessor::StoreType::Average,
1494 134 : surf.Name);
1495 268 : SetupOutputVariable(state,
1496 : "Surface Window Inside Face Shade Net Infrared Heat Transfer Rate",
1497 : Constant::Units::W,
1498 134 : state.dataSurface->SurfWinGainIRShadeToZoneRep(SurfLoop),
1499 : OutputProcessor::TimeStepType::Zone,
1500 : OutputProcessor::StoreType::Average,
1501 134 : surf.Name);
1502 134 : if (state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
1503 0 : SetupOutputVariable(state,
1504 : "Surface Window Inside Face Other Convection Heat Gain Rate",
1505 : Constant::Units::W,
1506 0 : state.dataSurface->SurfWinOtherConvHeatGain(SurfLoop),
1507 : OutputProcessor::TimeStepType::Zone,
1508 : OutputProcessor::StoreType::Average,
1509 0 : surf.Name);
1510 : }
1511 : }
1512 :
1513 : // Added TH 12/23/2008 for thermochromic windows
1514 : // CurrentModuleObject='Thermochromic Windows'
1515 6201 : if (state.dataConstruction->Construct(surf.Construction).TCFlag == 1) {
1516 2 : SetupOutputVariable(state,
1517 : "Surface Window Thermochromic Layer Temperature",
1518 : Constant::Units::C,
1519 1 : state.dataSurface->SurfWinTCLayerTemp(SurfLoop),
1520 : OutputProcessor::TimeStepType::Zone,
1521 : OutputProcessor::StoreType::Average,
1522 1 : surf.Name);
1523 2 : SetupOutputVariable(state,
1524 : "Surface Window Thermochromic Layer Property Specification Temperature",
1525 : Constant::Units::C,
1526 1 : state.dataSurface->SurfWinSpecTemp(SurfLoop),
1527 : OutputProcessor::TimeStepType::Zone,
1528 : OutputProcessor::StoreType::Average,
1529 1 : surf.Name);
1530 : }
1531 :
1532 : // Added TH 5/26/2009 for switchable windows to report switching factor (tinted level)
1533 : // CurrentModuleObject='Switchable Windows'
1534 6201 : if (surf.HasShadeControl) {
1535 151 : if (state.dataSurface->WindowShadingControl(surf.activeWindowShadingControl).ShadingType == WinShadingType::SwitchableGlazing) {
1536 : // IF (SurfaceWindow(SurfLoop)%ShadingFlag == WinShadingType::SwitchableGlazing) THEN !ShadingFlag is not set to
1537 : // WinShadingType::SwitchableGlazing yet!
1538 60 : SetupOutputVariable(state,
1539 : "Surface Window Switchable Glazing Switching Factor",
1540 : Constant::Units::None,
1541 30 : state.dataSurface->SurfWinSwitchingFactor(SurfLoop),
1542 : OutputProcessor::TimeStepType::Zone,
1543 : OutputProcessor::StoreType::Average,
1544 30 : surf.Name);
1545 60 : SetupOutputVariable(state,
1546 : "Surface Window Switchable Glazing Visible Transmittance",
1547 : Constant::Units::None,
1548 30 : state.dataSurface->SurfWinVisTransSelected(SurfLoop),
1549 : OutputProcessor::TimeStepType::Zone,
1550 : OutputProcessor::StoreType::Average,
1551 30 : surf.Name);
1552 : }
1553 : }
1554 :
1555 6201 : if (state.dataSurface->SurfWinFrameArea(SurfLoop) > 0.0) {
1556 : // CurrentModuleObject='Window Frames'
1557 260 : SetupOutputVariable(state,
1558 : "Surface Window Frame Heat Gain Rate",
1559 : Constant::Units::W,
1560 130 : state.dataSurface->SurfWinFrameHeatGain(SurfLoop),
1561 : OutputProcessor::TimeStepType::Zone,
1562 : OutputProcessor::StoreType::Average,
1563 130 : surf.Name);
1564 260 : SetupOutputVariable(state,
1565 : "Surface Window Frame Heat Loss Rate",
1566 : Constant::Units::W,
1567 130 : state.dataSurface->SurfWinFrameHeatLoss(SurfLoop),
1568 : OutputProcessor::TimeStepType::Zone,
1569 : OutputProcessor::StoreType::Average,
1570 130 : surf.Name);
1571 260 : SetupOutputVariable(state,
1572 : "Surface Window Frame Inside Temperature",
1573 : Constant::Units::C,
1574 130 : state.dataSurface->SurfWinFrameTempIn(SurfLoop),
1575 : OutputProcessor::TimeStepType::Zone,
1576 : OutputProcessor::StoreType::Average,
1577 130 : surf.Name);
1578 260 : SetupOutputVariable(state,
1579 : "Surface Window Frame Outside Temperature",
1580 : Constant::Units::C,
1581 130 : state.dataSurface->SurfWinFrameTempSurfOut(SurfLoop),
1582 : OutputProcessor::TimeStepType::Zone,
1583 : OutputProcessor::StoreType::Average,
1584 130 : surf.Name);
1585 : }
1586 6201 : if (state.dataSurface->SurfWinDividerArea(SurfLoop) > 0.0) {
1587 : // CurrentModuleObject='Window Dividers'
1588 128 : SetupOutputVariable(state,
1589 : "Surface Window Divider Heat Gain Rate",
1590 : Constant::Units::W,
1591 64 : state.dataSurface->SurfWinDividerHeatGain(SurfLoop),
1592 : OutputProcessor::TimeStepType::Zone,
1593 : OutputProcessor::StoreType::Average,
1594 64 : surf.Name);
1595 128 : SetupOutputVariable(state,
1596 : "Surface Window Divider Heat Loss Rate",
1597 : Constant::Units::W,
1598 64 : state.dataSurface->SurfWinDividerHeatLoss(SurfLoop),
1599 : OutputProcessor::TimeStepType::Zone,
1600 : OutputProcessor::StoreType::Average,
1601 64 : surf.Name);
1602 128 : SetupOutputVariable(state,
1603 : "Surface Window Divider Inside Temperature",
1604 : Constant::Units::C,
1605 64 : state.dataSurface->SurfWinDividerTempIn(SurfLoop),
1606 : OutputProcessor::TimeStepType::Zone,
1607 : OutputProcessor::StoreType::Average,
1608 64 : surf.Name);
1609 128 : SetupOutputVariable(state,
1610 : "Surface Window Divider Outside Temperature",
1611 : Constant::Units::C,
1612 64 : state.dataSurface->SurfWinDividerTempSurfOut(SurfLoop),
1613 : OutputProcessor::TimeStepType::Zone,
1614 : OutputProcessor::StoreType::Average,
1615 64 : surf.Name);
1616 : }
1617 :
1618 : // CurrentModuleObject='Windows'
1619 : // Energy
1620 12402 : SetupOutputVariable(state,
1621 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
1622 : Constant::Units::J,
1623 6201 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
1624 : OutputProcessor::TimeStepType::Zone,
1625 : OutputProcessor::StoreType::Sum,
1626 6201 : surf.Name);
1627 12402 : SetupOutputVariable(state,
1628 : "Surface Window Transmitted Solar Radiation Energy",
1629 : Constant::Units::J,
1630 6201 : state.dataSurface->SurfWinTransSolarEnergy(SurfLoop),
1631 : OutputProcessor::TimeStepType::Zone,
1632 : OutputProcessor::StoreType::Sum,
1633 6201 : surf.Name);
1634 12402 : SetupOutputVariable(state,
1635 : "Surface Window Transmitted Beam Solar Radiation Energy",
1636 : Constant::Units::J,
1637 6201 : state.dataSurface->SurfWinBmSolarEnergy(SurfLoop),
1638 : OutputProcessor::TimeStepType::Zone,
1639 : OutputProcessor::StoreType::Sum,
1640 6201 : surf.Name);
1641 :
1642 : // added TH 12/9/2009
1643 12402 : SetupOutputVariable(state,
1644 : "Surface Window Transmitted Beam To Beam Solar Radiation Energy",
1645 : Constant::Units::J,
1646 6201 : state.dataSurface->SurfWinBmBmSolarEnergy(SurfLoop),
1647 : OutputProcessor::TimeStepType::Zone,
1648 : OutputProcessor::StoreType::Sum,
1649 6201 : surf.Name);
1650 12402 : SetupOutputVariable(state,
1651 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Energy",
1652 : Constant::Units::J,
1653 6201 : state.dataSurface->SurfWinBmDifSolarEnergy(SurfLoop),
1654 : OutputProcessor::TimeStepType::Zone,
1655 : OutputProcessor::StoreType::Sum,
1656 6201 : surf.Name);
1657 :
1658 12402 : SetupOutputVariable(state,
1659 : "Surface Window Transmitted Diffuse Solar Radiation Energy",
1660 : Constant::Units::J,
1661 6201 : state.dataSurface->SurfWinDifSolarEnergy(SurfLoop),
1662 : OutputProcessor::TimeStepType::Zone,
1663 : OutputProcessor::StoreType::Sum,
1664 6201 : surf.Name);
1665 12402 : SetupOutputVariable(state,
1666 : "Surface Window Heat Gain Energy",
1667 : Constant::Units::J,
1668 6201 : state.dataSurface->SurfWinHeatGainRepEnergy(SurfLoop),
1669 : OutputProcessor::TimeStepType::Zone,
1670 : OutputProcessor::StoreType::Sum,
1671 6201 : surf.Name);
1672 12402 : SetupOutputVariable(state,
1673 : "Surface Window Heat Loss Energy",
1674 : Constant::Units::J,
1675 6201 : state.dataSurface->SurfWinHeatLossRepEnergy(SurfLoop),
1676 : OutputProcessor::TimeStepType::Zone,
1677 : OutputProcessor::StoreType::Sum,
1678 6201 : surf.Name);
1679 12402 : SetupOutputVariable(state,
1680 : "Surface Window Gap Convective Heat Transfer Energy",
1681 : Constant::Units::J,
1682 6201 : state.dataSurface->SurfWinGapConvHtFlowRepEnergy(SurfLoop),
1683 : OutputProcessor::TimeStepType::Zone,
1684 : OutputProcessor::StoreType::Sum,
1685 6201 : surf.Name);
1686 12402 : SetupOutputVariable(state,
1687 : "Surface Window Shading Device Absorbed Solar Radiation Energy",
1688 : Constant::Units::J,
1689 6201 : state.dataSurface->SurfWinShadingAbsorbedSolarEnergy(SurfLoop),
1690 : OutputProcessor::TimeStepType::Zone,
1691 : OutputProcessor::StoreType::Sum,
1692 6201 : surf.Name);
1693 12402 : SetupOutputVariable(state,
1694 : "Surface Window Net Heat Transfer Energy",
1695 : Constant::Units::J,
1696 6201 : state.dataSurface->SurfWinHeatTransferRepEnergy(SurfLoop),
1697 : OutputProcessor::TimeStepType::Zone,
1698 : OutputProcessor::StoreType::Sum,
1699 6201 : surf.Name);
1700 :
1701 12402 : SetupOutputVariable(state,
1702 : "Surface Window System Solar Transmittance",
1703 : Constant::Units::None,
1704 6201 : state.dataSurface->SurfWinSysSolTransmittance(SurfLoop),
1705 : OutputProcessor::TimeStepType::Zone,
1706 : OutputProcessor::StoreType::Average,
1707 6201 : surf.Name);
1708 12402 : SetupOutputVariable(state,
1709 : "Surface Window System Solar Reflectance",
1710 : Constant::Units::None,
1711 6201 : state.dataSurface->SurfWinSysSolReflectance(SurfLoop),
1712 : OutputProcessor::TimeStepType::Zone,
1713 : OutputProcessor::StoreType::Average,
1714 6201 : surf.Name);
1715 12402 : SetupOutputVariable(state,
1716 : "Surface Window System Solar Absorptance",
1717 : Constant::Units::None,
1718 6201 : state.dataSurface->SurfWinSysSolAbsorptance(SurfLoop),
1719 : OutputProcessor::TimeStepType::Zone,
1720 : OutputProcessor::StoreType::Average,
1721 6201 : surf.Name);
1722 6201 : SetupOutputVariable(state,
1723 : "Surface Window Inside Face Glazing Condensation Status",
1724 : Constant::Units::None,
1725 6201 : state.dataSurface->SurfWinInsideGlassCondensationFlag(SurfLoop),
1726 : OutputProcessor::TimeStepType::Zone,
1727 : OutputProcessor::StoreType::Average,
1728 6201 : surf.Name);
1729 6201 : SetupOutputVariable(state,
1730 : "Surface Window Inside Face Frame Condensation Status",
1731 : Constant::Units::None,
1732 6201 : state.dataSurface->SurfWinInsideFrameCondensationFlag(SurfLoop),
1733 : OutputProcessor::TimeStepType::Zone,
1734 : OutputProcessor::StoreType::Average,
1735 6201 : surf.Name);
1736 6201 : SetupOutputVariable(state,
1737 : "Surface Window Inside Face Divider Condensation Status",
1738 : Constant::Units::None,
1739 6201 : state.dataSurface->SurfWinInsideDividerCondensationFlag(SurfLoop),
1740 : OutputProcessor::TimeStepType::Zone,
1741 : OutputProcessor::StoreType::Average,
1742 6201 : surf.Name);
1743 :
1744 : // Outside reveal report variables
1745 : // IF (Surface(SurfLoop)%Reveal > 0.0) THEN
1746 12402 : SetupOutputVariable(state,
1747 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Rate",
1748 : Constant::Units::W,
1749 6201 : state.dataSurface->SurfWinBmSolRefldOutsRevealReport(SurfLoop),
1750 : OutputProcessor::TimeStepType::Zone,
1751 : OutputProcessor::StoreType::Average,
1752 6201 : surf.Name);
1753 : // Energy
1754 12402 : SetupOutputVariable(state,
1755 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Energy",
1756 : Constant::Units::J,
1757 6201 : state.dataSurface->SurfWinBmSolRefldOutsRevealRepEnergy(SurfLoop),
1758 : OutputProcessor::TimeStepType::Zone,
1759 : OutputProcessor::StoreType::Sum,
1760 6201 : surf.Name);
1761 : // ENDIF
1762 :
1763 : // Inside reveal report variables
1764 6201 : if (state.dataSurface->SurfWinInsideReveal(SurfLoop) > 0.0 || state.dataSurface->SurfWinInsideSillDepth(SurfLoop) > 0.0) {
1765 6 : SetupOutputVariable(state,
1766 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Rate",
1767 : Constant::Units::W,
1768 3 : state.dataSurface->SurfWinBmSolRefldInsRevealReport(SurfLoop),
1769 : OutputProcessor::TimeStepType::Zone,
1770 : OutputProcessor::StoreType::Average,
1771 3 : surf.Name);
1772 : // Energy
1773 6 : SetupOutputVariable(state,
1774 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Energy",
1775 : Constant::Units::J,
1776 3 : state.dataSurface->SurfWinBmSolRefldInsRevealRepEnergy(SurfLoop),
1777 : OutputProcessor::TimeStepType::Zone,
1778 : OutputProcessor::StoreType::Sum,
1779 3 : surf.Name);
1780 :
1781 : // Added report variables for inside reveal to debug CR 7596. TH 5/26/2009
1782 : // All reflected solar by the inside reveal is turned into diffuse
1783 6 : SetupOutputVariable(state,
1784 : "Surface Window Inside Reveal Absorbed Beam Solar Radiation Rate",
1785 : Constant::Units::W,
1786 3 : state.dataSurface->SurfWinBmSolAbsdInsRevealReport(SurfLoop),
1787 : OutputProcessor::TimeStepType::Zone,
1788 : OutputProcessor::StoreType::Average,
1789 3 : surf.Name);
1790 6 : SetupOutputVariable(state,
1791 : "Surface Window Inside Reveal Reflected Diffuse Zone Solar Radiation Rate",
1792 : Constant::Units::W,
1793 3 : state.dataSurface->SurfWinInsRevealDiffIntoZoneReport(SurfLoop),
1794 : OutputProcessor::TimeStepType::Zone,
1795 : OutputProcessor::StoreType::Average,
1796 3 : surf.Name);
1797 6 : SetupOutputVariable(state,
1798 : "Surface Window Inside Reveal Reflected Diffuse Frame Solar Radiation Rate",
1799 : Constant::Units::W,
1800 3 : state.dataSurface->SurfWinInsRevealDiffOntoFrameReport(SurfLoop),
1801 : OutputProcessor::TimeStepType::Zone,
1802 : OutputProcessor::StoreType::Average,
1803 3 : surf.Name);
1804 6 : SetupOutputVariable(state,
1805 : "Surface Window Inside Reveal Reflected Diffuse Glazing Solar Radiation Rate",
1806 : Constant::Units::W,
1807 3 : state.dataSurface->SurfWinInsRevealDiffOntoGlazingReport(SurfLoop),
1808 : OutputProcessor::TimeStepType::Zone,
1809 : OutputProcessor::StoreType::Average,
1810 3 : surf.Name);
1811 : }
1812 :
1813 : // Output blind report variables only when blinds are used
1814 6201 : if (state.dataSurface->SurfWinBlindNumber(SurfLoop) > 0) {
1815 : // CurrentModuleObject='Window Blinds'
1816 84 : SetupOutputVariable(state,
1817 : "Surface Window Blind Beam to Beam Solar Transmittance",
1818 : Constant::Units::None,
1819 42 : state.dataSurface->SurfWinBlTsolBmBm(SurfLoop),
1820 : OutputProcessor::TimeStepType::Zone,
1821 : OutputProcessor::StoreType::Average,
1822 42 : surf.Name);
1823 84 : SetupOutputVariable(state,
1824 : "Surface Window Blind Beam to Diffuse Solar Transmittance",
1825 : Constant::Units::None,
1826 42 : state.dataSurface->SurfWinBlTsolBmDif(SurfLoop),
1827 : OutputProcessor::TimeStepType::Zone,
1828 : OutputProcessor::StoreType::Average,
1829 42 : surf.Name);
1830 84 : SetupOutputVariable(state,
1831 : "Surface Window Blind Diffuse to Diffuse Solar Transmittance",
1832 : Constant::Units::None,
1833 42 : state.dataSurface->SurfWinBlTsolDifDif(SurfLoop),
1834 : OutputProcessor::TimeStepType::Zone,
1835 : OutputProcessor::StoreType::Average,
1836 42 : surf.Name);
1837 84 : SetupOutputVariable(state,
1838 : "Surface Window Blind and Glazing System Beam Solar Transmittance",
1839 : Constant::Units::None,
1840 42 : state.dataSurface->SurfWinBlGlSysTsolBmBm(SurfLoop),
1841 : OutputProcessor::TimeStepType::Zone,
1842 : OutputProcessor::StoreType::Average,
1843 42 : surf.Name);
1844 84 : SetupOutputVariable(state,
1845 : "Surface Window Blind and Glazing System Diffuse Solar Transmittance",
1846 : Constant::Units::None,
1847 42 : state.dataSurface->SurfWinBlGlSysTsolDifDif(SurfLoop),
1848 : OutputProcessor::TimeStepType::Zone,
1849 : OutputProcessor::StoreType::Average,
1850 42 : surf.Name);
1851 : }
1852 :
1853 : // Output screen report variables only when screens are used
1854 6201 : if (state.dataSurface->SurfaceWindow(SurfLoop).screenNum > 0) {
1855 : // CurrentModuleObject='Window Screens'
1856 16 : SetupOutputVariable(state,
1857 : "Surface Window Screen Beam to Beam Solar Transmittance",
1858 : Constant::Units::None,
1859 8 : state.dataSurface->SurfWinScTsolBmBm(SurfLoop),
1860 : OutputProcessor::TimeStepType::Zone,
1861 : OutputProcessor::StoreType::Average,
1862 8 : surf.Name);
1863 16 : SetupOutputVariable(state,
1864 : "Surface Window Screen Beam to Diffuse Solar Transmittance",
1865 : Constant::Units::None,
1866 8 : state.dataSurface->SurfWinScTsolBmDif(SurfLoop),
1867 : OutputProcessor::TimeStepType::Zone,
1868 : OutputProcessor::StoreType::Average,
1869 8 : surf.Name);
1870 16 : SetupOutputVariable(state,
1871 : "Surface Window Screen Diffuse to Diffuse Solar Transmittance",
1872 : Constant::Units::None,
1873 8 : state.dataSurface->SurfWinScTsolDifDif(SurfLoop),
1874 : OutputProcessor::TimeStepType::Zone,
1875 : OutputProcessor::StoreType::Average,
1876 8 : surf.Name);
1877 16 : SetupOutputVariable(state,
1878 : "Surface Window Screen and Glazing System Beam Solar Transmittance",
1879 : Constant::Units::None,
1880 8 : state.dataSurface->SurfWinScGlSysTsolBmBm(SurfLoop),
1881 : OutputProcessor::TimeStepType::Zone,
1882 : OutputProcessor::StoreType::Average,
1883 8 : surf.Name);
1884 16 : SetupOutputVariable(state,
1885 : "Surface Window Screen and Glazing System Diffuse Solar Transmittance",
1886 : Constant::Units::None,
1887 8 : state.dataSurface->SurfWinScGlSysTsolDifDif(SurfLoop),
1888 : OutputProcessor::TimeStepType::Zone,
1889 : OutputProcessor::StoreType::Average,
1890 8 : surf.Name);
1891 : }
1892 :
1893 : // CurrentModuleObject='Windows'
1894 12402 : SetupOutputVariable(state,
1895 : "Surface Window Solar Horizontal Profile Angle",
1896 : Constant::Units::deg,
1897 6201 : state.dataSurface->SurfWinProfileAngHor(SurfLoop),
1898 : OutputProcessor::TimeStepType::Zone,
1899 : OutputProcessor::StoreType::Average,
1900 6201 : surf.Name);
1901 12402 : SetupOutputVariable(state,
1902 : "Surface Window Solar Vertical Profile Angle",
1903 : Constant::Units::deg,
1904 6201 : state.dataSurface->SurfWinProfileAngVert(SurfLoop),
1905 : OutputProcessor::TimeStepType::Zone,
1906 : OutputProcessor::StoreType::Average,
1907 6201 : surf.Name);
1908 12402 : SetupOutputVariable(state,
1909 : "Surface Window Glazing Beam to Beam Solar Transmittance",
1910 : Constant::Units::None,
1911 6201 : state.dataSurface->SurfWinGlTsolBmBm(SurfLoop),
1912 : OutputProcessor::TimeStepType::Zone,
1913 : OutputProcessor::StoreType::Average,
1914 6201 : surf.Name);
1915 12402 : SetupOutputVariable(state,
1916 : "Surface Window Glazing Beam to Diffuse Solar Transmittance",
1917 : Constant::Units::None,
1918 6201 : state.dataSurface->SurfWinGlTsolBmDif(SurfLoop),
1919 : OutputProcessor::TimeStepType::Zone,
1920 : OutputProcessor::StoreType::Average,
1921 6201 : surf.Name);
1922 12402 : SetupOutputVariable(state,
1923 : "Surface Window Glazing Diffuse to Diffuse Solar Transmittance",
1924 : Constant::Units::None,
1925 6201 : state.dataSurface->SurfWinGlTsolDifDif(SurfLoop),
1926 : OutputProcessor::TimeStepType::Zone,
1927 : OutputProcessor::StoreType::Average,
1928 6201 : surf.Name);
1929 6201 : SetupOutputVariable(state,
1930 : "Surface Window Model Solver Iteration Count",
1931 : Constant::Units::None,
1932 6201 : state.dataSurface->SurfWinWindowCalcIterationsRep(SurfLoop),
1933 : OutputProcessor::TimeStepType::Zone,
1934 : OutputProcessor::StoreType::Average,
1935 6201 : surf.Name);
1936 : } else { // Not ExtSolar
1937 16 : if (state.dataGlobal->DisplayAdvancedReportVariables) {
1938 : // CurrentModuleObject='InteriorWindows(Advanced)'
1939 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
1940 0 : SetupOutputVariable(state,
1941 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
1942 : Constant::Units::W,
1943 0 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
1944 : OutputProcessor::TimeStepType::Zone,
1945 : OutputProcessor::StoreType::Average,
1946 0 : surf.Name);
1947 : }
1948 0 : SetupOutputVariable(state,
1949 : "Surface Window Total Glazing Layers Absorbed Shortwave Radiation Rate",
1950 : Constant::Units::W,
1951 0 : state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfLoop),
1952 : OutputProcessor::TimeStepType::Zone,
1953 : OutputProcessor::StoreType::Average,
1954 0 : surf.Name);
1955 :
1956 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
1957 0 : SetupOutputVariable(state,
1958 : "Surface Window Transmitted Solar Radiation Rate",
1959 : Constant::Units::W,
1960 0 : state.dataSurface->SurfWinTransSolar(SurfLoop),
1961 : OutputProcessor::TimeStepType::Zone,
1962 : OutputProcessor::StoreType::Average,
1963 0 : surf.Name);
1964 : }
1965 0 : SetupOutputVariable(state,
1966 : "Surface Window Transmitted Beam Solar Radiation Rate",
1967 : Constant::Units::W,
1968 0 : state.dataSurface->SurfWinBmSolar(SurfLoop),
1969 : OutputProcessor::TimeStepType::Zone,
1970 : OutputProcessor::StoreType::Average,
1971 0 : surf.Name);
1972 :
1973 : // added TH 12/9/2009
1974 0 : SetupOutputVariable(state,
1975 : "Surface Window Transmitted Beam To Beam Solar Radiation Rate",
1976 : Constant::Units::W,
1977 0 : state.dataSurface->SurfWinBmBmSolar(SurfLoop),
1978 : OutputProcessor::TimeStepType::Zone,
1979 : OutputProcessor::StoreType::Average,
1980 0 : surf.Name);
1981 0 : SetupOutputVariable(state,
1982 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Rate",
1983 : Constant::Units::W,
1984 0 : state.dataSurface->SurfWinBmDifSolar(SurfLoop),
1985 : OutputProcessor::TimeStepType::Zone,
1986 : OutputProcessor::StoreType::Average,
1987 0 : surf.Name);
1988 :
1989 0 : SetupOutputVariable(state,
1990 : "Surface Window Transmitted Diffuse Solar Radiation Rate",
1991 : Constant::Units::W,
1992 0 : state.dataSurface->SurfWinDifSolar(SurfLoop),
1993 : OutputProcessor::TimeStepType::Zone,
1994 : OutputProcessor::StoreType::Average,
1995 0 : surf.Name);
1996 0 : SetupOutputVariable(state,
1997 : "Surface Window Heat Gain Rate",
1998 : Constant::Units::W,
1999 0 : state.dataSurface->SurfWinHeatGainRep(SurfLoop),
2000 : OutputProcessor::TimeStepType::Zone,
2001 : OutputProcessor::StoreType::Average,
2002 0 : surf.Name);
2003 0 : SetupOutputVariable(state,
2004 : "Surface Window Heat Loss Rate",
2005 : Constant::Units::W,
2006 0 : state.dataSurface->SurfWinHeatLossRep(SurfLoop),
2007 : OutputProcessor::TimeStepType::Zone,
2008 : OutputProcessor::StoreType::Average,
2009 0 : surf.Name);
2010 0 : SetupOutputVariable(state,
2011 : "Surface Window Gap Convective Heat Transfer Rate",
2012 : Constant::Units::W,
2013 0 : state.dataSurface->SurfWinGapConvHtFlowRep(SurfLoop),
2014 : OutputProcessor::TimeStepType::Zone,
2015 : OutputProcessor::StoreType::Average,
2016 0 : surf.Name);
2017 0 : SetupOutputVariable(state,
2018 : "Surface Window Shading Device Absorbed Solar Radiation Rate",
2019 : Constant::Units::W,
2020 0 : state.dataSurface->SurfWinShadingAbsorbedSolar(SurfLoop),
2021 : OutputProcessor::TimeStepType::Zone,
2022 : OutputProcessor::StoreType::Average,
2023 0 : surf.Name);
2024 0 : if (state.dataSurface->SurfWinFrameArea(SurfLoop) > 0.0) {
2025 0 : SetupOutputVariable(state,
2026 : "Surface Window Frame Heat Gain Rate",
2027 : Constant::Units::W,
2028 0 : state.dataSurface->SurfWinFrameHeatGain(SurfLoop),
2029 : OutputProcessor::TimeStepType::Zone,
2030 : OutputProcessor::StoreType::Average,
2031 0 : surf.Name);
2032 0 : SetupOutputVariable(state,
2033 : "Surface Window Frame Heat Loss Rate",
2034 : Constant::Units::W,
2035 0 : state.dataSurface->SurfWinFrameHeatLoss(SurfLoop),
2036 : OutputProcessor::TimeStepType::Zone,
2037 : OutputProcessor::StoreType::Average,
2038 0 : surf.Name);
2039 0 : SetupOutputVariable(state,
2040 : "Surface Window Frame Inside Temperature",
2041 : Constant::Units::C,
2042 0 : state.dataSurface->SurfWinFrameTempIn(SurfLoop),
2043 : OutputProcessor::TimeStepType::Zone,
2044 : OutputProcessor::StoreType::Average,
2045 0 : surf.Name);
2046 0 : SetupOutputVariable(state,
2047 : "Surface Window Frame Outside Temperature",
2048 : Constant::Units::C,
2049 0 : state.dataSurface->SurfWinFrameTempSurfOut(SurfLoop),
2050 : OutputProcessor::TimeStepType::Zone,
2051 : OutputProcessor::StoreType::Average,
2052 0 : surf.Name);
2053 : }
2054 0 : if (state.dataSurface->SurfWinDividerArea(SurfLoop) > 0.0) {
2055 0 : SetupOutputVariable(state,
2056 : "Surface Window Divider Heat Gain Rate",
2057 : Constant::Units::W,
2058 0 : state.dataSurface->SurfWinDividerHeatGain(SurfLoop),
2059 : OutputProcessor::TimeStepType::Zone,
2060 : OutputProcessor::StoreType::Average,
2061 0 : surf.Name);
2062 0 : SetupOutputVariable(state,
2063 : "Surface Window Divider Heat Loss Rate",
2064 : Constant::Units::W,
2065 0 : state.dataSurface->SurfWinDividerHeatLoss(SurfLoop),
2066 : OutputProcessor::TimeStepType::Zone,
2067 : OutputProcessor::StoreType::Average,
2068 0 : surf.Name);
2069 0 : SetupOutputVariable(state,
2070 : "Surface Window Divider Inside Temperature",
2071 : Constant::Units::C,
2072 0 : state.dataSurface->SurfWinDividerTempIn(SurfLoop),
2073 : OutputProcessor::TimeStepType::Zone,
2074 : OutputProcessor::StoreType::Average,
2075 0 : surf.Name);
2076 0 : SetupOutputVariable(state,
2077 : "Surface Window Divider Outside Temperature",
2078 : Constant::Units::C,
2079 0 : state.dataSurface->SurfWinDividerTempSurfOut(SurfLoop),
2080 : OutputProcessor::TimeStepType::Zone,
2081 : OutputProcessor::StoreType::Average,
2082 0 : surf.Name);
2083 : }
2084 : // Energy
2085 :
2086 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
2087 0 : SetupOutputVariable(state,
2088 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
2089 : Constant::Units::J,
2090 0 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
2091 : OutputProcessor::TimeStepType::Zone,
2092 : OutputProcessor::StoreType::Sum,
2093 0 : surf.Name);
2094 : }
2095 :
2096 0 : if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
2097 0 : SetupOutputVariable(state,
2098 : "Surface Window Transmitted Solar Radiation Energy",
2099 : Constant::Units::J,
2100 0 : state.dataSurface->SurfWinTransSolarEnergy(SurfLoop),
2101 : OutputProcessor::TimeStepType::Zone,
2102 : OutputProcessor::StoreType::Sum,
2103 0 : surf.Name);
2104 : }
2105 0 : SetupOutputVariable(state,
2106 : "Surface Window Transmitted Beam Solar Radiation Energy",
2107 : Constant::Units::J,
2108 0 : state.dataSurface->SurfWinBmSolarEnergy(SurfLoop),
2109 : OutputProcessor::TimeStepType::Zone,
2110 : OutputProcessor::StoreType::Sum,
2111 0 : surf.Name);
2112 :
2113 0 : SetupOutputVariable(state,
2114 : "Surface Window Transmitted Beam To Beam Solar Radiation Energy",
2115 : Constant::Units::J,
2116 0 : state.dataSurface->SurfWinBmBmSolarEnergy(SurfLoop),
2117 : OutputProcessor::TimeStepType::Zone,
2118 : OutputProcessor::StoreType::Sum,
2119 0 : surf.Name);
2120 0 : SetupOutputVariable(state,
2121 : "Surface Window Transmitted Beam To Diffuse Solar Radiation Energy",
2122 : Constant::Units::J,
2123 0 : state.dataSurface->SurfWinBmDifSolarEnergy(SurfLoop),
2124 : OutputProcessor::TimeStepType::Zone,
2125 : OutputProcessor::StoreType::Sum,
2126 0 : surf.Name);
2127 :
2128 0 : SetupOutputVariable(state,
2129 : "Surface Window Transmitted Diffuse Solar Radiation Energy",
2130 : Constant::Units::J,
2131 0 : state.dataSurface->SurfWinDifSolarEnergy(SurfLoop),
2132 : OutputProcessor::TimeStepType::Zone,
2133 : OutputProcessor::StoreType::Sum,
2134 0 : surf.Name);
2135 0 : SetupOutputVariable(state,
2136 : "Surface Window Heat Gain Energy",
2137 : Constant::Units::J,
2138 0 : state.dataSurface->SurfWinHeatGainRepEnergy(SurfLoop),
2139 : OutputProcessor::TimeStepType::Zone,
2140 : OutputProcessor::StoreType::Sum,
2141 0 : surf.Name);
2142 0 : SetupOutputVariable(state,
2143 : "Surface Window Heat Loss Energy",
2144 : Constant::Units::J,
2145 0 : state.dataSurface->SurfWinHeatLossRepEnergy(SurfLoop),
2146 : OutputProcessor::TimeStepType::Zone,
2147 : OutputProcessor::StoreType::Sum,
2148 0 : surf.Name);
2149 0 : SetupOutputVariable(state,
2150 : "Surface Window Gap Convective Heat Transfer Energy",
2151 : Constant::Units::J,
2152 0 : state.dataSurface->SurfWinGapConvHtFlowRepEnergy(SurfLoop),
2153 : OutputProcessor::TimeStepType::Zone,
2154 : OutputProcessor::StoreType::Sum,
2155 0 : surf.Name);
2156 0 : SetupOutputVariable(state,
2157 : "Surface Window Shading Device Absorbed Solar Radiation Energy",
2158 : Constant::Units::J,
2159 0 : state.dataSurface->SurfWinShadingAbsorbedSolarEnergy(SurfLoop),
2160 : OutputProcessor::TimeStepType::Zone,
2161 : OutputProcessor::StoreType::Sum,
2162 0 : surf.Name);
2163 :
2164 0 : SetupOutputVariable(state,
2165 : "Surface Window System Solar Transmittance",
2166 : Constant::Units::None,
2167 0 : state.dataSurface->SurfWinSysSolTransmittance(SurfLoop),
2168 : OutputProcessor::TimeStepType::Zone,
2169 : OutputProcessor::StoreType::Average,
2170 0 : surf.Name);
2171 0 : SetupOutputVariable(state,
2172 : "Surface Window System Solar Reflectance",
2173 : Constant::Units::None,
2174 0 : state.dataSurface->SurfWinSysSolReflectance(SurfLoop),
2175 : OutputProcessor::TimeStepType::Zone,
2176 : OutputProcessor::StoreType::Average,
2177 0 : surf.Name);
2178 0 : SetupOutputVariable(state,
2179 : "Surface Window System Solar Absorptance",
2180 : Constant::Units::None,
2181 0 : state.dataSurface->SurfWinSysSolAbsorptance(SurfLoop),
2182 : OutputProcessor::TimeStepType::Zone,
2183 : OutputProcessor::StoreType::Average,
2184 0 : surf.Name);
2185 0 : SetupOutputVariable(state,
2186 : "Surface Window Inside Face Glazing Condensation Status",
2187 : Constant::Units::None,
2188 0 : state.dataSurface->SurfWinInsideGlassCondensationFlag(SurfLoop),
2189 : OutputProcessor::TimeStepType::Zone,
2190 : OutputProcessor::StoreType::Average,
2191 0 : surf.Name);
2192 0 : SetupOutputVariable(state,
2193 : "Surface Window Inside Face Frame Condensation Status",
2194 : Constant::Units::None,
2195 0 : state.dataSurface->SurfWinInsideFrameCondensationFlag(SurfLoop),
2196 : OutputProcessor::TimeStepType::Zone,
2197 : OutputProcessor::StoreType::Average,
2198 0 : surf.Name);
2199 0 : SetupOutputVariable(state,
2200 : "Surface Window Inside Face Divider Condensation Status",
2201 : Constant::Units::None,
2202 0 : state.dataSurface->SurfWinInsideDividerCondensationFlag(SurfLoop),
2203 : OutputProcessor::TimeStepType::Zone,
2204 : OutputProcessor::StoreType::Average,
2205 0 : surf.Name);
2206 0 : SetupOutputVariable(state,
2207 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Rate",
2208 : Constant::Units::W,
2209 0 : state.dataSurface->SurfWinBmSolRefldOutsRevealReport(SurfLoop),
2210 : OutputProcessor::TimeStepType::Zone,
2211 : OutputProcessor::StoreType::Average,
2212 0 : surf.Name);
2213 0 : SetupOutputVariable(state,
2214 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Rate",
2215 : Constant::Units::W,
2216 0 : state.dataSurface->SurfWinBmSolRefldInsRevealReport(SurfLoop),
2217 : OutputProcessor::TimeStepType::Zone,
2218 : OutputProcessor::StoreType::Average,
2219 0 : surf.Name);
2220 : // Energy
2221 0 : SetupOutputVariable(state,
2222 : "Surface Window Outside Reveal Reflected Beam Solar Radiation Energy",
2223 : Constant::Units::J,
2224 0 : state.dataSurface->SurfWinBmSolRefldOutsRevealRepEnergy(SurfLoop),
2225 : OutputProcessor::TimeStepType::Zone,
2226 : OutputProcessor::StoreType::Sum,
2227 0 : surf.Name);
2228 0 : SetupOutputVariable(state,
2229 : "Surface Window Inside Reveal Reflected Beam Solar Radiation Energy",
2230 : Constant::Units::J,
2231 0 : state.dataSurface->SurfWinBmSolRefldInsRevealRepEnergy(SurfLoop),
2232 : OutputProcessor::TimeStepType::Zone,
2233 : OutputProcessor::StoreType::Sum,
2234 0 : surf.Name);
2235 :
2236 : // Output blind report variables only when blinds are used
2237 0 : if (state.dataSurface->SurfWinBlindNumber(SurfLoop) > 0) {
2238 0 : SetupOutputVariable(state,
2239 : "Surface Window Blind Beam to Beam Solar Transmittance",
2240 : Constant::Units::None,
2241 0 : state.dataSurface->SurfWinBlTsolBmBm(SurfLoop),
2242 : OutputProcessor::TimeStepType::Zone,
2243 : OutputProcessor::StoreType::Average,
2244 0 : surf.Name);
2245 0 : SetupOutputVariable(state,
2246 : "Surface Window Blind Beam to Diffuse Solar Transmittance",
2247 : Constant::Units::None,
2248 0 : state.dataSurface->SurfWinBlTsolBmDif(SurfLoop),
2249 : OutputProcessor::TimeStepType::Zone,
2250 : OutputProcessor::StoreType::Average,
2251 0 : surf.Name);
2252 0 : SetupOutputVariable(state,
2253 : "Surface Window Blind Diffuse to Diffuse Solar Transmittance",
2254 : Constant::Units::None,
2255 0 : state.dataSurface->SurfWinBlTsolDifDif(SurfLoop),
2256 : OutputProcessor::TimeStepType::Zone,
2257 : OutputProcessor::StoreType::Average,
2258 0 : surf.Name);
2259 0 : SetupOutputVariable(state,
2260 : "Surface Window Blind and Glazing System Beam Solar Transmittance",
2261 : Constant::Units::None,
2262 0 : state.dataSurface->SurfWinBlGlSysTsolBmBm(SurfLoop),
2263 : OutputProcessor::TimeStepType::Zone,
2264 : OutputProcessor::StoreType::Average,
2265 0 : surf.Name);
2266 0 : SetupOutputVariable(state,
2267 : "Surface Window Blind and Glazing System Diffuse Solar Transmittance",
2268 : Constant::Units::None,
2269 0 : state.dataSurface->SurfWinBlGlSysTsolDifDif(SurfLoop),
2270 : OutputProcessor::TimeStepType::Zone,
2271 : OutputProcessor::StoreType::Average,
2272 0 : surf.Name);
2273 : }
2274 :
2275 : // Output screen report variables only when screens are used
2276 0 : if (state.dataSurface->SurfaceWindow(SurfLoop).screenNum > 0) {
2277 0 : SetupOutputVariable(state,
2278 : "Surface Window Screen Beam to Beam Solar Transmittance",
2279 : Constant::Units::None,
2280 0 : state.dataSurface->SurfWinScTsolBmBm(SurfLoop),
2281 : OutputProcessor::TimeStepType::Zone,
2282 : OutputProcessor::StoreType::Average,
2283 0 : surf.Name);
2284 0 : SetupOutputVariable(state,
2285 : "Surface Window Screen Beam to Diffuse Solar Transmittance",
2286 : Constant::Units::None,
2287 0 : state.dataSurface->SurfWinScTsolBmDif(SurfLoop),
2288 : OutputProcessor::TimeStepType::Zone,
2289 : OutputProcessor::StoreType::Average,
2290 0 : surf.Name);
2291 0 : SetupOutputVariable(state,
2292 : "Surface Window Screen Diffuse to Diffuse Solar Transmittance",
2293 : Constant::Units::None,
2294 0 : state.dataSurface->SurfWinScTsolDifDif(SurfLoop),
2295 : OutputProcessor::TimeStepType::Zone,
2296 : OutputProcessor::StoreType::Average,
2297 0 : surf.Name);
2298 0 : SetupOutputVariable(state,
2299 : "Surface Window Screen and Glazing System Beam Solar Transmittance",
2300 : Constant::Units::None,
2301 0 : state.dataSurface->SurfWinScGlSysTsolBmBm(SurfLoop),
2302 : OutputProcessor::TimeStepType::Zone,
2303 : OutputProcessor::StoreType::Average,
2304 0 : surf.Name);
2305 0 : SetupOutputVariable(state,
2306 : "Surface Window Screen and Glazing System Diffuse Solar Transmittance",
2307 : Constant::Units::None,
2308 0 : state.dataSurface->SurfWinScGlSysTsolDifDif(SurfLoop),
2309 : OutputProcessor::TimeStepType::Zone,
2310 : OutputProcessor::StoreType::Average,
2311 0 : surf.Name);
2312 : }
2313 :
2314 0 : SetupOutputVariable(state,
2315 : "Surface Window Solar Horizontal Profile Angle",
2316 : Constant::Units::deg,
2317 0 : state.dataSurface->SurfWinProfileAngHor(SurfLoop),
2318 : OutputProcessor::TimeStepType::Zone,
2319 : OutputProcessor::StoreType::Average,
2320 0 : surf.Name);
2321 0 : SetupOutputVariable(state,
2322 : "Surface Window Solar Vertical Profile Angle",
2323 : Constant::Units::deg,
2324 0 : state.dataSurface->SurfWinProfileAngVert(SurfLoop),
2325 : OutputProcessor::TimeStepType::Zone,
2326 : OutputProcessor::StoreType::Average,
2327 0 : surf.Name);
2328 0 : SetupOutputVariable(state,
2329 : "Surface Window Glazing Beam to Beam Solar Transmittance",
2330 : Constant::Units::None,
2331 0 : state.dataSurface->SurfWinGlTsolBmBm(SurfLoop),
2332 : OutputProcessor::TimeStepType::Zone,
2333 : OutputProcessor::StoreType::Average,
2334 0 : surf.Name);
2335 0 : SetupOutputVariable(state,
2336 : "Surface Window Glazing Beam to Diffuse Solar Transmittance",
2337 : Constant::Units::None,
2338 0 : state.dataSurface->SurfWinGlTsolBmDif(SurfLoop),
2339 : OutputProcessor::TimeStepType::Zone,
2340 : OutputProcessor::StoreType::Average,
2341 0 : surf.Name);
2342 0 : SetupOutputVariable(state,
2343 : "Surface Window Glazing Diffuse to Diffuse Solar Transmittance",
2344 : Constant::Units::None,
2345 0 : state.dataSurface->SurfWinGlTsolDifDif(SurfLoop),
2346 : OutputProcessor::TimeStepType::Zone,
2347 : OutputProcessor::StoreType::Average,
2348 0 : surf.Name);
2349 0 : SetupOutputVariable(state,
2350 : "Surface Window Model Solver Iteration Count",
2351 : Constant::Units::None,
2352 0 : state.dataSurface->SurfWinWindowCalcIterationsRep(SurfLoop),
2353 : OutputProcessor::TimeStepType::Zone,
2354 : OutputProcessor::StoreType::Average,
2355 0 : surf.Name);
2356 : }
2357 : } // end non extsolar reporting as advanced variables
2358 : } // Window Reporting
2359 44391 : if (surf.Class == SurfaceClass::Window && surf.ExtBoundCond > 0 && surf.ExtBoundCond != SurfLoop) { // Interzone window
2360 : // CurrentModuleObject='InterzoneWindows'
2361 28 : SetupOutputVariable(state,
2362 : "Surface Window Transmitted Beam Solar Radiation Rate",
2363 : Constant::Units::W,
2364 14 : state.dataSurface->SurfWinBmSolTransThruIntWinRep(SurfLoop),
2365 : OutputProcessor::TimeStepType::Zone,
2366 : OutputProcessor::StoreType::Average,
2367 14 : surf.Name);
2368 : // energy
2369 28 : SetupOutputVariable(state,
2370 : "Surface Window Transmitted Beam Solar Radiation Energy",
2371 : Constant::Units::J,
2372 14 : state.dataSurface->SurfWinBmSolTransThruIntWinRepEnergy(SurfLoop),
2373 : OutputProcessor::TimeStepType::Zone,
2374 : OutputProcessor::StoreType::Sum,
2375 14 : surf.Name);
2376 : }
2377 44391 : if (surf.Class == SurfaceClass::TDD_Dome && surf.ExtSolar) {
2378 : // CurrentModuleObject='TDD Domes'
2379 4 : SetupOutputVariable(state,
2380 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
2381 : Constant::Units::W,
2382 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
2383 : OutputProcessor::TimeStepType::Zone,
2384 : OutputProcessor::StoreType::Average,
2385 2 : surf.Name);
2386 4 : SetupOutputVariable(state,
2387 : "Surface Window Transmitted Solar Radiation Rate",
2388 : Constant::Units::W,
2389 2 : state.dataSurface->SurfWinTransSolar(SurfLoop),
2390 : OutputProcessor::TimeStepType::Zone,
2391 : OutputProcessor::StoreType::Average,
2392 2 : surf.Name);
2393 : // energy
2394 4 : SetupOutputVariable(state,
2395 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
2396 : Constant::Units::J,
2397 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
2398 : OutputProcessor::TimeStepType::Zone,
2399 : OutputProcessor::StoreType::Sum,
2400 2 : surf.Name);
2401 4 : SetupOutputVariable(state,
2402 : "Surface Window Transmitted Solar Radiation Energy",
2403 : Constant::Units::J,
2404 2 : state.dataSurface->SurfWinTransSolarEnergy(SurfLoop),
2405 : OutputProcessor::TimeStepType::Zone,
2406 : OutputProcessor::StoreType::Sum,
2407 2 : surf.Name);
2408 : }
2409 44391 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
2410 : // CurrentModuleObject='TDD Diffusers'
2411 4 : SetupOutputVariable(state,
2412 : "Surface Outside Face Incident Solar Radiation Rate per Area",
2413 : Constant::Units::W_m2,
2414 2 : state.dataHeatBal->SurfQRadSWOutIncident(SurfLoop),
2415 : OutputProcessor::TimeStepType::Zone,
2416 : OutputProcessor::StoreType::Average,
2417 2 : surf.Name);
2418 4 : SetupOutputVariable(state,
2419 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
2420 : Constant::Units::W,
2421 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
2422 : OutputProcessor::TimeStepType::Zone,
2423 : OutputProcessor::StoreType::Average,
2424 2 : surf.Name);
2425 4 : SetupOutputVariable(state,
2426 : "Surface Window Transmitted Solar Radiation Rate",
2427 : Constant::Units::W,
2428 2 : state.dataSurface->SurfWinTransSolar(SurfLoop),
2429 : OutputProcessor::TimeStepType::Zone,
2430 : OutputProcessor::StoreType::Average,
2431 2 : surf.Name);
2432 : // energy
2433 4 : SetupOutputVariable(state,
2434 : "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
2435 : Constant::Units::J,
2436 2 : state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
2437 : OutputProcessor::TimeStepType::Zone,
2438 : OutputProcessor::StoreType::Sum,
2439 2 : surf.Name);
2440 4 : SetupOutputVariable(state,
2441 : "Surface Window Transmitted Solar Radiation Energy",
2442 : Constant::Units::J,
2443 2 : state.dataSurface->SurfWinTransSolarEnergy(SurfLoop),
2444 : OutputProcessor::TimeStepType::Zone,
2445 : OutputProcessor::StoreType::Sum,
2446 2 : surf.Name);
2447 : }
2448 : }
2449 :
2450 46840 : for (int SurfLoop = 1; SurfLoop <= state.dataSurface->TotSurfaces; ++SurfLoop) {
2451 46044 : auto &surf = state.dataSurface->Surface(SurfLoop);
2452 46044 : if (!surf.HeatTransSurf) continue;
2453 : // CurrentModuleObject='Surfaces'
2454 88782 : SetupOutputVariable(state,
2455 : "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Rate per Area",
2456 : Constant::Units::W_m2,
2457 44391 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfLoop),
2458 : OutputProcessor::TimeStepType::Zone,
2459 : OutputProcessor::StoreType::Average,
2460 44391 : surf.Name);
2461 88782 : SetupOutputVariable(state,
2462 : "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Rate",
2463 : Constant::Units::W,
2464 44391 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfLoop),
2465 : OutputProcessor::TimeStepType::Zone,
2466 : OutputProcessor::StoreType::Average,
2467 44391 : surf.Name);
2468 88782 : SetupOutputVariable(state,
2469 : "Surface Inside Face Interior Windows Incident Beam Solar Radiation Rate per Area",
2470 : Constant::Units::W_m2,
2471 44391 : state.dataHeatBal->SurfIntBmIncInsSurfIntensRep(SurfLoop),
2472 : OutputProcessor::TimeStepType::Zone,
2473 : OutputProcessor::StoreType::Average,
2474 44391 : surf.Name);
2475 88782 : SetupOutputVariable(state,
2476 : "Surface Inside Face Interior Windows Incident Beam Solar Radiation Rate",
2477 : Constant::Units::W,
2478 44391 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRep(SurfLoop),
2479 : OutputProcessor::TimeStepType::Zone,
2480 : OutputProcessor::StoreType::Average,
2481 44391 : surf.Name);
2482 88782 : SetupOutputVariable(state,
2483 : "Surface Inside Face Initial Transmitted Diffuse Absorbed Solar Radiation Rate",
2484 : Constant::Units::W,
2485 44391 : state.dataHeatBal->SurfInitialDifSolInAbsReport(SurfLoop),
2486 : OutputProcessor::TimeStepType::Zone,
2487 : OutputProcessor::StoreType::Average,
2488 44391 : surf.Name);
2489 88782 : SetupOutputVariable(state,
2490 : "Surface Inside Face Initial Transmitted Diffuse Transmitted Out Window Solar Radiation Rate",
2491 : Constant::Units::W,
2492 44391 : state.dataHeatBal->SurfWinInitialDifSolInTransReport(SurfLoop),
2493 : OutputProcessor::TimeStepType::Zone,
2494 : OutputProcessor::StoreType::Average,
2495 44391 : surf.Name);
2496 88782 : SetupOutputVariable(state,
2497 : "Surface Inside Face Absorbed Shortwave Radiation Rate",
2498 : Constant::Units::W,
2499 44391 : state.dataHeatBal->SurfSWInAbsTotalReport(SurfLoop),
2500 : OutputProcessor::TimeStepType::Zone,
2501 : OutputProcessor::StoreType::Average,
2502 44391 : surf.Name);
2503 : // energy
2504 88782 : SetupOutputVariable(state,
2505 : "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Energy",
2506 : Constant::Units::J,
2507 44391 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfLoop),
2508 : OutputProcessor::TimeStepType::Zone,
2509 : OutputProcessor::StoreType::Sum,
2510 44391 : surf.Name);
2511 88782 : SetupOutputVariable(state,
2512 : "Surface Inside Face Interior Windows Incident Beam Solar Radiation Energy",
2513 : Constant::Units::J,
2514 44391 : state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy(SurfLoop),
2515 : OutputProcessor::TimeStepType::Zone,
2516 : OutputProcessor::StoreType::Sum,
2517 44391 : surf.Name);
2518 : }
2519 796 : }
2520 :
2521 916286 : void AnisoSkyViewFactors(EnergyPlusData &state)
2522 : {
2523 :
2524 : // SUBROUTINE INFORMATION:
2525 : // AUTHOR Fred Winkelmann
2526 : // DATE WRITTEN April 1999
2527 : // MODIFIED LKL; Dec 2002 -- Anisotropic is only sky radiance option
2528 : // RE-ENGINEERED na
2529 :
2530 : // PURPOSE OF THIS SUBROUTINE:
2531 : // Calculates view factor multiplier, SurfAnisoSkyMult, for diffuse
2532 : // sky irradiance on exterior surfaces taking into account
2533 : // anisotropic radiance of the sky. Called by InitSurfaceHeatBalance
2534 : // In this case the diffuse sky irradiance on a surface is given by
2535 : // SurfAnisoSkyMult(SurfNum) * DifSolarRad
2536 : // SurfAnisoSkyMult accounts not only for the sky radiance distribution but
2537 : // also for the effects of shading of sky diffuse radiation by
2538 : // shadowing surfaces such as overhangs. It does not account for reflection
2539 : // of sky diffuse radiation from shadowing surfaces.
2540 : // Based on an empirical model described in
2541 : // R. Perez, P. Ineichen, R. Seals, J. Michalsky and R. Stewart,
2542 : // "Modeling Daylight Availability and Irradiance Components from Direct
2543 : // and Global Irradiance," Solar Energy 44, 271-289, 1990.
2544 : // In this model the radiance of the sky consists of three distributions
2545 : // that are superimposed:
2546 :
2547 : // (1) An isotropic distribution that covers the entire sky dome;
2548 : // (2) A circumsolar brightening centered around the position of the sun;
2549 : // (3) A horizon brightening
2550 : // The circumsolar brightening is assumed to be concentrated at a point
2551 : // source at the center of the sun although this region actually begins at the
2552 : // periphery of the solar disk and falls off in intensity with increasing
2553 : // angular distance from the periphery.
2554 : // The horizon brightening is assumed to be concentrated at the horizon and
2555 : // to be independent of azimuth. In actuality, for clear skies, the horizon
2556 : // brightening is highest at the horizon and decreases in intensity away from
2557 : // the horizon. For overcast skies the horizon brightening has a negative value
2558 : // since for such skies the sky radiance increases rather than decreases away
2559 : // from the horizon.
2560 : // The F11R, F12R, etc. values were provided by R. Perez, private communication,
2561 : // 5/21/99. These values have higher precision than those listed in the above
2562 : // paper.
2563 :
2564 : // Using/Aliasing
2565 :
2566 : // Locals
2567 : // SUBROUTINE PARAMETER DEFINITIONS:
2568 : static constexpr std::array<Real64, 7> EpsilonLimit = {
2569 : 1.065, 1.23, 1.5, 1.95, 2.8, 4.5, 6.2}; // Upper limit of bins of the sky clearness parameter, Epsilon
2570 : // Circumsolar brightening coefficients; index corresponds to range of Epsilon, the sky clearness parameter
2571 : static constexpr std::array<Real64, 8> F11R = {-0.0083117, 0.1299457, 0.3296958, 0.5682053, 0.8730280, 1.1326077, 1.0601591, 0.6777470};
2572 : static constexpr std::array<Real64, 8> F12R = {0.5877285, 0.6825954, 0.4868735, 0.1874525, -0.3920403, -1.2367284, -1.5999137, -0.3272588};
2573 : static constexpr std::array<Real64, 8> F13R = {-0.0620636, -0.1513752, -0.2210958, -0.2951290, -0.3616149, -0.4118494, -0.3589221, -0.2504286};
2574 : // Horizon/zenith brightening coefficient array; index corresponds to range of Epsilon, the sky clearness parameter
2575 : static constexpr std::array<Real64, 8> F21R = {-0.0596012, -0.0189325, 0.0554140, 0.1088631, 0.2255647, 0.2877813, 0.2642124, 0.1561313};
2576 : static constexpr std::array<Real64, 8> F22R = {0.0721249, 0.0659650, -0.0639588, -0.1519229, -0.4620442, -0.8230357, -1.1272340, -1.3765031};
2577 : static constexpr std::array<Real64, 8> F23R = {-0.0220216, -0.0288748, -0.0260542, -0.0139754, 0.0012448, 0.0558651, 0.1310694, 0.2506212};
2578 :
2579 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2580 :
2581 : Real64 CosZenithAng; // Cosine of solar zenith angle
2582 : Real64 ZenithAng; // Solar zenith angle (radians)
2583 : Real64 ZenithAngDeg; // Solar zenith angle (degrees)
2584 : Real64 F1; // Circumsolar brightening coefficient
2585 : Real64 F2; // Horizon/zenith brightening coefficient
2586 : Real64 Epsilon; // Sky clearness parameter
2587 : Real64 Delta; // Sky brightness parameter
2588 : Real64 CosIncAngBeamOnSurface; // Cosine of incidence angle of beam solar on surface
2589 : int EpsilonBin; // Sky clearness (Epsilon) bin index
2590 : Real64 AirMass; // Relative air mass
2591 : Real64 AirMassH; // Intermediate variable for relative air mass calculation
2592 : Real64 CircumSolarFac; // Ratio of cosine of incidence angle to cosine of zenith angle
2593 : Real64 KappaZ3; // Intermediate variable
2594 : Real64 ViewFactorSkyGeom; // Geometrical sky view factor
2595 916286 : Real64 constexpr cosine_tolerance(0.0001);
2596 :
2597 : #ifdef EP_Count_Calls
2598 : ++state.dataTimingsData->NumAnisoSky_Calls;
2599 : #endif
2600 :
2601 916286 : CosZenithAng = state.dataEnvrn->SOLCOS(3);
2602 916286 : ZenithAng = std::acos(CosZenithAng);
2603 916286 : ZenithAngDeg = ZenithAng / Constant::DegToRadians;
2604 :
2605 916286 : state.dataSolarShading->SurfAnisoSkyMult = 0.0;
2606 :
2607 : // Relative air mass
2608 916286 : AirMassH = (1.0 - 0.1 * state.dataEnvrn->Elevation / 1000.0);
2609 916286 : if (ZenithAngDeg <= 75.0) {
2610 728270 : AirMass = AirMassH / CosZenithAng;
2611 : } else {
2612 188016 : AirMass = AirMassH / (CosZenithAng + 0.15 * std::pow(93.9 - ZenithAngDeg, -1.253));
2613 : }
2614 916286 : KappaZ3 = 1.041 * pow_3(ZenithAng);
2615 916286 : Epsilon = ((state.dataEnvrn->BeamSolarRad + state.dataEnvrn->DifSolarRad) / state.dataEnvrn->DifSolarRad + KappaZ3) / (1.0 + KappaZ3);
2616 916286 : Delta = state.dataEnvrn->DifSolarRad * AirMass / 1353.0; // 1353 is average extraterrestrial irradiance (W/m2)
2617 : // Circumsolar (F1) and horizon/zenith (F2) brightening coefficients
2618 5866881 : for (EpsilonBin = 0; EpsilonBin < 8; ++EpsilonBin) {
2619 5866881 : if (EpsilonBin == 7) break;
2620 5569444 : if (Epsilon < EpsilonLimit[EpsilonBin]) break;
2621 : }
2622 916286 : F1 = max(0.0, F11R[EpsilonBin] + F12R[EpsilonBin] * Delta + F13R[EpsilonBin] * ZenithAng);
2623 916286 : F2 = F21R[EpsilonBin] + F22R[EpsilonBin] * Delta + F23R[EpsilonBin] * ZenithAng;
2624 :
2625 23550042 : for (int SurfNum : state.dataSurface->AllExtSolarSurfaceList) {
2626 :
2627 22633756 : CosIncAngBeamOnSurface = state.dataEnvrn->SOLCOS(1) * state.dataSurface->Surface(SurfNum).OutNormVec(1) +
2628 22633756 : state.dataEnvrn->SOLCOS(2) * state.dataSurface->Surface(SurfNum).OutNormVec(2) +
2629 22633756 : state.dataEnvrn->SOLCOS(3) * state.dataSurface->Surface(SurfNum).OutNormVec(3);
2630 :
2631 : // 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
2632 : // for
2633 22633756 : if (CosIncAngBeamOnSurface > 1.0) {
2634 0 : if (CosIncAngBeamOnSurface > (1.0 + cosine_tolerance)) {
2635 0 : ShowSevereError(state, "Cosine of incident angle of beam solar on surface out of range...too high");
2636 0 : ShowContinueError(state, "This is a diagnostic error that should not be encountered under normal circumstances");
2637 0 : ShowContinueError(state, format("Occurs on surface: {}", state.dataSurface->Surface(SurfNum).Name));
2638 0 : ShowContinueError(state, format("Current value = {} ... should be within [-1, +1]", CosIncAngBeamOnSurface));
2639 0 : ShowFatalError(state, "Anisotropic solar calculation causes fatal error");
2640 : }
2641 0 : CosIncAngBeamOnSurface = 1.0;
2642 22633756 : } else if (CosIncAngBeamOnSurface < -1.0) {
2643 0 : if (CosIncAngBeamOnSurface < (-1.0 - cosine_tolerance)) {
2644 0 : ShowSevereError(state, "Cosine of incident angle of beam solar on surface out of range...too low");
2645 0 : ShowContinueError(state, "This is a diagnostic error that should not be encountered under normal circumstances");
2646 0 : ShowContinueError(state, format("Occurs on surface: {}", state.dataSurface->Surface(SurfNum).Name));
2647 0 : ShowContinueError(state, format("Current value = {} ... should be within [-1, +1]", CosIncAngBeamOnSurface));
2648 0 : ShowFatalError(state, "Anisotropic solar calculation causes fatal error");
2649 : }
2650 0 : CosIncAngBeamOnSurface = -1.0;
2651 : }
2652 :
2653 22633756 : ViewFactorSkyGeom = state.dataSurface->Surface(SurfNum).ViewFactorSky;
2654 22633756 : state.dataSolarShading->SurfMultIsoSky(SurfNum) = ViewFactorSkyGeom * (1.0 - F1);
2655 : // 0.0871557 below corresponds to a zenith angle of 85 deg
2656 22633756 : CircumSolarFac = max(0.0, CosIncAngBeamOnSurface) / max(0.0871557, CosZenithAng);
2657 : // For near-horizontal roofs, model has an inconsistency that gives sky diffuse
2658 : // irradiance significantly different from DifSolarRad when zenith angle is
2659 : // above 85 deg. The following forces irradiance to be very close to DifSolarRad
2660 : // in this case.
2661 22633756 : if (CircumSolarFac > 0.0 && CosZenithAng < 0.0871557 && state.dataSurface->Surface(SurfNum).Tilt < 2.0) CircumSolarFac = 1.0;
2662 22633756 : state.dataSolarShading->SurfMultCircumSolar(SurfNum) = F1 * CircumSolarFac;
2663 22633756 : state.dataSolarShading->SurfMultHorizonZenith(SurfNum) = F2 * state.dataSurface->Surface(SurfNum).SinTilt;
2664 :
2665 22633756 : if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm || !state.dataSurface->ShadingTransmittanceVaries ||
2666 0 : state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
2667 22633756 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum) =
2668 22633756 : state.dataSolarShading->SurfMultIsoSky(SurfNum) * state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) +
2669 22633756 : state.dataSolarShading->SurfMultCircumSolar(SurfNum) *
2670 22633756 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) +
2671 22633756 : state.dataSolarShading->SurfMultHorizonZenith(SurfNum) * state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum);
2672 : } else {
2673 0 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum) =
2674 0 : state.dataSolarShading->SurfMultIsoSky(SurfNum) *
2675 0 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum) +
2676 0 : state.dataSolarShading->SurfMultCircumSolar(SurfNum) *
2677 0 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) +
2678 0 : state.dataSolarShading->SurfMultHorizonZenith(SurfNum) *
2679 0 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum);
2680 0 : state.dataSolarShading->SurfCurDifShdgRatioIsoSky(SurfNum) =
2681 0 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum);
2682 : }
2683 22633756 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum) = max(0.0, state.dataSolarShading->SurfAnisoSkyMult(SurfNum)); // make sure not negative.
2684 916286 : }
2685 916286 : }
2686 :
2687 17956 : void CHKBKS(EnergyPlusData &state,
2688 : int const NBS, // Surface Number of the potential back surface
2689 : int const NRS // Surface Number of the potential shadow receiving surface
2690 : )
2691 : {
2692 :
2693 : // SUBROUTINE INFORMATION:
2694 : // AUTHOR Legacy Code
2695 : // DATE WRITTEN
2696 : // MODIFIED Nov 2001, FW: Reverse subroutine arguments NRS and NBS to
2697 : // correspond to how CHKBKS is called
2698 : // Jan 2002, FW: change error message
2699 : // RE-ENGINEERED Lawrie, Oct 2000
2700 : // Sep 2020: Revised the vector computation method to reliabily produce CVec,
2701 : // and simplified the warning messages.
2702 :
2703 : // PURPOSE OF THIS SUBROUTINE:
2704 : // Determines whether a any vertices of the back surface are in front of the receiving surface;
2705 : // if so, gives severe error. Only base heat transfer surfaces are checked.
2706 :
2707 : // METHODOLOGY EMPLOYED:
2708 : // na
2709 :
2710 : // REFERENCES:
2711 : // BLAST/IBLAST code, original author George Walton
2712 :
2713 : // Using/Aliasing
2714 : using namespace Vectors;
2715 :
2716 : int N; // Loop Control (vertex counter)
2717 : int NVRS; // Number of vertices of the receiving surface
2718 : int NVBS; // Number of vertices of the back surface
2719 : Real64 DOTP; // Dot product of C and D
2720 :
2721 : // Object Data
2722 17956 : Vector CVec(0.0); // Vector perpendicular to surface at vertex 1
2723 17956 : Vector DVec(0.0); // Vector from vertex 1 of first surface to vertex 'n' of second surface
2724 :
2725 17956 : NVRS = state.dataSurface->Surface(NRS).Sides;
2726 17956 : NVBS = state.dataSurface->Surface(NBS).Sides;
2727 :
2728 : // SEE IF ANY VERTICES OF THE back surface ARE IN FRONT OF THE receiving surface
2729 :
2730 53928 : for (N = 2; N < NVRS; N++) {
2731 71944 : CVec += cross(state.dataSurface->Surface(NRS).Vertex(N) - state.dataSurface->Surface(NRS).Vertex(1),
2732 107916 : state.dataSurface->Surface(NRS).Vertex((N + 1)) - state.dataSurface->Surface(NRS).Vertex(1));
2733 : }
2734 17956 : CVec /= (NVRS >= 3 ? NVRS : 3);
2735 :
2736 90252 : for (N = 1; N <= NVBS; ++N) {
2737 72296 : DVec = state.dataSurface->Surface(NBS).Vertex(N) - state.dataSurface->Surface(NRS).Vertex(1);
2738 72296 : DOTP = dot(CVec, DVec);
2739 72296 : if (DOTP > 0.0009) {
2740 0 : ShowSevereError(state, "Problem in interior solar distribution calculation (CHKBKS)");
2741 0 : ShowContinueError(
2742 0 : state, format(" Solar Distribution = FullInteriorExterior will not work in Zone={}", state.dataSurface->Surface(NRS).ZoneName));
2743 0 : ShowContinueError(state,
2744 0 : format(" because one or more of vertices, such as Vertex {} of back surface={}, is in front of receiving surface={}",
2745 : N,
2746 0 : state.dataSurface->Surface(NBS).Name,
2747 0 : state.dataSurface->Surface(NRS).Name));
2748 0 : ShowContinueError(state, format(" (Dot Product indicator={:20.4F})", DOTP));
2749 0 : ShowContinueError(state,
2750 : " Check surface geometry; if OK, use Solar Distribution = FullExterior instead. Use Output:Diagnostics, "
2751 : "DisplayExtraWarnings; for more details.");
2752 0 : if (!state.dataGlobal->DisplayExtraWarnings) break;
2753 : }
2754 : }
2755 17956 : }
2756 :
2757 398327 : void CHKGSS(EnergyPlusData &state,
2758 : int const NRS, // Surface number of the potential shadow receiving surface
2759 : int const NSS, // Surface number of the potential shadow casting surface
2760 : Real64 const ZMIN, // Lowest point of the receiving surface
2761 : bool &CannotShade // TRUE if shadow casting surface cannot shade receiving surface.
2762 : )
2763 : {
2764 :
2765 : // SUBROUTINE INFORMATION:
2766 : // AUTHOR Legacy Code
2767 : // DATE WRITTEN
2768 : // MODIFIED na
2769 : // RE-ENGINEERED Lawrie, Oct 2000
2770 :
2771 : // PURPOSE OF THIS SUBROUTINE:
2772 : // Determines the possible shadowing combinations. The
2773 : // routine checks detached shadowing or base heat transfer surfaces
2774 : // for the possibility that they cannot shade a given base heat transfer surface.
2775 :
2776 : // METHODOLOGY EMPLOYED:
2777 : // Shadowing is not possible if:
2778 : // 1. The lowest point of the shadow receiving surface (receiving surface)
2779 : // Is higher than the highest point of the shadow casting surface (s.s.)
2780 : // 2. The shadow casting surface Faces up (e.g. A flat roof)
2781 : // 3. The shadow casting surface Is behind the receiving surface
2782 : // 4. The receiving surface is behind the shadow casting surface
2783 :
2784 : // REFERENCES:
2785 : // BLAST/IBLAST code, original author George Walton
2786 :
2787 : // Using/Aliasing
2788 : using namespace Vectors;
2789 :
2790 : // Object Data
2791 :
2792 398327 : CannotShade = true;
2793 :
2794 : // see if no point of shadow casting surface is above low point of receiving surface
2795 :
2796 398327 : auto const &surface_C = state.dataSurface->Surface(NSS);
2797 512203 : if (surface_C.OutNormVec(3) > 0.9999) return; // Shadow Casting Surface is horizontal and facing upward
2798 309944 : auto const &vertex_C = surface_C.Vertex;
2799 309944 : Real64 ZMAX(vertex_C(1).z);
2800 1235420 : for (int i = 2, e = surface_C.Sides; i <= e; ++i) {
2801 925476 : ZMAX = std::max(ZMAX, vertex_C(i).z);
2802 : }
2803 309944 : if (ZMAX <= ZMIN) return;
2804 :
2805 : // SEE IF ANY VERTICES OF THE Shadow Casting Surface ARE ABOVE THE PLANE OF THE receiving surface
2806 :
2807 196068 : auto const &surface_R = state.dataSurface->Surface(NRS);
2808 196068 : auto const &vertex_R = surface_R.Vertex;
2809 196068 : Vector const &vertex_R_2 = vertex_R(2);
2810 196068 : Vector const AVec = (vertex_R(1) - vertex_R_2); // Vector from vertex 2 to vertex 1 of receiving surface
2811 196068 : Vector const BVec = (vertex_R(3) - vertex_R_2); // Vector from vertex 2 to vertex 3 of receiving surface
2812 :
2813 196068 : Vector const CVec = cross(BVec, AVec); // Vector perpendicular to surface at vertex 2
2814 :
2815 196068 : int const NVSS = surface_C.Sides; // Number of vertices of the shadow casting surface
2816 196068 : Real64 DOTP(0.0); // Dot Product
2817 766434 : for (int I = 1; I <= NVSS; ++I) {
2818 627334 : DOTP = dot(CVec, vertex_C(I) - vertex_R_2);
2819 627334 : if (DOTP > state.dataSolarShading->TolValue) break; // DO loop
2820 : }
2821 :
2822 : // SEE IF ANY VERTICES OF THE receiving surface ARE ABOVE THE PLANE OF THE S.S.
2823 :
2824 196068 : if (DOTP > state.dataSolarShading->TolValue) {
2825 :
2826 56968 : Vector const &vertex_C_2 = vertex_C(2);
2827 56968 : Vector const AVec(vertex_C(1) - vertex_C_2);
2828 56968 : Vector const BVec(vertex_C(3) - vertex_C_2);
2829 :
2830 56968 : Vector const CVec(cross(BVec, AVec));
2831 :
2832 56968 : int const NVRS = surface_R.Sides; // Number of vertices of the receiving surface
2833 181973 : for (int I = 1; I <= NVRS; ++I) {
2834 152647 : DOTP = dot(CVec, vertex_R(I) - vertex_C_2);
2835 152647 : if (DOTP > state.dataSolarShading->TolValue) {
2836 27642 : CannotShade = false;
2837 27642 : break; // DO loop
2838 : }
2839 : }
2840 56968 : }
2841 196068 : }
2842 :
2843 6593 : void CHKSBS(EnergyPlusData &state,
2844 : int const HTS, // Heat transfer surface number of the general receiving surf
2845 : int const GRSNR, // Surface number of general receiving surface
2846 : int const SBSNR // Surface number of subsurface
2847 : )
2848 : {
2849 :
2850 : // SUBROUTINE INFORMATION:
2851 : // AUTHOR Legacy Code
2852 : // DATE WRITTEN
2853 : // MODIFIED na
2854 : // RE-ENGINEERED Lawrie, Oct 2000
2855 :
2856 : // PURPOSE OF THIS SUBROUTINE:
2857 : // Checks that a subsurface is completely
2858 : // enclosed by its base surface.
2859 :
2860 : // REFERENCES:
2861 : // BLAST/IBLAST code, original author George Walton
2862 :
2863 : // 3D Planar Polygons
2864 : // In 3D applications, one sometimes wants to test a point and polygon that are in the same plane.
2865 : // For example, one may have the intersection point of a ray with the plane of a polyhedron's face,
2866 : // and want to test if it is inside the face. Or one may want to know if the base of a 3D perpendicular
2867 : // dropped from a point is inside a planar polygon.
2868 :
2869 : // 3D inclusion is easily determined by projecting the point and polygon into 2D. To do this, one simply
2870 : // ignores one of the 3D coordinates and uses the other two. To optimally select the coordinate to ignore,
2871 : // compute a normal vector to the plane, and select the coordinate with the largest absolute value [Snyder & Barr, 1987].
2872 : // This gives the projection of the polygon with maximum area, and results in robust computations.
2873 : // John M. Snyder & Alan H. Barr, "Ray Tracing Complex Models Containing Surface Tessellations",
2874 : // Computer Graphics 21(4), 119-126 (1987) [also in the Proceedings of SIGGRAPH 1987]
2875 : //--- using adapted routine from Triangulation code -- EnergyPlus.
2876 :
2877 : // MSG - for error message
2878 6593 : static Array1D_string const MSG(4, {"misses", "", "within", "overlaps"});
2879 :
2880 : int N; // Loop Control
2881 : int NVT; // Number of vertices
2882 : int NS1; // Number of the figure being overlapped
2883 : int NS2; // Number of the figure doing overlapping
2884 : int NS3; // Location to place results of overlap
2885 :
2886 : bool inside;
2887 :
2888 : bool Out;
2889 : Real64 X1; // ,SX,SY,SZ
2890 : Real64 Y1;
2891 : Real64 Z1;
2892 : Real64 X2;
2893 : Real64 Y2;
2894 : Real64 Z2;
2895 : Real64 BX;
2896 : Real64 BY;
2897 : Real64 BZ;
2898 : Real64 BMAX;
2899 : // INTEGER M
2900 :
2901 6593 : if (state.dataSolarShading->CHKSBSOneTimeFlag) {
2902 698 : state.dataSolarShading->XVT.allocate(state.dataSurface->MaxVerticesPerSurface + 1);
2903 698 : state.dataSolarShading->YVT.allocate(state.dataSurface->MaxVerticesPerSurface + 1);
2904 698 : state.dataSolarShading->ZVT.allocate(state.dataSurface->MaxVerticesPerSurface + 1);
2905 698 : state.dataSolarShading->XVT = 0.0;
2906 698 : state.dataSolarShading->YVT = 0.0;
2907 698 : state.dataSolarShading->ZVT = 0.0;
2908 698 : state.dataSolarShading->CHKSBSOneTimeFlag = false;
2909 : }
2910 :
2911 6593 : NS1 = 1;
2912 6593 : NS2 = 2;
2913 6593 : NS3 = 3;
2914 6593 : state.dataSolarShading->HCT(1) = 0.0;
2915 6593 : state.dataSolarShading->HCT(2) = 0.0;
2916 :
2917 : // Put coordinates of base surface into clockwise sequence on the x'-y' plane.
2918 :
2919 6593 : state.dataSolarShading->XVT = 0.0;
2920 6593 : state.dataSolarShading->YVT = 0.0;
2921 6593 : state.dataSolarShading->ZVT = 0.0;
2922 6593 : state.dataSolarShading->XVS = 0.0;
2923 6593 : state.dataSolarShading->YVS = 0.0;
2924 6593 : CTRANS(state, GRSNR, HTS, NVT, state.dataSolarShading->XVT, state.dataSolarShading->YVT, state.dataSolarShading->ZVT);
2925 33029 : for (N = 1; N <= NVT; ++N) {
2926 26436 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVT(NVT + 1 - N);
2927 26436 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVT(NVT + 1 - N);
2928 : }
2929 :
2930 6593 : HTRANS1(state, NS2, NVT);
2931 :
2932 : // Put coordinates of the subsurface into clockwise sequence.
2933 :
2934 6593 : state.dataSolarShading->NVS = state.dataSurface->Surface(SBSNR).Sides;
2935 32963 : for (N = 1; N <= state.dataSolarShading->NVS; ++N) {
2936 26370 : state.dataSolarShading->XVS(N) = state.dataSurface->ShadeV(SBSNR).XV(state.dataSolarShading->NVS + 1 - N);
2937 26370 : state.dataSolarShading->YVS(N) = state.dataSurface->ShadeV(SBSNR).YV(state.dataSolarShading->NVS + 1 - N);
2938 : }
2939 6593 : HTRANS1(state, NS1, state.dataSolarShading->NVS);
2940 :
2941 : // Determine the overlap condition.
2942 :
2943 6593 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
2944 :
2945 : // Print error condition if necessary.
2946 :
2947 6593 : if (state.dataSolarShading->OverlapStatus != FirstSurfWithinSecond) {
2948 19 : Out = false;
2949 : // C COMPUTE COMPONENTS OF VECTOR
2950 : // C NORMAL TO BASE SURFACE.
2951 19 : X1 = state.dataSurface->Surface(GRSNR).Vertex(1).x - state.dataSurface->Surface(GRSNR).Vertex(2).x; // XV(1,GRSNR)-XV(2,GRSNR)
2952 19 : Y1 = state.dataSurface->Surface(GRSNR).Vertex(1).y - state.dataSurface->Surface(GRSNR).Vertex(2).y; // YV(1,GRSNR)-YV(2,GRSNR)
2953 19 : Z1 = state.dataSurface->Surface(GRSNR).Vertex(1).z - state.dataSurface->Surface(GRSNR).Vertex(2).z; // ZV(1,GRSNR)-ZV(2,GRSNR)
2954 19 : X2 = state.dataSurface->Surface(GRSNR).Vertex(3).x - state.dataSurface->Surface(GRSNR).Vertex(2).x; // XV(3,GRSNR)-XV(2,GRSNR)
2955 19 : Y2 = state.dataSurface->Surface(GRSNR).Vertex(3).y - state.dataSurface->Surface(GRSNR).Vertex(2).y; // YV(3,GRSNR)-YV(2,GRSNR)
2956 19 : Z2 = state.dataSurface->Surface(GRSNR).Vertex(3).z - state.dataSurface->Surface(GRSNR).Vertex(2).z; // ZV(3,GRSNR)-ZV(2,GRSNR)
2957 19 : BX = Y1 * Z2 - Y2 * Z1;
2958 19 : BY = Z1 * X2 - Z2 * X1;
2959 19 : BZ = X1 * Y2 - X2 * Y1;
2960 : // C FIND LARGEST COMPONENT.
2961 19 : BMAX = max(std::abs(BX), std::abs(BY), std::abs(BZ));
2962 : // C
2963 19 : if (std::abs(BX) == BMAX) {
2964 : // write(outputfiledebug,*) ' looking bx-bmax',bmax
2965 10 : for (N = 1; N <= state.dataSurface->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
2966 8 : inside = polygon_contains_point(state.dataSurface->Surface(GRSNR).Sides,
2967 8 : state.dataSurface->Surface(GRSNR).Vertex,
2968 8 : state.dataSurface->Surface(SBSNR).Vertex(N),
2969 : true,
2970 : false,
2971 : false);
2972 8 : if (!inside) {
2973 0 : Out = true;
2974 : // do m=1,surface(grsnr)%sides
2975 : // write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
2976 : // write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
2977 : // enddo
2978 : // EXIT
2979 : }
2980 : // Y1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(NV(GRSNR),GRSNR)-YV(N,SBSNR)
2981 : // Z1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(NV(GRSNR),GRSNR)-ZV(N,SBSNR)
2982 : // DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
2983 : // Y2 = Y1
2984 : // Z2 = Z1
2985 : // Y1 = Surface(GRSNR)%Vertex(M)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(M,GRSNR)-YV(N,SBSNR)
2986 : // Z1 = Surface(GRSNR)%Vertex(M)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(M,GRSNR)-ZV(N,SBSNR)
2987 : // SX = Y1*Z2-Y2*Z1
2988 : // IF(SX*BX.LT.-1.0d-6) THEN
2989 : // OUT=.TRUE.
2990 : // write(outputfiledebug,*) 'sx*bx=',sx*bx
2991 : // write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
2992 : // write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
2993 : // endif
2994 : // ENDDO
2995 : // IF (OUT) EXIT
2996 : }
2997 17 : } else if (std::abs(BY) == BMAX) {
2998 : // write(outputfiledebug,*) ' looking by-bmax',bmax
2999 5 : for (N = 1; N <= state.dataSurface->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
3000 4 : inside = polygon_contains_point(state.dataSurface->Surface(GRSNR).Sides,
3001 4 : state.dataSurface->Surface(GRSNR).Vertex,
3002 4 : state.dataSurface->Surface(SBSNR).Vertex(N),
3003 : false,
3004 : true,
3005 : false);
3006 4 : if (!inside) {
3007 0 : Out = true;
3008 : // do m=1,surface(grsnr)%sides
3009 : // write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
3010 : // write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
3011 : // enddo
3012 : // EXIT
3013 : }
3014 : // Z1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(NV(GRSNR),GRSNR)-ZV(N,SBSNR)
3015 : // X1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%X-Surface(SBSNR)%Vertex(N)%X !XV(NV(GRSNR),GRSNR)-XV(N,SBSNR)
3016 : // DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
3017 : // Z2 = Z1
3018 : // X2 = X1
3019 : // Z1 = Surface(GRSNR)%Vertex(M)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(M,GRSNR)-ZV(N,SBSNR)
3020 : // X1 = Surface(GRSNR)%Vertex(M)%X-Surface(SBSNR)%Vertex(N)%X !XV(M,GRSNR)-XV(N,SBSNR)
3021 : // SY = Z1*X2-Z2*X1
3022 : // IF(SY*BY.LT.-1.0d-6) THEN
3023 : // OUT=.TRUE.
3024 : // write(outputfiledebug,*) 'sy*by=',sy*by
3025 : // write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
3026 : // write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
3027 : // ENDIF
3028 : // ENDDO
3029 : // IF (OUT) EXIT
3030 : }
3031 : } else {
3032 : // write(outputfiledebug,*) ' looking bz-bmax',bmax
3033 80 : for (N = 1; N <= state.dataSurface->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
3034 64 : inside = polygon_contains_point(state.dataSurface->Surface(GRSNR).Sides,
3035 64 : state.dataSurface->Surface(GRSNR).Vertex,
3036 64 : state.dataSurface->Surface(SBSNR).Vertex(N),
3037 : false,
3038 : false,
3039 : true);
3040 64 : if (!inside) {
3041 0 : Out = true;
3042 : // do m=1,surface(grsnr)%sides
3043 : // write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
3044 : // write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
3045 : // enddo
3046 : // EXIT
3047 : }
3048 : // X1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%X-Surface(SBSNR)%Vertex(N)%X !XV(NV(GRSNR),GRSNR)-XV(N,SBSNR)
3049 : // Y1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(NV(GRSNR),GRSNR)-YV(N,SBSNR)
3050 : // DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
3051 : // X2 = X1
3052 : // Y2 = Y1
3053 : // X1 = Surface(GRSNR)%Vertex(M)%X-Surface(SBSNR)%Vertex(N)%X !XV(M,GRSNR)-XV(N,SBSNR)
3054 : // Y1 = Surface(GRSNR)%Vertex(M)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(M,GRSNR)-YV(N,SBSNR)
3055 : // SZ = X1*Y2-X2*Y1
3056 : // IF(SZ*BZ.LT.-1.0d-6) THEN
3057 : // OUT=.TRUE.
3058 : // write(outputfiledebug,*) 'sz*bz=',sz*bz
3059 : // write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
3060 : // write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
3061 : // ENDIF
3062 : // ENDDO
3063 : // IF (OUT) EXIT
3064 : }
3065 : }
3066 : // CALL ShowWarningError(state, 'Base surface does not surround subsurface (CHKSBS), Overlap Status='// &
3067 : // TRIM(cOverLapStatus(OverlapStatus)))
3068 : // CALL ShowContinueError(state, 'Surface "'//TRIM(Surface(GRSNR)%Name)//'" '//TRIM(MSG(OverlapStatus))// &
3069 : // ' SubSurface "'//TRIM(Surface(SBSNR)%Name)//'"')
3070 : // IF (FirstSurroundError) THEN
3071 : // CALL ShowWarningError(state, 'Base Surface does not surround subsurface errors occuring...'// &
3072 : // 'Check that the SurfaceGeometry object is expressing the proper starting corner and '// &
3073 : // 'direction [CounterClockwise/Clockwise]')
3074 : // FirstSurroundError=.FALSE.
3075 : // ENDIF
3076 19 : if (Out) {
3077 0 : state.dataSolarShading->TrackBaseSubSurround.redimension(++state.dataSolarShading->NumBaseSubSurround);
3078 0 : state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).SurfIndex1 = GRSNR;
3079 0 : state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).SurfIndex2 = SBSNR;
3080 0 : state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).MiscIndex =
3081 0 : state.dataSolarShading->OverlapStatus;
3082 : // CALL ShowRecurringWarningErrorAtEnd(state, 'Base surface does not surround subsurface (CHKSBS), Overlap Status='// &
3083 : // TRIM(cOverLapStatus(OverlapStatus)), &
3084 : // TrackBaseSubSurround(GRSNR)%ErrIndex1)
3085 : // CALL ShowRecurringContinueErrorAtEnd(state, 'Surface "'//TRIM(Surface(GRSNR)%Name)//'" '//TRIM(MSG(OverlapStatus))// &
3086 : // ' SubSurface "'//TRIM(Surface(SBSNR)%Name)//'"', &
3087 : // TrackBaseSubSurround(SBSNR)%ErrIndex2)
3088 0 : if (state.dataSolarShading->shd_stream) {
3089 0 : *state.dataSolarShading->shd_stream << "==== Base does not Surround subsurface details ====\n";
3090 0 : *state.dataSolarShading->shd_stream << "Surface=" << state.dataSurface->Surface(GRSNR).Name << ' '
3091 0 : << state.dataSolarShading->cOverLapStatus(state.dataSolarShading->OverlapStatus) << '\n';
3092 0 : *state.dataSolarShading->shd_stream << "Surface#=" << std::setw(5) << GRSNR << " NSides=" << std::setw(5)
3093 0 : << state.dataSurface->Surface(GRSNR).Sides << '\n';
3094 0 : *state.dataSolarShading->shd_stream << std::fixed << std::setprecision(2);
3095 0 : for (N = 1; N <= state.dataSurface->Surface(GRSNR).Sides; ++N) {
3096 0 : Vector const &v(state.dataSurface->Surface(GRSNR).Vertex(N));
3097 0 : *state.dataSolarShading->shd_stream << "Vertex " << std::setw(5) << N << "=(" << std::setw(15) << v.x << ',' << std::setw(15)
3098 0 : << v.y << ',' << std::setw(15) << v.z << ")\n";
3099 : }
3100 0 : *state.dataSolarShading->shd_stream << "SubSurface=" << state.dataSurface->Surface(SBSNR).Name << '\n';
3101 0 : *state.dataSolarShading->shd_stream << "Surface#=" << std::setw(5) << SBSNR << " NSides=" << std::setw(5)
3102 0 : << state.dataSurface->Surface(SBSNR).Sides << '\n';
3103 0 : for (N = 1; N <= state.dataSurface->Surface(SBSNR).Sides; ++N) {
3104 0 : Vector const &v(state.dataSurface->Surface(SBSNR).Vertex(N));
3105 0 : *state.dataSolarShading->shd_stream << "Vertex " << std::setw(5) << N << "=(" << std::setw(15) << v.x << ',' << std::setw(15)
3106 0 : << v.y << ',' << std::setw(15) << v.z << ")\n";
3107 : }
3108 0 : *state.dataSolarShading->shd_stream << "================================\n";
3109 : }
3110 : }
3111 : }
3112 6593 : }
3113 :
3114 76 : bool polygon_contains_point(int const nsides, // number of sides (vertices)
3115 : Array1D<Vector> &polygon_3d, // points of polygon
3116 : Vector const &point_3d, // point to be tested
3117 : bool const ignorex,
3118 : bool const ignorey,
3119 : bool const ignorez)
3120 : {
3121 :
3122 : // Function information:
3123 : // Author Linda Lawrie
3124 : // Date written October 2005
3125 : // Modified na
3126 : // Re-engineered na
3127 :
3128 : // Purpose of this function:
3129 : // Determine if a point is inside a simple 2d polygon. For a simple polygon (one whose
3130 : // boundary never crosses itself). The polygon does not need to be convex.
3131 :
3132 : // References:
3133 : // M Shimrat, Position of Point Relative to Polygon, ACM Algorithm 112,
3134 : // Communications of the ACM, Volume 5, Number 8, page 434, August 1962.
3135 :
3136 : // Use statements:
3137 : // Using/Aliasing
3138 : using namespace DataVectorTypes;
3139 :
3140 : // return value, true=inside, false = not inside
3141 :
3142 76 : EP_SIZE_CHECK(polygon_3d, nsides);
3143 :
3144 : int ip1;
3145 :
3146 : // Object Data
3147 76 : Array1D<Vector_2d> polygon(nsides);
3148 76 : Vector_2d point;
3149 :
3150 76 : bool inside = false;
3151 76 : if (ignorex) {
3152 40 : for (int i = 1; i <= nsides; ++i) {
3153 32 : polygon(i).x = polygon_3d(i).y;
3154 32 : polygon(i).y = polygon_3d(i).z;
3155 : }
3156 8 : point.x = point_3d.y;
3157 8 : point.y = point_3d.z;
3158 68 : } else if (ignorey) {
3159 20 : for (int i = 1; i <= nsides; ++i) {
3160 16 : polygon(i).x = polygon_3d(i).x;
3161 16 : polygon(i).y = polygon_3d(i).z;
3162 : }
3163 4 : point.x = point_3d.x;
3164 4 : point.y = point_3d.z;
3165 64 : } else if (ignorez) {
3166 576 : for (int i = 1; i <= nsides; ++i) {
3167 512 : polygon(i).x = polygon_3d(i).x;
3168 512 : polygon(i).y = polygon_3d(i).y;
3169 : }
3170 64 : point.x = point_3d.x;
3171 64 : point.y = point_3d.y;
3172 : } else { // Illegal
3173 0 : assert(false);
3174 : point.x = point.y = 0.0; // Elim possibly used uninitialized warnings
3175 : }
3176 :
3177 636 : for (int i = 1; i <= nsides; ++i) {
3178 :
3179 560 : if (i < nsides) {
3180 484 : ip1 = i + 1;
3181 : } else {
3182 76 : ip1 = 1;
3183 : }
3184 :
3185 560 : if ((polygon(i).y < point.y && point.y <= polygon(ip1).y) || (point.y <= polygon(i).y && polygon(ip1).y < point.y)) {
3186 152 : if ((point.x - polygon(i).x) - (point.y - polygon(i).y) * (polygon(ip1).x - polygon(i).x) / (polygon(ip1).y - polygon(i).y) < 0) {
3187 76 : inside = !inside;
3188 : }
3189 : }
3190 : }
3191 :
3192 76 : return inside;
3193 76 : }
3194 :
3195 346 : void ComputeIntSolarAbsorpFactors(EnergyPlusData &state)
3196 : {
3197 :
3198 : // SUBROUTINE INFORMATION:
3199 : // AUTHOR Legacy Code
3200 : // MODIFIED B. Griffith, Oct 2010, deal with no floor case
3201 : // L. Lawrie, Mar 2012, relax >154 tilt even further (>120 considered non-wall by ASHRAE)
3202 : // RE-ENGINEERED Lawrie, Oct 2000
3203 :
3204 : // PURPOSE OF THIS SUBROUTINE:
3205 : // This routine computes the fractions of diffusely transmitted
3206 : // solar energy absorbed by each zone surface.
3207 :
3208 : // METHODOLOGY EMPLOYED:
3209 : // It is assumed that all transmitted solar energy is incident
3210 : // on the floors of the zone (or enclosure). The fraction directly absorbed in
3211 : // the floor is given by 'ISABSF'. It is proportional to the
3212 : // area * solar absorptance. The remaining solar energy is then
3213 : // distributed uniformly around the room according to
3214 : // area*absorptance product
3215 :
3216 : // REFERENCES:
3217 : // BLAST/IBLAST code, original author George Walton
3218 :
3219 : using namespace DataWindowEquivalentLayer;
3220 :
3221 : Real64 AreaSum; // Intermediate calculation value
3222 : int Lay; // Window glass layer number
3223 : Real64 AbsDiffTotWin; // Sum of a window's glass layer solar absorptances
3224 : Real64 TestFractSum;
3225 : Real64 HorizAreaSum;
3226 :
3227 2468 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
3228 2122 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
3229 :
3230 2122 : AreaSum = 0.0;
3231 2122 : TestFractSum = 0.0;
3232 20372 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
3233 36500 : if (state.dataHeatBal->Zone(state.dataSurface->Surface(SurfNum).Zone).OfType == StandardZone &&
3234 18250 : state.dataSurface->Surface(SurfNum).CosTilt < -0.5) {
3235 3275 : AreaSum += state.dataSurface->Surface(SurfNum).Area;
3236 : }
3237 : }
3238 :
3239 2122 : HorizAreaSum = AreaSum;
3240 :
3241 2122 : if ((thisEnclosure.FloorArea <= 0.0) && (HorizAreaSum > 0.0)) {
3242 : // fill floor area even though surfs not called "Floor", they are roughly horizontal and face upwards.
3243 0 : thisEnclosure.FloorArea = HorizAreaSum;
3244 0 : ShowWarningError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
3245 0 : ShowContinueError(state, format("...Enclosure=\"{}\" has no floor, but has approximate horizontal surfaces.", thisEnclosure.Name));
3246 0 : ShowContinueError(state, format("...these Tilt > 120 degrees, (area=[{:.2R}] m2) will be used.", HorizAreaSum));
3247 : }
3248 :
3249 : // Compute ISABSF
3250 :
3251 20372 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
3252 :
3253 : // only horizontal surfaces. ! !CR 8229, relaxed from -0.99 to -0.5 (Tilt > 154)
3254 : // only horizontal surfaces. ! !CR8769 use ASHRAE std of >120, -0.9 to -0.5 (Tilt > 120)
3255 18250 : if ((state.dataHeatBal->Zone(state.dataSurface->Surface(SurfNum).Zone).OfType != StandardZone ||
3256 21525 : state.dataSurface->Surface(SurfNum).CosTilt < -0.5) &&
3257 3275 : (state.dataHeatBal->Zone(state.dataSurface->Surface(SurfNum).Zone).OfType == StandardZone ||
3258 0 : state.dataSurface->Surface(SurfNum).ExtBoundCond > 0)) {
3259 :
3260 3275 : int const ConstrNum = state.dataSurface->SurfActiveConstruction(SurfNum);
3261 3275 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
3262 : // last minute V3.1
3263 3275 : if (thisConstruct.TransDiff <= 0.0) { // Opaque surface
3264 3275 : if (AreaSum > 0.0)
3265 3275 : state.dataSolarShading->SurfIntAbsFac(SurfNum) =
3266 3275 : state.dataSurface->Surface(SurfNum).Area * thisConstruct.InsideAbsorpSolar / AreaSum;
3267 : } else { // Window (floor windows are assumed to have no shading device and no divider,
3268 : // and assumed to be non-switchable)
3269 0 : AbsDiffTotWin = 0.0;
3270 0 : if (!state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).WindowTypeEQL) {
3271 0 : for (Lay = 1; Lay <= thisConstruct.TotGlassLayers; ++Lay) {
3272 0 : AbsDiffTotWin += thisConstruct.AbsDiffBack(Lay);
3273 : }
3274 : } else {
3275 0 : for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(thisConstruct.EQLConsPtr).NL; ++Lay) {
3276 0 : AbsDiffTotWin += thisConstruct.AbsDiffBackEQL(Lay);
3277 : }
3278 : }
3279 0 : if (AreaSum > 0.0)
3280 0 : state.dataSolarShading->SurfIntAbsFac(SurfNum) = state.dataSurface->Surface(SurfNum).Area * AbsDiffTotWin / AreaSum;
3281 : }
3282 : }
3283 : // CR 8229 test ISABSF for problems
3284 18250 : TestFractSum += state.dataSolarShading->SurfIntAbsFac(SurfNum);
3285 : }
3286 :
3287 2122 : if (TestFractSum <= 0.0) {
3288 0 : if (thisEnclosure.ExtWindowArea > 0.0) { // we have a problem, the sun has no floor to go to
3289 0 : if (thisEnclosure.FloorArea <= 0.0) {
3290 0 : ShowSevereError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
3291 0 : ShowContinueError(state, format("but Zone or Enclosure =\"{}\" does not appear to have any floor surfaces.", thisEnclosure.Name));
3292 0 : ShowContinueError(state, "Solar gains will be spread evenly on all surfaces in the zone, and the simulation continues...");
3293 : } else { // Floor Area > 0 but still can't absorb
3294 0 : ShowSevereError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
3295 0 : ShowContinueError(state, format("but Zone or Enclosure =\"{}\" floor cannot absorb any solar gains. ", thisEnclosure.Name));
3296 0 : ShowContinueError(state, "Check the solar absorptance of the inside layer of the floor surface construction/material.");
3297 0 : ShowContinueError(state, "Solar gains will be spread evenly on all surfaces in the zone, and the simulation continues...");
3298 : }
3299 :
3300 : // try again but use an even spread across all the surfaces in the zone, regardless of horizontal
3301 : // so as to not lose solar energy
3302 0 : AreaSum = 0.0;
3303 0 : for (int SurfNum : thisEnclosure.SurfacePtr) {
3304 0 : AreaSum += state.dataSurface->Surface(SurfNum).Area;
3305 : }
3306 :
3307 0 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
3308 0 : int const ConstrNum = state.dataSurface->SurfActiveConstruction(SurfNum);
3309 0 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
3310 0 : if (thisConstruct.TransDiff <= 0.0) { // Opaque surface
3311 0 : if (AreaSum > 0.0)
3312 0 : state.dataSolarShading->SurfIntAbsFac(SurfNum) =
3313 0 : state.dataSurface->Surface(SurfNum).Area * thisConstruct.InsideAbsorpSolar / AreaSum;
3314 : } else { // Window (floor windows are assumed to have no shading device and no divider,
3315 : // and assumed to be non-switchable)
3316 0 : AbsDiffTotWin = 0.0;
3317 0 : if (!state.dataConstruction->Construct(state.dataSurface->Surface(SurfNum).Construction).WindowTypeEQL) {
3318 0 : for (Lay = 1; Lay <= thisConstruct.TotGlassLayers; ++Lay) {
3319 0 : AbsDiffTotWin += thisConstruct.AbsDiffBack(Lay);
3320 : }
3321 : } else {
3322 0 : for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(thisConstruct.EQLConsPtr).NL; ++Lay) {
3323 0 : AbsDiffTotWin += thisConstruct.AbsDiffBackEQL(Lay);
3324 : }
3325 : }
3326 :
3327 0 : if (AreaSum > 0.0)
3328 0 : state.dataSolarShading->SurfIntAbsFac(SurfNum) = state.dataSurface->Surface(SurfNum).Area * AbsDiffTotWin / AreaSum;
3329 : }
3330 : }
3331 : }
3332 : }
3333 :
3334 : } // enclosure loop
3335 346 : }
3336 :
3337 3487318 : void CLIP(EnergyPlusData &state, int const NVT, Array1D<Real64> &XVT, Array1D<Real64> &YVT, Array1D<Real64> &ZVT)
3338 : {
3339 :
3340 : // SUBROUTINE INFORMATION:
3341 : // AUTHOR Legacy Code
3342 : // DATE WRITTEN
3343 : // MODIFIED na
3344 : // RE-ENGINEERED Lawrie, Oct 2000
3345 :
3346 : // PURPOSE OF THIS SUBROUTINE:
3347 : // This subroutine 'clips' the shadow casting surface polygon so that
3348 : // none of it lies below the plane of the receiving surface polygon. This
3349 : // prevents the casting of 'false' shadows.
3350 :
3351 : // REFERENCES:
3352 : // BLAST/IBLAST code, original author George Walton
3353 :
3354 3487318 : int NABOVE(0); // Number of vertices of shadow casting surface. above the plane of receiving surface
3355 3487318 : int NEXT(0); // First vertex above plane of receiving surface
3356 3487318 : int NON(0); // Number of vertices of shadow casting surface. on plane of receiving surface
3357 3487318 : Real64 XIN(0.0); // X of entry point of shadow casting surface. into plane of receiving surface
3358 3487318 : Real64 XOUT(0.0); // X of exit point of shadow casting surface. from plane of receiving surface
3359 3487318 : Real64 YIN(0.0); // Y of entry point of shadow casting surface. into plane of receiving surface
3360 3487318 : Real64 YOUT(0.0); // Y of exit point of shadow casting surface. from plane of receiving surface
3361 : // INTEGER NVS ! Number of vertices of the shadow/clipped surface
3362 :
3363 : // Determine if the shadow casting surface. is above, below, or intersects with the plane of the receiving surface
3364 :
3365 3487318 : state.dataSolarShading->NumVertInShadowOrClippedSurface = state.dataSolarShading->NVS;
3366 17371378 : for (int N = 1; N <= NVT; ++N) {
3367 13884060 : Real64 const ZVT_N(ZVT(N));
3368 13884060 : if (ZVT_N > 0.0) {
3369 11046634 : ++NABOVE;
3370 2837426 : } else if (ZVT_N == 0.0) {
3371 1324648 : ++NON;
3372 : }
3373 : }
3374 :
3375 3487318 : if (NABOVE + NON == NVT) { // Rename the unclipped shadow casting surface.
3376 :
3377 2729230 : state.dataSolarShading->NVS = NVT;
3378 2729230 : state.dataSolarShading->NumVertInShadowOrClippedSurface = NVT;
3379 13617994 : for (int N = 1; N <= NVT; ++N) {
3380 10888764 : state.dataSolarShading->XVC(N) = XVT(N);
3381 10888764 : state.dataSolarShading->YVC(N) = YVT(N);
3382 10888764 : state.dataSolarShading->ZVC(N) = ZVT(N);
3383 : }
3384 :
3385 758088 : } else if (NABOVE == 0) { // Totally submerged shadow casting surface.
3386 :
3387 0 : state.dataSolarShading->NVS = 0;
3388 0 : state.dataSolarShading->NumVertInShadowOrClippedSurface = 0;
3389 :
3390 : } else { // Remove (clip) that portion of the shadow casting surface. which is below the receiving surface
3391 :
3392 758088 : state.dataSolarShading->NVS = NABOVE + 2;
3393 758088 : state.dataSolarShading->NumVertInShadowOrClippedSurface = NABOVE + 2;
3394 758088 : Real64 ZVT_N, ZVT_P(ZVT(1));
3395 758088 : XVT(NVT + 1) = XVT(1);
3396 758088 : YVT(NVT + 1) = YVT(1);
3397 758088 : ZVT(NVT + 1) = ZVT_P;
3398 3753384 : for (int N = 1, P = 2; N <= NVT; ++N, ++P) {
3399 2995296 : ZVT_N = ZVT_P;
3400 2995296 : ZVT_P = ZVT(P);
3401 2995296 : if (ZVT_N >= 0.0 && ZVT_P < 0.0) { // Line enters plane of receiving surface
3402 758088 : Real64 const ZVT_fac(1.0 / (ZVT_P - ZVT_N));
3403 758088 : XIN = (ZVT_P * XVT(N) - ZVT_N * XVT(P)) * ZVT_fac;
3404 758088 : YIN = (ZVT_P * YVT(N) - ZVT_N * YVT(P)) * ZVT_fac;
3405 2995296 : } else if (ZVT_N <= 0.0 && ZVT_P > 0.0) { // Line exits plane of receiving surface
3406 758088 : NEXT = N + 1;
3407 758088 : Real64 const ZVT_fac(1.0 / (ZVT_P - ZVT_N));
3408 758088 : XOUT = (ZVT_P * XVT(N) - ZVT_N * XVT(P)) * ZVT_fac;
3409 758088 : YOUT = (ZVT_P * YVT(N) - ZVT_N * YVT(P)) * ZVT_fac;
3410 : }
3411 : }
3412 :
3413 : // Renumber the vertices of the clipped shadow casting surface. so they are still counter-clockwise sequential.
3414 :
3415 758088 : state.dataSolarShading->XVC(1) = XOUT; //? Verify that the IN and OUT values were ever set?
3416 758088 : state.dataSolarShading->YVC(1) = YOUT;
3417 758088 : state.dataSolarShading->ZVC(1) = 0.0;
3418 758088 : state.dataSolarShading->XVC(state.dataSolarShading->NVS) = XIN;
3419 758088 : state.dataSolarShading->YVC(state.dataSolarShading->NVS) = YIN;
3420 758088 : state.dataSolarShading->ZVC(state.dataSolarShading->NVS) = 0.0;
3421 2215185 : for (int N = 1; N <= NABOVE; ++N) {
3422 1457097 : if (NEXT > NVT) NEXT = 1;
3423 1457097 : state.dataSolarShading->XVC(N + 1) = XVT(NEXT);
3424 1457097 : state.dataSolarShading->YVC(N + 1) = YVT(NEXT);
3425 1457097 : state.dataSolarShading->ZVC(N + 1) = ZVT(NEXT);
3426 1457097 : ++NEXT;
3427 : }
3428 : }
3429 3487318 : }
3430 :
3431 6393685 : void CTRANS(EnergyPlusData &state,
3432 : int const NS, // Surface number whose vertex coordinates are being transformed
3433 : int const NGRS, // Base surface number for surface NS
3434 : int &NVT, // Number of vertices for surface NS
3435 : Array1D<Real64> &XVT, // XYZ coordinates of vertices of NS in plane of NGRS
3436 : Array1D<Real64> &YVT,
3437 : Array1D<Real64> &ZVT)
3438 : {
3439 :
3440 : // SUBROUTINE INFORMATION:
3441 : // AUTHOR Legacy Code
3442 : // DATE WRITTEN
3443 : // MODIFIED na
3444 : // RE-ENGINEERED Lawrie, Oct 2000
3445 :
3446 : // PURPOSE OF THIS SUBROUTINE:
3447 : // Transforms the general coordinates of the vertices
3448 : // of surface NS to coordinates in the plane of the receiving surface NGRS.
3449 : // See subroutine 'CalcCoordinateTransformation' SurfaceGeometry Module.
3450 :
3451 : // REFERENCES:
3452 : // BLAST/IBLAST code, original author George Walton
3453 : // NECAP subroutine 'SHADOW'
3454 :
3455 : Real64 Xdif; // Intermediate Result
3456 : Real64 Ydif; // Intermediate Result
3457 : Real64 Zdif; // Intermediate Result
3458 :
3459 : // Tuned
3460 6393685 : auto const &surface = state.dataSurface->Surface(NS);
3461 6393685 : auto const &base_surface = state.dataSurface->Surface(NGRS);
3462 6393685 : auto const &base_lcsx = base_surface.lcsx;
3463 6393685 : auto const &base_lcsy = base_surface.lcsy;
3464 6393685 : auto const &base_lcsz = base_surface.lcsz;
3465 6393685 : Real64 const base_X0 = state.dataSurface->X0(NGRS);
3466 6393685 : Real64 const base_Y0 = state.dataSurface->Y0(NGRS);
3467 6393685 : Real64 const base_Z0 = state.dataSurface->Z0(NGRS);
3468 :
3469 6393685 : NVT = surface.Sides;
3470 :
3471 : // Perform transformation
3472 31918615 : for (int N = 1; N <= NVT; ++N) {
3473 25524930 : auto const &vertex = surface.Vertex(N);
3474 :
3475 25524930 : Xdif = vertex.x - base_X0;
3476 25524930 : Ydif = vertex.y - base_Y0;
3477 25524930 : Zdif = vertex.z - base_Z0;
3478 :
3479 25524930 : if (std::abs(Xdif) <= 1.E-15) Xdif = 0.0;
3480 25524930 : if (std::abs(Ydif) <= 1.E-15) Ydif = 0.0;
3481 25524930 : if (std::abs(Zdif) <= 1.E-15) Zdif = 0.0;
3482 :
3483 25524930 : XVT(N) = base_lcsx.x * Xdif + base_lcsx.y * Ydif + base_lcsx.z * Zdif;
3484 25524930 : YVT(N) = base_lcsy.x * Xdif + base_lcsy.y * Ydif + base_lcsy.z * Zdif;
3485 25524930 : ZVT(N) = base_lcsz.x * Xdif + base_lcsz.y * Ydif + base_lcsz.z * Zdif;
3486 : }
3487 6393685 : }
3488 :
3489 0 : void HTRANS(EnergyPlusData &state,
3490 : int const I, // Mode selector: 0 - Compute H.C. of sides
3491 : int const NS, // Figure Number
3492 : int const NumVertices // Number of vertices
3493 : )
3494 : {
3495 :
3496 : // SUBROUTINE INFORMATION:
3497 : // AUTHOR Legacy Code
3498 : // DATE WRITTEN
3499 : // MODIFIED na
3500 : // RE-ENGINEERED Lawrie, Oct 2000
3501 :
3502 : // PURPOSE OF THIS SUBROUTINE:
3503 : // This subroutine sets up the homogeneous coordinates.
3504 : // This routine converts the cartesian coordinates of a surface
3505 : // or shadow polygon to homogeneous coordinates. It also
3506 : // computes the area of the polygon.
3507 :
3508 : // METHODOLOGY EMPLOYED:
3509 : // Note: Original legacy code used integer arithmetic (tests in subroutines
3510 : // INCLOS and INTCPT are sensitive to round-off error). However, porting to Fortran 77
3511 : // (BLAST/IBLAST) required some variables to become REAL(r64) instead.
3512 :
3513 : // Notes on homogeneous coordinates:
3514 : // A point (X,Y) is represented by a 3-element vector
3515 : // (W*X,W*Y,W), where W may be any REAL(r64) number except 0. a line
3516 : // is also represented by a 3-element vector (A,B,C). The
3517 : // directed line (A,B,C) from point (W*X1,W*Y1,W) to point
3518 : // (V*X2,V*Y2,V) is given by (A,B,C) = (W*X1,W*Y1,W) cross
3519 : // (V*X2,V*Y2,V). The sequence of the cross product is a
3520 : // convention to determine sign. The condition that a point lie
3521 : // on a line is that (A,B,C) dot (W*X,W*Y,W) = 0. 'Normalize'
3522 : // the representation of a point by setting W to 1. Then if
3523 : // (A,B,C) dot (X,Y,1) > 0.0, The point is to the left of the
3524 : // line, and if it is less than zero, the point is to the right
3525 : // of the line. The intercept of two lines is given by
3526 : // (W*X,W*Y,W) = (A1,B1,C1) cross (A2,B2,C3).
3527 :
3528 : // REFERENCES:
3529 : // BLAST/IBLAST code, original author George Walton
3530 : // W. M. Newman & R. F. Sproull, 'Principles of Interactive Computer Graphics', Appendix II, McGraw-Hill, 1973.
3531 : // 'CRC Math Tables', 22 ED, 'Analytic Geometry', P.369
3532 :
3533 : // Using/Aliasing
3534 :
3535 : // Locals
3536 : // SUBROUTINE ARGUMENT DEFINITIONS:
3537 : // 1 - Compute H.C. of vertices & sides
3538 :
3539 0 : if (NS > 2 * state.dataSolarShading->MaxHCS) {
3540 0 : ShowFatalError(state, format("Solar Shading: HTrans: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
3541 : }
3542 :
3543 0 : state.dataSolarShading->HCNV(NS) = NumVertices;
3544 :
3545 : // Tuned Linear indexing
3546 :
3547 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
3548 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
3549 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
3550 0 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
3551 0 : int const l1(state.dataSolarShading->HCX.index(NS, 1));
3552 0 : if (I != 0) { // Transform vertices of figure ns.
3553 :
3554 : // See comment at top of module regarding HCMULT
3555 0 : int l(l1);
3556 0 : for (int N = 1; N <= NumVertices; ++N, ++l) { // [ l ] == ( NS, N )
3557 0 : state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XVS(N) * HCMULT);
3558 0 : state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YVS(N) * HCMULT);
3559 : }
3560 : }
3561 :
3562 : // Establish extra point for finding lines between points.
3563 :
3564 0 : int l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
3565 0 : Int64 HCX_m = state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]; // [ l ] == ( NS, NumVertices + 1 ), [ l1 ] == ( NS, 1 )
3566 0 : Int64 HCY_m = state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]; // [ l ] == ( NS, NumVertices + 1 ), [ l1 ] == ( NS, 1 )
3567 :
3568 : // Determine lines between points.
3569 0 : l = l1;
3570 0 : int m = l1 + 1u;
3571 : Int64 HCX_l;
3572 : Int64 HCY_l;
3573 0 : Real64 SUM = 0.0; // Sum variable
3574 0 : for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
3575 0 : HCX_l = HCX_m;
3576 0 : HCY_l = HCY_m;
3577 0 : HCX_m = state.dataSolarShading->HCX[m];
3578 0 : HCY_m = state.dataSolarShading->HCY[m];
3579 0 : state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
3580 0 : state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
3581 0 : SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
3582 : }
3583 :
3584 : // Compute area of polygon.
3585 : // SUM=0.0D0
3586 : // DO N = 1, NumVertices
3587 : // 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
3588 : // END DO
3589 0 : state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
3590 : // HCAREA(NS)=0.5d0*SUM*(kHCMULT)
3591 0 : }
3592 :
3593 13282607 : void HTRANS0(EnergyPlusData &state,
3594 : int const NS, // Figure Number
3595 : int const NumVertices // Number of vertices
3596 : )
3597 : {
3598 : // Using/Aliasing
3599 :
3600 : // Locals
3601 :
3602 13282607 : if (NS > 2 * state.dataSolarShading->MaxHCS) {
3603 0 : ShowFatalError(state, format("Solar Shading: HTrans0: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
3604 : }
3605 :
3606 13282607 : state.dataSolarShading->HCNV(NS) = NumVertices;
3607 :
3608 : // Tuned Linear indexing
3609 :
3610 13282607 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
3611 13282607 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
3612 13282607 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
3613 13282607 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
3614 :
3615 13282607 : int const l1 = state.dataSolarShading->HCX.index(NS, 1);
3616 :
3617 13282607 : int l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
3618 13282607 : Int64 HCX_m = state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]; // [ l1 ] == ( NS, 1 )
3619 13282607 : Int64 HCY_m = state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]; // [ l1 ] == ( NS, 1 )
3620 :
3621 13282607 : l = l1;
3622 13282607 : int m = l1 + 1u;
3623 : Int64 HCX_l;
3624 : Int64 HCY_l;
3625 13282607 : Real64 SUM(0.0);
3626 45905889 : for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
3627 32623282 : HCX_l = HCX_m;
3628 32623282 : HCY_l = HCY_m;
3629 32623282 : HCX_m = state.dataSolarShading->HCX[m];
3630 32623282 : HCY_m = state.dataSolarShading->HCY[m];
3631 32623282 : state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
3632 32623282 : state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
3633 32623282 : SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
3634 : }
3635 :
3636 13282607 : state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
3637 13282607 : }
3638 :
3639 7802786 : void HTRANS1(EnergyPlusData &state,
3640 : int const NS, // Figure Number
3641 : int const NumVertices // Number of vertices
3642 : )
3643 : {
3644 : // Using/Aliasing
3645 :
3646 7802786 : if (NS > 2 * state.dataSolarShading->MaxHCS) {
3647 0 : ShowFatalError(state, format("Solar Shading: HTrans1: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
3648 : }
3649 :
3650 7802786 : state.dataSolarShading->HCNV(NS) = NumVertices;
3651 :
3652 : // Tuned Linear indexing
3653 :
3654 7802786 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
3655 7802786 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
3656 7802786 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
3657 7802786 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
3658 :
3659 7802786 : int const l1 = state.dataSolarShading->HCX.index(NS, 1);
3660 :
3661 : // only in HTRANS1
3662 7802786 : int l = l1;
3663 38941745 : for (int N = 1; N <= NumVertices; ++N, ++l) { // [ l ] == ( NS, N )
3664 31138959 : state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XVS(N) * HCMULT);
3665 31138959 : state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YVS(N) * HCMULT);
3666 : }
3667 :
3668 7802786 : l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
3669 7802786 : Int64 HCX_m(state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]); // [ l1 ] == ( NS, 1 )
3670 7802786 : Int64 HCY_m(state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]);
3671 :
3672 7802786 : l = l1;
3673 7802786 : int m = l1 + 1u;
3674 : Int64 HCX_l;
3675 : Int64 HCY_l;
3676 7802786 : Real64 SUM = 0.0;
3677 38941745 : for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
3678 31138959 : HCX_l = HCX_m;
3679 31138959 : HCY_l = HCY_m;
3680 31138959 : HCX_m = state.dataSolarShading->HCX[m];
3681 31138959 : HCY_m = state.dataSolarShading->HCY[m];
3682 31138959 : state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
3683 31138959 : state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
3684 31138959 : SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
3685 : }
3686 :
3687 7802786 : state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
3688 7802786 : }
3689 :
3690 0 : void INCLOS(EnergyPlusData &state,
3691 : int const N1, // Figure number of figure 1
3692 : int const N1NumVert, // Number of vertices of figure 1
3693 : int const N2, // Figure number of figure 2
3694 : int const N2NumVert, // Number of vertices of figure 2
3695 : int &NumVerticesOverlap, // Number of vertices which overlap
3696 : int &NIN // Number of vertices of figure 1 within figure 2
3697 : )
3698 : {
3699 :
3700 : // SUBROUTINE INFORMATION:
3701 : // AUTHOR Legacy Code
3702 : // DATE WRITTEN
3703 : // MODIFIED na
3704 : // RE-ENGINEERED Lawrie, Oct 2000
3705 :
3706 : // PURPOSE OF THIS SUBROUTINE:
3707 : // This subroutine determines which vertices of figure N1 lie within figure N2.
3708 :
3709 : // METHODOLOGY EMPLOYED:
3710 : // For vertex N of figure N1 to lie within figure N2, it must be
3711 : // on or to the right of all sides of figure N2, assuming
3712 : // figure N2 is convex.
3713 :
3714 : // REFERENCES:
3715 : // BLAST/IBLAST code, original author George Walton
3716 :
3717 : int K; // Vertex number of the overlap
3718 : int M; // Side number of figure N2
3719 : int N; // Vertex number of figure N1
3720 : bool CycleMainLoop; // Sets when to cycle main loop
3721 : Real64 HFunct;
3722 :
3723 0 : NIN = 0;
3724 :
3725 0 : for (N = 1; N <= N1NumVert; ++N) {
3726 :
3727 0 : CycleMainLoop = false;
3728 :
3729 : // Eliminate cases where vertex N is to the left of side M.
3730 :
3731 0 : for (M = 1; M <= N2NumVert; ++M) {
3732 0 : HFunct = state.dataSolarShading->HCX(N1, N) * state.dataSolarShading->HCA(N2, M) +
3733 0 : state.dataSolarShading->HCY(N1, N) * state.dataSolarShading->HCB(N2, M) + state.dataSolarShading->HCC(N2, M);
3734 0 : if (HFunct > 0.0) {
3735 0 : CycleMainLoop = true; // Set to cycle to the next value of N
3736 0 : break; // M DO loop
3737 : }
3738 : }
3739 :
3740 0 : if (CycleMainLoop) continue;
3741 0 : ++NIN;
3742 :
3743 : // Check for duplication of previously determined points.
3744 :
3745 0 : if (NumVerticesOverlap != 0) {
3746 0 : for (K = 1; K <= NumVerticesOverlap; ++K) {
3747 0 : if ((state.dataSolarShading->XTEMP(K) == state.dataSolarShading->HCX(N1, N)) &&
3748 0 : (state.dataSolarShading->YTEMP(K) == state.dataSolarShading->HCY(N1, N))) {
3749 0 : CycleMainLoop = true; // Set to cycle to the next value of N
3750 0 : break; // K DO loop
3751 : }
3752 : }
3753 0 : if (CycleMainLoop) continue;
3754 : }
3755 :
3756 : // Record enclosed vertices in temporary arrays.
3757 :
3758 0 : ++NumVerticesOverlap;
3759 0 : state.dataSolarShading->XTEMP(NumVerticesOverlap) = state.dataSolarShading->HCX(N1, N);
3760 0 : state.dataSolarShading->YTEMP(NumVerticesOverlap) = state.dataSolarShading->HCY(N1, N);
3761 : }
3762 0 : }
3763 :
3764 0 : void INTCPT(EnergyPlusData &state,
3765 : int const NV1, // Number of vertices of figure NS1
3766 : int const NV2, // Number of vertices of figure NS2
3767 : int &NV3, // Number of vertices of figure NS3
3768 : int const NS1, // Number of the figure being overlapped
3769 : int const NS2 // Number of the figure doing overlapping
3770 : )
3771 : {
3772 :
3773 : // SUBROUTINE INFORMATION:
3774 : // AUTHOR Legacy Code
3775 : // DATE WRITTEN
3776 : // MODIFIED na
3777 : // RE-ENGINEERED Lawrie, Oct 2000
3778 :
3779 : // PURPOSE OF THIS SUBROUTINE:
3780 : // This subroutine determines all intercepts between the sides of figure NS1
3781 : // and the sides of figure NS2.
3782 :
3783 : // METHODOLOGY EMPLOYED:
3784 : // The requirements for intersection are that the end points of
3785 : // line N lie on both sides of line M and vice versa. Also
3786 : // eliminate cases where the end point of one line lies exactly
3787 : // on the other to reduce duplication with the enclosed points.
3788 :
3789 : // REFERENCES:
3790 : // BLAST/IBLAST code, original author George Walton
3791 :
3792 : Real64 W; // Normalization factor
3793 : Real64 XUntrunc; // Untruncated X coordinate
3794 : Real64 YUntrunc; // Untruncated Y coordinate
3795 : Int64 I1; // Intermediate result for testing intersection
3796 : Int64 I2; // Intermediate result for testing intersection
3797 : int K;
3798 : int KK;
3799 : int M; // Side number of figure NS2
3800 : int N; // Side number of figure NS1
3801 :
3802 0 : for (N = 1; N <= NV1; ++N) {
3803 0 : for (M = 1; M <= NV2; ++M) {
3804 :
3805 : // Eliminate cases where sides N and M do not intersect.
3806 :
3807 0 : I1 = state.dataSolarShading->HCA(NS1, N) * state.dataSolarShading->HCX(NS2, M) +
3808 0 : state.dataSolarShading->HCB(NS1, N) * state.dataSolarShading->HCY(NS2, M) + state.dataSolarShading->HCC(NS1, N);
3809 0 : I2 = state.dataSolarShading->HCA(NS1, N) * state.dataSolarShading->HCX(NS2, M + 1) +
3810 0 : state.dataSolarShading->HCB(NS1, N) * state.dataSolarShading->HCY(NS2, M + 1) + state.dataSolarShading->HCC(NS1, N);
3811 0 : if (I1 >= 0 && I2 >= 0) continue;
3812 0 : if (I1 <= 0 && I2 <= 0) continue;
3813 :
3814 0 : I1 = state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCX(NS1, N) +
3815 0 : state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCY(NS1, N) + state.dataSolarShading->HCC(NS2, M);
3816 0 : I2 = state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCX(NS1, N + 1) +
3817 0 : state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCY(NS1, N + 1) + state.dataSolarShading->HCC(NS2, M);
3818 0 : if (I1 >= 0 && I2 >= 0) continue;
3819 0 : if (I1 <= 0 && I2 <= 0) continue;
3820 :
3821 : // Determine the point of intersection and record in the temporary array.
3822 :
3823 0 : KK = NV3;
3824 0 : ++NV3;
3825 0 : W = state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCA(NS1, N) -
3826 0 : state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCB(NS1, N);
3827 0 : XUntrunc = (state.dataSolarShading->HCC(NS2, M) * state.dataSolarShading->HCB(NS1, N) -
3828 0 : state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCC(NS1, N)) /
3829 : W;
3830 0 : YUntrunc = (state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCC(NS1, N) -
3831 0 : state.dataSolarShading->HCC(NS2, M) * state.dataSolarShading->HCA(NS1, N)) /
3832 : W;
3833 0 : if (NV3 > isize(state.dataSolarShading->XTEMP)) {
3834 0 : state.dataSolarShading->XTEMP.redimension(isize(state.dataSolarShading->XTEMP) + 10, 0.0);
3835 0 : state.dataSolarShading->YTEMP.redimension(isize(state.dataSolarShading->YTEMP) + 10, 0.0);
3836 : }
3837 0 : state.dataSolarShading->XTEMP(NV3) = nint64(XUntrunc);
3838 0 : state.dataSolarShading->YTEMP(NV3) = nint64(YUntrunc);
3839 :
3840 : // Eliminate near-duplicate points.
3841 :
3842 0 : if (KK != 0) {
3843 0 : Real64 const x(state.dataSolarShading->XTEMP(NV3));
3844 0 : Real64 const y(state.dataSolarShading->YTEMP(NV3));
3845 0 : for (K = 1; K <= KK; ++K) {
3846 0 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
3847 0 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
3848 0 : NV3 = KK;
3849 0 : break; // K DO loop
3850 : }
3851 : }
3852 : }
3853 : }
3854 0 : }
3855 :
3856 0 : inline bool neq(Real64 a, Real64 b)
3857 : {
3858 0 : return std::abs(a - b) > 2.0;
3859 : }
3860 :
3861 0 : inline bool d_eq(Real64 a, Real64 b)
3862 : {
3863 0 : return std::abs(a - b) < 2.0;
3864 : }
3865 :
3866 0 : void CLIPLINE(Real64 &x0, Real64 &x1, Real64 &y0, Real64 &y1, Real64 maxX, Real64 minX, Real64 maxY, Real64 minY, bool &visible)
3867 : {
3868 :
3869 : // Line segment clipping
3870 : // Reference:
3871 : // Liang, Y.D., Barsky, B.A., Slater, M.
3872 : // 2D line and polygon clipping based on space subdivision.
3873 : // The Visual Computer 10, 407–422 (1994).
3874 :
3875 : // Tweaked via microbenchmarking to improve efficiency
3876 :
3877 0 : bool rev = false;
3878 0 : if (x0 > x1) { // reverse for efficiency
3879 0 : std::swap(x0, x1);
3880 0 : std::swap(y0, y1);
3881 0 : rev = true;
3882 : }
3883 :
3884 0 : if (x0 > maxX || x1 < minX) {
3885 : // Both points are outside the clip window, so they can't cross it
3886 0 : return;
3887 : }
3888 :
3889 : // defining variables
3890 0 : Real64 const dx = x1 - x0; // >= 0
3891 0 : Real64 const dy = y1 - y0;
3892 :
3893 0 : Real64 const q1 = x0 - minX;
3894 0 : Real64 const q2 = maxX - x0;
3895 0 : Real64 const q3 = y0 - minY;
3896 0 : Real64 const q4 = maxY - y0;
3897 :
3898 0 : Real64 u1 = 0;
3899 0 : Real64 u2 = 1;
3900 :
3901 0 : if ((dx == 0 && (q1 < 0 || q2 < 0)) || (dy == 0 && (q3 < 0 || q4 < 0))) {
3902 : // Line is parallel to clipping window
3903 0 : return;
3904 : }
3905 0 : if (dx != 0) {
3906 0 : Real64 const r1 = q1 / -dx;
3907 0 : if (r1 > u1) {
3908 0 : u1 = r1;
3909 : }
3910 0 : Real64 const r2 = q2 / dx;
3911 0 : if (r2 < u2) {
3912 0 : u2 = r2;
3913 : }
3914 : }
3915 0 : if (dy != 0) {
3916 0 : Real64 const r3 = q3 / -dy;
3917 0 : Real64 const r4 = q4 / dy;
3918 0 : if (dy > 0) {
3919 0 : if (r3 > u1) {
3920 0 : u1 = r3;
3921 : }
3922 0 : if (r4 < u2) {
3923 0 : u2 = r4;
3924 : }
3925 : } else {
3926 0 : if (r4 > u1) {
3927 0 : u1 = r4;
3928 : }
3929 0 : if (r3 < u2) {
3930 0 : u2 = r3;
3931 : }
3932 : }
3933 : }
3934 :
3935 0 : if (u1 > u2) { // reject
3936 : // Line is outside the clipping window
3937 0 : return;
3938 : }
3939 :
3940 0 : visible = true;
3941 :
3942 0 : Real64 const xn0 = x0 + dx * u1;
3943 0 : Real64 const yn0 = y0 + dy * u1;
3944 :
3945 0 : Real64 const xn1 = x0 + dx * u2;
3946 0 : Real64 const yn1 = y0 + dy * u2;
3947 :
3948 0 : if (rev) {
3949 0 : x0 = xn1;
3950 0 : y0 = yn1;
3951 0 : x1 = xn0;
3952 0 : y1 = yn0;
3953 : } else {
3954 0 : x0 = xn0;
3955 0 : y0 = yn0;
3956 0 : x1 = xn1;
3957 0 : y1 = yn1;
3958 : }
3959 : }
3960 :
3961 0 : void CLIPRECT(EnergyPlusData &state, int const NS2, int const NV1, int &NV3)
3962 : {
3963 : // Polygon clipping by line segment clipping for rectangles
3964 : // Reference:
3965 : // Slater, M., Barsky, B.A.
3966 : // 2D line and polygon clipping based on space subdivision.
3967 : // The Visual Computer 10, 407–422 (1994).
3968 0 : bool INTFLAG = false;
3969 0 : int l = state.dataSolarShading->HCA.index(NS2, 1);
3970 : Real64 maxX, minX, maxY, minY;
3971 0 : if (state.dataSolarShading->HCX[l] > state.dataSolarShading->HCX[l + 2]) {
3972 0 : maxX = state.dataSolarShading->HCX[l];
3973 0 : minX = state.dataSolarShading->HCX[l + 2];
3974 : } else {
3975 0 : maxX = state.dataSolarShading->HCX[l + 2];
3976 0 : minX = state.dataSolarShading->HCX[l];
3977 : }
3978 0 : if (state.dataSolarShading->HCY[l] > state.dataSolarShading->HCY[l + 2]) {
3979 0 : maxY = state.dataSolarShading->HCY[l];
3980 0 : minY = state.dataSolarShading->HCY[l + 2];
3981 : } else {
3982 0 : maxY = state.dataSolarShading->HCY[l + 2];
3983 0 : minY = state.dataSolarShading->HCY[l];
3984 : }
3985 :
3986 : Real64 arrx[20]; // Temp array for output X
3987 : Real64 arry[20]; // Temp array for output Y
3988 0 : int arrc = 0; // Number of items in output
3989 :
3990 0 : for (int j = 0; j < NV1; ++j) {
3991 0 : Real64 x_1 = state.dataSolarShading->XTEMP[j];
3992 0 : Real64 y_1 = state.dataSolarShading->YTEMP[j];
3993 0 : Real64 x_2 = state.dataSolarShading->XTEMP[(j + 1) % NV1];
3994 0 : Real64 y_2 = state.dataSolarShading->YTEMP[(j + 1) % NV1];
3995 0 : Real64 x1 = x_1, x2 = x_2, y1 = y_1, y2 = y_2;
3996 :
3997 0 : bool visible = false;
3998 0 : CLIPLINE(x_1, x_2, y_1, y_2, maxX, minX, maxY, minY, visible);
3999 0 : if (visible) {
4000 0 : if ((x_1 != x1 || y_1 != y1) || (x_2 != x2 || y_2 != y2)) {
4001 0 : INTFLAG = true;
4002 : }
4003 : // if line on edge, or inside, add both points
4004 0 : 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)))) {
4005 0 : arrx[arrc] = x_1;
4006 0 : arry[arrc] = y_1;
4007 0 : arrc += 1;
4008 0 : if ((neq(x_1, x_2) || neq(y_1, y_2)) && (neq(arrx[0], x_2) || neq(arry[0], y_2))) {
4009 0 : arrx[arrc] = x_2;
4010 0 : arry[arrc] = y_2;
4011 0 : arrc += 1;
4012 : }
4013 0 : } else if ((neq(arrx[arrc - 1], x_2) || neq(arry[arrc - 1], y_2)) && (neq(arrx[0], x_2) || neq(arry[0], y_2))) {
4014 0 : arrx[arrc] = x_2;
4015 0 : arry[arrc] = y_2;
4016 0 : arrc += 1;
4017 : }
4018 : }
4019 : }
4020 0 : NV3 = arrc;
4021 :
4022 : // Re-populate XTEMP/YTEMP
4023 0 : if (NV3 > 1) {
4024 0 : int LastEdgeIndex = -1, incr = 0;
4025 0 : double cornerXs[4] = {minX, minX, maxX, maxX};
4026 0 : double cornerYs[4] = {minY, maxY, maxY, minY};
4027 0 : Real64 edges[4] = {minX, maxY, maxX, minY};
4028 : Real64 LastEdgeX, LastEdgeY;
4029 0 : for (int i = 0; i <= arrc; i++) {
4030 0 : int k = i % arrc;
4031 :
4032 0 : Real64 currX = arrx[k], currY = arry[k];
4033 :
4034 0 : int edgeCount = 0, EdgeIndex = -1;
4035 0 : for (int m = 0; m < 4; m++) {
4036 0 : if (m % 2 == 0 && d_eq(currX, edges[m])) { // MinX or MaxX
4037 0 : edgeCount++;
4038 0 : EdgeIndex = m;
4039 0 : } else if (m % 2 == 1 && d_eq(currY, edges[m])) {
4040 0 : edgeCount++;
4041 0 : EdgeIndex = m;
4042 : }
4043 : }
4044 0 : if (edgeCount == 0) { // On inside
4045 0 : if (i != arrc) {
4046 0 : state.dataSolarShading->XTEMP[incr] = currX;
4047 0 : state.dataSolarShading->YTEMP[incr] = currY;
4048 0 : incr++;
4049 : }
4050 0 : continue;
4051 0 : } else if (edgeCount > 1) { // On corner
4052 0 : if (d_eq(currX, minX)) {
4053 0 : if (d_eq(currY, minY)) {
4054 0 : EdgeIndex = 3;
4055 : } else {
4056 0 : EdgeIndex = 0;
4057 : }
4058 : } else {
4059 0 : if (d_eq(currY, maxY)) {
4060 0 : EdgeIndex = 1;
4061 : } else {
4062 0 : EdgeIndex = 2;
4063 : }
4064 : }
4065 : }
4066 0 : if ((LastEdgeIndex > -1 && EdgeIndex > -1) && LastEdgeIndex != EdgeIndex) {
4067 0 : int jumpCount = 0;
4068 0 : if ((EdgeIndex == 0 && LastEdgeIndex == 3) || (EdgeIndex - LastEdgeIndex == 1)) {
4069 0 : jumpCount = 1;
4070 0 : } else if (EdgeIndex % 2 == LastEdgeIndex % 2) {
4071 : // Clockwise double jump
4072 0 : jumpCount = 2;
4073 0 : } else if ((EdgeIndex == 3 && LastEdgeIndex == 0) || (LastEdgeIndex - EdgeIndex == 1)) {
4074 : // Clockwise triple jump
4075 0 : jumpCount = 3;
4076 : }
4077 0 : if (jumpCount > 0) {
4078 : Real64 cornerX;
4079 : Real64 cornerY;
4080 0 : int startIndex = (LastEdgeIndex + 1) % 4;
4081 0 : int added = 0;
4082 0 : for (int i1 = startIndex, j1 = 0; j1 < jumpCount; i1 = (i1 + 1) % 4, j1++) {
4083 0 : cornerX = cornerXs[i1];
4084 0 : cornerY = cornerYs[i1];
4085 0 : if (cornerX == LastEdgeX && cornerY == LastEdgeY) continue; // skip if jump started on corner
4086 :
4087 0 : bool insideFlag = true;
4088 0 : for (int j = 0; j < NV1; ++j) {
4089 0 : if ((state.dataSolarShading->ATEMP[j] * cornerX) + (cornerY * state.dataSolarShading->BTEMP[j]) +
4090 0 : state.dataSolarShading->CTEMP[j] >
4091 : 0.0) {
4092 0 : insideFlag = false;
4093 0 : break;
4094 : }
4095 : }
4096 :
4097 0 : if (insideFlag &&
4098 0 : (incr == 0 ||
4099 0 : ((neq(cornerX, state.dataSolarShading->XTEMP[incr - 1]) || neq(cornerY, state.dataSolarShading->YTEMP[incr - 1])) &&
4100 0 : (neq(cornerX, state.dataSolarShading->XTEMP[0]) || neq(cornerY, state.dataSolarShading->YTEMP[0]))))) {
4101 0 : state.dataSolarShading->XTEMP[incr] = cornerX;
4102 0 : state.dataSolarShading->YTEMP[incr] = cornerY;
4103 0 : incr++;
4104 0 : added++;
4105 : }
4106 : }
4107 0 : if (jumpCount > 2 && (added == jumpCount && edgeCount == 1)) {
4108 0 : if (i != arrc) {
4109 0 : state.dataSolarShading->XTEMP[incr] = currX;
4110 0 : state.dataSolarShading->YTEMP[incr] = currY;
4111 0 : incr++;
4112 : }
4113 0 : break;
4114 : }
4115 : }
4116 : }
4117 0 : if (i != arrc) {
4118 0 : state.dataSolarShading->XTEMP[incr] = currX;
4119 0 : state.dataSolarShading->YTEMP[incr] = currY;
4120 0 : incr++;
4121 : }
4122 0 : LastEdgeIndex = EdgeIndex;
4123 0 : LastEdgeX = currX;
4124 0 : LastEdgeY = currY;
4125 : }
4126 0 : NV3 = incr;
4127 :
4128 : } else {
4129 0 : if (NV3 == 1) {
4130 0 : state.dataSolarShading->XTEMP[0] = arrx[0];
4131 0 : state.dataSolarShading->YTEMP[0] = arry[0];
4132 : }
4133 0 : if (NV3 == 0) {
4134 0 : double cornerXs[4] = {minX, minX, maxX, maxX};
4135 0 : double cornerYs[4] = {minY, maxY, maxY, minY};
4136 0 : Real64 cornerX = cornerXs[0];
4137 0 : Real64 cornerY = cornerYs[0];
4138 0 : bool insideFlag = true;
4139 0 : for (int j = 0; j < NV1; ++j) {
4140 0 : if ((state.dataSolarShading->ATEMP[j] * cornerX) + (cornerY * state.dataSolarShading->BTEMP[j]) + state.dataSolarShading->CTEMP[j] >=
4141 : 0.0) {
4142 0 : insideFlag = false;
4143 0 : break;
4144 : }
4145 : }
4146 0 : if (insideFlag) {
4147 0 : for (int i1 = 0; i1 < 4; i1++) {
4148 0 : state.dataSolarShading->XTEMP[i1] = cornerXs[i1];
4149 0 : state.dataSolarShading->YTEMP[i1] = cornerYs[i1];
4150 : }
4151 0 : NV3 = 4;
4152 0 : INTFLAG = true;
4153 : }
4154 : }
4155 : }
4156 :
4157 : // update homogenous edges A,B,C
4158 0 : if (NV3 > 0) {
4159 0 : Real64 const X_0(state.dataSolarShading->XTEMP[0]);
4160 0 : Real64 const Y_0(state.dataSolarShading->YTEMP[0]);
4161 0 : Real64 XP_0 = X_0, XP_1;
4162 0 : Real64 YP_0 = Y_0, YP_1;
4163 0 : for (int P = 0; P < NV3 - 1; ++P) {
4164 0 : XP_1 = state.dataSolarShading->XTEMP[P + 1];
4165 0 : YP_1 = state.dataSolarShading->YTEMP[P + 1];
4166 :
4167 0 : state.dataSolarShading->ATEMP[P] = YP_0 - YP_1;
4168 0 : state.dataSolarShading->BTEMP[P] = XP_1 - XP_0;
4169 0 : state.dataSolarShading->CTEMP[P] = XP_0 * YP_1 - YP_0 * XP_1;
4170 0 : XP_0 = XP_1;
4171 0 : YP_0 = YP_1;
4172 : }
4173 :
4174 0 : state.dataSolarShading->ATEMP[NV3 - 1] = YP_1 - Y_0;
4175 0 : state.dataSolarShading->BTEMP[NV3 - 1] = X_0 - XP_1;
4176 0 : state.dataSolarShading->CTEMP[NV3 - 1] = XP_1 * Y_0 - YP_1 * X_0;
4177 : }
4178 :
4179 : // Determine overlap status
4180 0 : if (NV3 < 3) { // Determine overlap status
4181 0 : state.dataSolarShading->OverlapStatus = NoOverlap;
4182 0 : } else if (!INTFLAG) {
4183 0 : state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
4184 : }
4185 0 : }
4186 :
4187 8293466 : void CLIPPOLY(EnergyPlusData &state,
4188 : int const NS1, // Figure number of figure 1 (The subject polygon)
4189 : int const NS2, // Figure number of figure 2 (The clipping polygon)
4190 : int const NV1, // Number of vertices of figure 1
4191 : int const NV2, // Number of vertices of figure 2
4192 : int &NV3 // Number of vertices of figure 3
4193 : )
4194 : {
4195 :
4196 : // SUBROUTINE INFORMATION:
4197 : // AUTHOR Tyler Hoyt
4198 : // DATE WRITTEN May 4, 2010
4199 : // MODIFIED na
4200 : // RE-ENGINEERED na
4201 :
4202 : // PURPOSE OF THIS SUBROUTINE:
4203 : // Populate global arrays XTEMP and YTEMP with the vertices
4204 : // of the overlap between NS1 and NS2, and determine relevant
4205 : // overlap status.
4206 :
4207 : // METHODOLOGY EMPLOYED:
4208 : // The Sutherland-Hodgman algorithm for polygon clipping is employed.
4209 :
4210 : using General::SafeDivide;
4211 :
4212 : typedef Array2D<Int64>::size_type size_type;
4213 : bool INTFLAG; // For overlap status
4214 : int S; // Test vertex
4215 : int KK; // Duplicate test index
4216 : int NVOUT; // Current output length for loops
4217 : int NVTEMP;
4218 :
4219 : Real64 W; // Normalization factor
4220 : Real64 HFunct;
4221 :
4222 : #ifdef EP_Count_Calls
4223 : ++state.dataTimingsData->NumClipPoly_Calls;
4224 : #endif
4225 : // Tuned Linear indexing
4226 :
4227 8293466 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
4228 8293466 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
4229 8293466 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
4230 8293466 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
4231 :
4232 : // Populate the arrays with the original polygon
4233 41333094 : for (size_type j = 0, l = state.dataSolarShading->HCX.index(NS1, 1), e = NV1; j < e; ++j, ++l) {
4234 33039628 : state.dataSolarShading->XTEMP[j] = state.dataSolarShading->HCX[l]; // [ l ] == ( NS1, j+1 )
4235 33039628 : state.dataSolarShading->YTEMP[j] = state.dataSolarShading->HCY[l];
4236 33039628 : state.dataSolarShading->ATEMP[j] = state.dataSolarShading->HCA[l];
4237 33039628 : state.dataSolarShading->BTEMP[j] = state.dataSolarShading->HCB[l];
4238 33039628 : state.dataSolarShading->CTEMP[j] = state.dataSolarShading->HCC[l];
4239 : }
4240 :
4241 8293466 : NVOUT = NV1; // First point-loop is the length of the subject polygon.
4242 8293466 : INTFLAG = false;
4243 8293466 : NVTEMP = 0;
4244 8293466 : KK = 0;
4245 :
4246 : // Check if clipping polygon is rectangle
4247 8293466 : if (state.dataSysVars->SlaterBarsky) {
4248 0 : int l1 = state.dataSolarShading->HCA.index(NS2, 1);
4249 0 : bool rectFlag = ((NV2 == 4) && (((((state.dataSolarShading->HCX[l1] == state.dataSolarShading->HCX[l1 + 1] &&
4250 0 : state.dataSolarShading->HCY[l1] != state.dataSolarShading->HCY[l1 + 1]) &&
4251 0 : ((state.dataSolarShading->HCY[l1 + 2] == state.dataSolarShading->HCY[l1 + 1] &&
4252 0 : state.dataSolarShading->HCY[l1 + 3] == state.dataSolarShading->HCY[l1]))) &&
4253 0 : state.dataSolarShading->HCX[l1 + 2] == state.dataSolarShading->HCX[l1 + 3]) ||
4254 0 : ((((state.dataSolarShading->HCY[l1] == state.dataSolarShading->HCY[l1 + 1] &&
4255 0 : state.dataSolarShading->HCX[l1] != state.dataSolarShading->HCX[l1 + 1]) &&
4256 0 : (state.dataSolarShading->HCX[l1 + 2] == state.dataSolarShading->HCX[l1 + 1] &&
4257 0 : state.dataSolarShading->HCX[l1 + 3] == state.dataSolarShading->HCX[l1])) &&
4258 0 : (state.dataSolarShading->HCY[l1 + 2] == state.dataSolarShading->HCY[l1 + 3]))))));
4259 0 : if (rectFlag) {
4260 0 : CLIPRECT(state, NS2, NV1, NV3);
4261 0 : return;
4262 : }
4263 : }
4264 :
4265 8293466 : int l = state.dataSolarShading->HCA.index(NS2, 1);
4266 26808757 : for (int E = 1; E <= NV2; ++E, ++l) { // Loop over edges of the clipping polygon
4267 118143909 : for (int P = 1; P <= NVOUT; ++P) {
4268 94697701 : state.dataSolarShading->XTEMP1(P) = state.dataSolarShading->XTEMP(P);
4269 94697701 : state.dataSolarShading->YTEMP1(P) = state.dataSolarShading->YTEMP(P);
4270 : }
4271 23446208 : S = NVOUT;
4272 23446208 : Real64 const HCA_E(state.dataSolarShading->HCA[l]);
4273 23446208 : Real64 const HCB_E(state.dataSolarShading->HCB[l]);
4274 23446208 : Real64 const HCC_E(state.dataSolarShading->HCC[l]);
4275 23446208 : Real64 XTEMP1_S(state.dataSolarShading->XTEMP1(S));
4276 23446208 : Real64 YTEMP1_S(state.dataSolarShading->YTEMP1(S));
4277 118143909 : for (int P = 1; P <= NVOUT; ++P) {
4278 94697701 : Real64 const XTEMP1_P(state.dataSolarShading->XTEMP1(P));
4279 94697701 : Real64 const YTEMP1_P(state.dataSolarShading->YTEMP1(P));
4280 94697701 : HFunct = XTEMP1_P * HCA_E + YTEMP1_P * HCB_E + HCC_E;
4281 : // S is constant within this block
4282 94697701 : if (HFunct <= 0.0) { // Vertex is not in the clipping plane
4283 62461914 : HFunct = XTEMP1_S * HCA_E + YTEMP1_S * HCB_E + HCC_E;
4284 62461914 : if (HFunct > 0.0) { // Test vertex is in the clipping plane
4285 :
4286 : // Find/store the intersection of the clip edge and the line connecting S and P
4287 6675171 : KK = NVTEMP;
4288 6675171 : ++NVTEMP;
4289 6675171 : Real64 const ATEMP_S(state.dataSolarShading->ATEMP(S));
4290 6675171 : Real64 const BTEMP_S(state.dataSolarShading->BTEMP(S));
4291 6675171 : Real64 const CTEMP_S(state.dataSolarShading->CTEMP(S));
4292 6675171 : W = HCB_E * ATEMP_S - HCA_E * BTEMP_S;
4293 6675171 : if (W != 0.0) {
4294 6675171 : Real64 const W_inv(1.0 / W);
4295 6675171 : state.dataSolarShading->XTEMP(NVTEMP) = nint64((HCC_E * BTEMP_S - HCB_E * CTEMP_S) * W_inv);
4296 6675171 : state.dataSolarShading->YTEMP(NVTEMP) = nint64((HCA_E * CTEMP_S - HCC_E * ATEMP_S) * W_inv);
4297 : } else {
4298 0 : state.dataSolarShading->XTEMP(NVTEMP) = SafeDivide(HCC_E * BTEMP_S - HCB_E * CTEMP_S, W);
4299 0 : state.dataSolarShading->YTEMP(NVTEMP) = SafeDivide(HCA_E * CTEMP_S - HCC_E * ATEMP_S, W);
4300 : }
4301 6675171 : INTFLAG = true;
4302 :
4303 6675171 : if (E == NV2) { // Remove near-duplicates on last edge
4304 1335227 : if (KK != 0) {
4305 519913 : Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
4306 519913 : Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
4307 1282522 : for (int K = 1; K <= KK; ++K) {
4308 765553 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
4309 41510 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
4310 2944 : NVTEMP = KK;
4311 2944 : break; // K loop
4312 : }
4313 : }
4314 : }
4315 : }
4316 :
4317 62461914 : KK = NVTEMP;
4318 62461914 : ++NVTEMP;
4319 62461914 : if (NVTEMP > state.dataSolarShading->MAXHCArrayBounds) {
4320 0 : int const NewArrayBounds(state.dataSolarShading->MAXHCArrayBounds + state.dataSolarShading->MAXHCArrayIncrement);
4321 0 : state.dataSolarShading->XTEMP.redimension(NewArrayBounds, 0.0);
4322 0 : state.dataSolarShading->YTEMP.redimension(NewArrayBounds, 0.0);
4323 0 : state.dataSolarShading->XTEMP1.redimension(NewArrayBounds, 0.0);
4324 0 : state.dataSolarShading->YTEMP1.redimension(NewArrayBounds, 0.0);
4325 0 : state.dataSolarShading->ATEMP.redimension(NewArrayBounds, 0.0);
4326 0 : state.dataSolarShading->BTEMP.redimension(NewArrayBounds, 0.0);
4327 0 : state.dataSolarShading->CTEMP.redimension(NewArrayBounds, 0.0);
4328 0 : state.dataSolarShading->MAXHCArrayBounds = NewArrayBounds;
4329 : }
4330 :
4331 62461914 : state.dataSolarShading->XTEMP(NVTEMP) = XTEMP1_P;
4332 62461914 : state.dataSolarShading->YTEMP(NVTEMP) = YTEMP1_P;
4333 :
4334 62461914 : if (E == NV2) { // Remove near-duplicates on last edge
4335 11483729 : if (KK != 0) {
4336 9246592 : Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
4337 9246592 : Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
4338 26400172 : for (int K = 1; K <= KK; ++K) {
4339 18487040 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
4340 5393454 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
4341 1333460 : NVTEMP = KK;
4342 1333460 : break; // K loop
4343 : }
4344 : }
4345 : }
4346 :
4347 : } else {
4348 32235787 : HFunct = XTEMP1_S * HCA_E + YTEMP1_S * HCB_E + HCC_E;
4349 32235787 : if (HFunct <= 0.0) { // Test vertex is not in the clipping plane
4350 6675171 : if (NVTEMP < 2 * (state.dataSurface->MaxVerticesPerSurface + 1)) { // avoid assigning to element outside of XTEMP array size
4351 6675171 : KK = NVTEMP;
4352 6675171 : ++NVTEMP;
4353 6675171 : Real64 const ATEMP_S(state.dataSolarShading->ATEMP(S));
4354 6675171 : Real64 const BTEMP_S(state.dataSolarShading->BTEMP(S));
4355 6675171 : Real64 const CTEMP_S(state.dataSolarShading->CTEMP(S));
4356 6675171 : W = HCB_E * ATEMP_S - HCA_E * BTEMP_S;
4357 6675171 : if (W != 0.0) {
4358 6675171 : Real64 const W_inv(1.0 / W);
4359 6675171 : state.dataSolarShading->XTEMP(NVTEMP) = nint64((HCC_E * BTEMP_S - HCB_E * CTEMP_S) * W_inv);
4360 6675171 : state.dataSolarShading->YTEMP(NVTEMP) = nint64((HCA_E * CTEMP_S - HCC_E * ATEMP_S) * W_inv);
4361 : } else {
4362 0 : state.dataSolarShading->XTEMP(NVTEMP) = SafeDivide(HCC_E * BTEMP_S - HCB_E * CTEMP_S, W);
4363 0 : state.dataSolarShading->YTEMP(NVTEMP) = SafeDivide(HCA_E * CTEMP_S - HCC_E * ATEMP_S, W);
4364 : }
4365 6675171 : INTFLAG = true;
4366 :
4367 6675171 : if (E == NV2) { // Remove near-duplicates on last edge
4368 1335227 : if (KK != 0) {
4369 1025129 : Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
4370 1025129 : Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
4371 3560475 : for (int K = 1; K <= KK; ++K) {
4372 2628572 : if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
4373 489784 : if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
4374 93226 : NVTEMP = KK;
4375 93226 : break; // K loop
4376 : }
4377 : }
4378 : }
4379 : }
4380 : }
4381 : }
4382 94697701 : S = P;
4383 94697701 : XTEMP1_S = XTEMP1_P;
4384 94697701 : YTEMP1_S = YTEMP1_P;
4385 : } // end loop over points of subject polygon
4386 :
4387 23446208 : NVOUT = NVTEMP;
4388 23446208 : if (NVOUT == 0) break; // Added to avoid array bounds violation of XTEMP1 and YTEMP1 and wasted looping
4389 18515291 : NVTEMP = 0;
4390 :
4391 18515291 : if (E != NV2) {
4392 15152742 : if (NVOUT > 2) { // Compute HC values for edges of output polygon
4393 15152742 : Real64 const X_1(state.dataSolarShading->XTEMP(1));
4394 15152742 : Real64 const Y_1(state.dataSolarShading->YTEMP(1));
4395 15152742 : Real64 X_P(X_1), X_P1;
4396 15152742 : Real64 Y_P(Y_1), Y_P1;
4397 61658073 : for (int P = 1; P < NVOUT; ++P) {
4398 46505331 : X_P1 = state.dataSolarShading->XTEMP(P + 1);
4399 46505331 : Y_P1 = state.dataSolarShading->YTEMP(P + 1);
4400 46505331 : state.dataSolarShading->ATEMP(P) = Y_P - Y_P1;
4401 46505331 : state.dataSolarShading->BTEMP(P) = X_P1 - X_P;
4402 46505331 : state.dataSolarShading->CTEMP(P) = X_P * Y_P1 - Y_P * X_P1;
4403 46505331 : X_P = X_P1;
4404 46505331 : Y_P = Y_P1;
4405 : }
4406 15152742 : state.dataSolarShading->ATEMP(NVOUT) = Y_P1 - Y_1;
4407 15152742 : state.dataSolarShading->BTEMP(NVOUT) = X_1 - X_P1;
4408 15152742 : state.dataSolarShading->CTEMP(NVOUT) = X_P1 * Y_1 - Y_P1 * X_1;
4409 : }
4410 : }
4411 :
4412 : } // end loop over edges in NS2
4413 :
4414 8293466 : NV3 = NVOUT;
4415 :
4416 8293466 : if (NV3 < 3) { // Determine overlap status
4417 5109246 : state.dataSolarShading->OverlapStatus = NoOverlap;
4418 3184220 : } else if (!INTFLAG) {
4419 341958 : state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
4420 : }
4421 : }
4422 :
4423 2247281 : void MULTOL(EnergyPlusData &state,
4424 : int const NNN, // argument
4425 : int const LOC0, // Location in the homogeneous coordinate array
4426 : int const NRFIGS // Number of figures overlapped
4427 : )
4428 : {
4429 :
4430 : // SUBROUTINE INFORMATION:
4431 : // AUTHOR Legacy Code
4432 : // DATE WRITTEN
4433 : // MODIFIED na
4434 : // RE-ENGINEERED Lawrie, Oct 2000
4435 :
4436 : // PURPOSE OF THIS SUBROUTINE:
4437 : // This subroutine determines the overlaps of figure 'NS2' with previous figures
4438 : // 'LOC0+1' through 'LOC0+NRFIGS'. For example, if NS2
4439 : // is a shadow, overlap with previous shadows.
4440 :
4441 : // REFERENCES:
4442 : // BLAST/IBLAST code, original author George Walton
4443 :
4444 : int I; // Loop Control
4445 : int NS1; // Number of the figure being overlapped
4446 : int NS2; // Number of the figure doing overlapping
4447 : int NS3; // Location to place results of overlap
4448 :
4449 2247281 : state.dataSolarShading->maxNumberOfFigures = max(state.dataSolarShading->maxNumberOfFigures, NRFIGS);
4450 :
4451 2247281 : NS2 = NNN;
4452 5532689 : for (I = 1; I <= NRFIGS; ++I) {
4453 3285408 : NS1 = LOC0 + I;
4454 3285408 : NS3 = state.dataSolarShading->LOCHCA + 1;
4455 :
4456 3285408 : DeterminePolygonOverlap(state, NS1, NS2, NS3); // Find overlap of figure NS2 on figure NS1.
4457 :
4458 : // Process overlap cases:
4459 :
4460 3285408 : if (state.dataSolarShading->OverlapStatus == NoOverlap) continue;
4461 :
4462 1565519 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) break;
4463 :
4464 1565519 : state.dataSolarShading->LOCHCA = NS3; // Increment h.c. arrays pointer.
4465 : }
4466 2247281 : }
4467 :
4468 0 : void ORDER(EnergyPlusData &state,
4469 : int const NV3, // Number of vertices of figure NS3
4470 : int const NS3 // Location to place results of overlap
4471 : )
4472 : {
4473 :
4474 : // SUBROUTINE INFORMATION:
4475 : // AUTHOR Legacy Code
4476 : // DATE WRITTEN
4477 : // MODIFIED na
4478 : // RE-ENGINEERED Lawrie, Oct 2000
4479 :
4480 : // PURPOSE OF THIS SUBROUTINE:
4481 : // This subroutine sorts the vertices found by inclosure and
4482 : // intercept in to clockwise order so that the overlap polygon
4483 : // may be used in computing subsequent overlaps.
4484 :
4485 : // METHODOLOGY EMPLOYED:
4486 : // The slopes of the lines from the left-most vertex to all
4487 : // others are found. The slopes are sorted into descending
4488 : // sequence. This sequence puts the vertices in clockwise order.
4489 :
4490 : // REFERENCES:
4491 : // BLAST/IBLAST code, original author George Walton
4492 :
4493 : Real64 DELTAX; // Difference between X coordinates of two vertices
4494 : Real64 DELTAY; // Difference between Y coordinates of two vertices
4495 : Real64 SAVES; // Temporary location for exchange of variables
4496 : Real64 SAVEX; // Temporary location for exchange of variables
4497 : Real64 SAVEY; // Temporary location for exchange of variables
4498 : Real64 XMIN; // X coordinate of left-most vertex
4499 : Real64 YXMIN;
4500 : int I; // Sort index
4501 : int IM1; // Sort control
4502 : int J; // Sort index
4503 : int M; // Number of slopes to be sorted
4504 : int N; // Vertex number
4505 : int P; // Location of first slope to be sorted
4506 :
4507 0 : if (state.dataSolarShading->ORDERFirstTimeFlag) {
4508 0 : state.dataSolarShading->SLOPE.allocate(max(10, state.dataSurface->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 8293466 : 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 8293466 : 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 8293466 : state.dataSolarShading->OverlapStatus = PartialOverlap;
4651 8293466 : int NV1 = state.dataSolarShading->HCNV(NS1); // Number of vertices of figure NS1
4652 8293466 : int NV2 = state.dataSolarShading->HCNV(NS2); // Number of vertices of figure NS2
4653 8293466 : int NV3 = 0; // Number of vertices of figure NS3 (the overlap of NS1 and NS2)
4654 8293466 : int NIN1 = 0; // Number of vertices of NS1 within NS2
4655 8293466 : int NIN2 = 0; // Number of vertices of NS2 within NS1
4656 :
4657 8293466 : 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 8293466 : CLIPPOLY(state, NS1, NS2, NV1, NV2, NV3);
4686 : }
4687 :
4688 8293466 : if (NV3 < state.dataSolarShading->MaxHCV) {
4689 :
4690 8293466 : if (!state.dataSysVars->SutherlandHodgman) {
4691 0 : ORDER(state, NV3, NS3); // Put vertices in clockwise order.
4692 : } else {
4693 8293466 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
4694 8293466 : int l = state.dataSolarShading->HCX.index(NS3, 1);
4695 21018019 : for (int N = 1; N <= NV3; ++N, ++l) {
4696 12724553 : state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XTEMP(N)); // [ l ] == ( N, NS3 )
4697 12724553 : state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YTEMP(N));
4698 : }
4699 : }
4700 :
4701 8293466 : HTRANS0(state, NS3, NV3); // Determine h.c. values of sides.
4702 : // Skip overlaps of negligible area.
4703 :
4704 8293466 : if (std::abs(state.dataSolarShading->HCAREA(NS3)) * HCMULT < std::abs(state.dataSolarShading->HCAREA(NS1))) {
4705 5112461 : state.dataSolarShading->OverlapStatus = NoOverlap;
4706 : } else {
4707 3181005 : if (state.dataSolarShading->HCAREA(NS1) * state.dataSolarShading->HCAREA(NS2) > 0.0) {
4708 1226663 : state.dataSolarShading->HCAREA(NS3) = -state.dataSolarShading->HCAREA(NS3); // Determine sign of area of overlap
4709 : }
4710 3181005 : Real64 const HCT_1 = state.dataSolarShading->HCT(NS1);
4711 3181005 : Real64 const HCT_2 = state.dataSolarShading->HCT(NS2);
4712 3181005 : if (HCT_2 == 1.0 || HCT_1 == 1.0) {
4713 3083737 : 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 97268 : 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 14627 : 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 ScheduleManager::LookUpScheduleValue;
4768 : using WindowComplexManager::InitComplexWindows;
4769 : using WindowComplexManager::UpdateComplexWindows;
4770 :
4771 : int iHour; // Hour index number
4772 : int TS; // TimeStep Loop Countergit
4773 :
4774 14627 : if (state.dataSolarShading->InitComplexOnce) InitComplexWindows(state);
4775 14627 : state.dataSolarShading->InitComplexOnce = false;
4776 :
4777 14627 : if (state.dataGlobal->KickOffSizing || state.dataGlobal->KickOffSimulation) return; // Skip solar calcs for these Initialization steps.
4778 :
4779 : #ifdef EP_Count_Calls
4780 : ++state.dataTimingsData->NumCalcPerSolBeam_Calls;
4781 : #endif
4782 :
4783 : // Initialize some values for the appropriate period
4784 10788 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4785 23141 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
4786 40906 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
4787 20489 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
4788 20489 : int firstSurf = thisSpace.OpaqOrIntMassSurfaceFirst;
4789 20489 : int lastSurf = thisSpace.OpaqOrIntMassSurfaceLast;
4790 174398 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4791 153909 : state.dataSurface->SurfOpaqAO(surfNum) = 0.0;
4792 : }
4793 20489 : firstSurf = thisSpace.HTSurfaceFirst;
4794 20489 : lastSurf = thisSpace.HTSurfaceLast;
4795 199558 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4796 179069 : state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
4797 : }
4798 512225 : for (int hour = 1; hour <= 24; ++hour) {
4799 4789392 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4800 4297656 : state.dataHeatBal->SurfSunlitFracHR(hour, surfNum) = 0.0;
4801 4297656 : state.dataHeatBal->SurfCosIncAngHR(hour, surfNum) = 0.0;
4802 : }
4803 : }
4804 512225 : for (int hour = 1; hour <= 24; ++hour) {
4805 3033000 : for (int timestep = 1; timestep <= state.dataGlobal->NumOfTimeStepInHour; ++timestep) {
4806 24484176 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4807 21942912 : state.dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum) = 0.0;
4808 21942912 : state.dataHeatBal->SurfCosIncAng(hour, timestep, surfNum) = 0.0;
4809 21942912 : state.dataHeatBal->SurfSunlitFracWithoutReveal(hour, timestep, surfNum) = 0.0;
4810 : }
4811 : }
4812 : }
4813 512225 : for (int hour = 1; hour <= 24; ++hour) {
4814 3033000 : for (int timestep = 1; timestep <= state.dataGlobal->NumOfTimeStepInHour; ++timestep) {
4815 53366544 : for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
4816 489683520 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4817 438858240 : state.dataHeatBal->SurfWinBackSurfaces(hour, timestep, backSurfNum, surfNum) = 0.0;
4818 438858240 : state.dataHeatBal->SurfWinOverlapAreas(hour, timestep, backSurfNum, surfNum) = 0.0;
4819 : }
4820 : }
4821 : } // for (timestep)
4822 : } // for (hour)
4823 20417 : } // for (spaceNum)
4824 : } // for (zoneNum)
4825 :
4826 187911 : for (auto &e : state.dataSurface->SurfaceWindow) {
4827 185187 : std::fill(e.OutProjSLFracMult.begin(), e.OutProjSLFracMult.end(), 1.0);
4828 185187 : std::fill(e.InOutProjSLFracMult.begin(), e.InOutProjSLFracMult.end(), 1.0);
4829 2724 : }
4830 : } else {
4831 56448 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
4832 96768 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
4833 48384 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
4834 48384 : int const firstSurf = thisSpace.HTSurfaceFirst;
4835 48384 : int const lastSurf = thisSpace.HTSurfaceLast;
4836 604800 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4837 556416 : state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
4838 556416 : state.dataSurface->SurfOpaqAO(surfNum) = 0.0;
4839 556416 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
4840 556416 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
4841 556416 : state.dataHeatBal->SurfSunlitFracHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
4842 556416 : state.dataHeatBal->SurfCosIncAngHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
4843 556416 : state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
4844 : }
4845 1016064 : for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
4846 12096000 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
4847 11128320 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0;
4848 11128320 : state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0.0;
4849 : }
4850 : }
4851 48384 : }
4852 : }
4853 :
4854 564480 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
4855 556416 : state.dataSurface->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;
4856 556416 : state.dataSurface->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;
4857 : }
4858 : }
4859 :
4860 10788 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4861 68100 : for (iHour = 1; iHour <= 24; ++iHour) { // Do for all hours
4862 423840 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
4863 358464 : FigureSunCosines(state, iHour, TS, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
4864 : }
4865 : }
4866 : } else {
4867 8064 : FigureSunCosines(state, state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
4868 : }
4869 : // Initialize/update the Complex Fenestration geometry and optical properties
4870 10788 : UpdateComplexWindows(state);
4871 10788 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4872 68100 : for (iHour = 1; iHour <= 24; ++iHour) { // Do for all hours.
4873 423840 : for (TS = 1; TS <= state.dataGlobal->NumOfTimeStepInHour; ++TS) {
4874 358464 : FigureSolarBeamAtTimestep(state, iHour, TS);
4875 : } // TimeStep Loop
4876 : } // Hour Loop
4877 : } else {
4878 8064 : FigureSolarBeamAtTimestep(state, state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
4879 : }
4880 : }
4881 :
4882 366528 : void FigureSunCosines(EnergyPlusData &state,
4883 : int const iHour,
4884 : int const iTimeStep,
4885 : Real64 const EqOfTime, // value of Equation of Time for period
4886 : Real64 const SinSolarDeclin, // value of Sine of Solar Declination for period
4887 : Real64 const CosSolarDeclin // value of Cosine of Solar Declination for period
4888 : )
4889 : {
4890 :
4891 : // SUBROUTINE INFORMATION:
4892 : // AUTHOR B. Griffith
4893 : // DATE WRITTEN October 2012
4894 : // MODIFIED na
4895 : // RE-ENGINEERED na
4896 :
4897 : // PURPOSE OF THIS SUBROUTINE:
4898 : // Determine solar position. Default for sun below horizon.
4899 :
4900 : // METHODOLOGY EMPLOYED:
4901 : // Given hour, timestep, equation of time, solar declination sine, and solar declination cosine,
4902 : // determine sun directions for use elsewhere
4903 :
4904 : // Using/Aliasing
4905 :
4906 : Real64 CurrentTime; // Current Time for passing to Solar Position Routine
4907 :
4908 366528 : if (state.dataGlobal->NumOfTimeStepInHour != 1) {
4909 365856 : CurrentTime = double(iHour - 1) + double(iTimeStep) * (state.dataGlobal->TimeStepZone);
4910 : } else {
4911 672 : CurrentTime = double(iHour) + state.dataEnvrn->TS1TimeOffset;
4912 : }
4913 366528 : SUN4(state, CurrentTime, EqOfTime, SinSolarDeclin, CosSolarDeclin);
4914 :
4915 : // Save hourly values for use in DaylightingManager
4916 366528 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4917 358464 : if (iTimeStep == state.dataGlobal->NumOfTimeStepInHour) state.dataSurface->SurfSunCosHourly(iHour) = state.dataSolarShading->SUNCOS;
4918 : } else {
4919 8064 : state.dataSurface->SurfSunCosHourly(iHour) = state.dataSolarShading->SUNCOS;
4920 : }
4921 : // Save timestep values for use in WindowComplexManager
4922 366528 : state.dataBSDFWindow->SUNCOSTS(iTimeStep, iHour) = state.dataSolarShading->SUNCOS;
4923 366528 : }
4924 :
4925 366528 : void FigureSolarBeamAtTimestep(EnergyPlusData &state, int const iHour, int const iTimeStep)
4926 : {
4927 :
4928 : // SUBROUTINE INFORMATION:
4929 : // AUTHOR B.Griffith, derived from CalcPerSolarBeam, Legacy and Lawrie.
4930 : // DATE WRITTEN October 2012
4931 : // MODIFIED na
4932 : // RE-ENGINEERED na
4933 :
4934 : // PURPOSE OF THIS SUBROUTINE:
4935 : // This subroutine computes solar gain multipliers for beam solar
4936 :
4937 : using DataSystemVariables::ShadingMethod;
4938 : using ScheduleManager::LookUpScheduleValue;
4939 :
4940 : Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
4941 : Real64 Fac1WoShdg; // Intermediate calculation factor, without shading
4942 : Real64 Fac1WithShdg; // Intermediate calculation factor, with shading
4943 : Real64 FracIlluminated; // Fraction of surface area illuminated by a sky patch
4944 :
4945 : // Recover the sun direction from the array stored in previous loop
4946 366528 : state.dataSolarShading->SUNCOS = state.dataBSDFWindow->SUNCOSTS(iTimeStep, iHour);
4947 :
4948 366528 : state.dataSolarShading->SurfSunCosTheta = 0.0;
4949 :
4950 366528 : if (state.dataSolarShading->SUNCOS(3) < DataEnvironment::SunIsUpValue) return;
4951 :
4952 11896009 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
4953 23423044 : state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS(1) * state.dataSurface->Surface(SurfNum).OutNormVec(1) +
4954 11711522 : state.dataSolarShading->SUNCOS(2) * state.dataSurface->Surface(SurfNum).OutNormVec(2) +
4955 11711522 : state.dataSolarShading->SUNCOS(3) * state.dataSurface->Surface(SurfNum).OutNormVec(3);
4956 11711522 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4957 11433314 : if (iTimeStep == state.dataGlobal->NumOfTimeStepInHour)
4958 2241167 : state.dataHeatBal->SurfCosIncAngHR(iHour, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
4959 : } else {
4960 278208 : state.dataHeatBal->SurfCosIncAngHR(iHour, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
4961 : }
4962 11711522 : state.dataHeatBal->SurfCosIncAng(iHour, iTimeStep, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
4963 : }
4964 :
4965 368879 : if ((state.dataSysVars->shadingMethod == ShadingMethod::Scheduled || state.dataSysVars->shadingMethod == ShadingMethod::Imported) &&
4966 368879 : !state.dataGlobal->DoingSizing && state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather) {
4967 0 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
4968 0 : if (state.dataSurface->Surface(SurfNum).SurfSchedExternalShadingFrac) {
4969 0 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) =
4970 0 : LookUpScheduleValue(state, state.dataSurface->Surface(SurfNum).SurfExternalShadingSchInd, iHour, iTimeStep);
4971 : } else {
4972 0 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 1.0;
4973 : }
4974 : }
4975 : } else {
4976 184487 : SHADOW(state, iHour, iTimeStep); // Determine sunlit areas and solar multipliers for all surfaces.
4977 11896009 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
4978 11711522 : if (state.dataSurface->Surface(SurfNum).Area >= 1.e-10) {
4979 11711522 : SurfArea = state.dataSurface->Surface(SurfNum).NetAreaShadowCalc;
4980 11711522 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
4981 11433314 : if (iTimeStep == state.dataGlobal->NumOfTimeStepInHour)
4982 2241167 : state.dataHeatBal->SurfSunlitFracHR(iHour, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
4983 : } else {
4984 278208 : state.dataHeatBal->SurfSunlitFracHR(iHour, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
4985 : }
4986 11711522 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
4987 11711522 : if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) < 1.e-5)
4988 9081548 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 0.0;
4989 : }
4990 : // Added check
4991 11711522 : if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) > 1.0) {
4992 0 : state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 1.0;
4993 : }
4994 : }
4995 : }
4996 : // Note -- if not the below, values are set in SkyDifSolarShading routine (constant for simulation)
4997 184487 : if (state.dataSysVars->DetailedSkyDiffuseAlgorithm && state.dataSurface->ShadingTransmittanceVaries &&
4998 0 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
4999 0 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
5000 0 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) = 0.;
5001 0 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) = 0.;
5002 0 : state.dataSolarShading->SurfWithShdgHoriz(SurfNum) = 0.;
5003 0 : state.dataSolarShading->SurfWoShdgHoriz(SurfNum) = 0.;
5004 : }
5005 :
5006 0 : for (int IPhi = 0; IPhi < NPhi; ++IPhi) { // Loop over patch altitude values
5007 0 : state.dataSolarShading->SUNCOS(3) = state.dataSolarShading->sin_Phi[IPhi];
5008 :
5009 0 : for (int ITheta = 0; ITheta < NTheta; ++ITheta) { // Loop over patch azimuth values
5010 0 : state.dataSolarShading->SUNCOS(1) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->cos_Theta[ITheta];
5011 0 : state.dataSolarShading->SUNCOS(2) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->sin_Theta[ITheta];
5012 :
5013 0 : for (int SurfNum : state.dataSurface->AllExtSolAndShadingSurfaceList) {
5014 0 : state.dataSolarShading->SurfSunCosTheta(SurfNum) =
5015 0 : state.dataSolarShading->SUNCOS(1) * state.dataSurface->Surface(SurfNum).OutNormVec(1) +
5016 0 : state.dataSolarShading->SUNCOS(2) * state.dataSurface->Surface(SurfNum).OutNormVec(2) +
5017 0 : state.dataSolarShading->SUNCOS(3) * state.dataSurface->Surface(SurfNum).OutNormVec(3);
5018 0 : }
5019 :
5020 0 : SHADOW(state, iHour, iTimeStep); // Determine sunlit areas and solar multipliers for all surfaces.
5021 :
5022 0 : for (int SurfNum : state.dataSurface->AllExtSolAndShadingSurfaceList) {
5023 :
5024 0 : if (state.dataSolarShading->SurfSunCosTheta(SurfNum) < 0.0) continue;
5025 :
5026 0 : Fac1WoShdg = state.dataSolarShading->cos_Phi[IPhi] * DThetaDPhi * state.dataSolarShading->SurfSunCosTheta(SurfNum);
5027 0 : SurfArea = state.dataSurface->Surface(SurfNum).NetAreaShadowCalc;
5028 0 : if (SurfArea > Eps) {
5029 0 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
5030 : } else {
5031 0 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / (SurfArea + Eps);
5032 : }
5033 0 : Fac1WithShdg = Fac1WoShdg * FracIlluminated;
5034 0 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) += Fac1WithShdg;
5035 0 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) += Fac1WoShdg;
5036 :
5037 : // Horizon region
5038 0 : if (IPhi == 0) {
5039 0 : state.dataSolarShading->SurfWithShdgHoriz(SurfNum) += Fac1WithShdg;
5040 0 : state.dataSolarShading->SurfWoShdgHoriz(SurfNum) += Fac1WoShdg;
5041 : }
5042 0 : } // End of surface loop
5043 : } // End of Theta loop
5044 : } // End of Phi loop
5045 :
5046 0 : for (int SurfNum : state.dataSurface->AllExtSolAndShadingSurfaceList) {
5047 : // Original conditions:
5048 : // if (!state.dataSurface->Surface(SurfNum).IsShadowing &&
5049 : // (!state.dataSurface->Surface(SurfNum).HeatTransSurf || !state.dataSurface->Surface(SurfNum).ExtSolar))
5050 : // continue;
5051 :
5052 0 : if (std::abs(state.dataSolarShading->SurfWoShdgIsoSky(SurfNum)) > Eps) {
5053 0 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(iTimeStep, iHour, SurfNum) =
5054 0 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum));
5055 : } else {
5056 0 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(iTimeStep, iHour, SurfNum) =
5057 0 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) + Eps);
5058 : }
5059 0 : if (std::abs(state.dataSolarShading->SurfWoShdgHoriz(SurfNum)) > Eps) {
5060 0 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS(iTimeStep, iHour, SurfNum) =
5061 0 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum));
5062 : } else {
5063 0 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS(iTimeStep, iHour, SurfNum) =
5064 0 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum) + Eps);
5065 : }
5066 0 : }
5067 :
5068 : // ! Get IR view factors. An exterior surface can receive IR radiation from
5069 : // ! sky, ground or shadowing surfaces. Assume shadowing surfaces have same
5070 : // ! temperature as outside air (and therefore same temperature as ground),
5071 : // ! so that the view factor to these shadowing surfaces can be included in
5072 : // ! the ground view factor. Sky IR is assumed to be isotropic and shadowing
5073 : // ! surfaces are assumed to be opaque to IR so they totally "shade" IR from
5074 : // ! sky or ground.
5075 :
5076 : // DO SurfNum = 1,TotSurfaces
5077 : // Surface(SurfNum)%ViewFactorSkyIR = Surface(SurfNum)%ViewFactorSkyIR * DifShdgRatioIsoSky(SurfNum,IHOUR,TS)
5078 : // Surface(SurfNum)%ViewFactorGroundIR = 1.0 - Surface(SurfNum)%ViewFactorSkyIR
5079 : // END DO
5080 :
5081 : } // test for shading surfaces
5082 :
5083 261810 : for (int SurfNum : state.dataSurface->AllExtSolWinWithFrameSurfaceList) {
5084 : // For exterior windows with frame/divider that are partially or fully sunlit,
5085 : // correct SunlitFrac due to shadowing of frame and divider projections onto window glass.
5086 : // Note: if SunlitFrac = 0.0 the window is either completely shaded or the sun is in back
5087 : // of the window; in either case, frame/divider shadowing doesn't have to be done.
5088 :
5089 77323 : if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) > 0.0) {
5090 69685 : CalcFrameDividerShadow(state, SurfNum, state.dataSurface->Surface(SurfNum).FrameDivider, iHour);
5091 : }
5092 184487 : }
5093 : }
5094 :
5095 796 : void DetermineShadowingCombinations(EnergyPlusData &state)
5096 : {
5097 :
5098 : // SUBROUTINE INFORMATION:
5099 : // AUTHOR From Legacy Code
5100 : // DATE WRITTEN
5101 : // MODIFIED LKL; March 2002 -- another missing translation from BLAST's routine
5102 : // FCW; Jan 2003 -- removed line that prevented beam solar through interior windows
5103 : // RE-ENGINEERED Rick Strand; 1998
5104 : // Linda Lawrie; Oct 2000
5105 :
5106 : // PURPOSE OF THIS SUBROUTINE:
5107 : // This routine prepares a list of heat transfer surfaces and
5108 : // their possible shadowers which is used to direct the hourly
5109 : // calculation of shadows and sunlit areas.
5110 :
5111 : // METHODOLOGY EMPLOYED:
5112 : // As appropriate surfaces are identified, they are placed into the
5113 : // ShadowComb data structure (module level) with the accompanying lists
5114 : // of other surface numbers.
5115 :
5116 : // REFERENCES:
5117 : // BLAST/IBLAST code, original author George Walton
5118 :
5119 : // Using/Aliasing
5120 : using namespace DataErrorTracking;
5121 :
5122 796 : Array1D_int GSS; // List of shadowing surfaces numbers for a receiving surface
5123 796 : Array1D_int BKS; // List of back surface numbers for a receiving surface
5124 796 : Array1D_int SBS; // List of subsurfaces for a receiving surface
5125 : bool CannotShade; // TRUE if subsurface cannot shade receiving surface
5126 : bool HasWindow; // TRUE if a window is present on receiving surface
5127 : Real64 ZMIN; // Lowest point on the receiving surface
5128 : int BackSurfaceNumber; // Back surface number
5129 : int HTS; // Heat transfer surface number for a receiving surface
5130 : int GRSNR; // Receiving surface number
5131 : int GSSNR; // Shadowing surface number
5132 : int SBSNR; // Subsurface number
5133 : int NBKS; // Number of back surfaces for a receiving surface
5134 : int NGSS; // Number of shadowing surfaces for a receiving surface
5135 : int NSBS; // Number of subsurfaces for a receiving surface
5136 : bool ShadowingSurf; // True if a receiving surface is a shadowing surface
5137 796 : Array1D_bool CastingSurface; // tracking during setup of ShadowComb
5138 :
5139 : #ifdef EP_Count_Calls
5140 : ++state.dataTimingsData->NumDetShadowCombs_Calls;
5141 : #endif
5142 :
5143 1592 : state.dataShadowComb->ShadowComb.dimension(state.dataSurface->TotSurfaces,
5144 1592 : ShadowingCombinations{}); // Set all elements to default constructed state
5145 :
5146 796 : CastingSurface.dimension(state.dataSurface->TotSurfaces, false);
5147 :
5148 796 : state.dataSolarShading->HCA.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5149 796 : state.dataSolarShading->HCB.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5150 796 : state.dataSolarShading->HCC.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5151 796 : state.dataSolarShading->HCX.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5152 796 : state.dataSolarShading->HCY.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
5153 796 : state.dataSolarShading->HCAREA.dimension(2 * state.dataSolarShading->MaxHCS, 0.0);
5154 796 : state.dataSolarShading->HCNS.dimension(2 * state.dataSolarShading->MaxHCS, 0);
5155 796 : state.dataSolarShading->HCNV.dimension(2 * state.dataSolarShading->MaxHCS, 0);
5156 796 : state.dataSolarShading->HCT.dimension(2 * state.dataSolarShading->MaxHCS, 0.0);
5157 :
5158 796 : GSS.dimension(state.dataSolarShading->MaxGSS, 0);
5159 796 : BKS.dimension(state.dataSolarShading->MaxGSS, 0);
5160 796 : SBS.dimension(state.dataSolarShading->MaxGSS, 0);
5161 :
5162 796 : state.dataSolarShading->penumbraIDs.clear();
5163 :
5164 796 : HTS = 0;
5165 :
5166 : // Check every surface as a possible shadow receiving surface ("RS" = receiving surface).
5167 796 : if (state.dataEnvrn->IgnoreSolarRadiation) {
5168 0 : return;
5169 : }
5170 :
5171 46840 : for (GRSNR = 1; GRSNR <= state.dataSurface->TotSurfaces; ++GRSNR) { // Loop through all surfaces (looking for potential receiving surfaces)...
5172 :
5173 46044 : ShadowingSurf = state.dataSurface->Surface(GRSNR).IsShadowing;
5174 46044 : NGSS = 0;
5175 46044 : NSBS = 0;
5176 46044 : NBKS = 0;
5177 :
5178 46044 : if (!ShadowingSurf && !state.dataSurface->Surface(GRSNR).HeatTransSurf) continue;
5179 46026 : HTS = GRSNR;
5180 :
5181 : #ifndef EP_NO_OPENGL
5182 46026 : if (state.dataSolarShading->penumbra) {
5183 113 : bool skipSurface = state.dataSurface->Surface(GRSNR).MirroredSurf;
5184 : // Penumbra doesn't need mirrored surfaces TODO: Don't bother creating them in the first place?
5185 :
5186 : // Skip interior surfaces if the other side has already been added to penumbra
5187 113 : if (state.dataSurface->Surface(GRSNR).ExtBoundCond > 0) {
5188 20 : if (state.dataSurface->SurfPenumbraID(state.dataSurface->Surface(GRSNR).ExtBoundCond) >= 0) {
5189 10 : state.dataSurface->SurfPenumbraID(GRSNR) = state.dataSurface->SurfPenumbraID(state.dataSurface->Surface(GRSNR).ExtBoundCond);
5190 10 : skipSurface = true;
5191 : }
5192 : }
5193 :
5194 113 : if (!skipSurface) {
5195 : // Add surfaces to penumbra...
5196 92 : Penumbra::Polygon poly;
5197 :
5198 92 : if (state.dataSurface->Surface(GRSNR).Reveal > 0.0) {
5199 21 : Real64 R = state.dataSurface->Surface(GRSNR).Reveal;
5200 21 : auto &norm = state.dataSurface->Surface(GRSNR).NewellSurfaceNormalVector;
5201 21 : auto &v = state.dataSurface->Surface(GRSNR).Vertex;
5202 105 : for (unsigned i = 0; i < v.size(); ++i) {
5203 84 : poly.push_back(v[i].x);
5204 84 : poly.push_back(v[i].y);
5205 84 : poly.push_back(v[i].z);
5206 :
5207 84 : Vector vPrev;
5208 84 : if (i == 0) {
5209 21 : vPrev = v[v.size() - 1];
5210 : } else {
5211 63 : vPrev = v[i - 1];
5212 : }
5213 :
5214 84 : Penumbra::Polygon rPoly; // Reveal surface
5215 84 : rPoly.push_back(v[i].x);
5216 84 : rPoly.push_back(v[i].y);
5217 84 : rPoly.push_back(v[i].z);
5218 :
5219 84 : rPoly.push_back(v[i].x + norm.x * R);
5220 84 : rPoly.push_back(v[i].y + norm.y * R);
5221 84 : rPoly.push_back(v[i].z + norm.z * R);
5222 :
5223 84 : rPoly.push_back(vPrev.x + norm.x * R);
5224 84 : rPoly.push_back(vPrev.y + norm.y * R);
5225 84 : rPoly.push_back(vPrev.z + norm.z * R);
5226 :
5227 84 : rPoly.push_back(vPrev.x);
5228 84 : rPoly.push_back(vPrev.y);
5229 84 : rPoly.push_back(vPrev.z);
5230 :
5231 168 : Penumbra::Surface rSurf(rPoly, fmt::format("{} reveal {}", state.dataSurface->Surface(GRSNR).Name, i));
5232 84 : state.dataSolarShading->penumbra->add_surface(rSurf);
5233 84 : }
5234 : } else {
5235 353 : for (auto const &v : state.dataSurface->Surface(GRSNR).Vertex) {
5236 282 : poly.push_back(v.x);
5237 282 : poly.push_back(v.y);
5238 282 : poly.push_back(v.z);
5239 : }
5240 : }
5241 92 : Penumbra::Surface pSurf(poly, state.dataSurface->Surface(GRSNR).Name);
5242 :
5243 : // Punch holes for subsurfaces
5244 92 : if (state.dataSurface->Surface(GRSNR).BaseSurf == GRSNR) { // Only look for subsurfaces on base surfaces
5245 6840 : for (int subSurface = 1; subSurface <= state.dataSurface->TotSurfaces; ++subSurface) {
5246 6840 : if (state.dataSurface->Surface(subSurface).BaseSurf != GRSNR) continue; // Ignore subsurfaces of other surfaces
5247 81 : if (!state.dataSurface->Surface(subSurface).HeatTransSurf) continue; // Skip non heat transfer subsurfaces
5248 81 : if (subSurface == GRSNR) continue; // Surface itself cannot be its own subsurface
5249 :
5250 21 : Penumbra::Polygon subPoly;
5251 21 : if (state.dataSurface->Surface(subSurface).Reveal > 0.0) {
5252 21 : Real64 R = state.dataSurface->Surface(subSurface).Reveal;
5253 21 : auto &norm = state.dataSurface->Surface(subSurface).NewellSurfaceNormalVector;
5254 105 : for (auto const &v : state.dataSurface->Surface(subSurface).Vertex) {
5255 84 : subPoly.push_back(v.x + norm.x * R);
5256 84 : subPoly.push_back(v.y + norm.y * R);
5257 84 : subPoly.push_back(v.z + norm.z * R);
5258 : }
5259 : } else {
5260 0 : for (auto const &v : state.dataSurface->Surface(subSurface).Vertex) {
5261 0 : subPoly.push_back(v.x);
5262 0 : subPoly.push_back(v.y);
5263 0 : subPoly.push_back(v.z);
5264 : }
5265 : }
5266 :
5267 21 : pSurf.add_hole(subPoly);
5268 21 : }
5269 : }
5270 92 : state.dataSurface->SurfPenumbraID(GRSNR) = state.dataSolarShading->penumbra->add_surface(pSurf);
5271 92 : state.dataSolarShading->penumbraIDs.push_back(state.dataSurface->SurfPenumbraID(GRSNR));
5272 92 : }
5273 : }
5274 : #endif
5275 :
5276 46026 : if (!ShadowingSurf && !state.dataSurface->Surface(GRSNR).ExtSolar) continue; // Skip surfaces with no external solar
5277 :
5278 19332 : if (!ShadowingSurf && state.dataSurface->Surface(GRSNR).BaseSurf != GRSNR) { // Skip subsurfaces (SBS)
5279 6593 : continue;
5280 : }
5281 :
5282 : // Get the lowest point of receiving surface
5283 12739 : ZMIN = minval(state.dataSurface->Surface(GRSNR).Vertex, &Vector::z);
5284 :
5285 : // Check every surface as a possible shadow casting surface ("SS" = shadow sending)
5286 12739 : NGSS = 0;
5287 12739 : if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) { // Except when doing simplified exterior shadowing.
5288 :
5289 1674425 : for (GSSNR = 1; GSSNR <= state.dataSurface->TotSurfaces; ++GSSNR) { // Loop through all surfaces, looking for ones that could shade GRSNR
5290 :
5291 1663196 : if (GSSNR == GRSNR) continue; // Receiving surface cannot shade itself
5292 1651967 : if ((state.dataSurface->Surface(GSSNR).HeatTransSurf) && (state.dataSurface->Surface(GSSNR).BaseSurf == GRSNR))
5293 5672 : continue; // A heat transfer subsurface of a receiving surface
5294 : // cannot shade the receiving surface
5295 1646295 : if (ShadowingSurf) {
5296 : // If receiving surf is a shadowing surface exclude matching shadow surface as sending surface
5297 : // IF((GSSNR == GRSNR+1 .AND. Surface(GSSNR)%Name(1:3) == 'Mir').OR. &
5298 : // (GSSNR == GRSNR-1 .AND. Surface(GRSNR)%Name(1:3) == 'Mir')) CYCLE
5299 267299 : if (((GSSNR == GRSNR + 1) && state.dataSurface->Surface(GSSNR).MirroredSurf) ||
5300 133241 : ((GSSNR == GRSNR - 1) && state.dataSurface->Surface(GRSNR).MirroredSurf))
5301 1634 : continue;
5302 : }
5303 :
5304 1644661 : if (state.dataSurface->Surface(GSSNR).BaseSurf == GRSNR) { // Shadowing subsurface of receiving surface
5305 :
5306 0 : ++NGSS;
5307 0 : if (NGSS > state.dataSolarShading->MaxGSS) {
5308 0 : GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
5309 : }
5310 0 : GSS(NGSS) = GSSNR;
5311 :
5312 3231096 : } else if ((state.dataSurface->Surface(GSSNR).BaseSurf == 0) ||
5313 1586435 : ((state.dataSurface->Surface(GSSNR).BaseSurf == GSSNR) &&
5314 1322219 : ((state.dataSurface->Surface(GSSNR).ExtBoundCond == ExternalEnvironment) ||
5315 982968 : state.dataSurface->Surface(GSSNR).ExtBoundCond ==
5316 : OtherSideCondModeledExt))) { // Detached shadowing surface or | any other base surface
5317 : // exposed to outside environment
5318 :
5319 398327 : CHKGSS(state, GRSNR, GSSNR, ZMIN, CannotShade); // Check to see if this can shade the receiving surface
5320 398327 : if (!CannotShade) { // Update the shadowing surface data if shading is possible
5321 27642 : ++NGSS;
5322 27642 : if (NGSS > state.dataSolarShading->MaxGSS) {
5323 0 : GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
5324 : }
5325 27642 : GSS(NGSS) = GSSNR;
5326 : }
5327 : }
5328 :
5329 : } // ...end of surfaces DO loop (GSSNR)
5330 : } else { // Simplified Distribution -- still check for Shading Subsurfaces
5331 :
5332 469309 : for (GSSNR = 1; GSSNR <= state.dataSurface->TotSurfaces;
5333 : ++GSSNR) { // Loop through all surfaces (looking for surfaces which could shade GRSNR) ...
5334 :
5335 467799 : if (GSSNR == GRSNR) continue; // Receiving surface cannot shade itself
5336 466289 : if ((state.dataSurface->Surface(GSSNR).HeatTransSurf) && (state.dataSurface->Surface(GSSNR).BaseSurf == GRSNR))
5337 921 : continue; // Skip heat transfer subsurfaces of receiving surface
5338 465368 : if (state.dataSurface->Surface(GSSNR).BaseSurf == GRSNR) { // Shadowing subsurface of receiving surface
5339 0 : ++NGSS;
5340 0 : if (NGSS > state.dataSolarShading->MaxGSS) {
5341 0 : GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
5342 : }
5343 0 : GSS(NGSS) = GSSNR;
5344 : }
5345 : }
5346 :
5347 : } // ...end of check for simplified solar distribution
5348 :
5349 : // Check every surface as a receiving subsurface of the receiving surface
5350 12739 : NSBS = 0;
5351 12739 : HasWindow = false;
5352 : // legacy: IF (OSENV(HTS) > 10) WINDOW=.TRUE. -->Note: WINDOW was set true for roof ponds, solar walls, or other zones
5353 2143734 : for (SBSNR = 1; SBSNR <= state.dataSurface->TotSurfaces;
5354 : ++SBSNR) { // Loop through the surfaces yet again (looking for subsurfaces of GRSNR)...
5355 :
5356 2130995 : if (!state.dataSurface->Surface(SBSNR).HeatTransSurf) continue; // Skip non heat transfer subsurfaces
5357 2069037 : if (SBSNR == GRSNR) continue; // Surface itself cannot be its own subsurface
5358 2057933 : if (state.dataSurface->Surface(SBSNR).BaseSurf != GRSNR) continue; // Ignore subsurfaces of other surfaces and other surfaces
5359 :
5360 6593 : if (state.dataConstruction->Construct(state.dataSurface->Surface(SBSNR).Construction).TransDiff > 0.0)
5361 6198 : HasWindow = true; // Check for window
5362 6593 : CHKSBS(state, HTS, GRSNR, SBSNR); // Check that the receiving surface completely encloses the subsurface;
5363 : // severe error if not
5364 6593 : ++NSBS;
5365 6593 : if (NSBS > state.dataSolarShading->MaxSBS) {
5366 3 : SBS.redimension(state.dataSolarShading->MaxSBS *= 2, 0);
5367 : }
5368 6593 : SBS(NSBS) = SBSNR;
5369 :
5370 : } // ...end of surfaces DO loop (SBSNR)
5371 :
5372 : // Check every surface as a back surface
5373 12739 : NBKS = 0;
5374 : // Except for simplified
5375 : // interior solar distribution,
5376 12739 : if ((state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) &&
5377 : (HasWindow)) { // For full interior solar distribution | and a window present on base surface (GRSNR)
5378 :
5379 736770 : for (BackSurfaceNumber = 1; BackSurfaceNumber <= state.dataSurface->TotSurfaces;
5380 : ++BackSurfaceNumber) { // Loop through surfaces yet again, looking for back surfaces to GRSNR
5381 :
5382 734409 : if (!state.dataSurface->Surface(BackSurfaceNumber).HeatTransSurf) continue; // Skip non-heat transfer surfaces
5383 729495 : if (state.dataSurface->Surface(BackSurfaceNumber).BaseSurf == GRSNR) continue; // Skip subsurfaces of this GRSNR
5384 723352 : if (BackSurfaceNumber == GRSNR) continue; // A back surface cannot be GRSNR itself
5385 723352 : if (state.dataSurface->Surface(BackSurfaceNumber).SolarEnclIndex != state.dataSurface->Surface(GRSNR).SolarEnclIndex)
5386 703456 : continue; // Skip if back surface not in same solar enclosure
5387 :
5388 19896 : if (state.dataSurface->Surface(BackSurfaceNumber).Class == SurfaceClass::IntMass) continue;
5389 :
5390 : // Following line removed 1/27/03 by FCW. Was in original code that didn't do beam solar transmitted through
5391 : // interior windows. Was removed to allow such beam solar but then somehow was put back in.
5392 : // IF (Surface(BackSurfaceNumber)%BaseSurf /= BackSurfaceNumber) CYCLE ! Not for subsurfaces of Back Surface
5393 :
5394 18145 : if (!state.dataSolarShading->penumbra) {
5395 17956 : CHKBKS(state, BackSurfaceNumber, GRSNR); // CHECK FOR CONVEX ZONE; severe error if not
5396 : }
5397 18145 : ++NBKS;
5398 18145 : if (NBKS > state.dataSolarShading->MaxBKS) {
5399 0 : BKS.redimension(state.dataSolarShading->MaxBKS *= 2, 0);
5400 : }
5401 18145 : BKS(NBKS) = BackSurfaceNumber;
5402 :
5403 : } // ...end of surfaces DO loop (BackSurfaceNumber)
5404 : }
5405 :
5406 : // Put this into the ShadowComb data structure
5407 12739 : state.dataShadowComb->ShadowComb(GRSNR).UseThisSurf = true;
5408 12739 : state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf = NGSS;
5409 12739 : state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf = NBKS;
5410 12739 : state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf = NSBS;
5411 12739 : state.dataSolarShading->MaxDim = max(state.dataSolarShading->MaxDim, NGSS, NBKS, NSBS);
5412 :
5413 12739 : state.dataShadowComb->ShadowComb(GRSNR).GenSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf});
5414 12739 : state.dataShadowComb->ShadowComb(GRSNR).GenSurf(0) = 0;
5415 12739 : if (state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf > 0) {
5416 3876 : state.dataShadowComb->ShadowComb(GRSNR).GenSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf}) = GSS({1, NGSS});
5417 : }
5418 :
5419 12739 : state.dataShadowComb->ShadowComb(GRSNR).BackSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf});
5420 12739 : state.dataShadowComb->ShadowComb(GRSNR).BackSurf(0) = 0;
5421 12739 : if (state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf > 0) {
5422 2361 : state.dataShadowComb->ShadowComb(GRSNR).BackSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf}) = BKS({1, NBKS});
5423 : }
5424 :
5425 12739 : state.dataShadowComb->ShadowComb(GRSNR).SubSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf});
5426 12739 : state.dataShadowComb->ShadowComb(GRSNR).SubSurf(0) = 0;
5427 12739 : if (state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf > 0) {
5428 4240 : state.dataShadowComb->ShadowComb(GRSNR).SubSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf}) = SBS({1, NSBS});
5429 : }
5430 :
5431 : } // ...end of surfaces (GRSNR) DO loop
5432 :
5433 796 : GSS.deallocate();
5434 796 : SBS.deallocate();
5435 796 : BKS.deallocate();
5436 :
5437 796 : if (!state.dataSolarShading->penumbra) {
5438 795 : if (state.dataSolarShading->shd_stream) {
5439 795 : *state.dataSolarShading->shd_stream << "Shadowing Combinations\n";
5440 795 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
5441 104 : *state.dataSolarShading->shd_stream
5442 104 : << "..Solar Distribution=Minimal Shadowing, Detached Shading will not be used in shadowing calculations\n";
5443 691 : } else if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullExterior) {
5444 242 : if (state.dataSurface->CalcSolRefl) {
5445 3 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullExteriorWithReflectionsFromExteriorSurfaces\n";
5446 : } else {
5447 239 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullExterior\n";
5448 : }
5449 449 : } else if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
5450 449 : if (state.dataSurface->CalcSolRefl) {
5451 6 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullInteriorAndExteriorWithReflectionsFromExteriorSurfaces\n";
5452 : } else {
5453 443 : *state.dataSolarShading->shd_stream << "..Solar Distribution=FullInteriorAndExterior\n";
5454 : }
5455 : } else {
5456 : }
5457 :
5458 795 : *state.dataSolarShading->shd_stream << "..In the following, only the first 10 reference surfaces will be shown.\n";
5459 795 : *state.dataSolarShading->shd_stream << "..But all surfaces are used in the calculations.\n";
5460 :
5461 46726 : for (int HTSnum : state.dataSurface->AllSurfaceListReportOrder) {
5462 45931 : *state.dataSolarShading->shd_stream << "==================================\n";
5463 45931 : if (state.dataShadowComb->ShadowComb(HTSnum).UseThisSurf) {
5464 12671 : if (state.dataSurface->Surface(HTSnum).IsConvex) {
5465 25272 : *state.dataSolarShading->shd_stream << "Surface=" << state.dataSurface->Surface(HTSnum).Name
5466 25272 : << " is used as Receiving Surface in calculations and is convex.\n";
5467 : } else {
5468 70 : *state.dataSolarShading->shd_stream << "Surface=" << state.dataSurface->Surface(HTSnum).Name
5469 70 : << " is used as Receiving Surface in calculations and is non-convex.\n";
5470 35 : if (state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf > 0) {
5471 0 : if (state.dataGlobal->DisplayExtraWarnings) {
5472 0 : ShowWarningError(state,
5473 0 : format("DetermineShadowingCombinations: Surface=\"{}\" is a receiving surface and is non-convex.",
5474 0 : state.dataSurface->Surface(HTSnum).Name));
5475 0 : ShowContinueError(state,
5476 : "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5477 : } else {
5478 0 : ++state.dataErrTracking->TotalReceivingNonConvexSurfaces;
5479 : }
5480 : }
5481 : }
5482 : } else {
5483 66520 : *state.dataSolarShading->shd_stream << "Surface=" << state.dataSurface->Surface(HTSnum).Name
5484 66520 : << " is not used as Receiving Surface in calculations.\n";
5485 : }
5486 45931 : *state.dataSolarShading->shd_stream << "Number of general casting surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf
5487 45931 : << '\n';
5488 72940 : for (NGSS = 1; NGSS <= state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf; ++NGSS) {
5489 27009 : if (NGSS <= 10)
5490 15770 : *state.dataSolarShading->shd_stream
5491 15770 : << "..Surface=" << state.dataSurface->Surface(state.dataShadowComb->ShadowComb(HTSnum).GenSurf(NGSS)).Name << '\n';
5492 27009 : CastingSurface(state.dataShadowComb->ShadowComb(HTSnum).GenSurf(NGSS)) = true;
5493 : }
5494 45931 : *state.dataSolarShading->shd_stream << "Number of back surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumBackSurf << '\n';
5495 60716 : for (NGSS = 1; NGSS <= min(10, state.dataShadowComb->ShadowComb(HTSnum).NumBackSurf); ++NGSS) {
5496 14785 : *state.dataSolarShading->shd_stream
5497 14785 : << "...Surface=" << state.dataSurface->Surface(state.dataShadowComb->ShadowComb(HTSnum).BackSurf(NGSS)).Name << '\n';
5498 : }
5499 45931 : *state.dataSolarShading->shd_stream << "Number of receiving sub surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumSubSurf
5500 45931 : << '\n';
5501 52238 : for (NGSS = 1; NGSS <= min(10, state.dataShadowComb->ShadowComb(HTSnum).NumSubSurf); ++NGSS) {
5502 6307 : *state.dataSolarShading->shd_stream
5503 6307 : << "....Surface=" << state.dataSurface->Surface(state.dataShadowComb->ShadowComb(HTSnum).SubSurf(NGSS)).Name << '\n';
5504 : }
5505 795 : }
5506 : }
5507 :
5508 46726 : for (HTS = 1; HTS <= state.dataSurface->TotSurfaces; ++HTS) {
5509 45931 : if (CastingSurface(HTS) && !state.dataSurface->Surface(HTS).IsConvex) {
5510 0 : if (state.dataGlobal->DisplayExtraWarnings) {
5511 0 : ShowSevereError(state,
5512 0 : format("DetermineShadowingCombinations: Surface=\"{}\" is a casting surface and is non-convex.",
5513 0 : state.dataSurface->Surface(HTS).Name));
5514 0 : ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5515 : } else {
5516 0 : ++state.dataErrTracking->TotalCastingNonConvexSurfaces;
5517 : }
5518 : }
5519 : }
5520 :
5521 795 : if (state.dataErrTracking->TotalReceivingNonConvexSurfaces > 0) {
5522 0 : ShowWarningMessage(state,
5523 0 : format("DetermineShadowingCombinations: There are {} surfaces which are receiving surfaces and are non-convex.",
5524 0 : state.dataErrTracking->TotalReceivingNonConvexSurfaces));
5525 0 : ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5526 0 : ShowContinueError(state, "...Add Output:Diagnostics,DisplayExtraWarnings; to see individual warnings for each surface.");
5527 0 : state.dataErrTracking->TotalWarningErrors += state.dataErrTracking->TotalReceivingNonConvexSurfaces;
5528 : }
5529 :
5530 795 : if (state.dataErrTracking->TotalCastingNonConvexSurfaces > 0) {
5531 0 : ShowSevereMessage(state,
5532 0 : format("DetermineShadowingCombinations: There are {} surfaces which are casting surfaces and are non-convex.",
5533 0 : state.dataErrTracking->TotalCastingNonConvexSurfaces));
5534 0 : ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
5535 0 : ShowContinueError(state, "...Add Output:Diagnostics,DisplayExtraWarnings; to see individual severes for each surface.");
5536 0 : state.dataErrTracking->TotalSevereErrors += state.dataErrTracking->TotalCastingNonConvexSurfaces;
5537 : }
5538 : }
5539 :
5540 796 : CastingSurface.deallocate();
5541 :
5542 : #ifndef EP_NO_OPENGL
5543 796 : if (state.dataSolarShading->penumbra && state.dataSolarShading->penumbra->get_number_of_surfaces() > 0) {
5544 1 : state.dataSolarShading->penumbra->set_model();
5545 : }
5546 : #endif
5547 796 : }
5548 :
5549 299111 : void SHADOW(EnergyPlusData &state,
5550 : int const iHour, // Hour index
5551 : int const TS // Time Step
5552 : )
5553 : {
5554 :
5555 : // SUBROUTINE INFORMATION:
5556 : // AUTHOR Legacy Code
5557 : // DATE WRITTEN
5558 : // MODIFIED Nov 2003, FCW: modify to do shadowing on shadowing surfaces
5559 : // RE-ENGINEERED Lawrie, Oct 2000
5560 :
5561 : // PURPOSE OF THIS SUBROUTINE:
5562 : // This subroutine is a driving routine for calculations of shadows
5563 : // and sunlit areas used in computing the solar beam flux multipliers.
5564 :
5565 : // REFERENCES:
5566 : // BLAST/IBLAST code, original author George Walton
5567 :
5568 : Real64 XS; // Intermediate result
5569 : Real64 YS; // Intermediate result
5570 : Real64 ZS; // Intermediate result
5571 : int N; // Vertex number
5572 : int NGRS; // Coordinate transformation index
5573 : int NVT;
5574 : int HTS; // Heat transfer surface number of the general receiving surface
5575 : int GRSNR; // Surface number of general receiving surface
5576 : int NBKS; // Number of back surfaces
5577 : int NGSS; // Number of general shadowing surfaces
5578 : int NSBS; // Number of subsurfaces (windows and doors)
5579 : Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
5580 : // For windows, includes divider area
5581 :
5582 299111 : if (state.dataSolarShading->ShadowOneTimeFlag) {
5583 796 : state.dataSolarShading->XVrt.allocate(state.dataSurface->MaxVerticesPerSurface + 1);
5584 796 : state.dataSolarShading->YVrt.allocate(state.dataSurface->MaxVerticesPerSurface + 1);
5585 796 : state.dataSolarShading->ZVrt.allocate(state.dataSurface->MaxVerticesPerSurface + 1);
5586 796 : state.dataSolarShading->XVrt = 0.0;
5587 796 : state.dataSolarShading->YVrt = 0.0;
5588 796 : state.dataSolarShading->ZVrt = 0.0;
5589 796 : state.dataSolarShading->ShadowOneTimeFlag = false;
5590 : }
5591 :
5592 : #ifdef EP_Count_Calls
5593 : if (iHour == 0) {
5594 : ++state.dataTimingsData->NumShadow_Calls;
5595 : } else {
5596 : ++state.dataTimingsData->NumShadowAtTS_Calls;
5597 : }
5598 : #endif
5599 :
5600 299111 : state.dataSolarShading->SurfSunlitArea = 0.0;
5601 :
5602 : #ifndef EP_NO_OPENGL
5603 299111 : if (state.dataSolarShading->penumbra) {
5604 239 : Real64 ElevSun = Constant::PiOvr2 - std::acos(state.dataSolarShading->SUNCOS(3));
5605 239 : Real64 AzimSun = std::atan2(state.dataSolarShading->SUNCOS(1), state.dataSolarShading->SUNCOS(2));
5606 239 : state.dataSolarShading->penumbra->set_sun_position(AzimSun, ElevSun);
5607 239 : state.dataSolarShading->penumbra->submit_pssa();
5608 : }
5609 : #endif
5610 :
5611 18640969 : for (GRSNR = 1; GRSNR <= state.dataSurface->TotSurfaces; ++GRSNR) {
5612 :
5613 18341858 : if (!state.dataShadowComb->ShadowComb(GRSNR).UseThisSurf) continue;
5614 :
5615 4799513 : state.dataSolarShading->SurfSunlitArea(GRSNR) = 0.0;
5616 :
5617 4799513 : NGSS = state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf;
5618 4799513 : state.dataSolarShading->NGSSHC = 0;
5619 4799513 : NBKS = state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf;
5620 4799513 : state.dataSolarShading->NBKSHC = 0;
5621 4799513 : NSBS = state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf;
5622 4799513 : state.dataSolarShading->NRVLHC = 0;
5623 4799513 : state.dataSolarShading->NSBSHC = 0;
5624 4799513 : state.dataSolarShading->LOCHCA = 1;
5625 : // Temporarily determine the old heat transfer surface number (HTS)
5626 4799513 : HTS = GRSNR;
5627 :
5628 4799513 : if (state.dataSolarShading->SurfSunCosTheta(GRSNR) < DataEnvironment::SunIsUpValue) { //.001) THEN ! Receiving surface is not in the sun
5629 :
5630 2025044 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
5631 2025044 : SHDSBS(state, iHour, GRSNR, NBKS, NSBS, HTS, TS);
5632 :
5633 2774469 : } else if ((NGSS <= 0) && (NSBS <= 0)) { // Simple surface--no shaders or subsurfaces
5634 :
5635 1381305 : state.dataSolarShading->SurfSunlitArea(HTS) = state.dataSurface->Surface(GRSNR).NetAreaShadowCalc;
5636 : } else { // Surface in sun and either shading surfaces or subsurfaces present (or both)
5637 :
5638 : #ifndef EP_NO_OPENGL
5639 1393164 : int id = state.dataSurface->SurfPenumbraID(HTS);
5640 1393164 : if (state.dataSolarShading->penumbra && id >= 0) {
5641 : // SurfSunlitArea(HTS) = buildingPSSF.at(id) / SurfSunCosTheta(HTS);
5642 5410 : state.dataSolarShading->SurfSunlitArea(HTS) =
5643 5410 : state.dataSolarShading->penumbra->retrieve_pssa(id) / state.dataSolarShading->SurfSunCosTheta(HTS);
5644 : // SurfSunlitArea(HTS) = penumbra->fetchPSSA(Surface(HTS).PenumbraID)/SurfSunCosTheta(HTS);
5645 7987 : for (int SS = 1; SS <= NSBS; ++SS) {
5646 2577 : int HTSS = state.dataShadowComb->ShadowComb(HTS).SubSurf(SS);
5647 2577 : id = state.dataSurface->SurfPenumbraID(HTSS);
5648 2577 : if (id >= 0) {
5649 : // SurfSunlitArea(HTSS) = buildingPSSF.at(id) / SurfSunCosTheta(HTSS);
5650 2577 : state.dataSolarShading->SurfSunlitArea(HTSS) =
5651 2577 : state.dataSolarShading->penumbra->retrieve_pssa(id) / state.dataSolarShading->SurfSunCosTheta(HTSS);
5652 : // SurfSunlitArea(HTSS) = penumbra->fetchPSSA(Surface(HTSS).PenumbraID)/SurfSunCosTheta(HTSS);
5653 2577 : if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
5654 2328 : if (iHour > 0 && TS > 0)
5655 1059 : state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
5656 1059 : state.dataSolarShading->SurfSunlitArea(HTSS) / state.dataSurface->Surface(HTSS).Area;
5657 : }
5658 : }
5659 : }
5660 1387754 : } else if (!state.dataSolarShading->penumbra) {
5661 : #else
5662 : {
5663 : #endif
5664 1385603 : NGRS = state.dataSurface->Surface(GRSNR).BaseSurf;
5665 1385603 : if (state.dataSurface->Surface(GRSNR).IsShadowing) NGRS = GRSNR;
5666 :
5667 : // Compute the X and Y displacements of a shadow.
5668 1385603 : XS = state.dataSurface->Surface(NGRS).lcsx.x * state.dataSolarShading->SUNCOS(1) +
5669 1385603 : state.dataSurface->Surface(NGRS).lcsx.y * state.dataSolarShading->SUNCOS(2) +
5670 1385603 : state.dataSurface->Surface(NGRS).lcsx.z * state.dataSolarShading->SUNCOS(3);
5671 1385603 : YS = state.dataSurface->Surface(NGRS).lcsy.x * state.dataSolarShading->SUNCOS(1) +
5672 1385603 : state.dataSurface->Surface(NGRS).lcsy.y * state.dataSolarShading->SUNCOS(2) +
5673 1385603 : state.dataSurface->Surface(NGRS).lcsy.z * state.dataSolarShading->SUNCOS(3);
5674 1385603 : ZS = state.dataSurface->Surface(NGRS).lcsz.x * state.dataSolarShading->SUNCOS(1) +
5675 1385603 : state.dataSurface->Surface(NGRS).lcsz.y * state.dataSolarShading->SUNCOS(2) +
5676 1385603 : state.dataSurface->Surface(NGRS).lcsz.z * state.dataSolarShading->SUNCOS(3);
5677 :
5678 1385603 : if (std::abs(ZS) > Constant::SmallDistance) {
5679 1385596 : state.dataSolarShading->XShadowProjection = XS / ZS;
5680 1385596 : state.dataSolarShading->YShadowProjection = YS / ZS;
5681 1385596 : if (std::abs(state.dataSolarShading->XShadowProjection) < 1.e-8) state.dataSolarShading->XShadowProjection = 0.0;
5682 1385596 : if (std::abs(state.dataSolarShading->YShadowProjection) < 1.e-8) state.dataSolarShading->YShadowProjection = 0.0;
5683 : } else {
5684 7 : state.dataSolarShading->XShadowProjection = 0.0;
5685 7 : state.dataSolarShading->YShadowProjection = 0.0;
5686 : }
5687 :
5688 1385603 : CTRANS(state,
5689 : GRSNR,
5690 : NGRS,
5691 : NVT,
5692 1385603 : state.dataSolarShading->XVrt,
5693 1385603 : state.dataSolarShading->YVrt,
5694 1385603 : state.dataSolarShading->ZVrt); // Transform coordinates of the receiving surface to 2-D form
5695 :
5696 : // Re-order its vertices to clockwise sequential.
5697 6913953 : for (N = 1; N <= NVT; ++N) {
5698 5528350 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVrt(NVT + 1 - N);
5699 5528350 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVrt(NVT + 1 - N);
5700 : }
5701 :
5702 1385603 : HTRANS1(state, 1, NVT); // Transform to homogeneous coordinates.
5703 :
5704 1385603 : state.dataSolarShading->HCAREA(1) = -state.dataSolarShading->HCAREA(1); // Compute (+) gross surface area.
5705 1385603 : state.dataSolarShading->HCT(1) = 1.0;
5706 :
5707 1385603 : SHDGSS(state, NGRS, iHour, TS, GRSNR, NGSS, HTS); // Determine shadowing on surface.
5708 :
5709 1385603 : if (!state.dataSolarShading->CalcSkyDifShading) {
5710 888704 : SHDBKS(state, state.dataSurface->Surface(GRSNR).BaseSurf, GRSNR, NBKS, HTS); // Determine possible back surfaces.
5711 : }
5712 : }
5713 :
5714 1393164 : SHDSBS(state, iHour, GRSNR, NBKS, NSBS, HTS, TS); // Subtract subsurf areas from total
5715 :
5716 : // Error checking: require that 0 <= SurfSunlitArea <= AREA. + or - .01*AREA added for round-off errors
5717 1393164 : SurfArea = state.dataSurface->Surface(GRSNR).NetAreaShadowCalc;
5718 1393164 : state.dataSolarShading->SurfSunlitArea(HTS) = max(0.0, state.dataSolarShading->SurfSunlitArea(HTS));
5719 :
5720 1393164 : state.dataSolarShading->SurfSunlitArea(HTS) = min(state.dataSolarShading->SurfSunlitArea(HTS), SurfArea);
5721 : } // ...end of surface in sun/surface with shaders and/or subsurfaces IF-THEN block
5722 :
5723 : // NOTE:
5724 : // There used to be a call to legacy subroutine SHDCVR here when the
5725 : // zone type was not a standard zone.
5726 : }
5727 299111 : }
5728 :
5729 888704 : void SHDBKS(EnergyPlusData &state,
5730 : int const NGRS, // Number of the general receiving surface
5731 : int const CurSurf,
5732 : int const NBKS, // Number of back surfaces
5733 : int const HTS // Heat transfer surface number of the general receiving surf
5734 : )
5735 : {
5736 :
5737 : // SUBROUTINE INFORMATION:
5738 : // AUTHOR Legacy Code
5739 : // DATE WRITTEN
5740 : // MODIFIED na
5741 : // RE-ENGINEERED Lawrie, Oct 2000
5742 :
5743 : // PURPOSE OF THIS SUBROUTINE:
5744 : // This is the driving subroutine for computing
5745 : // the sunlit areas for back surfaces.
5746 :
5747 : // REFERENCES:
5748 : // BLAST/IBLAST code, original author George Walton
5749 :
5750 : typedef Array2D<Int64>::size_type size_type;
5751 : int I;
5752 : int M;
5753 : int N;
5754 : int NVR;
5755 : int NVT; // Number of vertices of back surface
5756 : int BackSurfaceNumber;
5757 : int NS1; // Number of the figure being overlapped
5758 : int NS2; // Number of the figure doing overlapping
5759 : int NS3; // Location to place results of overlap
5760 :
5761 : // Tuned Linear indexing
5762 :
5763 888704 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
5764 888704 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
5765 :
5766 888704 : if (state.dataSolarShading->SHDBKSOneTimeFlag) {
5767 703 : state.dataSolarShading->XVrtx.allocate(state.dataSurface->MaxVerticesPerSurface + 1);
5768 703 : state.dataSolarShading->YVrtx.allocate(state.dataSurface->MaxVerticesPerSurface + 1);
5769 703 : state.dataSolarShading->ZVrtx.allocate(state.dataSurface->MaxVerticesPerSurface + 1);
5770 703 : state.dataSolarShading->XVrtx = 0.0;
5771 703 : state.dataSolarShading->YVrtx = 0.0;
5772 703 : state.dataSolarShading->ZVrtx = 0.0;
5773 703 : state.dataSolarShading->SHDBKSOneTimeFlag = false;
5774 : }
5775 :
5776 1256526 : if ((NBKS <= 0) || (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0) || (state.dataSolarShading->OverlapStatus == TooManyVertices) ||
5777 367822 : (state.dataSolarShading->OverlapStatus == TooManyFigures))
5778 520882 : return;
5779 :
5780 367822 : state.dataSolarShading->FBKSHC = state.dataSolarShading->LOCHCA + 1;
5781 :
5782 2895853 : for (I = 1; I <= NBKS; ++I) { // Loop through all back surfaces associated with the receiving surface
5783 :
5784 2528031 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(CurSurf).BackSurf(I);
5785 :
5786 2528031 : if (state.dataSolarShading->SurfSunCosTheta(BackSurfaceNumber) > -DataEnvironment::SunIsUpValue)
5787 1026208 : continue; //-0.001) CYCLE ! go to next back surface since inside of this surface
5788 : // cannot be in sun if the outside can be
5789 :
5790 : // Transform coordinates of back surface from general system to the
5791 : // plane of the receiving surface
5792 :
5793 1501823 : CTRANS(state, BackSurfaceNumber, NGRS, NVT, state.dataSolarShading->XVrtx, state.dataSolarShading->YVrtx, state.dataSolarShading->ZVrtx);
5794 :
5795 : // Project "shadow" from back surface along sun's rays to receiving surface. Back surface vertices
5796 : // become clockwise sequential.
5797 :
5798 7538515 : for (N = 1; N <= NVT; ++N) {
5799 6036692 : state.dataSolarShading->XVS(N) =
5800 6036692 : state.dataSolarShading->XVrtx(N) - state.dataSolarShading->XShadowProjection * state.dataSolarShading->ZVrtx(N);
5801 6036692 : state.dataSolarShading->YVS(N) =
5802 6036692 : state.dataSolarShading->YVrtx(N) - state.dataSolarShading->YShadowProjection * state.dataSolarShading->ZVrtx(N);
5803 : }
5804 :
5805 : // Transform to the homogeneous coordinate system.
5806 :
5807 1501823 : NS3 = state.dataSolarShading->LOCHCA + 1;
5808 1501823 : state.dataSolarShading->HCT(NS3) = 0.0;
5809 1501823 : HTRANS1(state, NS3, NVT);
5810 :
5811 : // Adjust near-duplicate points.
5812 :
5813 1501823 : NVR = state.dataSolarShading->HCNV(1);
5814 1501823 : int l3 = state.dataSolarShading->HCX.index(NS3, 1);
5815 7538515 : for (N = 1; N <= NVT; ++N, ++l3) {
5816 6036692 : Real64 const x3 = state.dataSolarShading->HCX[l3]; // [ l3 ] == ( NS3, N )
5817 6036692 : Real64 const y3 = state.dataSolarShading->HCY[l3];
5818 6036692 : size_type l1 = 0;
5819 26266762 : for (M = 1; M <= NVR; ++M, ++l1) {
5820 21803854 : if (std::abs(state.dataSolarShading->HCX[l1] - x3) > 6) continue; // [ l1 ] == ( 1, M )
5821 2560006 : if (std::abs(state.dataSolarShading->HCY[l1] - y3) > 6) continue;
5822 1573784 : state.dataSolarShading->HCX[l3] = state.dataSolarShading->HCX[l1];
5823 1573784 : state.dataSolarShading->HCY[l3] = state.dataSolarShading->HCY[l1];
5824 1573784 : break;
5825 : }
5826 : }
5827 :
5828 1501823 : HTRANS0(state, NS3, NVT);
5829 :
5830 : // Determine area of overlap of projected back surface and receiving surface.
5831 :
5832 1501823 : NS1 = 1;
5833 1501823 : NS2 = NS3;
5834 1501823 : state.dataSolarShading->HCT(NS3) = 1.0;
5835 1501823 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
5836 :
5837 1501823 : if (state.dataSolarShading->OverlapStatus == NoOverlap) continue; // to next back surface
5838 980421 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
5839 0 : break; // back surfaces DO loop
5840 :
5841 : // Increment back surface count.
5842 :
5843 980421 : state.dataSolarShading->LOCHCA = NS3;
5844 980421 : state.dataSolarShading->HCNS(state.dataSolarShading->LOCHCA) = BackSurfaceNumber;
5845 980421 : state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
5846 980421 : state.dataSolarShading->NBKSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FBKSHC + 1;
5847 : }
5848 : }
5849 :
5850 1385603 : void SHDGSS(EnergyPlusData &state,
5851 : int const NGRS,
5852 : int const iHour, // Hour Counter
5853 : int const TS, // TimeStep
5854 : int const CurSurf, // Current Surface
5855 : int const NGSS, // Number of general shadowing surfaces
5856 : int const HTS // Heat transfer surface number of the general receiving surf
5857 : )
5858 : {
5859 :
5860 : // SUBROUTINE INFORMATION:
5861 : // AUTHOR Legacy Code
5862 : // DATE WRITTEN
5863 : // MODIFIED na
5864 : // RE-ENGINEERED Lawrie, Oct 2000
5865 :
5866 : // PURPOSE OF THIS SUBROUTINE:
5867 : // This subroutine determines the shadows on a general receiving surface.
5868 :
5869 : // REFERENCES:
5870 : // BLAST/IBLAST code, original author George Walton
5871 :
5872 : // Using/Aliasing
5873 : using ScheduleManager::GetCurrentScheduleValue;
5874 : using ScheduleManager::GetScheduleMinValue;
5875 : using ScheduleManager::GetScheduleName;
5876 : using ScheduleManager::LookUpScheduleValue;
5877 :
5878 : typedef Array2D<Int64>::size_type size_type;
5879 : int GSSNR; // General shadowing surface number
5880 : int MainOverlapStatus; // Overlap status of the main overlap calculation not the check for
5881 : // multiple overlaps (unless there was an error)
5882 : int NS1; // Number of the figure being overlapped
5883 : int NS2; // Number of the figure doing overlapping
5884 : int NS3; // Location to place results of overlap
5885 : Real64 SchValue; // Value for Schedule of shading transmittence
5886 :
5887 1385603 : if (state.dataSolarShading->SHDGSSOneTimeFlag) {
5888 703 : state.dataSolarShading->XVert.dimension(state.dataSurface->MaxVerticesPerSurface + 1, 0.0);
5889 703 : state.dataSolarShading->YVert.dimension(state.dataSurface->MaxVerticesPerSurface + 1, 0.0);
5890 703 : state.dataSolarShading->ZVert.dimension(state.dataSurface->MaxVerticesPerSurface + 1, 0.0);
5891 703 : state.dataSolarShading->SHDGSSOneTimeFlag = false;
5892 : }
5893 :
5894 1385603 : state.dataSolarShading->FGSSHC = state.dataSolarShading->LOCHCA + 1;
5895 1385603 : MainOverlapStatus = NoOverlap; // Set to ensure that the value from the last surface is not saved
5896 1385603 : state.dataSolarShading->OverlapStatus = NoOverlap;
5897 :
5898 1385603 : if (NGSS <= 0) { // IF NO S.S., receiving surface FULLY SUNLIT.
5899 :
5900 649691 : state.dataSolarShading->SurfSunlitArea(HTS) = state.dataSolarShading->HCAREA(1); // Surface fully sunlit
5901 :
5902 : } else {
5903 :
5904 735912 : int ExitLoopStatus = -1;
5905 735912 : auto const &GenSurf = state.dataShadowComb->ShadowComb(CurSurf).GenSurf;
5906 735912 : int const sunIsUp = DataEnvironment::SunIsUpValue;
5907 6183799 : for (int I = 1; I <= NGSS; ++I) { // Loop through all shadowing surfaces...
5908 :
5909 5464782 : GSSNR = GenSurf(I);
5910 :
5911 5464782 : if (state.dataSolarShading->SurfSunCosTheta(GSSNR) > sunIsUp) continue; //.001) CYCLE ! NO SHADOW IF GSS IN SUNLIGHT.
5912 :
5913 3525148 : auto const &surface = state.dataSurface->Surface(GSSNR);
5914 3525148 : bool const notHeatTransSurf = !surface.HeatTransSurf;
5915 :
5916 : // This used to check to see if the shadowing surface was not opaque (within the scheduled dates of
5917 : // transmittance value. Perhaps it ignored it if it were outside the range. (if so, was an error)
5918 : // The proper action seems to be delete this statement all together, but there would also be no shading if
5919 : // the shading surface were transparent...
5920 : //---former stmt IF ((.NOT.Surface(GSSNR)%HeatTransSurf) .AND. &
5921 : //---former stmt GetCurrentScheduleValue(state, Surface(GSSNR)%SchedShadowSurfIndex,IHOUR) == 0.0) CYCLE
5922 :
5923 3525148 : if (notHeatTransSurf) {
5924 1491292 : if (surface.IsTransparent) continue; // No shadow if shading surface is transparent
5925 1491292 : if (surface.SchedShadowSurfIndex > 0) {
5926 1159867 : if (LookUpScheduleValue(state, surface.SchedShadowSurfIndex, iHour) == 1.0) continue;
5927 1159867 : if (!state.dataSolarShading->CalcSkyDifShading) {
5928 626599 : if (LookUpScheduleValue(state, surface.SchedShadowSurfIndex, iHour, TS) == 1.0) continue;
5929 : }
5930 : }
5931 : }
5932 : // Elimate shawdowing surfaces that is supposed to be disabled.
5933 3525148 : if (state.dataSysVars->DisableAllSelfShading) {
5934 60945 : if (surface.Zone != 0) {
5935 31576 : continue; // Disable all shadowing surfaces in all zones. Attached shading surfaces are not part of a zone, zone value is 0.
5936 : }
5937 3464203 : } else if (state.dataSysVars->DisableGroupSelfShading) {
5938 59395 : std::vector<int> DisabledZones = state.dataSurface->SurfShadowDisabledZoneList(CurSurf);
5939 59395 : bool isDisabledShadowSurf = false;
5940 164659 : for (int i : DisabledZones) {
5941 111518 : if (surface.Zone == i) {
5942 6254 : isDisabledShadowSurf = true;
5943 6254 : break;
5944 : }
5945 59395 : }
5946 59395 : if (isDisabledShadowSurf) continue; // Disable all shadowing surfaces in all disabled zones.
5947 59395 : }
5948 :
5949 : // IF ((.NOT.Surface(GSSNR)%HeatTransSurf) .AND. &
5950 : // GetCurrentScheduleValue(state, Surface(GSSNR)%SchedShadowSurfIndex) == 1.0) CYCLE
5951 :
5952 : // Transform shadow casting surface from cartesian to homogeneous coordinates according to surface type.
5953 :
5954 3487318 : if ((notHeatTransSurf) && (surface.BaseSurf != 0)) {
5955 :
5956 : // For shadowing subsurface coordinates of shadow casting surface are relative to the receiving surface
5957 : // project shadow to the receiving surface
5958 :
5959 0 : state.dataSolarShading->NVS = surface.Sides;
5960 0 : auto const &XV = state.dataSurface->ShadeV(GSSNR).XV;
5961 0 : auto const &YV = state.dataSurface->ShadeV(GSSNR).YV;
5962 0 : auto const &ZV = state.dataSurface->ShadeV(GSSNR).ZV;
5963 0 : for (int N = 1; N <= state.dataSolarShading->NVS; ++N) {
5964 0 : state.dataSolarShading->XVS(N) = XV(N) - state.dataSolarShading->XShadowProjection * ZV(N);
5965 0 : state.dataSolarShading->YVS(N) = YV(N) - state.dataSolarShading->YShadowProjection * ZV(N);
5966 : }
5967 :
5968 0 : } else {
5969 : // Transform coordinates of shadow casting surface from general system to the system relative to the receiving surface
5970 : int NVT;
5971 3487318 : CTRANS(state, GSSNR, NGRS, NVT, state.dataSolarShading->XVert, state.dataSolarShading->YVert, state.dataSolarShading->ZVert);
5972 3487318 : CLIP(state,
5973 : NVT,
5974 3487318 : state.dataSolarShading->XVert,
5975 3487318 : state.dataSolarShading->YVert,
5976 3487318 : state.dataSolarShading->ZVert); // Clip portions of the shadow casting surface which are behind the receiving surface
5977 :
5978 3487318 : if (state.dataSolarShading->NumVertInShadowOrClippedSurface <= 2) continue;
5979 :
5980 : // Project shadow from shadow casting surface along sun's rays to receiving surface Shadow vertices
5981 : // become clockwise sequential
5982 :
5983 17349355 : for (int N = 1; N <= state.dataSolarShading->NumVertInShadowOrClippedSurface; ++N) {
5984 13862037 : state.dataSolarShading->XVS(N) =
5985 13862037 : state.dataSolarShading->XVC(N) - state.dataSolarShading->XShadowProjection * state.dataSolarShading->ZVC(N);
5986 13862037 : state.dataSolarShading->YVS(N) =
5987 13862037 : state.dataSolarShading->YVC(N) - state.dataSolarShading->YShadowProjection * state.dataSolarShading->ZVC(N);
5988 : }
5989 : }
5990 :
5991 : // Transform to the homogeneous coordinate system.
5992 :
5993 3487318 : NS3 = state.dataSolarShading->LOCHCA + 1;
5994 3487318 : HTRANS1(state, NS3, state.dataSolarShading->NVS);
5995 :
5996 : // Adjust near-duplicate points.
5997 :
5998 3487318 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
5999 3487318 : assert(state.dataSolarShading->HCX.index(1, 1) == 0u);
6000 3487318 : size_type j(state.dataSolarShading->HCX.index(NS3, 1));
6001 3487318 : size_type NVR(state.dataSolarShading->HCNV(1));
6002 17349355 : for (int N = 1; N <= state.dataSolarShading->NumVertInShadowOrClippedSurface;
6003 13862037 : ++N, ++j) { // Tuned Logic change: break after 1st "close" point found
6004 13862037 : Int64 const HCX_N(state.dataSolarShading->HCX[j]); // [ j ] == ( NS3, N )
6005 13862037 : Int64 const HCY_N(state.dataSolarShading->HCY[j]);
6006 68301876 : for (size_type l = 0; l < NVR; ++l) { // [ l ] == ( 1, l+1 )
6007 54734362 : Real64 const delX = std::abs(state.dataSolarShading->HCX[l] - HCX_N);
6008 54734362 : if (delX > 6) continue;
6009 926738 : Real64 const delY = std::abs(state.dataSolarShading->HCY[l] - HCY_N);
6010 926738 : if (delY > 6) continue;
6011 294523 : if (delX > 0) state.dataSolarShading->HCX[j] = state.dataSolarShading->HCX[l]; // [ j ] == ( NS3, N )
6012 294523 : if (delY > 0) state.dataSolarShading->HCY[j] = state.dataSolarShading->HCY[l];
6013 294523 : break;
6014 : }
6015 : }
6016 3487318 : HTRANS0(state, NS3, state.dataSolarShading->NumVertInShadowOrClippedSurface);
6017 3487318 : if (!state.dataSolarShading->CalcSkyDifShading) {
6018 2061484 : if (iHour != 0) {
6019 2061484 : SchValue = LookUpScheduleValue(state, surface.SchedShadowSurfIndex, iHour, TS);
6020 : } else {
6021 0 : SchValue = surface.SchedMinValue;
6022 : }
6023 : } else {
6024 1425834 : SchValue = surface.SchedMinValue;
6025 : }
6026 :
6027 3487318 : state.dataSolarShading->HCT(NS3) = SchValue;
6028 :
6029 : // Determine overlap of shadow with receiving surface
6030 :
6031 3487318 : state.dataSolarShading->CurrentShadowingSurface = I;
6032 3487318 : state.dataSolarShading->CurrentSurfaceBeingShadowed = GSSNR;
6033 3487318 : NS1 = 1;
6034 3487318 : NS2 = NS3;
6035 3487318 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
6036 : // Next statement is special to deal with transmitting shading devices
6037 3487318 : if (state.dataSolarShading->OverlapStatus == FirstSurfWithinSecond && SchValue > 0.0)
6038 328 : state.dataSolarShading->OverlapStatus = PartialOverlap;
6039 3487318 : MainOverlapStatus = state.dataSolarShading->OverlapStatus;
6040 3487318 : ExitLoopStatus = MainOverlapStatus;
6041 :
6042 3487318 : if (MainOverlapStatus == NoOverlap) { // No overlap of general surface shadow and receiving surface
6043 : // Continue
6044 623864 : } else if ((MainOverlapStatus == FirstSurfWithinSecond) || (MainOverlapStatus == TooManyVertices) ||
6045 : (MainOverlapStatus == TooManyFigures)) {
6046 16895 : goto ShadowingSurfaces_exit;
6047 606969 : } else if ((MainOverlapStatus == SecondSurfWithinFirst) || (MainOverlapStatus == PartialOverlap)) {
6048 : // Determine overlaps with previous shadows.
6049 606969 : state.dataSolarShading->LOCHCA = NS3;
6050 606969 : state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
6051 606969 : if (state.dataSolarShading->NGSSHC > 1)
6052 244058 : MULTOL(state,
6053 244058 : state.dataSolarShading->LOCHCA,
6054 244058 : state.dataSolarShading->FGSSHC - 1,
6055 244058 : state.dataSolarShading->NGSSHC - 1); // HOYT - Remove this call
6056 : } else {
6057 0 : goto ShadowingSurfaces_exit;
6058 : }
6059 :
6060 3470423 : ExitLoopStatus = -1;
6061 : }
6062 719017 : ShadowingSurfaces_exit:;
6063 :
6064 : // Compute sunlit area of surface (excluding effects of subsurfs).
6065 :
6066 735912 : if (ExitLoopStatus == FirstSurfWithinSecond) { // Surface fully shaded
6067 16895 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
6068 16895 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FGSSHC;
6069 :
6070 719017 : } else if ((ExitLoopStatus == TooManyVertices) || (ExitLoopStatus == TooManyFigures)) { // Array limits exceeded, estimate
6071 0 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.25 * state.dataSolarShading->HCAREA(1);
6072 :
6073 : } else {
6074 :
6075 : // Compute the sunlit area here.
6076 : // Call UnionShadow(FGSSHC,LOCHCA)
6077 :
6078 719017 : state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
6079 719017 : if (state.dataSolarShading->NGSSHC <= 0) {
6080 357261 : state.dataSolarShading->SurfSunlitArea(HTS) = state.dataSolarShading->HCAREA(1); // Surface fully sunlit
6081 : } else {
6082 361756 : Real64 A(state.dataSolarShading->HCAREA(1)); // Area
6083 1057762 : for (int i = state.dataSolarShading->FGSSHC, e = state.dataSolarShading->FGSSHC + state.dataSolarShading->NGSSHC - 1; i <= e; ++i) {
6084 696006 : A += state.dataSolarShading->HCAREA(i) * (1.0 - state.dataSolarShading->HCT(i));
6085 : }
6086 361756 : state.dataSolarShading->SurfSunlitArea(HTS) = A;
6087 361756 : if (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0) { // Surface fully shaded
6088 8955 : state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
6089 8955 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FGSSHC;
6090 : }
6091 : }
6092 : }
6093 : }
6094 1385603 : state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
6095 1385603 : }
6096 :
6097 1606249 : void CalcInteriorSolarOverlaps(EnergyPlusData &state,
6098 : int const iHour, // Hour Index
6099 : int const NBKS, // Number of back surfaces associated with this GRSNR (in general, only
6100 : int const HTSS, // Surface number of the subsurface (exterior window)
6101 : int const GRSNR, // General receiving surface number (base surface of the exterior window)
6102 : int const TS // Time step Index
6103 : )
6104 : {
6105 :
6106 : // SUBROUTINE INFORMATION:
6107 : // AUTHOR Fred Winkelmann
6108 : // DATE WRITTEN January 1999
6109 : // MODIFIED Nov 2001, FW: include beam radiation overlaps with
6110 : // back windows and doors; previously these subsurfaces ignored.
6111 : // May 2002, FW: fix problem where reveal was not being considered
6112 : // in calculating overlap areas if window is shaded only by reveal.
6113 : // June 2002, FW: fix problem that gave incorrect calculation when
6114 : // window is not shaded only by reveal
6115 : // June 2002, FW: remove incorrect multiplication of overlap areas
6116 : // by sunlit fraction when window is shaded only by reveal
6117 :
6118 : // PURPOSE OF THIS SUBROUTINE:
6119 : // For an exterior window with surface number HTSS, determines (1) the surface numbers of back
6120 : // surfaces receiving beam radiation from the window and (2) for each such back surface, the area
6121 : // of the portion of the window sending beam radiation to the back surface; this is called the
6122 : // "overlap area."
6123 :
6124 : // REFERENCES:
6125 : // BLAST/IBLAST code, original author George Walton
6126 :
6127 : // SUBROUTINE ARGUMENT DEFINITIONS:
6128 : // some of these will receive beam radiation from HTSS this hour)
6129 :
6130 : // SUBROUTINE PARAMETER DEFINITIONS:
6131 1606249 : int constexpr WindowShadedOnlyByReveal(2); // for use with RevealStatus
6132 :
6133 : typedef Array2D<Int64>::size_type size_type;
6134 : int JBKS; // Counter of back surfaces with non-zero overlap with HTSS
6135 : int BackSurfNum; // Back surface number
6136 :
6137 : bool UseSimpleDistribution; // TRUE means simple interior solar distribution
6138 : // (all incoming beam assumed to strike floor),
6139 : // FALSE means exact interior solar distribution
6140 : // (track which back surfaces beam illuminates)
6141 :
6142 : // Tuned Linear indexing
6143 :
6144 1606249 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
6145 1606249 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
6146 1606249 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
6147 1606249 : assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
6148 :
6149 1606249 : if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
6150 :
6151 864657 : UseSimpleDistribution = false;
6152 :
6153 864657 : if ((NBKS <= 0) || (state.dataSurface->Surface(GRSNR).ExtBoundCond > 0)) {
6154 :
6155 267123 : UseSimpleDistribution = true;
6156 :
6157 : } else {
6158 : // Using 'exact' distribution, replace subsurface HC entries with reveal HC entries
6159 : // so that the reveal HC is used in calculating interior solar overlap areas
6160 :
6161 : // Adding the following line fixes a problem where, if the window was shaded only
6162 : // by reveal, then the reveal was not considered in calculating interior solar
6163 : // overlap areas (FCW 5/3/02).
6164 : // IF(Surface(HTSS)%Reveal > 0.0) NRVLHC = 1
6165 : // Changing the line to the following avoids incorrect calculation when window is not shaded
6166 : // only by reveal (FCW 6/28/02).
6167 597534 : if (state.dataSolarShading->SurfWinRevealStatus(iHour, TS, HTSS) == WindowShadedOnlyByReveal) state.dataSolarShading->NRVLHC = 1;
6168 597534 : if (state.dataSolarShading->NRVLHC > 0) {
6169 22490 : for (int I = 1; I <= state.dataSolarShading->NRVLHC; ++I) {
6170 14472 : int const iS(state.dataSolarShading->FSBSHC - 1 + I);
6171 14472 : int const iR(state.dataSolarShading->FRVLHC - 1 + I);
6172 14472 : state.dataSolarShading->HCT(iS) = state.dataSolarShading->HCT(iR);
6173 14472 : state.dataSolarShading->HCNV(iS) = state.dataSolarShading->HCNV(iR);
6174 14472 : state.dataSolarShading->HCAREA(iS) = state.dataSolarShading->HCAREA(iR);
6175 14472 : size_type lS(state.dataSolarShading->HCX.index(iS, 1));
6176 14472 : size_type lR(state.dataSolarShading->HCX.index(iR, 1));
6177 231552 : for (int J = 1; J <= state.dataSolarShading->MaxHCV; ++J, ++lS, ++lR) { // [ lS ] == ( iS, J ), [ lR ] == ( iR, J )
6178 217080 : state.dataSolarShading->HCX[lS] = state.dataSolarShading->HCX[lR];
6179 217080 : state.dataSolarShading->HCY[lS] = state.dataSolarShading->HCY[lR];
6180 217080 : state.dataSolarShading->HCA[lS] = state.dataSolarShading->HCA[lR];
6181 217080 : state.dataSolarShading->HCB[lS] = state.dataSolarShading->HCB[lR];
6182 217080 : state.dataSolarShading->HCC[lS] = state.dataSolarShading->HCC[lR];
6183 : }
6184 : }
6185 8018 : state.dataSolarShading->NSBSHC = state.dataSolarShading->NRVLHC;
6186 : }
6187 : }
6188 :
6189 : // Check for array space.
6190 864657 : if (state.dataSolarShading->FSBSHC + state.dataSolarShading->NBKSHC > state.dataSolarShading->MaxHCS) UseSimpleDistribution = true;
6191 :
6192 864657 : if (!UseSimpleDistribution) { // Compute overlaps
6193 :
6194 597534 : std::unordered_map<unsigned, float> pssas;
6195 :
6196 : #ifndef EP_NO_OPENGL
6197 597534 : if (state.dataSolarShading->penumbra) {
6198 : // Add back surfaces to array
6199 1059 : std::vector<unsigned> pbBackSurfaces;
6200 11599 : for (int bkSurfNum : state.dataShadowComb->ShadowComb(GRSNR).BackSurf) {
6201 10540 : if (bkSurfNum == 0) continue;
6202 9481 : if (state.dataSolarShading->SurfSunCosTheta(bkSurfNum) < DataEnvironment::SunIsUpValue) {
6203 5405 : pbBackSurfaces.push_back(state.dataSurface->SurfPenumbraID(bkSurfNum));
6204 : }
6205 : }
6206 : pssas =
6207 1059 : state.dataSolarShading->penumbra->calculate_interior_pssas({(unsigned)state.dataSurface->SurfPenumbraID(HTSS)}, pbBackSurfaces);
6208 : // penumbra->render_interior_scene({(unsigned)Surface(HTSS).PenumbraID}, pbBackSurfaces);
6209 :
6210 1059 : JBKS = 0;
6211 11599 : for (int bkSurfNum : state.dataShadowComb->ShadowComb(GRSNR).BackSurf) {
6212 10540 : if (bkSurfNum == 0) continue;
6213 9481 : if (pssas[state.dataSurface->SurfPenumbraID(bkSurfNum)] > 0) {
6214 1655 : ++JBKS;
6215 1655 : state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, JBKS, HTSS) = bkSurfNum;
6216 1655 : Real64 OverlapArea = pssas[state.dataSurface->SurfPenumbraID(bkSurfNum)] / state.dataSolarShading->SurfSunCosTheta(HTSS);
6217 1655 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS) =
6218 1655 : OverlapArea * state.dataSurface->SurfaceWindow(HTSS).glazedFrac;
6219 : }
6220 : }
6221 1059 : }
6222 : #endif
6223 :
6224 597534 : if (!state.dataSolarShading->penumbra) {
6225 :
6226 596475 : state.dataSolarShading->FINSHC = state.dataSolarShading->FSBSHC + state.dataSolarShading->NSBSHC;
6227 :
6228 596475 : JBKS = 0;
6229 :
6230 2321412 : for (int IBKS = 1; IBKS <= state.dataSolarShading->NBKSHC;
6231 : ++IBKS) { // Loop over back surfaces to GRSNR this hour. NBKSHC is the number of
6232 : // back surfaces that would receive beam radiation from the base surface, GRSNR,
6233 : // if the base surface was transparent. In general, some (at least one) or all of these
6234 : // will receive beam radiation from the exterior window subsurface, HTSS, of GRSNR,
6235 : // depending on the size of HTSS and its location on GRSNR
6236 :
6237 1724937 : BackSurfNum = state.dataSolarShading->HCNS(state.dataSolarShading->FBKSHC - 1 + IBKS);
6238 :
6239 : // Determine if this back surface number can receive beam radiation from the
6240 : // exterior window, HTSS, this hour, i.e., overlap area is positive
6241 :
6242 1724937 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FINSHC - 1;
6243 :
6244 1724937 : MULTOL(state, state.dataSolarShading->FBKSHC - 1 + IBKS, state.dataSolarShading->FSBSHC - 1, state.dataSolarShading->NSBSHC);
6245 :
6246 : // Compute overlap area for this back surface
6247 :
6248 1724937 : state.dataSolarShading->NINSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FINSHC + 1;
6249 1724937 : if (state.dataSolarShading->NINSHC <= 0) continue;
6250 1108211 : Real64 OverlapArea = state.dataSolarShading->HCAREA(state.dataSolarShading->FINSHC);
6251 1181136 : for (int J = 2; J <= state.dataSolarShading->NINSHC; ++J) {
6252 72925 : OverlapArea += state.dataSolarShading->HCAREA(state.dataSolarShading->FINSHC - 1 + J) *
6253 72925 : (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FINSHC - 1 + J));
6254 : }
6255 :
6256 1108211 : if (OverlapArea > 0.001) {
6257 1100257 : ++JBKS;
6258 1100257 : if (JBKS <= state.dataBSDFWindow->MaxBkSurf) {
6259 1100257 : state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, JBKS, HTSS) = BackSurfNum;
6260 1100257 : int baseSurfaceNum = state.dataSurface->Surface(BackSurfNum).BaseSurf;
6261 1100257 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS) =
6262 1100257 : OverlapArea * state.dataSurface->SurfaceWindow(HTSS).glazedFrac;
6263 : // If this is a subsurface, subtract its overlap area from its base surface
6264 1100257 : if (baseSurfaceNum != BackSurfNum) {
6265 76781 : for (int iBaseBKS = 1; iBaseBKS <= JBKS; ++iBaseBKS) {
6266 76779 : if (baseSurfaceNum == state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, iBaseBKS, HTSS)) {
6267 58712 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, iBaseBKS, HTSS) =
6268 58712 : max(0.0,
6269 58712 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, iBaseBKS, HTSS) -
6270 58712 : state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS));
6271 58712 : break;
6272 : }
6273 : }
6274 : }
6275 : }
6276 : }
6277 : } // End of loop over back surfaces
6278 : }
6279 597534 : }
6280 : } // End of check that sunlit area > 0.
6281 1606249 : }
6282 915637 : void CalcInteriorSolarDistribution(EnergyPlusData &state)
6283 : {
6284 :
6285 : // SUBROUTINE INFORMATION:
6286 : // AUTHOR Fred Winkelmann
6287 : // DATE WRITTEN January 1999
6288 : // MODIFIED Nov 1999, FW, for Window5 calculation method
6289 : // Oct 2000, FW: add transmitted solar variables for reporting
6290 : // Mar 2001, FW: add new calc of solar absorbed by window shades
6291 : // May 2001, FW: add calc of solar transmitted and absorbed by window blinds
6292 : // Oct 2001, LL: remove interpolation, solar now at time step
6293 : // Oct 2001, FW: add solar transmitted through interior windows
6294 : // Mar 24, 2001, FW: remove incorrect multiplication of Boverlap by sunlit fraction
6295 : // since effect of shadowing is already included in Aoverlap
6296 : // Apr 2001, FW: add effects of beam solar reflection from outside and inside reveals
6297 : // Jan 2003, FW: add between-glass shades and blinds
6298 : // Dec 2003, FW: report beam incident on inside of surface
6299 : // Jan 2004, FW: for blinds with horizontal slats, allow different diffuse/diffuse
6300 : // transmittance for ground and sky solar
6301 : // Apr 2004, FW: allow diffusing glazing
6302 : // May 2006, RR: allow external window screen
6303 : // Jan 2010, TH: add calculating and reporting of WinBmBmSolar, WinBmDifSolar,
6304 : // WinBmBmSolarEnergy, and WinBmDifSolarEnergy
6305 : // Jun 2013, SV: scheduled surface gains for walls and windows
6306 :
6307 : // PURPOSE OF THIS SUBROUTINE:
6308 : // For a time step, calculates solar radiation absorbed by exterior
6309 : // surfaces and interior solar radiation distribution
6310 :
6311 : using Dayltg::TransTDD;
6312 : using General::POLYF;
6313 : using ScheduleManager::GetCurrentScheduleValue;
6314 : using namespace DataWindowEquivalentLayer;
6315 :
6316 915637 : Array1D<Real64> CFBoverlap; // Sum of boverlap for each back surface
6317 915637 : Array2D<Real64> CFDirBoverlap; // Directional boverlap (Direction, IBack)
6318 :
6319 : #ifdef EP_Count_Calls
6320 : ++state.dataTimingsData->NumIntSolarDist_Calls;
6321 : #endif
6322 7239760 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
6323 12663114 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
6324 6338991 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
6325 6338991 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
6326 6338991 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
6327 13851121 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
6328 60097040 : for (int lay = 1; lay <= CFSMAXNL + 1; ++lay) {
6329 52584910 : state.dataSurface->SurfWinA(SurfNum, lay) = 0.0;
6330 : }
6331 7512130 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfNum) = 0.0;
6332 7512130 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = 0.0;
6333 : }
6334 6338991 : int const firstSurfOpaque = thisSpace.OpaqOrIntMassSurfaceFirst;
6335 6338991 : int const lastSurfOpaque = thisSpace.OpaqOrIntMassSurfaceLast;
6336 53180088 : for (int SurfNum = firstSurfOpaque; SurfNum <= lastSurfOpaque; ++SurfNum) {
6337 46841097 : state.dataSurface->SurfOpaqAI(SurfNum) = 0.0;
6338 46841097 : state.dataSurface->SurfOpaqAO(SurfNum) = 0.0;
6339 : }
6340 6324123 : }
6341 : }
6342 915637 : if ((int)state.dataDaylightingDevicesData->TDDPipe.size() > 0) {
6343 1848 : for (auto &e : state.dataDaylightingDevicesData->TDDPipe) {
6344 1232 : int SurfDome = e.Dome;
6345 9856 : for (int lay = 1; lay <= CFSMAXNL + 1; ++lay) {
6346 8624 : state.dataSurface->SurfWinA(SurfDome, lay) = 0.0;
6347 : }
6348 1232 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfDome) = 0.0;
6349 1232 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfDome) = 0.0;
6350 : }
6351 : }
6352 :
6353 7238521 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
6354 : // Solar entering a zone as beam or diffuse radiation, originating as beam solar incident on exterior windows)/(Beam normal solar) [W/(W/m2)]
6355 6322884 : Real64 BTOTZone = 0.0;
6356 : // Beam radiation from exterior windows absorbed in a zone or transmitted through
6357 6322884 : Real64 BABSZone = 0.0;
6358 6322884 : state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
6359 6322884 : state.dataHeatBal->EnclSolDBSSG(enclosureNum) = 0.0;
6360 6322884 : state.dataHeatBal->EnclSolDBIntWin(enclosureNum) = 0.0;
6361 : // Loop over exterior surfaces in this zone
6362 6322884 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
6363 : // delete values from previous timestep
6364 6322884 : if (state.dataHeatBal->AnyBSDF) state.dataSurface->SurfWinACFOverlap = 0.0;
6365 :
6366 : //-------------------------------------------------------------------------
6367 : // EXTERIOR BEAM SOLAR RADIATION ABSORBED ON THE OUTSIDE OF OPAQUE SURFACES
6368 : //-------------------------------------------------------------------------
6369 : // TODO: use opaq and window loop after airboundary is sorted
6370 : // TODO: It may be useful to sort SurfacePtr to group windows and domes together to reduce if conditions
6371 60677343 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
6372 101196788 : if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Window &&
6373 46842329 : state.dataSurface->Surface(SurfNum).Class != SurfaceClass::TDD_Dome) {
6374 46841097 : if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
6375 46841097 : if (!state.dataSurface->Surface(SurfNum).ExtSolar) continue;
6376 13410153 : int const ConstrNum = state.dataSurface->SurfActiveConstruction(SurfNum);
6377 13410153 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
6378 13410153 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
6379 13410153 : state.dataSurface->SurfOpaqAO(SurfNum) = state.dataConstruction->Construct(ConstrNum).OutsideAbsorpSolar * CosInc * SunLitFract;
6380 : }
6381 : }
6382 :
6383 : //--------------------------------------------------------------------------------------------------------
6384 : // EXTERIOR WINDOWS OR TDD DOMES
6385 : //--------------------------------------------------------------------------------------------------------
6386 60677343 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
6387 54354459 : auto &surf = state.dataSurface->Surface(SurfNum);
6388 54354459 : auto &surfWin = state.dataSurface->SurfaceWindow(SurfNum);
6389 54354459 : if (surf.Class != SurfaceClass::Window && surf.Class != SurfaceClass::TDD_Dome) continue;
6390 7513362 : if (!surf.ExtSolar && surf.OriginalClass != SurfaceClass::TDD_Diffuser) continue;
6391 7504852 : int const ConstrNum = state.dataSurface->SurfActiveConstruction(SurfNum);
6392 7504852 : int const ConstrNumSh = state.dataSurface->SurfWinActiveShadedConstruction(SurfNum);
6393 7504852 : auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
6394 7504852 : int BlNum = state.dataSurface->SurfWinBlindNumber(SurfNum);
6395 7504852 : int ScNum = surfWin.screenNum;
6396 7504852 : WinShadingType ShadeFlag = state.dataSurface->SurfWinShadingFlag(SurfNum); // Set in subr. WindowShadingManager
6397 :
6398 7504852 : Real64 ProfAng = 0.0; // Window solar profile angle (radians)
6399 :
6400 7504852 : Real64 SlatAng = state.dataSurface->SurfWinSlatAngThisTS(SurfNum);
6401 7504852 : Real64 VarSlats = state.dataSurface->SurfWinMovableSlats(SurfNum);
6402 7504852 : int PipeNum = state.dataSurface->SurfWinTDDPipeNum(SurfNum);
6403 7504852 : int SurfNum2 = SurfNum;
6404 7504852 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
6405 1232 : SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
6406 : }
6407 7504852 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
6408 7504852 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
6409 :
6410 : //-----------------------------------------
6411 : // BLOCK 1
6412 : // EXTERIOR BEAM AND DIFFUSE SOLAR RADIATION ABSORBED IN THE GLASS LAYERS OF (SurfWinA)
6413 : // EXTERIOR BEAM ABSORBED BY SHADING DEVICE (SurfWinExtBeamAbsByShadFac)
6414 : //-----------------------------------------
6415 : // Somewhat of a kludge
6416 7504852 : if (surf.Class == SurfaceClass::TDD_Dome || surf.OriginalClass == SurfaceClass::TDD_Diffuser)
6417 2464 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) =
6418 : SunLitFract; // Frames/dividers not allow
6419 7504852 : int FenSolAbsPtr = 0;
6420 7504852 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
6421 12243 : FenSolAbsPtr = WindowScheduledSolarAbs(state, SurfNum, ConstrNum);
6422 : }
6423 : bool SunlitFracWithoutReveal =
6424 7504852 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) > 0;
6425 :
6426 : // Calculate interpolated blind properties
6427 : Real64 FrontDiffDiffTrans; // Bare-blind front diffuse-diffuse solar transmittance
6428 : Real64 FrontDiffDiffRefl;
6429 : Real64 FrontDiffAbs; // Bare-blind front diffuse solar reflectance
6430 : Real64 BackDiffDiffTrans; // Bare-blind back diffuse-diffuse solar transmittance
6431 : Real64 BackDiffDiffRefl;
6432 : Real64 BackDiffAbs; // Bare-blind back diffuse solar reflectance
6433 :
6434 : Real64 FrontBeamDiffTrans; // Blind ProfileAnglesolar front beam-diffuse transmittance
6435 : Real64 BackBeamDiffTrans; // Blind solar back beam-diffuse transmittance
6436 : Real64 FrontBeamDiffRefl; // Blind solar front beam-diffuse reflectance
6437 : Real64 BackBeamDiffRefl; // Blind solar back beam-diffuse reflectance
6438 : Real64 FrontBeamAbs; // Blind solar front beam absorptance
6439 : Real64 BackBeamAbs; // Blind solar back beam absorptance
6440 :
6441 7504852 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) != WindowModel::EQL && ANY_BLIND(ShadeFlag)) {
6442 71430 : int SlatsAngIndexLower = state.dataSurface->SurfWinSlatsAngIndex(SurfNum);
6443 71430 : int ProfAngIndexLower = state.dataSurface->SurfWinProfAngIndex(SurfNum);
6444 71430 : int SlatsAngIndexUpper = std::min(Material::MaxProfAngs, SlatsAngIndexLower + 1);
6445 71430 : int ProfAngIndexUpper = std::min(Material::MaxProfAngs, ProfAngIndexLower + 1);
6446 71430 : Real64 SlatsAngInterpFac = state.dataSurface->SurfWinSlatsAngInterpFac(SurfNum);
6447 71430 : Real64 ProfAngInterpFac = state.dataSurface->SurfWinProfAngInterpFac(SurfNum);
6448 :
6449 71430 : auto const &thisBlind = state.dataMaterial->Blind(BlNum);
6450 71430 : if (VarSlats) {
6451 : // Used in time step variable reporting
6452 3444 : FrontDiffDiffTrans = General::Interp(
6453 1722 : thisBlind.SolFrontDiffDiffTrans(SlatsAngIndexLower), thisBlind.SolFrontDiffDiffTrans(SlatsAngIndexUpper), SlatsAngInterpFac);
6454 : } else {
6455 69708 : FrontDiffDiffTrans = thisBlind.SolFrontDiffDiffTrans(1);
6456 : }
6457 :
6458 71430 : if (SunLitFract > 0.0 || SunlitFracWithoutReveal) {
6459 55691 : if (VarSlats) {
6460 1092 : FrontBeamDiffTrans = Window::InterpProfSlat(thisBlind.SolFrontBeamDiffTrans(SlatsAngIndexLower, ProfAngIndexLower),
6461 1092 : thisBlind.SolFrontBeamDiffTrans(SlatsAngIndexUpper, ProfAngIndexLower),
6462 1092 : thisBlind.SolFrontBeamDiffTrans(SlatsAngIndexLower, ProfAngIndexUpper),
6463 1092 : thisBlind.SolFrontBeamDiffTrans(SlatsAngIndexUpper, ProfAngIndexUpper),
6464 : SlatsAngInterpFac,
6465 : ProfAngInterpFac);
6466 1092 : FrontBeamAbs = Window::InterpProfSlat(thisBlind.SolFrontBeamAbs(SlatsAngIndexLower, ProfAngIndexLower),
6467 1092 : thisBlind.SolFrontBeamAbs(SlatsAngIndexUpper, ProfAngIndexLower),
6468 1092 : thisBlind.SolFrontBeamAbs(SlatsAngIndexLower, ProfAngIndexUpper),
6469 1092 : thisBlind.SolFrontBeamAbs(SlatsAngIndexUpper, ProfAngIndexUpper),
6470 : SlatsAngInterpFac,
6471 : ProfAngInterpFac);
6472 1092 : if (ShadeFlag != WinShadingType::ExtBlind) { // FRONT: interior or bg blinds
6473 728 : FrontDiffDiffRefl = General::Interp(thisBlind.SolFrontDiffDiffRefl(SlatsAngIndexLower),
6474 728 : thisBlind.SolFrontDiffDiffRefl(SlatsAngIndexUpper),
6475 : SlatsAngInterpFac);
6476 1456 : FrontDiffAbs = General::Interp(
6477 728 : thisBlind.SolFrontDiffAbs(SlatsAngIndexLower), thisBlind.SolFrontDiffAbs(SlatsAngIndexUpper), SlatsAngInterpFac);
6478 728 : FrontBeamDiffRefl = Window::InterpProfSlat(thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexLower, ProfAngIndexLower),
6479 728 : thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexUpper, ProfAngIndexLower),
6480 728 : thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexLower, ProfAngIndexUpper),
6481 728 : thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexUpper, ProfAngIndexUpper),
6482 : SlatsAngInterpFac,
6483 : ProfAngInterpFac);
6484 : }
6485 1092 : if (ShadeFlag != WinShadingType::IntBlind) { // BACK: exterior or bg blinds
6486 364 : BackDiffDiffTrans = General::Interp(thisBlind.SolBackDiffDiffTrans(SlatsAngIndexLower),
6487 364 : thisBlind.SolBackDiffDiffTrans(SlatsAngIndexUpper),
6488 : SlatsAngInterpFac);
6489 364 : BackDiffDiffRefl = General::Interp(thisBlind.SolBackDiffDiffRefl(SlatsAngIndexLower),
6490 364 : thisBlind.SolBackDiffDiffRefl(SlatsAngIndexUpper),
6491 : SlatsAngInterpFac);
6492 728 : BackDiffAbs = General::Interp(
6493 364 : thisBlind.SolBackDiffAbs(SlatsAngIndexLower), thisBlind.SolBackDiffAbs(SlatsAngIndexUpper), SlatsAngInterpFac);
6494 364 : BackBeamDiffTrans = Window::InterpProfSlat(thisBlind.SolBackBeamDiffTrans(SlatsAngIndexLower, ProfAngIndexLower),
6495 364 : thisBlind.SolBackBeamDiffTrans(SlatsAngIndexUpper, ProfAngIndexLower),
6496 364 : thisBlind.SolBackBeamDiffTrans(SlatsAngIndexLower, ProfAngIndexUpper),
6497 364 : thisBlind.SolBackBeamDiffTrans(SlatsAngIndexUpper, ProfAngIndexUpper),
6498 : SlatsAngInterpFac,
6499 : ProfAngInterpFac);
6500 364 : BackBeamDiffRefl = Window::InterpProfSlat(thisBlind.SolBackBeamDiffRefl(SlatsAngIndexLower, ProfAngIndexLower),
6501 364 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexUpper, ProfAngIndexLower),
6502 364 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexLower, ProfAngIndexUpper),
6503 364 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexUpper, ProfAngIndexUpper),
6504 : SlatsAngInterpFac,
6505 : ProfAngInterpFac);
6506 364 : BackBeamAbs = Window::InterpProfSlat(thisBlind.SolBackBeamAbs(SlatsAngIndexLower, ProfAngIndexLower),
6507 364 : thisBlind.SolBackBeamAbs(SlatsAngIndexUpper, ProfAngIndexLower),
6508 364 : thisBlind.SolBackBeamAbs(SlatsAngIndexLower, ProfAngIndexUpper),
6509 364 : thisBlind.SolBackBeamAbs(SlatsAngIndexUpper, ProfAngIndexUpper),
6510 : SlatsAngInterpFac,
6511 : ProfAngInterpFac);
6512 : }
6513 : } else {
6514 109198 : FrontBeamAbs = General::Interp(
6515 54599 : thisBlind.SolFrontBeamAbs(1, ProfAngIndexLower), thisBlind.SolFrontBeamAbs(1, ProfAngIndexUpper), ProfAngInterpFac);
6516 54599 : FrontBeamDiffTrans = General::Interp(thisBlind.SolFrontBeamDiffTrans(1, ProfAngIndexLower),
6517 54599 : thisBlind.SolFrontBeamDiffTrans(1, ProfAngIndexUpper),
6518 : ProfAngInterpFac);
6519 54599 : if (ShadeFlag != WinShadingType::ExtBlind) { // FRONT: interior or bg blinds
6520 54235 : FrontDiffDiffRefl = thisBlind.SolFrontDiffDiffRefl(1);
6521 54235 : FrontDiffAbs = thisBlind.SolFrontDiffAbs(1);
6522 54235 : FrontBeamDiffRefl = General::Interp(thisBlind.SolFrontBeamDiffRefl(1, ProfAngIndexLower),
6523 54235 : thisBlind.SolFrontBeamDiffRefl(1, ProfAngIndexUpper),
6524 : ProfAngInterpFac);
6525 : }
6526 54599 : if (ShadeFlag != WinShadingType::IntBlind) { // BACK: exterior or bg blinds{
6527 2310 : BackDiffDiffTrans = thisBlind.SolBackDiffDiffTrans(1);
6528 2310 : BackDiffDiffRefl = thisBlind.SolBackDiffDiffRefl(1);
6529 2310 : BackDiffAbs = thisBlind.SolBackDiffAbs(1);
6530 2310 : BackBeamDiffTrans = General::Interp(thisBlind.SolBackBeamDiffTrans(1, ProfAngIndexLower),
6531 2310 : thisBlind.SolBackBeamDiffTrans(1, ProfAngIndexUpper),
6532 : ProfAngInterpFac);
6533 2310 : BackBeamDiffRefl = General::Interp(thisBlind.SolBackBeamDiffRefl(1, ProfAngIndexLower),
6534 2310 : thisBlind.SolBackBeamDiffRefl(1, ProfAngIndexUpper),
6535 : ProfAngInterpFac);
6536 4620 : BackBeamAbs = General::Interp(
6537 2310 : thisBlind.SolBackBeamAbs(1, ProfAngIndexLower), thisBlind.SolBackBeamAbs(1, ProfAngIndexUpper), ProfAngInterpFac);
6538 : }
6539 : }
6540 : }
6541 : }
6542 :
6543 7504852 : if (SunlitFracWithoutReveal) {
6544 :
6545 3875813 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
6546 :
6547 : // For bare glazing or switchable glazing, the following includes the effects of
6548 : // (1) diffuse solar produced by beam solar incident on the outside and inside reveal
6549 : // surfaces, and (2) absorption of beam solar by outside and inside reveal surfaces.
6550 : // If there is an exterior shade/blind both of these effects are ignored. If there
6551 : // is an interior or between-glass shade/blind the effects of beam incident on
6552 : // inside reveal surfaces is ignored.
6553 3867966 : int NGlass = thisConstruct.TotGlassLayers;
6554 3867966 : Array1D<Real64> AbWin(NGlass); // Factor for front beam radiation absorbed in window glass layer
6555 8870540 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6556 10005148 : AbWin(Lay) = POLYF(CosInc, thisConstruct.AbsBeamCoef(Lay)) * CosInc * SunLitFract *
6557 5002574 : state.dataSurface->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
6558 : }
6559 3867966 : if (!IS_SHADED_NO_GLARE_CTRL(ShadeFlag)) {
6560 : // (ShadeFlag <= 0 || ShadeFlag >= 10) - Bare window (ShadeFlag = -1 or 0 or shading device of off)
6561 8514689 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6562 : // Add contribution of beam reflected from outside and inside reveal
6563 4784387 : state.dataSurface->SurfWinA(SurfNum, Lay) =
6564 4784387 : AbWin(Lay) + state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstruct.AbsDiff(Lay) +
6565 4784387 : state.dataSurface->SurfWinInsRevealDiffOntoGlazing(SurfNum) * thisConstruct.AbsDiffBack(Lay);
6566 : }
6567 : } else {
6568 : // Shade, screen, blind or switchable glazing on (ShadeFlag > 0)
6569 : Real64 FracSunLit =
6570 137664 : SunLitFract * state.dataSurface->SurfaceWindow(SurfNum)
6571 137664 : .OutProjSLFracMult[state.dataGlobal->HourOfDay]; // Effective fraction of window that is sunlit;
6572 137664 : Real64 InOutProjSLFracMult = state.dataSurface->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
6573 137664 : Array1D<Real64> AbWinSh(NGlass); // Like AbWin, but for shaded window
6574 137664 : Array1D<Real64> ADiffWinSh(NGlass); // Diffuse solar absorptance of glass layer, window with shading device
6575 137664 : if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) FracSunLit = SunLitFract;
6576 :
6577 137664 : if (ANY_SHADE(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
6578 80349 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
6579 : // Shade or switchable glazing on
6580 237735 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6581 157386 : AbWinSh(Lay) = POLYF(CosInc, thisConstructSh.AbsBeamCoef(Lay)) * CosInc * FracSunLit;
6582 157386 : ADiffWinSh(Lay) = thisConstructSh.AbsDiff(Lay);
6583 : }
6584 80349 : if (ShadeFlag == WinShadingType::IntShade) { // Exterior beam absorbed by INTERIOR SHADE
6585 : // Note that AbsBeamShadeCoef includes effect of shade/glazing inter-reflection
6586 21810 : Real64 AbsShade = POLYF(CosInc,
6587 10905 : thisConstructSh.AbsBeamShadeCoef); // Interior shade or blind beam solar absorptance
6588 10905 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6589 21810 : (AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
6590 10905 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstructSh.AbsDiffShade) *
6591 10905 : surfWin.glazedFrac;
6592 : // In the above, GlazedFrac corrects for shadowing of divider onto interior shade
6593 69444 : } else if (ShadeFlag == WinShadingType::ExtShade) { // Exterior beam absorbed by EXTERIOR SHADE
6594 9873 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = thisConstructSh.AbsDiffShade * CosInc * SunLitFract;
6595 59571 : } else if (ShadeFlag == WinShadingType::BGShade) { // Exterior beam absorbed by BETWEEN-GLASS SHADE
6596 1456 : Real64 AbsShade = POLYF(CosInc, thisConstructSh.AbsBeamShadeCoef);
6597 1456 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6598 2912 : AbsShade * CosInc * SunLitFract +
6599 1456 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstructSh.AbsDiffShade;
6600 : }
6601 :
6602 : } else {
6603 : // Blind or screen on
6604 57315 : ProfAng = state.dataSurface->SurfWinProfileAng(SurfNum);
6605 57315 : if (ShadeFlag == WinShadingType::IntBlind) {
6606 : // Interior blind on
6607 53017 : Real64 TBmBm = POLYF(CosInc, thisConstruct.TransSolBeamCoef);
6608 53017 : Real64 RGlDiffBack = thisConstruct.ReflectSolDiffBack; // Glazing system back diffuse solar reflectance
6609 53017 : Real64 RhoBlFront = FrontBeamDiffRefl; // Blind solar front beam reflectance
6610 53017 : Real64 RhoBlDiffFront = FrontDiffDiffRefl; // Blind solar front diffuse reflectance
6611 106034 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6612 53017 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6613 53017 : Real64 AGlDiffBack = thisConstruct.AbsDiffBack(Lay); // Glass layer back diffuse solar absorptance
6614 106034 : AbWinSh(Lay) =
6615 53017 : AbWin(Lay) + (TBmBm * AGlDiffBack * RhoBlFront / (1.0 - RhoBlFront * RGlDiffBack)) * CosInc * FracSunLit;
6616 53017 : ADiffWinSh(Lay) =
6617 53017 : ADiffWin + thisConstruct.TransDiff * AGlDiffBack * RhoBlDiffFront / (1.0 - RhoBlDiffFront * RGlDiffBack);
6618 : }
6619 : // Exterior beam absorbed by INTERIOR BLIND
6620 :
6621 53017 : Real64 AbsBlFront = FrontBeamAbs; // Blind solar front beam absorptance
6622 53017 : Real64 AbsBlDiffFront = FrontDiffAbs; // Blind solar front diffuse absorptance
6623 53017 : Real64 AbsShade =
6624 53017 : TBmBm * (AbsBlFront + RhoBlFront * RGlDiffBack * AbsBlDiffFront / (1.0 - RhoBlDiffFront * RGlDiffBack));
6625 53017 : Real64 AbsShadeDiff =
6626 53017 : thisConstruct.TransDiff *
6627 53017 : (AbsBlDiffFront + RhoBlDiffFront * RGlDiffBack * AbsBlDiffFront /
6628 53017 : (1.0 - RhoBlDiffFront * RGlDiffBack)); // Interior shade or blind diffuse solar absorptance
6629 :
6630 53017 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6631 106034 : (AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
6632 53017 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * AbsShadeDiff) *
6633 53017 : surfWin.glazedFrac;
6634 : // In the above, GlazedFrac corrects for shadowing of divider onto interior blind
6635 4298 : } else if (ShadeFlag == WinShadingType::ExtBlind) {
6636 : // Exterior blind on
6637 728 : Real64 TBlBmBm = state.dataSurface->SurfWinBlindBmBmTrans(SurfNum); // Blind solar front beam-beam transmittance
6638 728 : Real64 TBlDifDif = FrontDiffDiffTrans; // Diffuse-diffuse solar transmittance of blind
6639 728 : Real64 TBlBmDiff = FrontBeamDiffTrans; // Blind solar front beam-diffuse transmittance
6640 728 : Real64 RhoBlBack = BackBeamDiffRefl; // Blind solar back beam-diffuse reflectance
6641 728 : Real64 RhoBlDiffBack = BackDiffDiffRefl; // Blind solar back diffuse reflectance
6642 : Real64 RGlFront =
6643 728 : POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
6644 728 : Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
6645 1456 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6646 728 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6647 728 : Real64 AGlDiffFront = thisConstruct.AbsDiff(Lay); // Glass layer front diffuse solar absorptance
6648 728 : AbWinSh(Lay) = TBlBmBm * AbWin(Lay) + ((TBlBmBm * RGlFront * RhoBlBack + TBlBmDiff) * AGlDiffFront /
6649 728 : (1 - RGlDiffFront * RhoBlDiffBack)) *
6650 728 : CosInc * FracSunLit;
6651 : // ADiffWinSh = 0.0 ! Assumes no contribution from reveal reflection when exterior blind in place
6652 : // Replaced above line with (FCW, 2/10/03):
6653 728 : ADiffWinSh(Lay) = ADiffWin * TBlDifDif / (1.0 - RGlDiffFront * RhoBlDiffBack);
6654 : }
6655 : // Exterior beam absorbed by EXTERIOR BLIND
6656 728 : Real64 AbsBlFront = FrontBeamAbs;
6657 728 : Real64 AbsBlBack = BackBeamAbs; // Blind solar back beam absorptance
6658 728 : Real64 AbsBlDiffBack = BackDiffAbs; // Blind solar back diffuse absorptance
6659 728 : Real64 AbsShade = AbsBlFront + AbsBlBack * RGlFront * TBlBmBm +
6660 728 : (AbsBlDiffBack * RGlDiffFront / (1.0 - RhoBlDiffBack * RGlDiffFront)) *
6661 728 : (RGlFront * TBlBmBm * RhoBlBack + TBlBmDiff);
6662 728 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsShade * CosInc * SunLitFract * InOutProjSLFracMult;
6663 3570 : } else if (ShadeFlag == WinShadingType::ExtScreen) {
6664 : // Exterior screen on
6665 1624 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(state.dataMaterial->Material(ScNum));
6666 1624 : assert(screen != nullptr);
6667 :
6668 1624 : auto &surf = state.dataSurface->Surface(SurfNum);
6669 :
6670 1624 : Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
6671 1624 : Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
6672 1624 : Real64 winPhi = surf.Tilt * Constant::DegToRad;
6673 1624 : Real64 winTheta = surf.Azimuth * Constant::DegToRad;
6674 1624 : Real64 phi = std::abs(solPhi - winPhi);
6675 1624 : Real64 theta = std::abs(solTheta - winTheta);
6676 1624 : Material::NormalizePhiTheta(phi, theta);
6677 : #ifdef PRECALC_INTERP_SCREEN
6678 : int ip1, ip2, it1, it2;
6679 : General::BilinearInterpCoeffs coeffs;
6680 1624 : Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
6681 1624 : GetBilinearInterpCoeffs(
6682 1624 : phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
6683 1624 : auto const &b11 = screen->btars[ip1][it1];
6684 1624 : auto const &b12 = screen->btars[ip1][it2];
6685 1624 : auto const &b21 = screen->btars[ip2][it1];
6686 1624 : auto const &b22 = screen->btars[ip2][it2];
6687 :
6688 1624 : Real64 TScDifDif = screen->DfTrans;
6689 1624 : Real64 TScBmDif = BilinearInterp(b11.DfTrans, b12.DfTrans, b21.DfTrans, b22.DfTrans, coeffs);
6690 1624 : Real64 TScBmBm = BilinearInterp(b11.BmTrans, b12.BmTrans, b21.BmTrans, b22.BmTrans, coeffs);
6691 1624 : Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
6692 1624 : Real64 RScDifBack = screen->DfRef;
6693 :
6694 : Real64 RGlFront =
6695 1624 : POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
6696 1624 : Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
6697 1624 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
6698 : // Reduce the bare window absorbed beam by the screen beam transmittance and then account for
6699 : // interreflections
6700 4060 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6701 2436 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6702 2436 : AbWinSh(Lay) = TScBmBm * AbWin(Lay) + (TScBmBm * RGlFront * RScBack + TScBmDif) * thisConstruct.AbsDiff(Lay) /
6703 2436 : (1.0 - RGlDiffFront * RScDifBack) * CosInc * FracSunLit;
6704 2436 : ADiffWinSh(Lay) = ADiffWin * TScDifDif / (1.0 - RGlDifFr * RScDifBack);
6705 : }
6706 : // Exterior beam absorbed by EXTERIOR SCREEN
6707 1624 : Real64 AbsScBeam = BilinearInterp(b11.AbsSolFront, b12.AbsSolFront, b21.AbsSolFront, b22.AbsSolFront, coeffs);
6708 1624 : Real64 AbsScDiffBack = screen->DfAbs;
6709 1624 : Real64 AbsScreen = AbsScBeam * (1.0 + TScBmBm * RGlFront) +
6710 1624 : (AbsScDiffBack * TScBmBm * RGlFront * RGlDiffFront * RScBack /
6711 1624 : (1.0 - RScDifBack * RGlDiffFront)); // Exterior screen beam solar absorptance
6712 1624 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsScreen * CosInc * SunLitFract * InOutProjSLFracMult;
6713 : #else // !PRECALC_INTERP_SCREEN
6714 : Material::ScreenBmTransAbsRef btar;
6715 : CalcScreenTransmittance(state, screen, phi, theta, btar);
6716 :
6717 : Real64 TScDifDif = screen->DfTrans;
6718 : Real64 TScBmDif = btar.DfTrans;
6719 : Real64 TScBmBm = btar.BmTrans;
6720 : Real64 RScBack = btar.RefSolFront;
6721 : Real64 RScDifBack = screen->DfRef;
6722 :
6723 : Real64 RGlFront =
6724 : POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
6725 : Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
6726 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
6727 : // Reduce the bare window absorbed beam by the screen beam transmittance and then account for
6728 : // interreflections
6729 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6730 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
6731 : AbWinSh(Lay) = TScBmBm * AbWin(Lay) + (TScBmBm * RGlFront * RScBack + TScBmDif) * thisConstruct.AbsDiff(Lay) /
6732 : (1.0 - RGlDiffFront * RScDifBack) * CosInc * FracSunLit;
6733 : ADiffWinSh(Lay) = ADiffWin * TScDifDif / (1.0 - RGlDifFr * RScDifBack);
6734 : }
6735 : // Exterior beam absorbed by EXTERIOR SCREEN
6736 : Real64 AbsScBeam = btar.AbsSolFront;
6737 : Real64 AbsScDiffBack = screen->DfAbs;
6738 : Real64 AbsScreen = AbsScBeam * (1.0 + TScBmBm * RGlFront) +
6739 : (AbsScDiffBack * TScBmBm * RGlFront * RGlDiffFront * RScBack /
6740 : (1.0 - RScDifBack * RGlDiffFront)); // Exterior screen beam solar absorptance
6741 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsScreen * CosInc * SunLitFract * InOutProjSLFracMult;
6742 : #endif // PRECALC_INTERP_SCREEN
6743 1946 : } else if (ShadeFlag == WinShadingType::BGBlind) {
6744 : // Between-glass blind o
6745 : // Isolated glass and blind properties at current incidence angle, profile angle and slat angle
6746 3892 : Real64 t1 = POLYF(CosInc,
6747 1946 : thisConstruct.tBareSolCoef(1)); // Bare-glass beam solar transmittance for glass layers 1,2 and 3
6748 1946 : Real64 t2 = POLYF(CosInc, thisConstruct.tBareSolCoef(2));
6749 : Real64 af1 =
6750 3892 : POLYF(CosInc,
6751 1946 : thisConstruct.afBareSolCoef(1)); // Bare-glass beam solar front absorptance for glass layers 1,2 and 3
6752 1946 : Real64 af2 = POLYF(CosInc, thisConstruct.afBareSolCoef(2));
6753 : Real64 ab1 =
6754 3892 : POLYF(CosInc,
6755 1946 : thisConstruct.abBareSolCoef(1)); // Bare-glass beam solar back absorptance for glass layers 1,2 and 3
6756 1946 : Real64 ab2 = POLYF(CosInc, thisConstruct.abBareSolCoef(2));
6757 1946 : Real64 rf2 = POLYF(CosInc, thisConstruct.rfBareSolCoef(2));
6758 1946 : Real64 td1 = thisConstruct.tBareSolDiff(1); // Bare-glass diffuse solar transmittance for glass layers 1,2 and 3
6759 1946 : Real64 td2 = thisConstruct.tBareSolDiff(2);
6760 1946 : Real64 afd1 = thisConstruct.afBareSolDiff(1); // Bare-glass diffuse solar front absorptance for glass layers 1,2 and 3
6761 1946 : Real64 afd2 = thisConstruct.afBareSolDiff(2);
6762 1946 : Real64 abd1 = thisConstruct.abBareSolDiff(1); // Bare-glass diffuse solar back absorptance for glass layers 1,2 and 3
6763 1946 : Real64 abd2 = thisConstruct.abBareSolDiff(2);
6764 1946 : Real64 rfd2 = thisConstruct.rfBareSolDiff(2);
6765 1946 : Real64 rbd1 = thisConstruct.rbBareSolDiff(1); // Bare-glass diffuse solar back reflectance for glass layers 1,2 and 3
6766 1946 : Real64 rbd2 = thisConstruct.rbBareSolDiff(2);
6767 : Real64 tfshBB =
6768 1946 : state.dataSurface->SurfWinBlindBmBmTrans(SurfNum); // Bare-blind front and back beam-beam solar transmittance
6769 1946 : auto const &thisBlind = state.dataMaterial->Blind(BlNum);
6770 3892 : Real64 tbshBB = Window::BlindBeamBeamTrans(
6771 1946 : ProfAng, Constant::Pi - SlatAng, thisBlind.SlatWidth, thisBlind.SlatSeparation, thisBlind.SlatThickness);
6772 1946 : Real64 tfshBd = FrontBeamDiffTrans; // Bare-blind front and back beam-diffuse solar transmittance
6773 1946 : Real64 tbshBd = BackBeamDiffTrans;
6774 1946 : Real64 rfshB = FrontBeamDiffRefl; // Bare-blind front and back beam solar reflectance
6775 1946 : Real64 rbshB = BackBeamDiffRefl;
6776 1946 : Real64 afshB = FrontBeamAbs;
6777 1946 : Real64 abshB = BackBeamAbs;
6778 :
6779 1946 : Real64 tfshd = FrontDiffDiffTrans; // Bare-blind front and back diffuse-diffuse solar transmittance
6780 1946 : Real64 tbshd = BackDiffDiffTrans;
6781 1946 : Real64 rfshd = FrontDiffDiffRefl; // Bare-blind front and back diffuse solar reflectance
6782 1946 : Real64 rbshd = BackDiffDiffRefl;
6783 1946 : Real64 afshd = FrontDiffAbs;
6784 1946 : Real64 abshd = BackDiffAbs;
6785 :
6786 1946 : Real64 AbsShade = 0.0;
6787 1946 : Real64 AbsShadeDiff = 0.0;
6788 1946 : if (NGlass == 2) {
6789 2436 : AbWinSh(1) = CosInc * FracSunLit *
6790 1218 : (af1 + t1 * tfshBB * rf2 * tbshBB * ab1 +
6791 1218 : t1 * (rfshB + rfshB * rbd1 * rfshd + tfshBB * rf2 * tbshBd + tfshBd * rfd2 * tbshd) * abd1);
6792 1218 : ADiffWinSh(1) = afd1 + td1 * (rfshd + rfshd * rbd1 * rfshd + tfshd * rfd2 * tbshd) * abd1;
6793 2436 : AbWinSh(2) =
6794 1218 : CosInc * FracSunLit *
6795 1218 : (t1 * rfshB * af2 + t1 * (rfshB * rf2 * rbshd + tfshBd * (1 + rfd2 * rbshd) + rfshB * rbd1 * tfshd) * afd2);
6796 1218 : ADiffWinSh(2) = td1 * (tfshd * (1 + rfd2 * rbshd) + rfshd * rbd1 * tfshd) * afd2;
6797 1218 : AbsShade = t1 * (afshB + tfshBB * rf2 * abshB + tfshBd * rfd2 * abshd + rfshB * rbd1 * afshd);
6798 1218 : AbsShadeDiff = td1 * (afshd * (1 + rfshd * rbd1) + tfshd * rfd2 * abshd);
6799 728 : } else if (NGlass == 3) {
6800 728 : Real64 t1t2 = t1 * t2; // t1*t2
6801 728 : Real64 td1td2 = td1 * td2;
6802 728 : Real64 af3 = POLYF(CosInc, thisConstruct.afBareSolCoef(3));
6803 728 : Real64 rf3 = POLYF(CosInc, thisConstruct.rfBareSolCoef(3));
6804 728 : Real64 afd3 = thisConstruct.afBareSolDiff(3);
6805 728 : Real64 rfd3 = thisConstruct.rfBareSolDiff(3);
6806 728 : Real64 td2 = thisConstruct.tBareSolDiff(2);
6807 1456 : AbWinSh(1) = CosInc * FracSunLit *
6808 728 : (af1 + t1 * rf2 * ab1 + t1t2 * tfshBB * rf3 * tbshBB * t2 * ab1 +
6809 728 : t1t2 * (rfshB * td2 + rfshB * rbd2 * rfshd * td2 + tfshBd * rfd3 * tbshd * td2) * abd1);
6810 1456 : ADiffWinSh(1) = afd1 + td1 * rbd2 * abd1 +
6811 728 : td1td2 *
6812 728 : (rfshd * (1 + rbd2 * rfshd + td2 * rbd1 * td2 * rfshd) +
6813 728 : tfshd * (rfd3 * tbshd + rfd3 * rbshd * rfd3 * tbshd)) *
6814 728 : td2 * abd1;
6815 1456 : AbWinSh(2) = CosInc * FracSunLit *
6816 728 : (t1 * af2 + t1t2 * (tfshBB * rf3 * tbshBB * ab2 + rfshB * td2 * rbd1 * afd2) +
6817 728 : t1t2 * (rfshB * (1 + rbd2 * rfshd) + tfshBB * rf3 * tbshBd + tfshBd * rfd3 * tbshd) * abd2);
6818 1456 : ADiffWinSh(2) = td1 * afd2 + td1td2 * rfshd * td2 * rbd1 * afd2 +
6819 728 : td1td2 * (rfshd * (1 + rbd2 * rfshd) + tfshd * rfd3 * tbshd) * abd2;
6820 1456 : AbWinSh(3) = CosInc * FracSunLit *
6821 728 : (t1t2 * tfshBB * af3 + t1t2 *
6822 728 : (tfshBB * rf3 * rbshB + tfshBd * (1 + rfd3 * rbshd) +
6823 728 : rfshB * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) *
6824 : afd3);
6825 728 : ADiffWinSh(3) = td1td2 * (tfshd * (1 + rfd3 * rbshd) + rfshd * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) * afd3;
6826 728 : AbsShade = t1t2 * (afshB * (1 + tfshBB * rf3) + afshd * (tfshBd * rfd3 + rfshB * (rbd2 + td2 * rbd1 * td2)));
6827 728 : AbsShadeDiff = td1td2 * (afshd + tfshd * rfd3 * abshd + rfshd * (rfd2 + td2 * rbd2 * td2) * afshd);
6828 : } // End of check if NGlass
6829 1946 : state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
6830 3892 : AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
6831 1946 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * AbsShadeDiff;
6832 : } // End of check if blind is interior, exterior or between-glass
6833 : } // End of check if a blind is on
6834 :
6835 137664 : if (ShadeFlag != WinShadingType::SwitchableGlazing) {
6836 : // Interior or between glass shade or blind on
6837 181506 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6838 101957 : state.dataSurface->SurfWinA(SurfNum, Lay) = AbWinSh(Lay);
6839 : // Add contribution of diffuse from beam on outside reveal
6840 101957 : if (ANY_INTERIOR_SHADE_BLIND(ShadeFlag) || ANY_BETWEENGLASS_SHADE_BLIND(ShadeFlag))
6841 81519 : state.dataSurface->SurfWinA(SurfNum, Lay) +=
6842 81519 : ADiffWinSh(Lay) * state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum);
6843 : }
6844 : } else {
6845 58115 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
6846 : // Switchable glazing
6847 174345 : for (int Lay = 1; Lay <= NGlass; ++Lay) {
6848 116230 : Real64 SwitchFac = state.dataSurface->SurfWinSwitchingFactor(SurfNum);
6849 116230 : Real64 ADiffWin = thisConstruct.AbsDiff(Lay);
6850 116230 : state.dataSurface->SurfWinA(SurfNum, Lay) = Window::InterpSw(SwitchFac, AbWin(Lay), AbWinSh(Lay));
6851 : // Add contribution of diffuse from beam on outside and inside reveal
6852 116230 : state.dataSurface->SurfWinA(SurfNum, Lay) +=
6853 116230 : Window::InterpSw(SwitchFac, ADiffWin, ADiffWinSh(Lay)) *
6854 116230 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) +
6855 116230 : Window::InterpSw(SwitchFac, thisConstruct.AbsDiffBack(Lay), thisConstructSh.AbsDiffBack(Lay)) *
6856 116230 : state.dataSurface->SurfWinInsRevealDiffOntoGlazing(SurfNum);
6857 : }
6858 : }
6859 137664 : }
6860 :
6861 3875813 : } else if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
6862 : // Do not read from schedule file here since this will be called only if direct beam is hitting the window and schedule
6863 : // will not be loaded in that case even if diffuse part of solar radiation is entering through the window
6864 6461 : if (FenSolAbsPtr == 0) {
6865 : // Put in the equivalent layer absorptions
6866 : // Simon: This should not be multiplied with CosInc since Abs coefficient already includes angular
6867 : // factor
6868 24045 : for (int Lay = 1; Lay <= state.dataSurface->SurfaceWindow(SurfNum)
6869 24045 : .ComplexFen.State(state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6870 24045 : .NLayers;
6871 : ++Lay) {
6872 17640 : Real64 absBeamWin = state.dataSurface->SurfaceWindow(SurfNum)
6873 17640 : .ComplexFen.State(state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6874 17640 : .WinBmFtAbs(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, Lay);
6875 35280 : Real64 AbWin = absBeamWin * CosInc * SunLitFract *
6876 17640 : state.dataSurface->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
6877 :
6878 : // Add contribution of beam reflected from outside and inside reveal
6879 17640 : state.dataSurface->SurfWinA(SurfNum, Lay) =
6880 17640 : AbWin +
6881 17640 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) *
6882 17640 : state.dataSurface->SurfaceWindow(SurfNum)
6883 17640 : .ComplexFen.State(state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6884 17640 : .WinFtHemAbs(Lay) +
6885 17640 : state.dataSurface->SurfWinInsRevealDiffOntoGlazing(SurfNum) *
6886 17640 : state.dataSurface->SurfaceWindow(SurfNum)
6887 17640 : .ComplexFen.State(state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6888 17640 : .WinBkHemAbs(Lay);
6889 : }
6890 : }
6891 :
6892 1386 : } else if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
6893 : // call the ASHWAT fenestration model for optical properties
6894 : // determine the beam radiation absorptance and tranmittance of the
6895 : // the equivalent layer window model
6896 1386 : WindowEquivalentLayer::CalcEQLOpticalProperty(state, SurfNum, SolarArrays::BEAM, state.dataSolarShading->SurfWinAbsSolBeamEQL);
6897 1386 : auto &CFS = state.dataWindowEquivLayer->CFS;
6898 : // recalcuate the diffuse absorptance and transmittance of the
6899 : // the equivalent layer window model if there is shade control
6900 1386 : int EQLNum = state.dataConstruction->Construct(surf.Construction).EQLConsPtr; // equivalent layer fenestration index
6901 1386 : if (CFS(EQLNum).ISControlled) {
6902 0 : WindowEquivalentLayer::CalcEQLOpticalProperty(
6903 0 : state, SurfNum, SolarArrays::DIFF, state.dataSolarShading->SurfWinAbsSolDiffEQL);
6904 : } else {
6905 2772 : state.dataSolarShading->SurfWinAbsSolDiffEQL(_, {1, CFS(EQLNum).NL + 1}) =
6906 4158 : state.dataWindowEquivalentLayer->CFSDiffAbsTrans(_, {1, CFS(EQLNum).NL + 1}, EQLNum);
6907 : }
6908 1386 : thisConstruct.TransDiff = state.dataSolarShading->SurfWinAbsSolDiffEQL(1, CFS(EQLNum).NL + 1);
6909 :
6910 7658 : for (int Lay = 1; Lay <= CFS(EQLNum).NL + 1; ++Lay) {
6911 : // Factor for front beam radiation absorbed for equivalent layer window model
6912 6272 : Real64 AbWinEQL = state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay) * CosInc * SunLitFract *
6913 6272 : state.dataSurface->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
6914 : ;
6915 6272 : if (CFS(EQLNum).L(1).LTYPE != LayerType::GLAZE) {
6916 : // if the first layer is not glazing (or it is a shade) do not
6917 2842 : state.dataSurface->SurfWinA(SurfNum, Lay) = AbWinEQL;
6918 : } else {
6919 : // the first layer is a glazing, include the outside reveal reflection
6920 : // and the inside reveal reflection until indoor shade layer is encountered.
6921 3430 : if (CFS(EQLNum).L(Lay).LTYPE == LayerType::GLAZE) {
6922 1960 : state.dataSurface->SurfWinA(SurfNum, Lay) = AbWinEQL +
6923 1960 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) *
6924 1960 : state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay) +
6925 1960 : state.dataSurface->SurfWinInsRevealDiffOntoGlazing(SurfNum) *
6926 1960 : state.dataSolarShading->SurfWinAbsSolDiffEQL(2, Lay);
6927 : } else {
6928 2940 : state.dataSurface->SurfWinA(SurfNum, Lay) = AbWinEQL + state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) *
6929 1470 : state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay);
6930 : }
6931 : }
6932 : }
6933 : }
6934 : } // End of SunlitFrac check
6935 :
6936 : //-----------------------------------------------------------------
6937 : // BLOCK 2
6938 : // SKY AND GROUND DIFFUSE SOLAR GAIN INTO ZONE FROM EXTERIOR WINDOW
6939 : //-----------------------------------------------------------------
6940 :
6941 7504852 : Real64 SkySolarInc = state.dataSurface->SurfSkySolarInc(
6942 7504852 : SurfNum); // Incident solar radiation on a window: sky diffuse plus beam reflected from obstruction (W/m2)
6943 7504852 : Real64 DiffTrans = 0.0; // Glazing diffuse solar transmittance (including shade/blind/switching, if present)
6944 : Real64 DiffTransGnd; // Ground diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
6945 : Real64 DiffTransBmGnd; // Complex fen: diffuse solar transmittance for ground-reflected beam radiation
6946 : Real64 DiffTransSky; // Sky diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
6947 7504852 : Real64 NomDiffTrans = 0.0;
6948 :
6949 7504852 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // complex fenestration
6950 12243 : if (FenSolAbsPtr == 0) {
6951 : // Sky diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
6952 12145 : DiffTransSky = state.dataSurface->SurfaceWindow(SurfNum)
6953 12145 : .ComplexFen.State(state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6954 : .WinSkyTrans;
6955 : // Ground diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
6956 12145 : DiffTransGnd = state.dataSurface->SurfaceWindow(SurfNum)
6957 12145 : .ComplexFen.State(state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6958 : .WinSkyGndTrans;
6959 : // Complex fen: diffuse solar transmittance for ground-reflected beam radiation
6960 12145 : DiffTransBmGnd = state.dataSurface->SurfaceWindow(SurfNum)
6961 12145 : .ComplexFen.State(state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6962 12145 : .WinBmGndTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
6963 : // Define the effective transmittance for total sky and ground radiation
6964 12145 : if ((SkySolarInc + state.dataSurface->SurfWinBmGndSolarInc(SurfNum) + state.dataSurface->SurfWinSkyGndSolarInc(SurfNum)) != 0.0) {
6965 12145 : DiffTrans =
6966 12145 : (SkySolarInc * DiffTransSky + state.dataSurface->SurfWinBmGndSolarInc(SurfNum) * DiffTransBmGnd +
6967 12145 : state.dataSurface->SurfWinSkyGndSolarInc(SurfNum) * DiffTransGnd) /
6968 12145 : (SkySolarInc + state.dataSurface->SurfWinBmGndSolarInc(SurfNum) + state.dataSurface->SurfWinSkyGndSolarInc(SurfNum));
6969 : }
6970 : // Also update the nominal diffuse transmittance
6971 12145 : NomDiffTrans = state.dataSurface->SurfaceWindow(SurfNum)
6972 12145 : .ComplexFen.State(state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
6973 : .WinDiffTrans;
6974 : // Do not store in TransDiff because it is not used by BSDF and rest of the code uses it as flag for opaque
6975 : // surface incorrectly assuming wall heat transfer routines for windows.
6976 : // Construct( Surface( SurfNum ).Construction ).TransDiff = NomDiffTrans;
6977 : }
6978 7492609 : } else if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
6979 1232 : DiffTrans = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso);
6980 : } else {
6981 7491377 : DiffTrans = thisConstruct.TransDiff;
6982 : }
6983 :
6984 7504852 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
6985 7490131 : if (IS_SHADED_NO_GLARE_CTRL(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
6986 184682 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
6987 184682 : if (ShadeFlag != WinShadingType::SwitchableGlazing) {
6988 : // Shade or blind
6989 112896 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
6990 : // Shade or screen
6991 41466 : DiffTrans = thisConstructSh.TransDiff;
6992 : } else {
6993 : // Blind
6994 71430 : int SurfWinSlatsAngIndex = state.dataSurface->SurfWinSlatsAngIndex(SurfNum);
6995 71430 : Real64 SurfWinSlatsAngInterpFac = state.dataSurface->SurfWinSlatsAngInterpFac(SurfNum);
6996 71430 : if (state.dataSurface->SurfWinMovableSlats(SurfNum)) {
6997 1722 : DiffTrans = General::Interp(thisConstructSh.BlTransDiff(SurfWinSlatsAngIndex),
6998 3444 : thisConstructSh.BlTransDiff(std::min(Material::MaxSlatAngs, SurfWinSlatsAngIndex + 1)),
6999 : SurfWinSlatsAngInterpFac);
7000 : } else {
7001 69708 : DiffTrans = thisConstructSh.BlTransDiff(1);
7002 : }
7003 : // For blinds with horizontal slats, allow different diffuse/diffuse transmittance for
7004 : // ground and sky solar
7005 71430 : if (state.dataMaterial->Blind(state.dataSurface->SurfWinBlindNumber(SurfNum)).SlatOrientation ==
7006 : DataWindowEquivalentLayer::Orientation::Horizontal) {
7007 71430 : if (state.dataSurface->SurfWinMovableSlats(SurfNum)) {
7008 : DiffTransGnd =
7009 1722 : General::Interp(thisConstructSh.BlTransDiffGnd(SurfWinSlatsAngIndex),
7010 1722 : thisConstructSh.BlTransDiffGnd(std::min(Material::MaxSlatAngs, SurfWinSlatsAngIndex + 1)),
7011 : SurfWinSlatsAngInterpFac);
7012 : DiffTransSky =
7013 1722 : General::Interp(thisConstructSh.BlTransDiffSky(SurfWinSlatsAngIndex),
7014 3444 : thisConstructSh.BlTransDiffSky(std::min(Material::MaxSlatAngs, SurfWinSlatsAngIndex + 1)),
7015 : SurfWinSlatsAngInterpFac);
7016 : } else {
7017 69708 : DiffTransGnd = thisConstructSh.BlTransDiffGnd(1);
7018 69708 : DiffTransSky = thisConstructSh.BlTransDiffSky(1);
7019 : }
7020 : }
7021 : }
7022 :
7023 : } else {
7024 : // Switchable glazing
7025 71786 : Real64 SwitchFac = state.dataSurface->SurfWinSwitchingFactor(SurfNum); // Switching factor for a window
7026 71786 : DiffTrans = Window::InterpSw(SwitchFac, thisConstruct.TransDiff, thisConstructSh.TransDiff);
7027 : }
7028 : }
7029 : }
7030 :
7031 : // Reporting variables
7032 7504852 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
7033 7502374 : state.dataSurface->SurfWinBlGlSysTsolDifDif(SurfNum) = DiffTrans;
7034 7502374 : state.dataSurface->SurfWinScGlSysTsolDifDif(SurfNum) = DiffTrans;
7035 7502374 : if (ANY_BLIND(ShadeFlag) || ShadeFlag == WinShadingType::ExtScreen) {
7036 74678 : state.dataSurface->SurfWinBlGlSysTsolDifDif(SurfNum) = DiffTrans;
7037 74678 : state.dataSurface->SurfWinScGlSysTsolDifDif(SurfNum) = DiffTrans;
7038 74678 : if (ShadeFlag == WinShadingType::ExtScreen) {
7039 3248 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(state.dataMaterial->Material(ScNum));
7040 3248 : assert(screen != nullptr);
7041 3248 : state.dataSurface->SurfWinScTsolDifDif(SurfNum) = screen->DfTrans;
7042 : } else {
7043 71430 : state.dataSurface->SurfWinBlTsolDifDif(SurfNum) = FrontDiffDiffTrans;
7044 : }
7045 : }
7046 : }
7047 :
7048 : //-----------------------------------------------------------------
7049 : // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
7050 : //-----------------------------------------------------------------
7051 7504852 : Real64 TBmBm = 0.0; // Beam-beam solar transmittance for bare window or window with switchable glazing
7052 7504852 : Real64 TBmDif = 0.0; // Beam-diffuse solar transmittance for bare window with diffusing glass
7053 7504852 : Real64 TBmAllShBlSc = 0.0; // Beam-beam + beam-diffuse transmittance for window with shade, blind, screen, or switchable glazing
7054 7504852 : Real64 TBmBmShBlSc = 0.0; // Beam-beam transmittance for window with shade, blind, screen, or switchable glazing
7055 7504852 : Real64 TBmDifShBlSc = 0.0; // Beam-diffuse transmittance for window with shade, blind, screen, or switchable glazing
7056 : Real64 TBmBmBl; // Beam-beam transmittance for window with blind
7057 : Real64 TBmBmSc; // Beam-beam transmittance for window with screen
7058 : Real64 TDifBare; // Bare diffuse transmittance of exterior window
7059 : // Beam-beam transmittance for bare exterior window
7060 7504852 : if (SunLitFract > 0.0) {
7061 3865244 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
7062 1148 : TBmDif = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarBeam);
7063 1148 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolBeam = TBmDif; // Report variable
7064 3864096 : } else if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) { // Regular window
7065 3856249 : if (!state.dataSurface->SurfWinSolarDiffusing(SurfNum)) { // Clear glazing
7066 3856249 : TBmBm = POLYF(CosInc, thisConstruct.TransSolBeamCoef); //[-]
7067 : } else { // Diffusing glazing
7068 0 : TBmDif = POLYF(CosInc, thisConstruct.TransSolBeamCoef); //[-]
7069 : }
7070 7847 : } else if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
7071 : // Need to check what effect, if any, defining these here has
7072 6461 : TBmBm = state.dataSurface->SurfaceWindow(SurfNum)
7073 6461 : .ComplexFen.State(state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
7074 6461 : .WinDirSpecTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
7075 6461 : TBmDif = state.dataSurface->SurfaceWindow(SurfNum)
7076 6461 : .ComplexFen.State(state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
7077 6461 : .WinDirHemiTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep) -
7078 : TBmBm;
7079 1386 : } else if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
7080 : // get ASHWAT fenestration model beam-beam and beam-diffuse properties
7081 1386 : int EQLNum = state.dataConstruction->Construct(surf.Construction).EQLConsPtr; // equivalent layer fenestration index
7082 1386 : Real64 TBmBmEQL = state.dataSolarShading->SurfWinAbsSolBeamEQL(1, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1);
7083 : // Beam-diffuse transmittance
7084 1386 : Real64 TBmDiffEQL = max(0.0, state.dataSolarShading->SurfWinAbsSolBeamEQL(2, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1));
7085 : // Beam-beam transmittance: difference between beam-total and beam-diffuse transmittance
7086 1386 : TBmBmEQL = max(0.0, (TBmBmEQL - TBmDiffEQL));
7087 1386 : TBmBm = TBmBmEQL;
7088 1386 : TBmDif = TBmDiffEQL;
7089 : }
7090 : }
7091 : // Diffuse-diffuse transmittance for bare exterior window
7092 7504852 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
7093 1232 : TDifBare = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso);
7094 : } else {
7095 7503620 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
7096 : // Complex Fenestration: use hemispherical ave of directional-hemispherical transmittance
7097 : // Note: this is not quite the same as the effective transmittance for total of sky and ground radiation
7098 12243 : TDifBare = state.dataSurface->SurfaceWindow(SurfNum)
7099 12243 : .ComplexFen.State(state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
7100 : .WinDiffTrans;
7101 : } else { // Regular window
7102 7491377 : TDifBare = thisConstruct.TransDiff;
7103 : }
7104 : }
7105 :
7106 : //-----------------------------------------------------------------
7107 : // BLOCK 3 - SCREEN, BLINDS AND GLAZING SYSTEM BEAM SOLAR TRANSMITTANCE
7108 : //-----------------------------------------------------------------
7109 7504852 : if (ConstrNumSh != 0 && SunLitFract > 0.0) {
7110 168334 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
7111 168334 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
7112 168334 : if (IS_SHADED_NO_GLARE_CTRL(ShadeFlag)) {
7113 : // Shade or screen or blind on, or switchable glazing
7114 : // (note in the following that diffusing glass is not allowed in a window with shade, blind or switchable glazing)
7115 137664 : if (ANY_SHADE(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
7116 : // Shade on or switchable glazing
7117 80349 : TBmAllShBlSc = POLYF(CosInc, thisConstructSh.TransSolBeamCoef);
7118 : } else {
7119 : // Blind or Screen on
7120 : Real64 TScBmDif; // Beam-diffuse solar transmittance of screen
7121 : Real64 TBlBmDif; // Beam-diffuse solar transmittance of blind
7122 : Real64 TBlDifDif; // Diffuse-diffuse solar transmittance of blind
7123 : Real64 TScBmBm;
7124 : Real64 TBlBmBm;
7125 57315 : if (ShadeFlag == WinShadingType::ExtScreen) { // Exterior screen
7126 1624 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(state.dataMaterial->Material(ScNum));
7127 1624 : assert(screen != nullptr);
7128 :
7129 1624 : auto &surf = state.dataSurface->Surface(SurfNum);
7130 1624 : Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
7131 1624 : Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
7132 1624 : Real64 winPhi = surf.Tilt * Constant::DegToRad;
7133 1624 : Real64 winTheta = surf.Azimuth * Constant::DegToRad;
7134 1624 : Real64 phi = std::abs(solPhi - winPhi);
7135 1624 : Real64 theta = std::abs(solTheta - winTheta);
7136 1624 : Material::NormalizePhiTheta(phi, theta);
7137 : #ifdef PRECALC_INTERP_SCREEN
7138 : int ip1, ip2, it1, it2;
7139 : General::BilinearInterpCoeffs coeffs;
7140 1624 : Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
7141 1624 : GetBilinearInterpCoeffs(
7142 1624 : phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
7143 1624 : auto const &b11 = screen->btars[ip1][it1];
7144 1624 : auto const &b12 = screen->btars[ip1][it2];
7145 1624 : auto const &b21 = screen->btars[ip2][it1];
7146 1624 : auto const &b22 = screen->btars[ip2][it2];
7147 :
7148 1624 : Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
7149 1624 : Real64 RScDifBack = screen->DfRef;
7150 :
7151 1624 : Real64 RGlBmFr = POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Beam front reflectance of glass
7152 1624 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
7153 : // beam transmittance (written in subroutine CalcScreenTransmittance each time step)
7154 1624 : TScBmBm = BilinearInterp(b11.BmTrans, b12.BmTrans, b21.BmTrans, b22.BmTrans, coeffs);
7155 1624 : TBmBmSc = TBmBm * TScBmBm;
7156 1624 : TScBmDif = BilinearInterp(b11.DfTrans, b12.DfTrans, b21.DfTrans, b22.DfTrans, coeffs);
7157 : // beam-beam and diffuse transmittance of exterior beam
7158 1624 : TBmAllShBlSc = TScBmBm * (TBmBm + RGlBmFr * RScBack * TDifBare / (1 - RGlDifFr * RScDifBack)) +
7159 1624 : TScBmDif * TDifBare / (1 - RGlDifFr * RScDifBack);
7160 1624 : TBmBmShBlSc = TBmBmSc;
7161 1624 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7162 : // Report variable for Beam-to-Diffuse transmittance (scattered transmittance)
7163 1624 : state.dataSurface->SurfWinScGlSysTsolBmBm(SurfNum) = TBmBmSc;
7164 1624 : state.dataSurface->SurfWinScTsolBmBm(SurfNum) = TScBmBm;
7165 1624 : state.dataSurface->SurfWinScTsolBmDif(SurfNum) = TScBmDif;
7166 : #else // !PRECALC_INTERP_SCREEN
7167 : Material::ScreenBmTransAbsRef btar;
7168 : CalcScreenTransmittance(state, screen, phi, theta, btar);
7169 :
7170 : Real64 RScBack = btar.RefSolFront;
7171 : Real64 RScDifBack = screen->DfRef;
7172 :
7173 : Real64 RGlBmFr = POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Beam front reflectance of glass
7174 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront; // Diffuse front reflectance of glass
7175 : // beam transmittance (written in subroutine CalcScreenTransmittance each time step)
7176 : TScBmBm = btar.BmTrans;
7177 : TBmBmSc = TBmBm * TScBmBm;
7178 : TScBmDif = btar.DfTrans;
7179 : // beam-beam and diffuse transmittance of exterior beam
7180 : TBmAllShBlSc = TScBmBm * (TBmBm + RGlBmFr * RScBack * TDifBare / (1 - RGlDifFr * RScDifBack)) +
7181 : TScBmDif * TDifBare / (1 - RGlDifFr * RScDifBack);
7182 : TBmBmShBlSc = TBmBmSc;
7183 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7184 : // Report variable for Beam-to-Diffuse transmittance (scattered transmittance)
7185 : state.dataSurface->SurfWinScGlSysTsolBmBm(SurfNum) = TBmBmSc;
7186 : state.dataSurface->SurfWinScTsolBmBm(SurfNum) = TScBmBm;
7187 : state.dataSurface->SurfWinScTsolBmDif(SurfNum) = TScBmDif;
7188 : #endif // PRECALC_INTERP_SCREEN
7189 : } else {
7190 55691 : TBlBmBm = state.dataSurface->SurfWinBlindBmBmTrans(SurfNum);
7191 55691 : TBlBmDif = FrontBeamDiffTrans;
7192 55691 : if (ShadeFlag == WinShadingType::IntBlind) {
7193 53017 : Real64 RhoBlBmDifFr = FrontBeamDiffRefl; // Beam-diffuse front reflectance of blind
7194 53017 : Real64 RGlDifBk = thisConstruct.ReflectSolDiffBack; // Diffuse front reflectance of glass
7195 53017 : Real64 RhoBlDifDifFr = FrontDiffDiffRefl; // Diffuse-diffuse front refectance of blind
7196 : // beam-beam and diffuse transmittance of exterior beam
7197 53017 : TBmBmBl = TBmBm * TBlBmBm;
7198 53017 : TBlDifDif = FrontDiffDiffTrans;
7199 53017 : TBmAllShBlSc =
7200 53017 : TBmBm * (TBlBmBm + TBlBmDif + TBlDifDif * RhoBlBmDifFr * RGlDifBk / (1 - RhoBlDifDifFr * RGlDifBk));
7201 53017 : TBmBmShBlSc = TBmBmBl; // TBmBm * TBlBmBm
7202 53017 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7203 53017 : if (TBmDifShBlSc < 0.0) TBmDifShBlSc = 0.0;
7204 2674 : } else if (ShadeFlag == WinShadingType::ExtBlind) {
7205 728 : Real64 RhoBlBmDifBk = BackBeamDiffRefl; // Beam-diffuse back reflectance of blind
7206 728 : Real64 RhoBlDifDifBk = BackDiffDiffRefl; // Diffuse-diffuse back refectance of blind
7207 728 : Real64 RGlBmFr = POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef);
7208 728 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
7209 : // beam-beam and diffuse transmittance of exterior beam
7210 728 : TBmBmBl = TBmBm * TBlBmBm;
7211 728 : TBmAllShBlSc = TBlBmBm * (TBmBm + TDifBare * RGlBmFr * RhoBlBmDifBk / (1 - RGlDifFr * RhoBlDifDifBk)) +
7212 728 : TBlBmDif * TDifBare / (1 - RGlDifFr * RhoBlDifDifBk);
7213 728 : TBmBmShBlSc = TBmBmBl; // TBmBm * TBlBmBm
7214 728 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7215 : } else {
7216 : // Between-glass blind on
7217 1946 : int NGlass = thisConstruct.TotGlassLayers;
7218 1946 : Real64 td2 = thisConstruct.tBareSolDiff(2);
7219 1946 : Real64 rbd1 = thisConstruct.rbBareSolDiff(1);
7220 1946 : Real64 rbshB = BackBeamDiffRefl;
7221 1946 : Real64 rfshd = FrontDiffDiffRefl;
7222 1946 : Real64 rbshd = BackDiffDiffRefl;
7223 1946 : Real64 tfshBd = FrontBeamDiffTrans;
7224 1946 : Real64 t1 = POLYF(CosInc, thisConstruct.tBareSolCoef(1));
7225 1946 : Real64 t2 = POLYF(CosInc, thisConstruct.tBareSolCoef(2));
7226 1946 : Real64 tfshBB = state.dataSurface->SurfWinBlindBmBmTrans(SurfNum);
7227 1946 : if (NGlass == 2) {
7228 1218 : Real64 rf2 = POLYF(CosInc, thisConstruct.rfBareSolCoef(2));
7229 1218 : Real64 rfshB = FrontBeamDiffRefl;
7230 1218 : Real64 rfd2 = thisConstruct.rfBareSolDiff(2);
7231 1218 : TBmBmBl = t1 * tfshBB * t2;
7232 1218 : TBmAllShBlSc = t1 * tfshBB * t2 +
7233 1218 : t1 * (tfshBB * rf2 * rbshB + tfshBd * (1.0 + rfd2 * rbshd) + rfshB * rbd1 * rfshd) * td2;
7234 : } else { // NGlass = 3
7235 728 : Real64 t1t2 = t1 * t2;
7236 728 : Real64 t3 = POLYF(CosInc, thisConstruct.tBareSolCoef(3));
7237 728 : Real64 td3 = thisConstruct.tBareSolDiff(3);
7238 728 : Real64 rf3 = POLYF(CosInc, thisConstruct.rfBareSolCoef(3));
7239 728 : Real64 rbd2 = thisConstruct.rbBareSolDiff(2);
7240 728 : Real64 rfd3 = thisConstruct.rfBareSolDiff(3);
7241 728 : Real64 tfshd = FrontDiffDiffTrans;
7242 728 : TBmBmBl = t1 * t2 * tfshBB * t3;
7243 728 : TBmAllShBlSc = t1t2 * tfshBB * t3 + t1t2 *
7244 728 : (tfshBB * rf3 * rbshB + tfshBd * (1.0 + rfd3 * rbshd) +
7245 728 : rbshB * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) *
7246 : td3;
7247 : }
7248 : // added TH 12/9/2009
7249 1946 : TBmBmShBlSc = TBmBmBl;
7250 1946 : TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
7251 : }
7252 55691 : state.dataSurface->SurfWinBlTsolBmBm(SurfNum) = TBlBmBm;
7253 55691 : state.dataSurface->SurfWinBlTsolBmDif(SurfNum) = TBlBmDif;
7254 55691 : state.dataSurface->SurfWinBlGlSysTsolBmBm(SurfNum) = TBmBmBl;
7255 : }
7256 : }
7257 : } // End of check if ShadeFlag > 0 and ShadeFlag < 10
7258 : } // end of checking if not eql window model
7259 : } // end of checking if sunlitfract > 0
7260 :
7261 7504852 : if (ShadeFlag == WinShadingType::SwitchableGlazing) {
7262 : // Switchable glazing
7263 71786 : Real64 SwitchFac = state.dataSurface->SurfWinSwitchingFactor(SurfNum);
7264 71786 : if (!state.dataSurface->SurfWinSolarDiffusing(SurfNum)) {
7265 71786 : TBmBm = Window::InterpSw(SwitchFac, TBmBm, TBmAllShBlSc);
7266 : } else {
7267 0 : TBmDif = Window::InterpSw(SwitchFac, TBmDif, TBmAllShBlSc);
7268 : }
7269 : }
7270 : // Report variables
7271 7504852 : state.dataSurface->SurfWinGlTsolBmBm(SurfNum) = TBmBm;
7272 7504852 : state.dataSurface->SurfWinGlTsolBmDif(SurfNum) = TBmDif;
7273 7504852 : state.dataSurface->SurfWinGlTsolDifDif(SurfNum) = TDifBare;
7274 :
7275 : //-----------------------------------------------------------------
7276 : // BLOCK 4 - REPORT WINDOW TRANSMITTANCE
7277 : //-----------------------------------------------------------------
7278 :
7279 : // The following SurfWinTransBmSolar and SurfWinTransDifSolar will be combined later to give
7280 : // WinTransSolar for reporting
7281 7504852 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = 0.0;
7282 7504852 : state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = 0.0;
7283 7504852 : state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = 0.0;
7284 7504852 : state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = 0.0;
7285 7504852 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) =
7286 : 0.0; // Factor for exterior beam to beam solar transmitted through window, or window plus shade, into zone at current time (m2)
7287 7504852 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) =
7288 : 0.0; // Factor for exterior beam to diffuse solar transmitted through window, or window plus shade, into zone at current time (m2)
7289 :
7290 7504852 : Real64 InOutProjSLFracMult = state.dataSurface->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
7291 7504852 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
7292 7502374 : state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = DiffTrans * surf.Area;
7293 7502374 : if (ANY_BLIND(ShadeFlag)) {
7294 71430 : if (state.dataMaterial->Blind(state.dataSurface->SurfWinBlindNumber(SurfNum)).SlatOrientation ==
7295 : DataWindowEquivalentLayer::Orientation::Horizontal) {
7296 71430 : state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = DiffTransGnd * surf.Area;
7297 71430 : state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = DiffTransSky * surf.Area;
7298 : }
7299 : }
7300 : } else {
7301 : // In equivalent layer window model system diffuse transmittance is based on unit
7302 : // diffuse radiation flux, and hence doesn't distinguish between sky and
7303 : // ground reflected diffuse radiations
7304 2478 : state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = DiffTrans * surf.Area;
7305 2478 : state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = DiffTrans * surf.Area;
7306 2478 : state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = DiffTrans * surf.Area;
7307 : }
7308 :
7309 7504852 : if (!IS_SHADED_NO_GLARE_CTRL(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
7310 : // Unshaded or switchable glazing
7311 : // Note: with previous defs of TBmBm & TBmDif, these come out right for Complex Fenestration
7312 : // SurfWinTransBmSolar uses the directional-hemispherical transmittance
7313 7383906 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = (TBmBm + TBmDif) * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7314 7383906 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBm * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7315 7383906 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDif * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7316 :
7317 : } else {
7318 120946 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = TBmAllShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7319 120946 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBmShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7320 120946 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDifShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7321 : }
7322 :
7323 : // Add diffuse transmitted by window from beam reflected from outside reveal
7324 7504852 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // Complex Fenestration
7325 12243 : if (FenSolAbsPtr == 0) {
7326 12145 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = (TBmBm + TBmDif) * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
7327 12145 : state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBm * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7328 12145 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDif * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
7329 12145 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) +=
7330 12145 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
7331 12145 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) +=
7332 12145 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
7333 : } else {
7334 98 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = 0.0;
7335 98 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = 0.0;
7336 : }
7337 : } else { // Regular window
7338 : // this is also valid for equivalent layer window
7339 7492609 : state.dataSolarShading->SurfWinTransBmSolar(SurfNum) +=
7340 7492609 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
7341 7492609 : state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) +=
7342 7492609 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
7343 : }
7344 :
7345 : //-----------------------------------------------------------------
7346 : // BLOCK 5 - UPDATE SOLAR ENTERING A ZONE AS BEAM OR DIFFUSE RADIATION
7347 : //-----------------------------------------------------------------
7348 : // Increment factor for total exterior beam solar entering zone through window as beam or diffuse
7349 7504852 : if (SunLitFract > 0.0 && surf.Class != SurfaceClass::TDD_Dome) {
7350 : // Window is schedule surface gained. Do not make addition to what enters into zone since that information is not available
7351 3864096 : if (FenSolAbsPtr == 0) {
7352 : Real64 TBmAll; // Window beam-to-(beam+diffuse) transmittance
7353 11523619 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) != WindowModel::BSDF &&
7354 7659579 : (ANY_BLIND(ShadeFlag) || ANY_SHADE_SCREEN(ShadeFlag))) {
7355 79549 : TBmAll = TBmAllShBlSc;
7356 : } else {
7357 3784491 : TBmAll = TBmBm + TBmDif;
7358 : }
7359 3864040 : BTOTZone += surf.IncSolMultiplier * TBmAll * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // [m2]
7360 : }
7361 : }
7362 :
7363 : // Correct for effect of (1) beam absorbed by inside reveal, (2) diffuse entering zone from beam
7364 : // reflected by inside reveal and (3) diffuse transmitted by window from beam reflected from outside reveal.
7365 7504852 : if (CosInc > 0.0) {
7366 : // The BTOTZone is the solar into zone assuming no inside or outside reveals
7367 : // The inside reveals receive solar (reflected part + absorbed part) from the window, this amount should be deducted from the
7368 : // BTOTZone, then adds the InsRevealDiffIntoZone
7369 4071550 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // Complex Fenestration
7370 : // Do not add total into zone from scheduled surface gains. That will be added later
7371 6461 : if (SurfaceScheduledSolarInc(state, SurfNum, ConstrNum) == 0) {
7372 6461 : BTOTZone = BTOTZone - state.dataSurface->SurfWinBmSolRefldInsReveal(SurfNum) -
7373 6461 : state.dataSurface->SurfWinBmSolAbsdInsReveal(SurfNum) + state.dataSurface->SurfWinInsRevealDiffIntoZone(SurfNum) +
7374 6461 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
7375 : }
7376 : } else { // Regular window
7377 4065089 : BTOTZone = BTOTZone - state.dataSurface->SurfWinBmSolRefldInsReveal(SurfNum) -
7378 4065089 : state.dataSurface->SurfWinBmSolAbsdInsReveal(SurfNum) + state.dataSurface->SurfWinInsRevealDiffIntoZone(SurfNum) +
7379 4065089 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
7380 : }
7381 : // Add beam solar absorbed by outside reveal to outside of window's base surface. Add beam solar absorbed by inside reveal to inside
7382 : // of window's base surface. This ignores 2-D heat transfer effects.
7383 4071550 : int BaseSurfNum = surf.BaseSurf;
7384 4071550 : state.dataSurface->SurfOpaqAI(BaseSurfNum) +=
7385 4071550 : state.dataSurface->SurfWinBmSolAbsdInsReveal(SurfNum) / state.dataSurface->Surface(BaseSurfNum).Area;
7386 4071550 : state.dataSurface->SurfOpaqAO(BaseSurfNum) +=
7387 4071550 : state.dataSurface->SurfWinBmSolAbsdOutsReveal(SurfNum) / state.dataSurface->Surface(BaseSurfNum).Area;
7388 : }
7389 :
7390 : //-----------------------------------------------------------------
7391 : // BLOCK 6 - INTERIOR BEAM FROM EXTERIOR WINDOW THAT IS ABSORBED/TRANSMITTED BY BACK SURFACES
7392 : //-----------------------------------------------------------------
7393 :
7394 : // If shade is in place or there is a diffusing glass layer there is no interior beam
7395 : // from this exterior window since the beam-beam transmittance of shades and diffusing glass
7396 : // is assumed to be zero. The beam-beam transmittance of tubular daylighting devices is also
7397 : // assumed to be zero.
7398 7504852 : if (SunLitFract > 0.0) {
7399 3865244 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) != WindowModel::BSDF)
7400 7695332 : if (ANY_SHADE(ShadeFlag) || state.dataSurface->SurfWinSolarDiffusing(SurfNum) ||
7401 7695332 : surf.OriginalClass == SurfaceClass::TDD_Diffuser || surf.Class == SurfaceClass::TDD_Dome)
7402 24530 : continue;
7403 :
7404 : // Find interior beam radiation that is:
7405 : // (1) absorbed by opaque back surfaces;
7406 : // (2) absorbed by glass layers of back surfaces that are interior or exterior windows;
7407 : // (3) absorbed by interior, exterior or between-glass shades or blinds of back surfaces
7408 : // that are exterior windows; and
7409 : // (4) transmitted through back surfaces that are interior or exterior windows.
7410 : // Beam-beam transmittance of exterior window
7411 : Real64 TBm; // Window beam-beam transmittance
7412 : Real64 TBmDenom; // TBmDenominator
7413 3840714 : Real64 TBmBmSc = state.dataSurface->SurfWinScGlSysTsolBmBm(SurfNum);
7414 3840714 : Real64 TBmBmBl = state.dataSurface->SurfWinBlGlSysTsolBmBm(SurfNum);
7415 3840714 : Real64 TBmBm = state.dataSurface->SurfWinGlTsolBmBm(SurfNum);
7416 :
7417 3840714 : Real64 InOutProjSLFracMult = state.dataSurface->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
7418 3840714 : int InShelfSurf = 0; // Inside daylighting shelf surface number
7419 3840714 : int ShelfNum = state.dataSurface->SurfDaylightingShelfInd(SurfNum);
7420 3840714 : if (ShelfNum > 0) { // Daylighting shelf
7421 364 : InShelfSurf = state.dataDaylightingDevicesData->Shelf(ShelfNum).InSurf;
7422 : }
7423 3840714 : if (ANY_BLIND(ShadeFlag)) {
7424 55691 : TBm = TBmBmBl; // Interior, exterior or between-glass blind on
7425 3785023 : } else if (ShadeFlag == WinShadingType::ExtScreen) {
7426 1624 : TBm = TBmBmSc; // Exterior screen on
7427 : } else {
7428 3783399 : TBm = TBmBm; // Bare glass or switchable glazing
7429 : // Correction for beam absorbed by inside reveal
7430 3783399 : TBmDenom = (SunLitFract * CosInc * surf.Area * InOutProjSLFracMult);
7431 3783399 : if (TBmDenom != 0.0) { // when =0.0, no correction
7432 3783399 : TBm -= state.dataSurface->SurfWinBmSolAbsdInsReveal(SurfNum) / TBmDenom;
7433 : }
7434 3783399 : TBm = max(0.0, TBm);
7435 : // this multiplier doesn't work with other shading, so no need to apply in other branches
7436 3783399 : TBm *= surf.IncSolMultiplier;
7437 : }
7438 :
7439 3840714 : if (TBm == 0.0) continue;
7440 3782316 : if (InShelfSurf > 0) { // Inside daylighting shelf
7441 : // Inside daylighting shelves assume that no beam will pass the end of the shelf.
7442 : // Since all beam is absorbed on the shelf, this might cause them to get unrealistically hot at times.
7443 : // BTOTWinZone - Transmitted beam solar factor for a window [m2]
7444 364 : Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * InOutProjSLFracMult;
7445 : // Shelf surface area is divided by 2 because only one side sees beam (Area was multiplied by 2 during init)
7446 364 : state.dataSurface->SurfOpaqAI(InShelfSurf) += BTOTWinZone / (0.5 * state.dataSurface->Surface(InShelfSurf).Area); //[-]
7447 364 : BABSZone += BTOTWinZone; //[m2]
7448 364 : continue;
7449 364 : }
7450 :
7451 3781952 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) { // Full interior solar distribution
7452 2488955 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
7453 : // Loop over back surfaces irradiated by beam from this exterior window
7454 7053935 : for (int IBack = 1; IBack <= state.dataBSDFWindow->MaxBkSurf; ++IBack) {
7455 : int BackSurfNum =
7456 7053935 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
7457 7053935 : if (BackSurfNum == 0) break; // No more irradiated back surfaces for this exterior window
7458 4570377 : int ConstrNumBack = state.dataSurface->SurfActiveConstruction(BackSurfNum);
7459 4570377 : int NBackGlass = state.dataConstruction->Construct(ConstrNumBack).TotGlassLayers;
7460 : // Irradiated (overlap) area for this back surface, projected onto window plane
7461 : // (includes effect of shadowing on exterior window)
7462 : Real64 AOverlap =
7463 4570377 : state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
7464 : // Back surface area irradiated by beam solar from an exterior window, projected onto window plane
7465 4570377 : Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
7466 : // AOverlap multiplied by exterior window beam transmittance and cosine of incidence angle
7467 4570377 : if (state.dataConstruction->Construct(ConstrNumBack).TransDiff <= 0.0) {
7468 :
7469 : // Back surface is opaque interior or exterior wall
7470 : // Interior solar absorptance of opaque surface
7471 4284906 : Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
7472 4284906 : state.dataSurface->SurfOpaqAI(BackSurfNum) +=
7473 4284906 : BOverlap * AbsIntSurf / state.dataSurface->Surface(BackSurfNum).Area; //[-]
7474 4284906 : BABSZone += BOverlap * AbsIntSurf; //[m2]
7475 :
7476 : } else {
7477 :
7478 : // Back surface is an interior or exterior window
7479 : // Note that exterior back windows can have a shading device but interior back windows
7480 : // are assumed to be bare, i.e., they have no shading device and are non-switchable.
7481 : // The layer order for interior windows is "outside" to "inside," where "outside" refers to
7482 : // the adjacent zone and "inside" refers to the current zone.
7483 285471 : WinShadingType ShadeFlagBack = state.dataSurface->SurfWinShadingFlag(BackSurfNum);
7484 285471 : Real64 SlatAngBack = state.dataSurface->SurfWinSlatAngThisTS(BackSurfNum);
7485 : Real64 CosIncBack =
7486 285471 : std::abs(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, BackSurfNum));
7487 285471 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
7488 : // Transmitting window is complex fen, change the incident angle to one for ray joining
7489 : // transmitting and back window centers
7490 0 : CosIncBack = std::abs(state.dataBSDFWindow->ComplexWind(SurfNum).sdotN(IBack));
7491 : }
7492 285471 : int ConstrNumBackShRaw = state.dataSurface->SurfWinActiveShadedConstruction(BackSurfNum);
7493 285471 : int const ConstrNumBackSh = ConstrNumBackShRaw == 0 ? ConstrNumBack : ConstrNumBackShRaw;
7494 285471 : state.dataSolarShading->SurfWinAbsBeam.dimension(state.dataHeatBal->MaxSolidWinLayers, 0.0);
7495 285471 : Real64 TransBeamWin = 0.0; // Beam solar transmittance of a window
7496 285471 : Real64 AbsBeamTotWin = 0.0; // Sum of window glass layer beam solar absorptances
7497 285471 : Real64 backSurfBeamSolInTrans = 0.0; // Fraction of BeamSolarRad transmitted out through window inside face [W]
7498 :
7499 : // Interior beam absorptance of glass layers and beam transmittance of back exterior &
7500 : // or interior window WITHOUT SHADING this timestep
7501 285471 : if (NOT_SHADED(ShadeFlagBack)) {
7502 710310 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7503 424839 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7504 424839 : POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).AbsBeamBackCoef(Lay));
7505 : }
7506 285471 : TransBeamWin = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).TransSolBeamCoef);
7507 : }
7508 :
7509 : // Interior beam absorptance of glass layers and beam transmittance
7510 : // of back exterior window with SHADE
7511 285471 : if (ANY_SHADE(ShadeFlagBack)) {
7512 0 : for (int Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNumBackSh).TotGlassLayers; ++Lay) {
7513 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7514 0 : POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).AbsBeamBackCoef(Lay));
7515 : }
7516 0 : TransBeamWin = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).TransSolBeamCoef);
7517 : }
7518 :
7519 : // Interior beam absorbed by INTERIOR SHADE of back exterior window
7520 :
7521 285471 : if (ShadeFlagBack == WinShadingType::IntShade) {
7522 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7523 0 : BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade /
7524 0 : (state.dataSurface->Surface(BackSurfNum).Area + state.dataSurface->SurfWinDividerArea(BackSurfNum));
7525 0 : BABSZone += BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade;
7526 0 : backSurfBeamSolInTrans += BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade;
7527 285471 : } else if (ShadeFlagBack ==
7528 : WinShadingType::ExtShade) { // Interior beam absorbed by EXTERIOR SHADE of back exterior window
7529 0 : Real64 RGlFront = state.dataConstruction->Construct(ConstrNumBack).ReflectSolDiffFront;
7530 0 : auto const *thisMaterial = dynamic_cast<Material::MaterialChild *>(
7531 0 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(1)));
7532 0 : assert(thisMaterial != nullptr);
7533 0 : Real64 AbsSh = thisMaterial->AbsorpSolar;
7534 0 : Real64 RhoSh = 1.0 - AbsSh - thisMaterial->Trans;
7535 0 : Real64 AShBack = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).TransSolBeamCoef) * AbsSh /
7536 0 : (1.0 - RGlFront * RhoSh);
7537 0 : BABSZone += BOverlap * AShBack;
7538 0 : backSurfBeamSolInTrans += BOverlap * AShBack;
7539 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7540 0 : BOverlap * AShBack /
7541 0 : (state.dataSurface->Surface(BackSurfNum).Area + state.dataSurface->SurfWinDividerArea(BackSurfNum));
7542 285471 : } else if (ShadeFlagBack ==
7543 : WinShadingType::BGShade) { // Interior beam absorbed by BETWEEN-GLASS SHADE of back exterior window
7544 0 : Real64 rbd1k = state.dataConstruction->Construct(ConstrNumBack).rbBareSolDiff(1);
7545 0 : Real64 rfd2k = state.dataConstruction->Construct(ConstrNumBack).rfBareSolDiff(2);
7546 : Real64 AShBack; // System shade absorptance for interior beam solar
7547 0 : if (NBackGlass == 2) {
7548 0 : Real64 t2k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).tBareSolCoef(2));
7549 0 : auto const *thisMaterial = dynamic_cast<Material::MaterialChild *>(
7550 0 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(3)));
7551 0 : assert(thisMaterial != nullptr);
7552 0 : Real64 TrSh = thisMaterial->Trans; // Shade material solar transmittance
7553 0 : Real64 RhoSh = thisMaterial->ReflectShade; // Shade material solar absorptance
7554 0 : Real64 AbsSh = min(1.0, max(0.0, 1 - TrSh - RhoSh)); // Shade material solar absorptance
7555 0 : AShBack = t2k * (1 + RhoSh * rfd2k + TrSh * rbd1k) * AbsSh;
7556 : } else { // NBackGlass = 3
7557 0 : Real64 t3k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).tBareSolCoef(3));
7558 0 : Real64 td2k = state.dataConstruction->Construct(ConstrNumBack).tBareSolDiff(2);
7559 0 : Real64 rbd2k = state.dataConstruction->Construct(ConstrNumBack).rbBareSolDiff(2);
7560 0 : Real64 rfd3k = state.dataConstruction->Construct(ConstrNumBack).rfBareSolDiff(3);
7561 0 : auto const *thisMaterial = dynamic_cast<Material::MaterialChild *>(
7562 0 : state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(5)));
7563 0 : assert(thisMaterial != nullptr);
7564 0 : Real64 TrSh = thisMaterial->Trans;
7565 0 : Real64 RhoSh = thisMaterial->ReflectShade;
7566 0 : Real64 AbsSh = min(1.0, max(0.0, 1 - TrSh - RhoSh));
7567 0 : AShBack = t3k * (1 + RhoSh * rfd3k + TrSh * (rbd2k + td2k * rbd1k * td2k)) * AbsSh;
7568 : }
7569 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7570 0 : BOverlap * AShBack / state.dataSurface->Surface(BackSurfNum).Area;
7571 0 : BABSZone += BOverlap * AShBack;
7572 0 : backSurfBeamSolInTrans += BOverlap * AShBack;
7573 : }
7574 :
7575 : // Interior beam absorptance of glass layers and beam absorbed in blind
7576 : // of back exterior window with BLIND
7577 285471 : if (ANY_BLIND(ShadeFlagBack)) {
7578 0 : int BlNumBack = state.dataSurface->SurfWinBlindNumber(BackSurfNum); // Back surface blind number
7579 0 : auto const &thisBlindBack = state.dataMaterial->Blind(BlNumBack);
7580 0 : auto const &thisBlind = state.dataMaterial->Blind(BlNum);
7581 : Real64 ProfAngBack =
7582 0 : state.dataSurface->SurfWinProfileAng(BackSurfNum); // Back window solar profile angle (radians)
7583 :
7584 0 : int SlatsAngIndexLowerBack = state.dataSurface->SurfWinSlatsAngIndex(BackSurfNum);
7585 0 : int ProfAngIndexLowerBack = state.dataSurface->SurfWinProfAngIndex(BackSurfNum);
7586 0 : int SlatsAngIndexUpperBack = std::min(Material::MaxProfAngs, SlatsAngIndexLowerBack + 1);
7587 0 : int ProfAngIndexUpperBack = std::min(Material::MaxProfAngs, ProfAngIndexLowerBack + 1);
7588 0 : Real64 SlatsAngInterpFacBack = state.dataSurface->SurfWinSlatsAngInterpFac(BackSurfNum);
7589 0 : Real64 ProfAngInterpFacBack = state.dataSurface->SurfWinProfAngInterpFac(BackSurfNum);
7590 :
7591 0 : Real64 TGlBmBack = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).TransSolBeamCoef);
7592 : Real64 TBlBmBmBack =
7593 0 : Window::BlindBeamBeamTrans(ProfAngBack,
7594 : Constant::Pi - SlatAngBack,
7595 0 : thisBlindBack.SlatWidth,
7596 0 : thisBlindBack.SlatSeparation,
7597 0 : thisBlindBack.SlatThickness); // Blind solar back beam-beam transmittance
7598 : Real64 TBlBmDiffBack; // Blind solar back beam-diffuse transmittance
7599 0 : if (state.dataSurface->SurfWinMovableSlats(BackSurfNum)) {
7600 : TBlBmDiffBack =
7601 0 : Window::InterpProfSlat(thisBlind.SolBackBeamDiffTrans(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7602 0 : thisBlind.SolBackBeamDiffTrans(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7603 0 : thisBlind.SolBackBeamDiffTrans(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7604 0 : thisBlind.SolBackBeamDiffTrans(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7605 : SlatsAngInterpFacBack,
7606 : ProfAngInterpFacBack);
7607 : } else {
7608 0 : TBlBmDiffBack = General::Interp(thisBlind.SolBackBeamDiffTrans(1, ProfAngIndexLowerBack),
7609 0 : thisBlind.SolBackBeamDiffTrans(1, ProfAngIndexUpperBack),
7610 : ProfAngInterpFacBack);
7611 : }
7612 :
7613 0 : if (ShadeFlagBack == WinShadingType::IntBlind) {
7614 : // Interior beam absorptance of GLASS LAYERS of exterior back window with INTERIOR BLIND
7615 : Real64 RhoBlFront; // Blind solar front diffuse reflectance
7616 : Real64 AbsBlFront; // Blind solar front beam absorptance
7617 : Real64 AbsBlBack; // Blind solar back beam absorptance
7618 0 : if (state.dataSurface->SurfWinMovableSlats(BackSurfNum)) {
7619 0 : FrontDiffDiffRefl = General::Interp(
7620 0 : thisBlindBack.SolFrontDiffDiffRefl(state.dataSurface->SurfWinSlatsAngIndex(BackSurfNum)),
7621 0 : thisBlindBack.SolFrontDiffDiffRefl(
7622 0 : std::min(Material::MaxSlatAngs, state.dataSurface->SurfWinSlatsAngIndex(BackSurfNum) + 1)),
7623 0 : state.dataSurface->SurfWinSlatsAngInterpFac(BackSurfNum));
7624 : FrontDiffAbs =
7625 0 : General::Interp(thisBlindBack.SolFrontDiffAbs(state.dataSurface->SurfWinSlatsAngIndex(BackSurfNum)),
7626 0 : thisBlindBack.SolFrontDiffAbs(std::min(
7627 0 : Material::MaxSlatAngs, state.dataSurface->SurfWinSlatsAngIndex(BackSurfNum) + 1)),
7628 0 : state.dataSurface->SurfWinSlatsAngInterpFac(BackSurfNum));
7629 : RhoBlFront =
7630 0 : Window::InterpProfSlat(thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7631 0 : thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7632 0 : thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7633 0 : thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7634 : SlatsAngInterpFacBack,
7635 : ProfAngInterpFacBack);
7636 : AbsBlFront =
7637 0 : Window::InterpProfSlat(thisBlind.SolFrontBeamAbs(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7638 0 : thisBlind.SolFrontBeamAbs(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7639 0 : thisBlind.SolFrontBeamAbs(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7640 0 : thisBlind.SolFrontBeamAbs(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7641 : SlatsAngInterpFacBack,
7642 : ProfAngInterpFacBack);
7643 : AbsBlBack =
7644 0 : Window::InterpProfSlat(thisBlind.SolBackBeamAbs(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7645 0 : thisBlind.SolBackBeamAbs(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7646 0 : thisBlind.SolBackBeamAbs(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7647 0 : thisBlind.SolBackBeamAbs(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7648 : SlatsAngInterpFacBack,
7649 : ProfAngInterpFacBack);
7650 : } else {
7651 0 : FrontDiffDiffRefl = thisBlindBack.SolFrontDiffDiffRefl(1); // Blind solar front beam reflectance
7652 0 : FrontDiffAbs = thisBlindBack.SolFrontDiffAbs(1);
7653 0 : RhoBlFront = General::Interp(thisBlind.SolFrontBeamDiffRefl(1, ProfAngIndexLowerBack),
7654 0 : thisBlind.SolFrontBeamDiffRefl(1, ProfAngIndexUpperBack),
7655 : ProfAngInterpFacBack);
7656 0 : AbsBlFront = General::Interp(thisBlind.SolFrontBeamAbs(1, ProfAngIndexLowerBack),
7657 0 : thisBlind.SolFrontBeamAbs(1, ProfAngIndexUpperBack),
7658 : ProfAngInterpFacBack);
7659 0 : AbsBlBack = General::Interp(thisBlind.SolBackBeamAbs(1, ProfAngIndexLowerBack),
7660 0 : thisBlind.SolBackBeamAbs(1, ProfAngIndexUpperBack),
7661 : ProfAngInterpFacBack);
7662 : }
7663 :
7664 0 : Real64 RhoBlDiffFront = FrontDiffDiffRefl; // Glazing system solar back beam-beam reflectance
7665 0 : Real64 RGlBack = POLYF(CosIncBack,
7666 0 : state.dataConstruction->Construct(ConstrNumBack)
7667 0 : .ReflSolBeamBackCoef); // Glazing system back diffuse solar reflectance
7668 0 : Real64 RGlDiffBack = state.dataConstruction->Construct(ConstrNumBack).ReflectSolDiffBack;
7669 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7670 : Real64 AbWinBack =
7671 0 : POLYF(CosIncBack,
7672 0 : state.dataConstruction->Construct(ConstrNumBack)
7673 0 : .AbsBeamBackCoef(Lay)); // Factor for back beam radiation absorbed in window glass layer
7674 0 : Real64 AGlDiffBack = state.dataConstruction->Construct(ConstrNumBack)
7675 0 : .AbsDiffBack(Lay); // Glass layer back diffuse solar absorptance
7676 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7677 0 : TBlBmBmBack * AbWinBack + ((TBlBmBmBack * RGlBack * RhoBlFront + TBlBmDiffBack) * AGlDiffBack /
7678 0 : (1.0 - RGlDiffBack * RhoBlDiffFront));
7679 : }
7680 :
7681 : // Interior beam transmitted by exterior back window with INTERIOR BLIND
7682 : Real64 TGlDif =
7683 0 : state.dataConstruction->Construct(ConstrNumBack).TransDiff; // Bare diffuse transmittance of back window
7684 0 : TransBeamWin =
7685 0 : TBlBmBmBack * (TGlBmBack + TGlDif * RGlBack * RhoBlFront / (1.0 - RGlDiffBack * RhoBlDiffFront)) +
7686 0 : TBlBmDiffBack * TGlDif / (1.0 - RGlDiffBack * RhoBlDiffFront);
7687 :
7688 : // Interior beam absorbed by BLIND on exterior back window with INTERIOR BLIND
7689 :
7690 0 : Real64 AbsBlDiffFront = FrontDiffAbs; // Blind solar front diffuse absorptance
7691 0 : Real64 ABlBack = AbsBlBack + TBlBmBmBack * RGlBack * AbsBlFront +
7692 0 : (AbsBlDiffFront * RGlDiffBack / (1 - RhoBlDiffFront * RGlDiffBack)) *
7693 0 : (RGlBack * TBlBmBmBack * RhoBlFront +
7694 : TBlBmDiffBack); // Blind solar back absorptance for interior solar
7695 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7696 0 : BOverlap * ABlBack /
7697 0 : (state.dataSurface->Surface(BackSurfNum).Area + state.dataSurface->SurfWinDividerArea(BackSurfNum));
7698 0 : BABSZone += BOverlap * ABlBack;
7699 0 : backSurfBeamSolInTrans += BOverlap * ABlBack;
7700 :
7701 0 : } else if (ShadeFlagBack == WinShadingType::ExtBlind) {
7702 :
7703 : // Interior beam absorptance of GLASS LAYERS of exterior back window with EXTERIOR BLIND
7704 :
7705 0 : Real64 RGlDiffFront = state.dataConstruction->Construct(ConstrNumBack)
7706 0 : .ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
7707 : Real64 RhoBlBack; // Blind solar back beam-diffuse reflectance
7708 : Real64 RhoBlBmDifBk;
7709 : Real64 AbsBlBack;
7710 0 : if (state.dataSurface->SurfWinMovableSlats(BackSurfNum)) {
7711 : RhoBlBack =
7712 0 : Window::InterpProfSlat(thisBlind.SolBackBeamDiffRefl(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7713 0 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7714 0 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7715 0 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7716 : SlatsAngInterpFacBack,
7717 : ProfAngInterpFacBack);
7718 : RhoBlBmDifBk =
7719 0 : Window::InterpProfSlat(thisBlind.SolBackBeamDiffRefl(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7720 0 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7721 0 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7722 0 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7723 : SlatsAngInterpFacBack,
7724 : ProfAngInterpFacBack);
7725 : AbsBlBack =
7726 0 : Window::InterpProfSlat(thisBlind.SolBackBeamAbs(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7727 0 : thisBlind.SolBackBeamAbs(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7728 0 : thisBlind.SolBackBeamAbs(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7729 0 : thisBlind.SolBackBeamAbs(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7730 : SlatsAngInterpFacBack,
7731 : ProfAngInterpFacBack);
7732 : } else {
7733 0 : RhoBlBack = General::Interp(thisBlind.SolBackBeamDiffRefl(1, ProfAngIndexLowerBack),
7734 0 : thisBlind.SolBackBeamDiffRefl(1, ProfAngIndexUpperBack),
7735 : ProfAngInterpFacBack);
7736 0 : RhoBlBmDifBk = General::Interp(thisBlind.SolBackBeamDiffRefl(1, ProfAngIndexLowerBack),
7737 0 : thisBlind.SolBackBeamDiffRefl(1, ProfAngIndexUpperBack),
7738 : ProfAngInterpFacBack);
7739 0 : AbsBlBack = General::Interp(thisBlind.SolBackBeamAbs(1, ProfAngIndexLowerBack),
7740 0 : thisBlind.SolBackBeamAbs(1, ProfAngIndexUpperBack),
7741 : ProfAngInterpFacBack);
7742 : }
7743 :
7744 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7745 : Real64 AbWinBack =
7746 0 : POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).AbsBeamBackCoef(Lay));
7747 0 : Real64 AGlDiffFront = state.dataConstruction->Construct(ConstrNumBack).AbsDiff(Lay);
7748 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7749 0 : AbWinBack + (TGlBmBack * AGlDiffFront * RhoBlBack / (1.0 - RhoBlBack * RGlDiffFront));
7750 : }
7751 :
7752 : // Interior beam transmitted by exterior back window with EXTERIOR BLIND
7753 0 : Real64 TBlDifDif = BackDiffDiffTrans;
7754 0 : Real64 RhoBlDifDifBk = BackDiffDiffRefl;
7755 0 : Real64 AbsBlDiffBack = BackDiffAbs;
7756 0 : Real64 ABlBack =
7757 0 : TGlBmBack * (AbsBlBack + RhoBlBack * RGlDiffFront * AbsBlDiffBack / (1 - RhoBlDifDifBk * RGlDiffFront));
7758 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
7759 0 : TransBeamWin = TGlBmBack * (TBlBmBmBack + TBlBmDiffBack +
7760 0 : TBlDifDif * RhoBlBmDifBk * RGlDifFr / (1.0 - RhoBlDifDifBk * RGlDifFr));
7761 : // Interior beam absorbed by EXTERIOR BLIND on exterior back window
7762 0 : BABSZone += BOverlap * ABlBack;
7763 0 : backSurfBeamSolInTrans += BOverlap * ABlBack;
7764 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7765 0 : BOverlap * ABlBack /
7766 0 : (state.dataSurface->Surface(BackSurfNum).Area + state.dataSurface->SurfWinDividerArea(BackSurfNum));
7767 :
7768 : } else {
7769 : // ShadeFlagBack == BGBlindOn
7770 0 : Real64 t1k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).tBareSolCoef(1));
7771 0 : Real64 t2k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).tBareSolCoef(2));
7772 0 : Real64 af2k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).afBareSolCoef(2));
7773 0 : Real64 ab1k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).abBareSolCoef(1));
7774 0 : Real64 ab2k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).abBareSolCoef(2));
7775 0 : Real64 rb1k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).rbBareSolCoef(1));
7776 0 : Real64 rb2k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).rbBareSolCoef(2));
7777 0 : Real64 td1k = state.dataConstruction->Construct(ConstrNumBack).tBareSolDiff(1);
7778 0 : Real64 td2k = state.dataConstruction->Construct(ConstrNumBack).tBareSolDiff(2);
7779 0 : Real64 afd2k = state.dataConstruction->Construct(ConstrNumBack).afBareSolDiff(2);
7780 0 : Real64 abd1k = state.dataConstruction->Construct(ConstrNumBack).abBareSolDiff(1);
7781 0 : Real64 abd2k = state.dataConstruction->Construct(ConstrNumBack).abBareSolDiff(2);
7782 0 : Real64 rfd2k = state.dataConstruction->Construct(ConstrNumBack).rfBareSolDiff(2);
7783 0 : Real64 rbd1k = state.dataConstruction->Construct(ConstrNumBack).rbBareSolDiff(1);
7784 0 : Real64 rbd2k = state.dataConstruction->Construct(ConstrNumBack).rbBareSolDiff(2);
7785 0 : Real64 tfshBBk = Window::BlindBeamBeamTrans(ProfAngBack,
7786 : SlatAngBack,
7787 0 : thisBlindBack.SlatWidth,
7788 0 : thisBlindBack.SlatSeparation,
7789 0 : thisBlindBack.SlatThickness);
7790 0 : Real64 tbshBBk = Window::BlindBeamBeamTrans(ProfAngBack,
7791 : Constant::Pi - SlatAngBack,
7792 0 : thisBlindBack.SlatWidth,
7793 0 : thisBlindBack.SlatSeparation,
7794 0 : thisBlindBack.SlatThickness);
7795 :
7796 0 : Real64 tfshBdk = General::Interp(thisBlind.SolFrontBeamDiffTrans(1, ProfAngIndexLowerBack),
7797 0 : thisBlind.SolFrontBeamDiffTrans(1, ProfAngIndexUpperBack),
7798 : ProfAngInterpFacBack);
7799 0 : Real64 tbshBdk = General::Interp(thisBlind.SolBackBeamDiffTrans(1, ProfAngIndexLowerBack),
7800 0 : thisBlind.SolBackBeamDiffTrans(1, ProfAngIndexUpperBack),
7801 : ProfAngInterpFacBack);
7802 0 : Real64 rfshBk = General::Interp(thisBlind.SolFrontBeamDiffRefl(1, ProfAngIndexLowerBack),
7803 0 : thisBlind.SolFrontBeamDiffRefl(1, ProfAngIndexUpperBack),
7804 : ProfAngInterpFacBack);
7805 0 : Real64 rbshBk = General::Interp(thisBlind.SolBackBeamDiffRefl(1, ProfAngIndexLowerBack),
7806 0 : thisBlind.SolBackBeamDiffRefl(1, ProfAngIndexUpperBack),
7807 : ProfAngInterpFacBack);
7808 0 : Real64 afshBk = General::Interp(thisBlind.SolFrontBeamAbs(1, ProfAngIndexLowerBack),
7809 0 : thisBlind.SolFrontBeamAbs(1, ProfAngIndexUpperBack),
7810 : ProfAngInterpFacBack);
7811 0 : Real64 abshBk = General::Interp(thisBlind.SolBackBeamAbs(1, ProfAngIndexLowerBack),
7812 0 : thisBlind.SolBackBeamAbs(1, ProfAngIndexUpperBack),
7813 : ProfAngInterpFacBack);
7814 0 : Real64 tfshdk = thisBlindBack.SolFrontDiffDiffTrans(1);
7815 0 : Real64 rfshdk = thisBlindBack.SolFrontDiffDiffRefl(1);
7816 0 : Real64 afshdk = thisBlindBack.SolFrontDiffAbs(1);
7817 0 : Real64 tbshdk = thisBlindBack.SolBackDiffDiffTrans(1);
7818 0 : Real64 rbshdk = thisBlindBack.SolBackDiffDiffRefl(1);
7819 0 : Real64 abshdk = thisBlindBack.SolBackDiffAbs(1);
7820 0 : if (state.dataSurface->SurfWinMovableSlats(BackSurfNum)) {
7821 0 : tfshdk = General::Interp(thisBlindBack.SolFrontDiffDiffTrans(SlatsAngIndexLowerBack),
7822 0 : thisBlindBack.SolFrontDiffDiffTrans(SlatsAngIndexUpperBack),
7823 : SlatsAngInterpFacBack);
7824 0 : rfshdk = General::Interp(thisBlindBack.SolFrontDiffDiffRefl(SlatsAngIndexLowerBack),
7825 0 : thisBlindBack.SolFrontDiffDiffRefl(SlatsAngIndexUpperBack),
7826 : SlatsAngInterpFacBack);
7827 0 : afshdk = General::Interp(thisBlindBack.SolFrontDiffAbs(SlatsAngIndexLowerBack),
7828 0 : thisBlindBack.SolFrontDiffAbs(SlatsAngIndexUpperBack),
7829 : SlatsAngInterpFacBack);
7830 0 : tbshdk = General::Interp(thisBlindBack.SolBackDiffDiffTrans(SlatsAngIndexLowerBack),
7831 0 : thisBlindBack.SolBackDiffDiffTrans(SlatsAngIndexUpperBack),
7832 : SlatsAngInterpFacBack);
7833 0 : rbshdk = General::Interp(thisBlindBack.SolBackDiffDiffRefl(SlatsAngIndexLowerBack),
7834 0 : thisBlindBack.SolBackDiffDiffRefl(SlatsAngIndexUpperBack),
7835 : SlatsAngInterpFacBack);
7836 0 : abshdk = General::Interp(thisBlindBack.SolBackDiffAbs(SlatsAngIndexLowerBack),
7837 0 : thisBlindBack.SolBackDiffAbs(SlatsAngIndexUpperBack),
7838 : SlatsAngInterpFacBack);
7839 : tfshBdk =
7840 0 : Window::InterpProfSlat(thisBlind.SolFrontBeamDiffTrans(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7841 0 : thisBlind.SolFrontBeamDiffTrans(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7842 0 : thisBlind.SolFrontBeamDiffTrans(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7843 0 : thisBlind.SolFrontBeamDiffTrans(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7844 : SlatsAngInterpFacBack,
7845 : ProfAngInterpFacBack);
7846 : tbshBdk =
7847 0 : Window::InterpProfSlat(thisBlind.SolBackBeamDiffTrans(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7848 0 : thisBlind.SolBackBeamDiffTrans(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7849 0 : thisBlind.SolBackBeamDiffTrans(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7850 0 : thisBlind.SolBackBeamDiffTrans(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7851 : SlatsAngInterpFacBack,
7852 : ProfAngInterpFacBack);
7853 : rfshBk =
7854 0 : Window::InterpProfSlat(thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7855 0 : thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7856 0 : thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7857 0 : thisBlind.SolFrontBeamDiffRefl(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7858 : SlatsAngInterpFacBack,
7859 : ProfAngInterpFacBack);
7860 : rbshBk =
7861 0 : Window::InterpProfSlat(thisBlind.SolBackBeamDiffRefl(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7862 0 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7863 0 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7864 0 : thisBlind.SolBackBeamDiffRefl(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7865 : SlatsAngInterpFacBack,
7866 : ProfAngInterpFacBack);
7867 0 : afshBk = Window::InterpProfSlat(thisBlind.SolFrontBeamAbs(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7868 0 : thisBlind.SolFrontBeamAbs(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7869 0 : thisBlind.SolFrontBeamAbs(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7870 0 : thisBlind.SolFrontBeamAbs(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7871 : SlatsAngInterpFacBack,
7872 : ProfAngInterpFacBack);
7873 0 : abshBk = Window::InterpProfSlat(thisBlind.SolBackBeamAbs(SlatsAngIndexLowerBack, ProfAngIndexLowerBack),
7874 0 : thisBlind.SolBackBeamAbs(SlatsAngIndexUpperBack, ProfAngIndexLowerBack),
7875 0 : thisBlind.SolBackBeamAbs(SlatsAngIndexLowerBack, ProfAngIndexUpperBack),
7876 0 : thisBlind.SolBackBeamAbs(SlatsAngIndexUpperBack, ProfAngIndexUpperBack),
7877 : SlatsAngInterpFacBack,
7878 : ProfAngInterpFacBack);
7879 : }
7880 :
7881 : Real64 ABlBack;
7882 0 : if (NBackGlass == 2) {
7883 : // Interior beam absorptance of GLASS LAYERS of exterior back window with BETWEEN-GLASS BLIND
7884 0 : state.dataSolarShading->SurfWinAbsBeam(2) =
7885 0 : ab2k + t2k * tbshBBk * rb1k * tfshBBk * af2k +
7886 0 : t2k * (tbshBBk * rb1k * tfshBdk + tbshBdk * rbd1k * tfshdk + rbshBk * (1.0 + rfd2k * rbshdk)) * afd2k;
7887 0 : state.dataSolarShading->SurfWinAbsBeam(1) =
7888 0 : t2k * tbshBBk * ab1k + t2k * (rbshBk * rfd2k * tbshdk + tbshBdk * (1.0 + rbd1k * rfshdk)) * abd1k;
7889 : // Interior beam transmitted by exterior back window with BETWEEN-GLASS BLIND
7890 0 : TransBeamWin =
7891 0 : t2k * tbshBBk * t1k +
7892 0 : t2k * (tbshBBk * rb1k * rfshBk + rbshBk * rfd2k * tbshdk + tbshBdk * (1.0 + rbd1k * rfshdk)) * td1k;
7893 : // Interior beam absorbed by BLIND on exterior back window with BETWEEN-GLASS BLIND
7894 0 : ABlBack = t2k * (abshBk + tbshBBk * rb1k * afshBk + rbshBk * rfd2k * abshdk + tbshBdk * rbd1k * afshdk);
7895 : } else { // NBackGlass = 3
7896 0 : Real64 t3k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).tBareSolCoef(3));
7897 0 : Real64 af3k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).afBareSolCoef(3));
7898 0 : Real64 ab3k = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).abBareSolCoef(3));
7899 0 : Real64 afd3k = state.dataConstruction->Construct(ConstrNumBack).afBareSolDiff(3);
7900 0 : Real64 rfd3k = state.dataConstruction->Construct(ConstrNumBack).rfBareSolDiff(3);
7901 0 : state.dataSolarShading->SurfWinAbsBeam(3) =
7902 0 : ab3k + t3k * tbshBBk * (rb2k + t2k * rb1k * t2k) * tfshBBk * af3k +
7903 0 : t3k *
7904 0 : (tbshBdk * rbd2k * tfshdk + tbshBdk * td2k * rbd1k * td2k * tfshdk +
7905 0 : rbshBk * (1.0 + rfd3k * rbshdk)) *
7906 : afd3k;
7907 0 : state.dataSolarShading->SurfWinAbsBeam(2) =
7908 0 : t3k * tbshBBk * (ab2k + t2k * rb1k * (af2k + t2k * rfshBk * abd2k)) +
7909 0 : t3k * (tbshBdk + tbshBdk * (rbd2k + td2k * rbd1k * td2k) * rfshdk + rbshBk * rfd3k * tbshdk) * abd2k +
7910 0 : t3k * tbshBdk * td2k * rbd1k * afd2k;
7911 0 : state.dataSolarShading->SurfWinAbsBeam(1) =
7912 0 : t3k * tbshBBk * (t2k * ab1k + (rb2k + t2k * rb1k * t2k) * rfshBk * td2k * abd1k) +
7913 0 : t3k * (rbshBk * rfd3k * tbshdk + tbshBdk * (1.0 + rbd2k * rfshdk + td2k * rbd2k * td2k * rfshdk)) *
7914 0 : td2k * abd1k;
7915 0 : TransBeamWin = t3k * tbshBBk * t2k * t1k +
7916 0 : t3k *
7917 0 : (tbshBBk * (rb2k * rfshBk + t2k * rb1k * t2k * rfshBk) + rbshBk * rfd3k * tbshdk +
7918 0 : tbshBdk * (1.0 + rbd2k * rfshdk + td2k * rbd1k * td2k * rfshdk)) *
7919 0 : td2k * td1k;
7920 0 : ABlBack = t3k * abshBk + t3k * tbshBBk * (rb2k + t2k * rb1k * t2k) * afshBk +
7921 0 : t3k * rbshBk * rfd3k * abshdk + t3k * tbshBdk * (rbd2k + td2k * rbd1k * td2k) * afshdk;
7922 : }
7923 :
7924 0 : BABSZone += BOverlap * ABlBack;
7925 0 : backSurfBeamSolInTrans += BOverlap * ABlBack;
7926 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7927 0 : BOverlap * ABlBack / state.dataSurface->Surface(BackSurfNum).Area;
7928 :
7929 : } // End of check if between-glass blind is on back window
7930 285471 : } else if (ShadeFlagBack == WinShadingType::ExtScreen) {
7931 :
7932 : // Interior beam absorptance of GLASS LAYERS of exterior back window with EXTERIOR SCREEN
7933 0 : int ScNumBack = surfWin.screenNum; // Back surface screen number
7934 0 : Real64 TGlBmBack = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).TransSolBeamCoef);
7935 0 : Real64 RGlDiffFront = state.dataConstruction->Construct(ConstrNumBack).ReflectSolDiffFront;
7936 :
7937 0 : auto const *screen = dynamic_cast<Material::MaterialScreen const *>(state.dataMaterial->Material(ScNum));
7938 0 : assert(screen != nullptr);
7939 :
7940 0 : auto &surf = state.dataSurface->Surface(SurfNum);
7941 0 : Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
7942 0 : Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
7943 0 : Real64 winPhi = surf.Tilt * Constant::DegToRad;
7944 0 : Real64 winTheta = surf.Azimuth * Constant::DegToRad;
7945 0 : Real64 phi = std::abs(solPhi - winPhi);
7946 0 : Real64 theta = std::abs(solTheta - winTheta);
7947 0 : Material::NormalizePhiTheta(phi, theta);
7948 : #ifdef PRECALC_INTERP_SCREEN
7949 : int ip1, ip2, it1, it2;
7950 : General::BilinearInterpCoeffs coeffs;
7951 0 : Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
7952 0 : GetBilinearInterpCoeffs(
7953 0 : phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
7954 0 : auto const &b11 = screen->btars[ip1][it1];
7955 0 : auto const &b12 = screen->btars[ip1][it2];
7956 0 : auto const &b21 = screen->btars[ip2][it1];
7957 0 : auto const &b22 = screen->btars[ip2][it2];
7958 :
7959 0 : Real64 TScBmBmBack = BilinearInterp(b11.BmTransBack, b12.BmTransBack, b21.BmTransBack, b22.BmTransBack, coeffs);
7960 0 : Real64 TScBmDiffBack = BilinearInterp(b11.DfTransBack, b12.DfTransBack, b21.DfTransBack, b22.DfTransBack, coeffs);
7961 0 : Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
7962 0 : Real64 RScDifBack = screen->DfRef;
7963 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
7964 0 : Real64 AbWinBack = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).AbsBeamBackCoef(Lay));
7965 0 : Real64 AGlDiffFront = state.dataConstruction->Construct(ConstrNumBack).AbsDiff(Lay);
7966 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
7967 0 : AbWinBack + (TGlBmBack * AGlDiffFront * RScBack / (1.0 - RScDifBack * RGlDiffFront));
7968 : }
7969 :
7970 : // Interior beam transmitted by exterior back window with EXTERIOR SCREEN
7971 0 : Real64 TScDifDif = screen->DfTrans;
7972 0 : Real64 RScBmDifBk = BilinearInterp(b11.RefSolBack, b12.RefSolBack, b21.RefSolBack, b22.RefSolBack, coeffs);
7973 0 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
7974 0 : Real64 RScDifDifBk = screen->DfRef;
7975 0 : TransBeamWin = TGlBmBack *
7976 0 : (TScBmBmBack + TScBmDiffBack + TScDifDif * RScBmDifBk * RGlDifFr / (1.0 - RScDifDifBk * RGlDifFr));
7977 :
7978 : // Interior beam absorbed by EXTERIOR SCREEN on exterior back window
7979 0 : Real64 AbsScBack = BilinearInterp(b11.AbsSolBack, b12.AbsSolBack, b21.AbsSolBack, b22.AbsSolBack, coeffs);
7980 0 : Real64 AbsScDiffBack = screen->DfAbs;
7981 0 : Real64 RScDiffBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
7982 : // Screen solar back absorptance for interior solar
7983 0 : Real64 AScBack =
7984 0 : TGlBmBack * (AbsScBack + RScBack * RGlDiffFront * AbsScDiffBack / (1.0 - RScDiffBack * RGlDiffFront));
7985 :
7986 0 : BABSZone += BOverlap * AScBack;
7987 0 : backSurfBeamSolInTrans += BOverlap * AScBack;
7988 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
7989 0 : BOverlap * AScBack /
7990 0 : (state.dataSurface->Surface(BackSurfNum).Area + state.dataSurface->SurfWinDividerArea(BackSurfNum));
7991 : #else // !PRECALC_INTERP_SCREEN
7992 : Material::ScreenBmTransAbsRef btar;
7993 : Material::CalcScreenTransmittance(state, screen, phi, theta, btar);
7994 :
7995 : Real64 TScBmBmBack = btar.BmTransBack;
7996 : Real64 TScBmDiffBack = btar.DfTransBack;
7997 : Real64 RScBack = btar.RefSolFront;
7998 : Real64 RScDifBack = screen->DfRef;
7999 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
8000 : Real64 AbWinBack = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBack).AbsBeamBackCoef(Lay));
8001 : Real64 AGlDiffFront = state.dataConstruction->Construct(ConstrNumBack).AbsDiff(Lay);
8002 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
8003 : AbWinBack + (TGlBmBack * AGlDiffFront * RScBack / (1.0 - RScDifBack * RGlDiffFront));
8004 : }
8005 :
8006 : // Interior beam transmitted by exterior back window with EXTERIOR SCREEN
8007 : Real64 TScDifDif = screen->DfTrans;
8008 : Real64 RScBmDifBk = btar.RefSolBack;
8009 : Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
8010 : Real64 RScDifDifBk = screen->DfRef;
8011 : TransBeamWin = TGlBmBack *
8012 : (TScBmBmBack + TScBmDiffBack + TScDifDif * RScBmDifBk * RGlDifFr / (1.0 - RScDifDifBk * RGlDifFr));
8013 :
8014 : // Interior beam absorbed by EXTERIOR SCREEN on exterior back window
8015 : Real64 AbsScBack = btar.AbsSolBack;
8016 : Real64 AbsScDiffBack = screen->DfAbs;
8017 : Real64 RScDiffBack = btar.RefSolFront;
8018 : // Screen solar back absorptance for interior solar
8019 : Real64 AScBack =
8020 : TGlBmBack * (AbsScBack + RScBack * RGlDiffFront * AbsScDiffBack / (1.0 - RScDiffBack * RGlDiffFront));
8021 :
8022 : BABSZone += BOverlap * AScBack;
8023 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
8024 : BOverlap * AScBack /
8025 : (state.dataSurface->Surface(BackSurfNum).Area + state.dataSurface->SurfWinDividerArea(BackSurfNum));
8026 : #endif // PRECALC_INTERP_SCREEN
8027 :
8028 : } // End of check if exterior screen on back window
8029 :
8030 : // Interior beam absorptance of glass layers of back exterior window with SWITCHABLE GLAZING
8031 285471 : if (ShadeFlagBack == WinShadingType::SwitchableGlazing && state.dataSurface->Surface(BackSurfNum).ExtBoundCond == 0) {
8032 0 : Real64 SwitchFac = state.dataSurface->SurfWinSwitchingFactor(SurfNum); // Switching factor for a window
8033 : Real64 AbsBeamWinSh; // Glass layer beam solar absorptance of a shaded window
8034 0 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
8035 0 : AbsBeamWinSh = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).AbsBeamBackCoef(Lay));
8036 0 : state.dataSolarShading->SurfWinAbsBeam(Lay) =
8037 0 : Window::InterpSw(SwitchFac, state.dataSolarShading->SurfWinAbsBeam(Lay), AbsBeamWinSh);
8038 : }
8039 : // Beam solar transmittance of a shaded window
8040 0 : Real64 TransBeamWinSh = POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).TransSolBeamCoef);
8041 0 : TransBeamWin = Window::InterpSw(SwitchFac, TransBeamWin, TransBeamWinSh);
8042 : }
8043 :
8044 : // Sum of interior beam absorbed by all glass layers of back window
8045 285471 : AbsBeamTotWin = 0.0;
8046 710310 : for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
8047 424839 : AbsBeamTotWin += state.dataSolarShading->SurfWinAbsBeam(Lay);
8048 424839 : state.dataSurface->SurfWinA(BackSurfNum, Lay) +=
8049 424839 : BOverlap * state.dataSolarShading->SurfWinAbsBeam(Lay) /
8050 424839 : (state.dataSurface->Surface(BackSurfNum).Area + state.dataSurface->SurfWinDividerArea(BackSurfNum)); //[-]
8051 : }
8052 :
8053 : // To BABSZon, add interior beam glass absorption and overall beam transmission for this back window
8054 285471 : BABSZone += BOverlap * (AbsBeamTotWin + TransBeamWin);
8055 285471 : backSurfBeamSolInTrans += BOverlap * (AbsBeamTotWin + TransBeamWin);
8056 285471 : state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfNum) +=
8057 285471 : backSurfBeamSolInTrans * state.dataEnvrn->BeamSolarRad; //[W]
8058 : // Interior beam transmitted to adjacent zone through an interior back window (assumed unshaded);
8059 : // this beam radiation is categorized as diffuse radiation in the adjacent zone.
8060 285471 : int AdjSurfNum = state.dataSurface->Surface(BackSurfNum).ExtBoundCond;
8061 285471 : if (AdjSurfNum > 0) {
8062 399 : int adjEnclosureNum = state.dataSurface->Surface(AdjSurfNum).SolarEnclIndex;
8063 399 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BOverlap * TransBeamWin; //[m2]
8064 399 : state.dataSurface->SurfWinBmSolTransThruIntWinRep(BackSurfNum) +=
8065 399 : BOverlap * TransBeamWin * state.dataEnvrn->BeamSolarRad; //[W]
8066 399 : state.dataSurface->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfNum) =
8067 399 : state.dataSurface->SurfWinBmSolTransThruIntWinRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
8068 : }
8069 : } // End of check if back surface is opaque or window
8070 4570377 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) += BOverlap;
8071 4570377 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(BackSurfNum) =
8072 4570377 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
8073 : } // End of loop over back surfaces
8074 5397 : } else if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
8075 : // For complex window calculation goes over outgoing basis directions for current state
8076 : int CurCplxFenState =
8077 5397 : state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState; // Current state for complex fenestration
8078 : // Get construction number which keeps transmittance properties
8079 : int IConst =
8080 5397 : state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.State(CurCplxFenState).Konst; // Current surface construction number
8081 : // (it depends of state too)
8082 : // Solar radiation from this window will be calculated only in case when this window is not scheduled surface gained
8083 5397 : if (WindowScheduledSolarAbs(state, SurfNum, IConst) == 0) {
8084 : // Current incoming direction number (Sun direction)
8085 5341 : int IBm = state.dataBSDFWindow->ComplexWind(SurfNum)
8086 5341 : .Geom(CurCplxFenState)
8087 5341 : .SolBmIndex(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
8088 : // Report variables for complex fenestration here
8089 5341 : state.dataHeatBal->SurfWinBSDFBeamDirectionRep(SurfNum) = IBm;
8090 5341 : state.dataHeatBal->SurfWinBSDFBeamThetaRep(SurfNum) =
8091 5341 : state.dataBSDFWindow->ComplexWind(SurfNum)
8092 5341 : .Geom(CurCplxFenState)
8093 5341 : .ThetaBm(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
8094 10682 : state.dataHeatBal->SurfWinBSDFBeamPhiRep(SurfNum) = state.dataBSDFWindow->ComplexWind(SurfNum)
8095 5341 : .Geom(CurCplxFenState)
8096 5341 : .PhiBm(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
8097 :
8098 5341 : int BaseSurf = surf.BaseSurf; // Base surface number for current complex window
8099 : // Get total number of back surfaces for current window (surface)
8100 : // Note that it is organized by base surface
8101 5341 : int NBkSurf = state.dataShadowComb->ShadowComb(BaseSurf).NumBackSurf;
8102 5341 : if (!allocated(CFBoverlap)) {
8103 5341 : CFBoverlap.allocate(NBkSurf);
8104 : }
8105 5341 : if (!allocated(CFDirBoverlap)) {
8106 5341 : CFDirBoverlap.allocate(NBkSurf, state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis);
8107 : }
8108 :
8109 5341 : CFBoverlap = 0.0;
8110 : // Calculate effects on all back surfaces for each of basis directions. Each of basis directions from the back of the
8111 : // window has to be considered as beam and therefore calcualte CFBoverlap for each of them
8112 491498 : for (int CurTrnDir = 1; CurTrnDir <= state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis;
8113 : ++CurTrnDir) {
8114 486157 : Real64 CurLambda = state.dataBSDFWindow->ComplexWind(SurfNum)
8115 486157 : .Geom(CurCplxFenState)
8116 486157 : .Trn.Lamda(CurTrnDir); // Current lambda value in BSDF outgoing directions
8117 486157 : Real64 DirTrans = state.dataConstruction->Construct(IConst).BSDFInput.SolFrtTrans(
8118 486157 : IBm, CurTrnDir); // Current BSDF directional transmittance
8119 : // Now calculate effect of this direction on all back surfaces
8120 3545346 : for (int IBack = 1; IBack <= NBkSurf; ++IBack) {
8121 6118378 : CFDirBoverlap(IBack, CurTrnDir) =
8122 3059189 : state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).AOverlap(IBack, CurTrnDir) * DirTrans *
8123 3059189 : CurLambda * CosInc;
8124 3059189 : CFBoverlap(IBack) += CFDirBoverlap(IBack, CurTrnDir);
8125 : } // DO IBack = 1,MaxBkSurf
8126 : }
8127 :
8128 : // Summarizing results
8129 38850 : for (int IBack = 1; IBack <= NBkSurf; ++IBack) {
8130 33509 : int BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(IBack);
8131 33509 : int ConstrNumBack = state.dataSurface->Surface(BackSurfaceNumber).Construction;
8132 : // Do not perform any calculation if surface is scheduled for incoming solar radiation
8133 33509 : int SurfSolIncPtr = SurfaceScheduledSolarInc(state, BackSurfaceNumber, ConstrNumBack);
8134 :
8135 33509 : if (SurfSolIncPtr == 0) {
8136 : // Surface hit is another complex fenestration
8137 33509 : if (state.dataSurface->SurfWinWindowModelType(BackSurfaceNumber) == WindowModel::BSDF) {
8138 : int CurBackState =
8139 6804 : state.dataSurface->SurfaceWindow(BackSurfaceNumber)
8140 6804 : .ComplexFen.CurrentState; // Current state for back surface if that surface is complex fenestration
8141 : // Do not take into account this window if it is scheduled for surface gains
8142 6804 : if (WindowScheduledSolarAbs(state, BackSurfaceNumber, ConstrNumBack) == 0) {
8143 : // Calculate energy loss per each outgoing orientation
8144 635208 : for (int CurTrnDir = 1;
8145 635208 : CurTrnDir <= state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis;
8146 : ++CurTrnDir) {
8147 : Real64 bestDot; // complex fenestration hits other complex fenestration, it is important to find
8148 : // matching beam directions. Beam leving one window will have certaing number for it's basis
8149 : // while same beam reaching back surface will have different beam number. This value is used
8150 : // to keep best matching dot product for those directions
8151 : Real64 curDot; // temporary variable for current dot product
8152 : int bestBackTrn; // Direction corresponding best dot product for back surface window
8153 77061768 : for (int CurBackDir = 1;
8154 77061768 : CurBackDir <= state.dataBSDFWindow->ComplexWind(BackSurfaceNumber).Geom(CurBackState).Trn.NBasis;
8155 : ++CurBackDir) {
8156 : // Purpose of this part is to find best match for outgoing beam number of window back surface
8157 : // and incoming beam number of complex fenestration which this beam will hit on (back surface
8158 : // again)
8159 : curDot =
8160 76433364 : dot(state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).sTrn(CurTrnDir),
8161 76433364 : state.dataBSDFWindow->ComplexWind(BackSurfaceNumber).Geom(CurBackState).sTrn(CurBackDir));
8162 76433364 : if (CurBackDir == 1) {
8163 628404 : bestDot = curDot;
8164 628404 : bestBackTrn = CurBackDir;
8165 : } else {
8166 75804960 : if (curDot < bestDot) {
8167 8032227 : bestDot = curDot;
8168 8032227 : bestBackTrn = CurBackDir;
8169 : }
8170 : }
8171 : }
8172 : // CurLambda = ComplexWind(BackSurfaceNumber)%Geom(CurBackState)%Trn%Lamda(CurTrnDir)
8173 : // Add influence of this exact direction to what stays in the zone. It is important to note that
8174 : // this needs to be done for each outgoing direction
8175 : Real64 babs =
8176 628404 : CFDirBoverlap(IBack, CurTrnDir) * (1 - state.dataSurface->SurfaceWindow(BackSurfaceNumber)
8177 628404 : .ComplexFen.State(CurBackState)
8178 628404 : .IntegratedBkRefl(bestBackTrn));
8179 628404 : BABSZone += babs;
8180 628404 : state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfaceNumber) +=
8181 628404 : babs * state.dataEnvrn->BeamSolarRad; //[W]
8182 :
8183 : // Absorptance from current back direction
8184 628404 : int TotSolidLay = state.dataConstruction->Construct(ConstrNumBack).TotSolidLayers;
8185 2625266 : for (int Lay = 1; Lay <= TotSolidLay; ++Lay) {
8186 : // IF (ALLOCATED(Construct(ConstrNumBack)%BSDFInput)) THEN
8187 : // CFDirBoverlap is energy transmitted for current basis beam. It is important to note that
8188 : // AWinOverlap array needs to contain flux and not absorbed energy because later in the code
8189 : // this will be multiplied with window area
8190 1996862 : state.dataSurface->SurfWinACFOverlap(BackSurfaceNumber, Lay) +=
8191 1996862 : state.dataConstruction->Construct(ConstrNumBack).BSDFInput.Layer(Lay).BkAbs(bestBackTrn, 1) *
8192 1996862 : CFDirBoverlap(IBack, CurTrnDir) / state.dataSurface->Surface(BackSurfaceNumber).Area;
8193 : // END IF
8194 : }
8195 :
8196 : // Interior beam transmitted to adjacent zone through an interior back window;
8197 : // This beam radiation is categorized as diffuse radiation in the adjacent zone.
8198 : // Note that this is done for each outgoing direction of exterior window
8199 628404 : int AdjSurfNum = state.dataSurface->Surface(BackSurfaceNumber).ExtBoundCond;
8200 628404 : if (AdjSurfNum > 0) {
8201 0 : int adjEnclosureNum = state.dataSurface->Surface(AdjSurfNum).SolarEnclIndex;
8202 0 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) +=
8203 0 : CFDirBoverlap(IBack, CurTrnDir) * state.dataSurface->SurfaceWindow(BackSurfaceNumber)
8204 0 : .ComplexFen.State(CurBackState)
8205 0 : .IntegratedBkTrans(bestBackTrn);
8206 0 : state.dataSurface->SurfWinBmSolTransThruIntWinRep(BackSurfaceNumber) +=
8207 0 : CFDirBoverlap(IBack, CurTrnDir) *
8208 0 : state.dataSurface->SurfaceWindow(BackSurfaceNumber)
8209 0 : .ComplexFen.State(CurBackState)
8210 0 : .IntegratedBkTrans(bestBackTrn) *
8211 0 : state.dataEnvrn->BeamSolarRad; //[W]
8212 0 : state.dataSurface->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfaceNumber) =
8213 0 : state.dataSurface->SurfWinBmSolTransThruIntWinRep(BackSurfaceNumber) *
8214 0 : state.dataGlobal->TimeStepZoneSec;
8215 : }
8216 : }
8217 : }
8218 : } else {
8219 26705 : if (state.dataConstruction->Construct(ConstrNumBack).TransDiff <= 0.0) {
8220 : // Do not take into account this window if it is scheduled for surface gains
8221 26705 : Real64 AbsIntSurf = state.dataConstruction->Construct(ConstrNumBack).InsideAbsorpSolar;
8222 26705 : state.dataSurface->SurfOpaqAI(BackSurfaceNumber) +=
8223 26705 : CFBoverlap(IBack) * AbsIntSurf / state.dataSurface->Surface(BackSurfaceNumber).Area;
8224 26705 : BABSZone += CFBoverlap(IBack) * AbsIntSurf;
8225 : } else {
8226 : // Code for mixed windows goes here. It is same as above code for "ordinary" windows.
8227 : // Try to do something which will not produce duplicate code.
8228 : }
8229 : }
8230 : }
8231 : }
8232 :
8233 5341 : if (allocated(CFBoverlap)) CFBoverlap.deallocate();
8234 5341 : if (allocated(CFDirBoverlap)) CFDirBoverlap.deallocate();
8235 : }
8236 :
8237 0 : } else if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
8238 :
8239 0 : for (int IBack = 1; IBack <= state.dataBSDFWindow->MaxBkSurf; ++IBack) {
8240 : int BackSurfNum =
8241 0 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
8242 0 : if (BackSurfNum == 0) break; // No more irradiated back surfaces for this exterior window
8243 0 : if (state.dataSurface->SurfWinWindowModelType(IBack) != WindowModel::EQL) continue; // only EQL back window is allowed
8244 :
8245 0 : int ConstrNumBack = state.dataSurface->Surface(BackSurfNum).Construction;
8246 0 : int NBackGlass = state.dataConstruction->Construct(ConstrNumBack).TotGlassLayers;
8247 : // Irradiated (overlap) area for this back surface, projected onto window plane
8248 : // (includes effect of shadowing on exterior window)
8249 :
8250 : Real64 AOverlap =
8251 0 : state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
8252 0 : Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
8253 :
8254 0 : if (state.dataConstruction->Construct(ConstrNumBack).TransDiff <= 0.0) {
8255 :
8256 : // Back surface is opaque interior or exterior wall
8257 0 : Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
8258 0 : state.dataSurface->SurfOpaqAI(BackSurfNum) +=
8259 0 : BOverlap * AbsIntSurf / state.dataSurface->Surface(BackSurfNum).Area; //[-]
8260 0 : BABSZone += BOverlap * AbsIntSurf; //[m2]
8261 :
8262 : } else {
8263 :
8264 : // Back surface is an interior or exterior window
8265 : // Note that exterior back windows with and without shades are treated as defined.
8266 : // Equivalent Layer window model has no distinction when treating windows with and
8267 : // without shades (interior, inbetween and exterior shades)
8268 : // Note in equivalent layer window model if storm window exists it is defined as part of
8269 : // window construction, hence it does not require a separate treatment
8270 0 : state.dataSolarShading->SurfWinAbsBeamEQL = 0.0;
8271 0 : Real64 TransBeamWin = 0.0; // Beam solar transmittance of a window
8272 0 : Real64 backSurfBeamSolInTrans = 0.0; // Fraction of BeamSolarRad transmitted out through window inside face [W]
8273 :
8274 : // Interior beam absorptance of glass layers and beam transmittance of back exterior &
8275 : // or interior window (treates windows with/without shades as defined) for this timestep
8276 :
8277 : // call the ASHWAT fenestration model for beam radiation here
8278 0 : WindowEquivalentLayer::CalcEQLOpticalProperty(
8279 0 : state, BackSurfNum, SolarArrays::BEAM, state.dataSolarShading->SurfWinAbsSolBeamBackEQL);
8280 0 : auto &CFS = state.dataWindowEquivLayer->CFS;
8281 0 : int EQLNum = state.dataConstruction->Construct(ConstrNumBack).EQLConsPtr;
8282 0 : state.dataSolarShading->SurfWinAbsBeamEQL({1, CFS(EQLNum).NL}) =
8283 0 : state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, {1, CFS(EQLNum).NL});
8284 : // get the interior beam transmitted through back exterior or interior EQL window
8285 0 : TransBeamWin = state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL + 1);
8286 : // Absorbed by the interior shade layer of back exterior window
8287 0 : if (CFS(EQLNum).L(CFS(EQLNum).NL).LTYPE != LayerType::GLAZE) {
8288 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
8289 0 : BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL) /
8290 0 : (state.dataSurface->Surface(BackSurfNum).Area + state.dataSurface->SurfWinDividerArea(BackSurfNum));
8291 0 : BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL);
8292 0 : backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL);
8293 : }
8294 : // Absorbed by the exterior shade layer of back exterior window
8295 0 : if (CFS(EQLNum).L(1).LTYPE != LayerType::GLAZE) {
8296 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
8297 0 : BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1) /
8298 0 : (state.dataSurface->Surface(BackSurfNum).Area + state.dataSurface->SurfWinDividerArea(BackSurfNum));
8299 0 : BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1);
8300 0 : backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1);
8301 : }
8302 :
8303 : // determine the number of glass layers
8304 0 : NBackGlass = 0;
8305 0 : for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
8306 0 : if (CFS(EQLNum).L(Lay).LTYPE != LayerType::GLAZE) continue;
8307 0 : ++NBackGlass;
8308 : }
8309 0 : if (NBackGlass >= 2) {
8310 : // If the number of glass is greater than 2, in between glass shade can be present
8311 0 : for (int Lay = 2; Lay <= CFS(EQLNum).NL - 1; ++Lay) {
8312 0 : if (CFS(EQLNum).L(CFS(EQLNum).NL).LTYPE != LayerType::GLAZE) {
8313 : // if there is in between shade glass determine the shade absorptance
8314 0 : state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) +=
8315 0 : BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay) /
8316 0 : state.dataSurface->Surface(BackSurfNum).Area;
8317 0 : BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay);
8318 0 : backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay);
8319 : }
8320 : }
8321 : }
8322 : // Sum of interior beam absorbed by all glass layers of back window
8323 0 : Real64 AbsBeamTotWin = 0.0; // Glass layer beam solar absorptance of a shaded window
8324 0 : for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
8325 0 : AbsBeamTotWin += state.dataSolarShading->SurfWinAbsBeamEQL(Lay);
8326 0 : state.dataSurface->SurfWinA(BackSurfNum, Lay) +=
8327 0 : BOverlap * state.dataSolarShading->SurfWinAbsBeamEQL(Lay) /
8328 0 : (state.dataSurface->Surface(BackSurfNum).Area + state.dataSurface->SurfWinDividerArea(BackSurfNum)); //[-]
8329 : }
8330 :
8331 : // To BABSZon, add interior beam glass absorption and overall beam transmission for this back window
8332 :
8333 0 : BABSZone += BOverlap * (AbsBeamTotWin + TransBeamWin);
8334 0 : backSurfBeamSolInTrans += BOverlap * (AbsBeamTotWin + TransBeamWin);
8335 0 : state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfNum) +=
8336 0 : backSurfBeamSolInTrans * state.dataEnvrn->BeamSolarRad; //[W]
8337 :
8338 : // Interior beam transmitted to adjacent zone through an interior back window (assumed unshaded);
8339 : // this beam radiation is categorized as diffuse radiation in the adjacent zone.
8340 :
8341 0 : int AdjSurfNum = state.dataSurface->Surface(BackSurfNum).ExtBoundCond;
8342 0 : if (AdjSurfNum > 0) {
8343 0 : int adjEnclosureNum = state.dataSurface->Surface(AdjSurfNum).SolarEnclIndex;
8344 0 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BOverlap * TransBeamWin; //[m2]
8345 0 : state.dataSurface->SurfWinBmSolTransThruIntWinRep(BackSurfNum) +=
8346 0 : BOverlap * TransBeamWin * state.dataEnvrn->BeamSolarRad; //[W]
8347 0 : state.dataSurface->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfNum) =
8348 0 : state.dataSurface->SurfWinBmSolTransThruIntWinRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
8349 : }
8350 : } // End of check if back surface is opaque or window
8351 0 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) += BOverlap;
8352 0 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(BackSurfNum) =
8353 0 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
8354 : } // End of loop over back surfaces
8355 :
8356 : // *****************************
8357 :
8358 : } // IF (SurfaceWindow(SurfNum)%WindowModelType /= WindowModel:: BSDF) THEN
8359 : } else { // Simple interior solar distribution. All beam from exterior windows falls on floor;
8360 : // some of this is absorbed/transmitted, rest is reflected to other surfaces.
8361 :
8362 18630689 : for (int const FloorNum : thisEnclosure.SurfacePtr) {
8363 : // In following, ISABSF is zero except for nominal floor surfaces
8364 17337692 : if (state.dataSolarShading->SurfIntAbsFac(FloorNum) <= 0.0 || FloorNum == SurfNum) continue; // Keep only floor surfaces
8365 1469663 : int const FlConstrNum = state.dataSurface->SurfActiveConstruction(FloorNum);
8366 :
8367 1469663 : Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * InOutProjSLFracMult; //[m2]
8368 1469663 : Real64 AbsBeamTotWin = 0.0;
8369 :
8370 1469663 : if (state.dataConstruction->Construct(FlConstrNum).TransDiff <= 0.0) {
8371 : // Opaque surface
8372 1469663 : state.dataSurface->SurfOpaqAI(FloorNum) +=
8373 1469663 : BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) / state.dataSurface->Surface(FloorNum).Area; //[-]
8374 : } else {
8375 : // Window
8376 :
8377 : // Note that diffuse solar absorptance is used here for floor windows even though we're
8378 : // dealing with incident beam radiation. This is because, for this simple interior distribution,
8379 : // the beam radiation from exterior windows is assumed to be uniformly distributed over the
8380 : // floor and so it makes no sense to use directional absorptances. Note also that floor windows
8381 : // are assumed to not have blinds or shades in this calculation.
8382 : // For the case of the floor window a complex fenestration (strange situation) the correct back
8383 : // diffuse layer absorptions have already been put into the construction
8384 :
8385 0 : for (int Lay = 1; Lay <= state.dataConstruction->Construct(FlConstrNum).TotGlassLayers; ++Lay) {
8386 0 : AbsBeamTotWin += state.dataConstruction->Construct(FlConstrNum).AbsDiffBack(Lay);
8387 : }
8388 : // In the following we have to multiply by the AbsDiffBack(Lay)/AbsBeamTotWin ratio to get the
8389 : // layer by layer absorbed beam since ISABSF(FloorNum) is proportional to AbsBeamTotWin
8390 : // (see ComputeIntSolarAbsorpFactors).
8391 :
8392 0 : for (int Lay = 1; Lay <= state.dataConstruction->Construct(FlConstrNum).TotGlassLayers; ++Lay) {
8393 0 : state.dataSurface->SurfWinA(FloorNum, Lay) +=
8394 0 : state.dataConstruction->Construct(FlConstrNum).AbsDiffBack(Lay) / AbsBeamTotWin * BTOTWinZone *
8395 0 : state.dataSolarShading->SurfIntAbsFac(FloorNum) / state.dataSurface->Surface(FloorNum).Area; //[-]
8396 : }
8397 : }
8398 :
8399 1469663 : BABSZone += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum); //[m2]
8400 :
8401 1469663 : int AdjSurfNum = state.dataSurface->Surface(FloorNum).ExtBoundCond;
8402 1469663 : if (state.dataConstruction->Construct(FlConstrNum).TransDiff > 0.0 && AdjSurfNum > 0) {
8403 :
8404 : // Window in an interior floor
8405 :
8406 0 : int adjEnclosureNum = state.dataSurface->Surface(AdjSurfNum).SolarEnclIndex;
8407 :
8408 : // Contribution (assumed diffuse) to adjacent zone of beam radiation passing
8409 : // through this window
8410 0 : state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) *
8411 0 : state.dataConstruction->Construct(FlConstrNum).TransDiff /
8412 : AbsBeamTotWin;
8413 :
8414 0 : BABSZone += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) *
8415 0 : state.dataConstruction->Construct(FlConstrNum).TransDiff / AbsBeamTotWin;
8416 : }
8417 :
8418 : } // End of loop over floor sections
8419 : } // End of check on complex vs. simple interior solar distribution
8420 :
8421 : } // End of sunlit fraction > 0 test
8422 : } // End of first loop over surfaces in zone
8423 :
8424 6322884 : Real64 BABSZoneSSG = 0.0; // Beam radiation from exterior windows absorbed in a zone (only for scheduled surface gains)
8425 6322884 : Real64 BTOTZoneSSG = 0.0; // Solar entering a zone in case of scheduled surface gains
8426 6323472 : for (int iSSG = 1; iSSG <= state.dataSurface->TotSurfIncSolSSG; ++iSSG) {
8427 588 : int SurfNum = state.dataSurface->SurfIncSolSSG(iSSG).SurfPtr;
8428 588 : auto &surf = state.dataSurface->Surface(SurfNum);
8429 : // do calculation only if construction number match.
8430 588 : if (state.dataSurface->SurfIncSolSSG(iSSG).ConstrPtr == surf.Construction) {
8431 588 : if (surf.SolarEnclIndex == enclosureNum) {
8432 588 : Real64 AbsIntSurf = state.dataConstruction->Construct(surf.Construction).InsideAbsorpSolar;
8433 : // SolarIntoZone = GetCurrentScheduleValue(SurfIncSolSSG(iSSG)%SchedPtr) * Surface(SurfNum)%Area
8434 1176 : Real64 SolarIntoZone = GetCurrentScheduleValue(
8435 588 : state, state.dataSurface->SurfIncSolSSG(iSSG).SchedPtr); // Solar radiation into zone to current surface
8436 588 : state.dataSurface->SurfOpaqAI(SurfNum) = SolarIntoZone * AbsIntSurf;
8437 588 : BABSZoneSSG += state.dataSurface->SurfOpaqAI(SurfNum) * surf.Area;
8438 588 : BTOTZoneSSG += SolarIntoZone * surf.Area;
8439 : }
8440 : }
8441 : }
8442 6322884 : state.dataHeatBal->EnclSolDBSSG(enclosureNum) = BTOTZoneSSG - BABSZoneSSG;
8443 6322884 : state.dataHeatBal->EnclSolDB(enclosureNum) = BTOTZone - BABSZone;
8444 :
8445 6322884 : if (state.dataHeatBal->EnclSolDB(enclosureNum) < 0.0) {
8446 13899 : state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
8447 : }
8448 :
8449 : // Variables for reporting
8450 60677343 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
8451 54354459 : auto &surf = state.dataSurface->Surface(SurfNum);
8452 54354459 : Real64 SurfIncSolarMultiplier = surf.IncSolMultiplier;
8453 54354459 : Real64 currBeamSolarRad = state.dataEnvrn->BeamSolarRad * SurfIncSolarMultiplier;
8454 54354459 : Real64 currDifSolarRad = state.dataEnvrn->DifSolarRad * SurfIncSolarMultiplier;
8455 54354459 : Real64 currGndSolarRad = state.dataEnvrn->GndSolarRad * SurfIncSolarMultiplier;
8456 54354459 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
8457 35173796 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) *= currBeamSolarRad;
8458 35173796 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) =
8459 35173796 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8460 35173796 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) =
8461 35173796 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) / (surf.Area + state.dataSurface->SurfWinDividerArea(SurfNum));
8462 : } else { // Simple interior solar distribution. All beam falls on floor.
8463 19180663 : if (state.dataSolarShading->SurfIntAbsFac(SurfNum) > 0.0 && surf.HeatTransSurf) {
8464 3495565 : if (thisEnclosure.FloorArea > 0.0) {
8465 : // spread onto all floor surfaces, these may or may not be called "floor"
8466 3495565 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = currBeamSolarRad * BTOTZone / thisEnclosure.FloorArea;
8467 0 : } else if (thisEnclosure.TotalSurfArea > 0.0) {
8468 : // spread onto all interior surfaces
8469 0 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = currBeamSolarRad * BTOTZone / thisEnclosure.TotalSurfArea;
8470 : } else { // divide be zero otherwise
8471 0 : state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = 0.0;
8472 : }
8473 : }
8474 19180663 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) = surf.Area * state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum);
8475 19180663 : state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) =
8476 19180663 : state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8477 : }
8478 54354459 : if (surf.Class == SurfaceClass::Window || surf.Class == SurfaceClass::TDD_Dome) {
8479 :
8480 7513362 : state.dataSurface->SurfWinIntBeamAbsByShade(SurfNum) = state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfNum);
8481 7513362 : state.dataSurface->SurfWinExtBeamAbsByShade(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum);
8482 :
8483 7513362 : if ((surf.ExtBoundCond == ExternalEnvironment) || (surf.ExtBoundCond == OtherSideCondModeledExt)) {
8484 :
8485 7504852 : WinShadingType ShadeFlag = state.dataSurface->SurfWinShadingFlag(SurfNum);
8486 7504852 : int ShelfNum = state.dataSurface->SurfDaylightingShelfInd(SurfNum);
8487 7504852 : int OutShelfSurf = 0;
8488 7504852 : if (ShelfNum > 0) { // Outside daylighting shelf
8489 616 : OutShelfSurf = state.dataDaylightingDevicesData->Shelf(ShelfNum).OutSurf;
8490 : }
8491 :
8492 : // This lookup may be avoid if this 2nd surf loop can be combined with the 1st
8493 7504852 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
8494 1232 : int PipeNum = state.dataSurface->SurfWinTDDPipeNum(SurfNum);
8495 1232 : int SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
8496 1232 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8497 : // Exterior diffuse solar incident on window (W/m2)
8498 1232 : Real64 DifSolarInc = currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(SurfNum2) +
8499 1232 : currGndSolarRad * state.dataSurface->Surface(SurfNum2).ViewFactorGround;
8500 : // Exterior diffuse sky solar transmitted by TDD (W/m2)
8501 1232 : Real64 SkySolarTrans = currDifSolarRad * TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso) *
8502 1232 : state.dataSolarShading->SurfAnisoSkyMult(SurfNum2);
8503 : // Exterior diffuse ground solar transmitted by TDD (W/m2)
8504 1232 : Real64 GndSolarTrans = currGndSolarRad * state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolIso *
8505 1232 : state.dataSurface->Surface(SurfNum2).ViewFactorGround;
8506 :
8507 1232 : state.dataSurface->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
8508 1232 : state.dataSurface->SurfWinDifSolar(SurfNum) = SkySolarTrans * surf.Area + GndSolarTrans * surf.Area;
8509 1232 : state.dataSurface->SurfWinBmSolarEnergy(SurfNum) =
8510 1232 : state.dataSurface->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8511 1232 : state.dataSurface->SurfWinDifSolarEnergy(SurfNum) =
8512 1232 : state.dataSurface->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8513 :
8514 1232 : state.dataSurface->SurfWinTransSolar(SurfNum) =
8515 1232 : state.dataSurface->SurfWinBmSolar(SurfNum) + state.dataSurface->SurfWinDifSolar(SurfNum); //[W]
8516 1232 : state.dataSurface->SurfWinTransSolarEnergy(SurfNum) =
8517 1232 : state.dataSurface->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8518 :
8519 1232 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransmittedSolar = state.dataSurface->SurfWinTransSolar(SurfNum);
8520 : // TDDPipe(PipeNum)%TransSolBeam = TBmBm ! Reported above
8521 1232 : if (DifSolarInc > 0) {
8522 1232 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolDiff = (SkySolarTrans + GndSolarTrans) / DifSolarInc;
8523 : } else {
8524 0 : state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolDiff = 0.0;
8525 : }
8526 :
8527 7503620 : } else if (OutShelfSurf > 0) { // Outside daylighting shelf
8528 : Real64 ShelfSolarRad =
8529 616 : (currBeamSolarRad *
8530 616 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, OutShelfSurf) *
8531 616 : state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, OutShelfSurf) +
8532 616 : currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(OutShelfSurf)) *
8533 616 : state.dataDaylightingDevicesData->Shelf(ShelfNum).OutReflectSol;
8534 :
8535 616 : Real64 DifSolarInc = currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(SurfNum) +
8536 616 : currGndSolarRad * surf.ViewFactorGround +
8537 616 : ShelfSolarRad * state.dataDaylightingDevicesData->Shelf(ShelfNum).ViewFactor;
8538 :
8539 616 : state.dataSurface->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
8540 616 : state.dataSurface->SurfWinDifSolar(SurfNum) = DifSolarInc * state.dataSolarShading->SurfWinTransDifSolar(SurfNum);
8541 616 : state.dataSurface->SurfWinBmSolarEnergy(SurfNum) =
8542 616 : state.dataSurface->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8543 616 : state.dataSurface->SurfWinDifSolarEnergy(SurfNum) =
8544 616 : state.dataSurface->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8545 :
8546 616 : state.dataSurface->SurfWinTransSolar(SurfNum) =
8547 616 : state.dataSurface->SurfWinBmSolar(SurfNum) + state.dataSurface->SurfWinDifSolar(SurfNum); //[W]
8548 616 : state.dataSurface->SurfWinTransSolarEnergy(SurfNum) =
8549 616 : state.dataSurface->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8550 :
8551 : } else { // Regular window
8552 7503004 : Real64 SkySolarInc = state.dataSurface->SurfSkySolarInc(SurfNum);
8553 7503004 : Real64 GndSolarInc = state.dataSurface->SurfGndSolarInc(SurfNum);
8554 7503004 : Real64 DifSolarInc = SkySolarInc + GndSolarInc;
8555 7503004 : state.dataSurface->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
8556 : // Note: for complex fenestration, SurfWinTransDifSolar has previously been defined using the effective
8557 : // transmittance for sky and ground diffuse radiation (including beam radiation reflected from the ground)
8558 : // so these calculations should be correct
8559 7503004 : state.dataSurface->SurfWinDifSolar(SurfNum) = DifSolarInc * state.dataSolarShading->SurfWinTransDifSolar(SurfNum);
8560 7503004 : state.dataSurface->SurfWinBmSolarEnergy(SurfNum) =
8561 7503004 : state.dataSurface->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8562 7503004 : state.dataSurface->SurfWinDifSolarEnergy(SurfNum) =
8563 7503004 : state.dataSurface->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8564 7503004 : if (ANY_BLIND(ShadeFlag)) {
8565 71430 : if (state.dataMaterial->Blind(state.dataSurface->SurfWinBlindNumber(SurfNum)).SlatOrientation ==
8566 : DataWindowEquivalentLayer::Orientation::Horizontal) {
8567 142860 : state.dataSurface->SurfWinDifSolar(SurfNum) = SkySolarInc * state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) +
8568 71430 : GndSolarInc * state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum);
8569 71430 : state.dataSurface->SurfWinDifSolarEnergy(SurfNum) =
8570 71430 : state.dataSurface->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8571 : }
8572 : }
8573 :
8574 7503004 : state.dataSurface->SurfWinTransSolar(SurfNum) =
8575 7503004 : state.dataSurface->SurfWinBmSolar(SurfNum) + state.dataSurface->SurfWinDifSolar(SurfNum); //[W]
8576 7503004 : state.dataSurface->SurfWinTransSolarEnergy(SurfNum) =
8577 7503004 : state.dataSurface->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8578 : }
8579 :
8580 : // added TH 12/9/2009, CR 7907 & 7809
8581 7504852 : state.dataSurface->SurfWinBmBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum);
8582 :
8583 7504852 : state.dataSurface->SurfWinBmDifSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum);
8584 7504852 : state.dataSurface->SurfWinBmBmSolarEnergy(SurfNum) =
8585 7504852 : state.dataSurface->SurfWinBmBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8586 7504852 : state.dataSurface->SurfWinBmDifSolarEnergy(SurfNum) =
8587 7504852 : state.dataSurface->SurfWinBmDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8588 :
8589 : // Solar not added by TDD:DOME; added to zone via TDD:DIFFUSER
8590 7504852 : if (surf.Class != SurfaceClass::TDD_Dome) {
8591 7503620 : state.dataHeatBal->ZoneTransSolar(enclosureNum) += state.dataSurface->SurfWinTransSolar(SurfNum); //[W]
8592 7503620 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) =
8593 7503620 : state.dataHeatBal->ZoneTransSolar(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8594 7503620 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) += state.dataSurface->SurfWinBmSolar(SurfNum);
8595 7503620 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) += state.dataSurface->SurfWinDifSolar(SurfNum);
8596 7503620 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) =
8597 7503620 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8598 7503620 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) =
8599 7503620 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8600 : }
8601 : }
8602 : }
8603 : } // End of second loop over surfaces in zone
8604 :
8605 : } // End of first zone loop
8606 :
8607 : // Add interior window contribution to EnclSolDB
8608 :
8609 7238521 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
8610 6322884 : state.dataHeatBal->EnclSolDB(enclosureNum) += state.dataHeatBal->EnclSolDBIntWin(enclosureNum);
8611 6322884 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum) = state.dataHeatBal->EnclSolDBIntWin(enclosureNum) * state.dataEnvrn->BeamSolarRad;
8612 6322884 : state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclosureNum) =
8613 6322884 : state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8614 : }
8615 :
8616 : // RJH - Calculate initial distribution of diffuse solar transmitted by exterior windows into each zone
8617 : // to all interior surfaces in the zone
8618 : // Includes subsequent transmittance of diffuse solar to adjacent zones through interior windows
8619 915637 : CalcWinTransDifSolInitialDistribution(state);
8620 915637 : }
8621 826 : void CalcAbsorbedOnExteriorOpaqueSurfaces(EnergyPlusData &state)
8622 : {
8623 : // SUBROUTINE INFORMATION:
8624 : // AUTHOR Simon Vidanovic
8625 : // DATE WRITTEN May 2017
8626 : // MODIFIED na
8627 : // RE-ENGINEERED na
8628 :
8629 : // PURPOSE OF THIS SUBROUTINE:
8630 : // Calculates solar energy absorbed on exterior opaque surfaces
8631 :
8632 1652 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
8633 1652 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
8634 826 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
8635 6608 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
8636 5782 : auto &surf = state.dataSurface->Surface(SurfNum);
8637 : // TH added 3/24/2010 while debugging CR 7872
8638 5782 : if (!surf.ExtSolar && surf.OriginalClass != SurfaceClass::TDD_Diffuser) continue;
8639 1652 : int const ConstrNum = state.dataSurface->SurfActiveConstruction(SurfNum);
8640 1652 : int SurfNum2 = SurfNum;
8641 1652 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
8642 0 : int PipeNum = state.dataSurface->SurfWinTDDPipeNum(SurfNum);
8643 0 : SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
8644 : }
8645 1652 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8646 1652 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8647 :
8648 : //-------------------------------------------------------------------------
8649 : // EXTERIOR BEAM SOLAR RADIATION ABSORBED ON THE OUTSIDE OF OPAQUE SURFACES
8650 : //-------------------------------------------------------------------------
8651 :
8652 1652 : if (SunLitFract > 0.0 && state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) {
8653 490 : state.dataSurface->SurfOpaqAO(SurfNum) = state.dataConstruction->Construct(ConstrNum).OutsideAbsorpSolar * CosInc * SunLitFract;
8654 :
8655 : // Note: movable insulation, if present, is accounted for in subr. InitIntSolarDistribution,
8656 : // where SurfQRadSWOutMvIns is calculated from SurfOpaqQRadSWOutAbs and insulation solar absorptance
8657 : }
8658 : }
8659 826 : }
8660 : }
8661 826 : }
8662 :
8663 826 : void CalcInteriorSolarDistributionWCESimple(EnergyPlusData &state)
8664 : {
8665 :
8666 : // SUBROUTINE INFORMATION:
8667 : // AUTHOR Simon Vidanovic
8668 : // DATE WRITTEN May 2017
8669 :
8670 : // PURPOSE OF THIS SUBROUTINE:
8671 : // For a time step, calculates solar radiation absorbed by window layers, sky and diffuse solar
8672 : // gain into zone from exterior window, beam solar on exterior window transmitted as beam and/or diffuse
8673 : // and interior beam from exterior window that is absorbed/transmitted by back surfaces
8674 :
8675 : using ScheduleManager::GetCurrentScheduleValue;
8676 : using namespace MultiLayerOptics;
8677 :
8678 1652 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
8679 1652 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
8680 826 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
8681 826 : int const firstSurf = thisSpace.HTSurfaceFirst;
8682 826 : int const lastSurf = thisSpace.HTSurfaceLast;
8683 6608 : for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
8684 5782 : state.dataSurface->SurfOpaqAI(surfNum) = 0.0;
8685 5782 : state.dataSurface->SurfOpaqAO(surfNum) = 0.0;
8686 : }
8687 826 : }
8688 : }
8689 :
8690 1652 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
8691 :
8692 826 : Real64 BABSZone = 0;
8693 826 : Real64 BTOTZone = 0;
8694 826 : state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
8695 826 : state.dataHeatBal->EnclSolDBIntWin(enclosureNum) = 0.0;
8696 826 : state.dataHeatBal->ZoneTransSolar(enclosureNum) = 0;
8697 826 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) = 0;
8698 826 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) = 0;
8699 826 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) = 0;
8700 826 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) = 0;
8701 826 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) = 0;
8702 826 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
8703 :
8704 6608 : for (int const SurfNum : thisEnclosure.SurfacePtr) {
8705 5782 : auto &surf = state.dataSurface->Surface(SurfNum);
8706 5782 : if (surf.Class != SurfaceClass::Window) continue;
8707 826 : int SurfNum2 = 0;
8708 826 : if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
8709 0 : int PipeNum = state.dataSurface->SurfWinTDDPipeNum(SurfNum);
8710 0 : SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
8711 : } else {
8712 826 : SurfNum2 = SurfNum;
8713 : }
8714 826 : auto &window = state.dataSurface->SurfaceWindow(SurfNum2);
8715 826 : Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2); // Note: surfnum 2
8716 826 : Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
8717 :
8718 826 : std::pair<Real64, Real64> incomingAngle = getSunWCEAngles(state, SurfNum2, BSDFDirection::Incoming);
8719 826 : Real64 Theta = incomingAngle.first;
8720 826 : Real64 Phi = incomingAngle.second;
8721 :
8722 826 : int ConstrNum = state.dataSurface->Surface(SurfNum2).Construction;
8723 826 : if (state.dataSurface->Surface(SurfNum2).activeShadedConstruction > 0)
8724 826 : ConstrNum = state.dataSurface->Surface(SurfNum2).activeShadedConstruction;
8725 : auto aLayer = // (AUTO_OK_OBJ)
8726 826 : CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, WavelengthRange::Solar, ConstrNum);
8727 :
8728 : ///////////////////////////////////////////////
8729 : // Solar absorbed in window layers
8730 : ///////////////////////////////////////////////
8731 826 : if (state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2) > 0.0) {
8732 490 : size_t numOfLayers = aLayer->getNumOfLayers();
8733 490 : if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
8734 0 : int CurrentState = state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.CurrentState;
8735 0 : auto &cplxState = state.dataSurface->SurfaceWindow(SurfNum).ComplexFen.State(CurrentState);
8736 0 : for (size_t Lay = 1; Lay <= numOfLayers; ++Lay) {
8737 : // Simon: Imporant note about this equation is to use BeamSolarRad and not SurfQRadSWOutIncident
8738 : // is becuase BeamSolarRad is direct normal radiation (looking at the Sun) while SurfRadSWOutIncident
8739 : // is normal to window incidence. Since BSDF coefficients are taking into account angle of incidence,
8740 : // BeamSolarRad should be used in this case
8741 0 : state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) =
8742 0 : cplxState.WinSkyFtAbs(Lay) * state.dataSurface->SurfSkySolarInc(SurfNum2) +
8743 0 : cplxState.WinSkyGndAbs(Lay) * state.dataSurface->SurfGndSolarInc(SurfNum2) +
8744 0 : state.dataSurface->SurfWinA(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad +
8745 0 : state.dataSurface->SurfWinACFOverlap(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad;
8746 0 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfNum, Lay) = state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) * surf.Area;
8747 0 : state.dataSurface->SurfWinADiffFront(SurfNum, Lay) = cplxState.WinSkyGndAbs(Lay);
8748 : }
8749 : } else {
8750 1470 : for (size_t Lay = 1; Lay <= numOfLayers; ++Lay) {
8751 980 : Real64 AbWinBeam = aLayer->getAbsorptanceLayer(Lay, Side::Front, ScatteringSimple::Direct, Theta, Phi) *
8752 980 : window.OutProjSLFracMult[state.dataGlobal->HourOfDay];
8753 980 : Real64 AbWinDiffFront = aLayer->getAbsorptanceLayer(Lay, Side::Front, ScatteringSimple::Diffuse, Theta, Phi);
8754 : // Real64 AbWinDiffBack = aLayer->getAbsorptanceLayer(Lay, Side::Back, ScatteringSimple::Diffuse,
8755 : // Theta, Phi);
8756 :
8757 : // Simon: This should not be multiplied with cosine of incident angle. This however gives same
8758 : // results as BSDF and Winkelmann models.
8759 980 : state.dataSurface->SurfWinA(SurfNum, Lay) =
8760 980 : AbWinBeam * CosInc * SunLitFract *
8761 980 : state.dataSurface->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
8762 980 : state.dataSurface->SurfWinADiffFront(SurfNum, Lay) = AbWinDiffFront;
8763 :
8764 : // Simon: Same not as for BSDF. Normal solar radiation should be taken here because angle of
8765 : // incidence is already taken into account
8766 980 : Real64 absBeam = state.dataSurface->SurfWinA(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad;
8767 980 : Real64 absDiff = state.dataSurface->SurfWinADiffFront(SurfNum, Lay) *
8768 980 : (state.dataSurface->SurfSkySolarInc(SurfNum2) + state.dataSurface->SurfGndSolarInc(SurfNum2));
8769 980 : state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) = (absBeam + absDiff);
8770 980 : state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfNum, Lay) = state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) * surf.Area;
8771 : }
8772 : }
8773 : }
8774 :
8775 : ////////////////////////////////////////////////////////////////////
8776 : // SKY AND GROUND DIFFUSE SOLAR GAIN INTO ZONE FROM EXTERIOR WINDOW
8777 : ////////////////////////////////////////////////////////////////////
8778 826 : constexpr Real64 minLambda{0.3};
8779 826 : constexpr Real64 maxLambda{2.5};
8780 : const Real64 Tdiff =
8781 826 : aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DiffuseDiffuse, Theta, Phi);
8782 826 : state.dataConstruction->Construct(ConstrNum).TransDiff = Tdiff;
8783 826 : Real64 EnclSolDSWin = state.dataSurface->SurfSkySolarInc(SurfNum2) * Tdiff * state.dataSurface->Surface(SurfNum2).Area;
8784 826 : if ((state.dataEnvrn->DifSolarRad != 0)) {
8785 826 : EnclSolDSWin /= state.dataEnvrn->DifSolarRad;
8786 : } else {
8787 0 : EnclSolDSWin /= 1e-8;
8788 : }
8789 :
8790 826 : Real64 EnclSolDGWin = state.dataSurface->SurfGndSolarInc(SurfNum2) * Tdiff * state.dataSurface->Surface(SurfNum2).Area;
8791 826 : (state.dataEnvrn->GndSolarRad != 0) ? EnclSolDGWin /= state.dataEnvrn->GndSolarRad : EnclSolDGWin /= 1e-8;
8792 :
8793 : ////////////////////////////////////////////////////////////////////
8794 : // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
8795 : ////////////////////////////////////////////////////////////////////
8796 826 : Real64 TBmBm = aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DirectDirect, Theta, Phi);
8797 826 : Real64 TBmDif = aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DirectDiffuse, Theta, Phi);
8798 826 : Real64 SurfWinTransBmBmSolar = TBmBm * SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
8799 826 : Real64 SurfWinTransBmDifSolar = TBmDif * SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
8800 826 : BTOTZone += SurfWinTransBmBmSolar + SurfWinTransBmDifSolar;
8801 :
8802 826 : Real64 DifSolarRadiation = state.dataSurface->SurfSkySolarInc(SurfNum2) + state.dataSurface->SurfGndSolarInc(SurfNum2);
8803 826 : state.dataSurface->SurfWinBmSolar(SurfNum) = state.dataEnvrn->BeamSolarRad * (TBmBm + TBmDif) * surf.Area * CosInc;
8804 826 : state.dataSurface->SurfWinDifSolar(SurfNum) = DifSolarRadiation * Tdiff * surf.Area;
8805 826 : state.dataSurface->SurfWinBmSolarEnergy(SurfNum) = state.dataSurface->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8806 826 : state.dataSurface->SurfWinDifSolarEnergy(SurfNum) = state.dataSurface->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8807 826 : state.dataSurface->SurfWinTransSolar(SurfNum) = state.dataSurface->SurfWinBmSolar(SurfNum) + state.dataSurface->SurfWinDifSolar(SurfNum);
8808 826 : state.dataSurface->SurfWinTransSolarEnergy(SurfNum) = state.dataSurface->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
8809 :
8810 : // Add beam solar absorbed by outside reveal to outside of window's base surface.
8811 : // Add beam solar absorbed by inside reveal to inside of window's base surface.
8812 : // This ignores 2-D heat transfer effects.
8813 826 : int BaseSurfNum = surf.BaseSurf;
8814 826 : state.dataSurface->SurfOpaqAI(BaseSurfNum) =
8815 826 : state.dataSurface->SurfWinBmSolAbsdInsReveal(SurfNum2) / state.dataSurface->Surface(BaseSurfNum).Area;
8816 826 : state.dataSurface->SurfOpaqAO(BaseSurfNum) =
8817 826 : state.dataSurface->SurfWinBmSolAbsdOutsReveal(SurfNum2) / state.dataSurface->Surface(BaseSurfNum).Area;
8818 :
8819 : ////////////////////////////////////////////////////////////////////
8820 : // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
8821 : ////////////////////////////////////////////////////////////////////
8822 826 : Real64 TBm = TBmBm;
8823 : // Correction for beam absorbed by inside reveal
8824 826 : Real64 TBmDenom = SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
8825 826 : if (TBmDenom != 0.0) { // when =0.0, no correction
8826 490 : TBm -= state.dataSurface->SurfWinBmSolAbsdInsReveal(SurfNum) / TBmDenom;
8827 : }
8828 :
8829 826 : TBm = max(0.0, TBm);
8830 826 : TBm *= surf.IncSolMultiplier;
8831 :
8832 826 : int NumOfBackSurf = state.dataShadowComb->ShadowComb(BaseSurfNum).NumBackSurf;
8833 :
8834 826 : if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
8835 1792 : for (int IBack = 1; IBack <= NumOfBackSurf; ++IBack) {
8836 :
8837 : int const BackSurfNum =
8838 1792 : state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
8839 :
8840 1792 : if (BackSurfNum == 0) break; // No more irradiated back surfaces for this exterior window
8841 966 : int ConstrNumBack = state.dataSurface->Surface(BackSurfNum).Construction;
8842 : // NBackGlass = Construct( ConstrNumBack ).TotGlassLayers;
8843 : // Irradiated (overlap) area for this back surface, projected onto window plane
8844 : // (includes effect of shadowing on exterior window)
8845 966 : Real64 AOverlap = state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
8846 966 : Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
8847 :
8848 966 : if (state.dataConstruction->Construct(ConstrNumBack).TransDiff <= 0.0) {
8849 : // Back surface is opaque interior or exterior wall
8850 :
8851 966 : Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
8852 966 : state.dataSurface->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / state.dataSurface->Surface(BackSurfNum).Area; //[-]
8853 966 : BABSZone += BOverlap * AbsIntSurf; //[m2]
8854 : }
8855 : }
8856 : } else {
8857 0 : for (int const FloorNum : thisEnclosure.SurfacePtr) {
8858 : // In following, ISABSF is zero except for nominal floor surfaces
8859 0 : if (!state.dataSurface->Surface(FloorNum).HeatTransSurf) continue;
8860 0 : if (state.dataSolarShading->SurfIntAbsFac(FloorNum) <= 0.0 || FloorNum == SurfNum) continue; // Keep only floor surfaces
8861 :
8862 0 : Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay]; //[m2]
8863 :
8864 0 : if (state.dataConstruction->Construct(state.dataSurface->Surface(FloorNum).Construction).TransDiff <= 0.0) {
8865 : // Opaque surface
8866 0 : state.dataSurface->SurfOpaqAI(FloorNum) +=
8867 0 : BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) / state.dataSurface->Surface(FloorNum).Area; //[-]
8868 : }
8869 : }
8870 : }
8871 826 : state.dataHeatBal->ZoneTransSolar(enclosureNum) += state.dataSurface->SurfWinTransSolar(SurfNum); //[W]
8872 826 : state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) =
8873 826 : state.dataHeatBal->ZoneTransSolar(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8874 826 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) += state.dataSurface->SurfWinBmSolar(SurfNum);
8875 826 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) += state.dataSurface->SurfWinDifSolar(SurfNum);
8876 826 : state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) =
8877 826 : state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8878 826 : state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) =
8879 826 : state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
8880 826 : }
8881 826 : state.dataHeatBal->EnclSolDB(enclosureNum) = BTOTZone - BABSZone;
8882 : }
8883 826 : }
8884 :
8885 36688 : int WindowScheduledSolarAbs(EnergyPlusData &state,
8886 : int const SurfNum, // Surface number
8887 : int const ConstNum // Construction number
8888 : )
8889 : {
8890 : // SUBROUTINE INFORMATION:
8891 : // AUTHOR Simon Vidanovic
8892 : // DATE WRITTEN June 2013
8893 :
8894 : // PURPOSE OF THIS SUBROUTINE:
8895 : // Returns scheduled surface gain object for given surface-construction combination
8896 :
8897 : // Return value
8898 : int WindowScheduledSolarAbs;
8899 :
8900 36688 : WindowScheduledSolarAbs = 0;
8901 :
8902 36688 : for (int i = 1; i <= state.dataSurface->TotFenLayAbsSSG; ++i) {
8903 253 : if ((state.dataSurface->FenLayAbsSSG(i).SurfPtr == SurfNum) && (state.dataSurface->FenLayAbsSSG(i).ConstrPtr == ConstNum)) {
8904 253 : WindowScheduledSolarAbs = i;
8905 253 : return WindowScheduledSolarAbs;
8906 : }
8907 : }
8908 :
8909 36435 : return WindowScheduledSolarAbs;
8910 : }
8911 :
8912 46886029 : int SurfaceScheduledSolarInc(EnergyPlusData &state,
8913 : int const SurfNum, // Surface number
8914 : int const ConstNum // Construction number
8915 : )
8916 : {
8917 : // SUBROUTINE INFORMATION:
8918 : // AUTHOR Simon Vidanovic
8919 : // DATE WRITTEN June 2013
8920 :
8921 : // PURPOSE OF THIS SUBROUTINE:
8922 : // Returns scheduled surface gain pointer for given surface-construction combination
8923 :
8924 : // Return value
8925 : int SurfaceScheduledSolarInc;
8926 :
8927 46886029 : SurfaceScheduledSolarInc = 0;
8928 :
8929 46887850 : for (int i = 1; i <= state.dataSurface->TotSurfIncSolSSG; ++i) {
8930 2415 : if ((state.dataSurface->SurfIncSolSSG(i).SurfPtr == SurfNum) && (state.dataSurface->SurfIncSolSSG(i).ConstrPtr == ConstNum)) {
8931 594 : SurfaceScheduledSolarInc = i;
8932 594 : return SurfaceScheduledSolarInc;
8933 : }
8934 : }
8935 :
8936 46885435 : return SurfaceScheduledSolarInc;
8937 : }
8938 :
8939 33439 : void PerformSolarCalculations(EnergyPlusData &state)
8940 : {
8941 :
8942 : // SUBROUTINE INFORMATION:
8943 : // AUTHOR Linda K. Lawrie
8944 : // DATE WRITTEN July 1999
8945 : // MODIFIED Sept 2003, FCW: add calls to CalcBeamSolDiffuseReflFactors and
8946 : // CalcBeamSolSpecularReflFactors
8947 : // Jan 2004, FCW: call CalcDayltgCoefficients if storm window status on
8948 : // any window has changed
8949 : // RE-ENGINEERED na
8950 :
8951 : // PURPOSE OF THIS SUBROUTINE:
8952 : // This subroutine determines if new solar/shading calculations need
8953 : // to be performed and calls the proper routines to do the job.
8954 :
8955 : // METHODOLOGY EMPLOYED:
8956 : // Users are allowed to enter a value for number of days in each period that
8957 : // will be used for calculating solar. (Later, this could be more complicated as
8958 : // in allowing a number of days in a month or something). Using this value or the
8959 : // default (20 days) if nothing is entered by the user, the routine will use the
8960 : // number of days left to determine if a new set of calculations should be done.
8961 : // The calculations use the average of "equation of time" and "solar declination"
8962 : // to perform the calculations.
8963 :
8964 : // REFERENCES:
8965 : // na
8966 :
8967 : // Using/Aliasing
8968 : using Dayltg::CalcDayltgCoefficients;
8969 : // Locals
8970 : // SUBROUTINE ARGUMENT DEFINITIONS:
8971 : // na
8972 :
8973 : // SUBROUTINE PARAMETER DEFINITIONS:
8974 : // na
8975 :
8976 : // INTERFACE BLOCK SPECIFICATIONS
8977 : // na
8978 :
8979 : // DERIVED TYPE DEFINITIONS
8980 : // na
8981 :
8982 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
8983 : Real64 SumDec;
8984 : Real64 SumET;
8985 : Real64 AvgEqOfTime;
8986 : Real64 AvgSinSolarDeclin;
8987 : Real64 AvgCosSolarDeclin;
8988 : int PerDayOfYear;
8989 : int Count;
8990 : Real64 SinDec;
8991 : Real64 EqTime;
8992 : // not used INTEGER SurfNum
8993 :
8994 : // Calculate sky diffuse shading
8995 :
8996 33439 : if (state.dataGlobal->BeginSimFlag) {
8997 796 : state.dataSolarShading->CalcSkyDifShading = true;
8998 796 : SkyDifSolarShading(state); // Calculate factors for shading of sky diffuse solar
8999 796 : state.dataSolarShading->CalcSkyDifShading = false;
9000 : }
9001 :
9002 33439 : if (state.dataGlobal->BeginEnvrnFlag) {
9003 6443 : state.dataSolarShading->ShadowingDaysLeft = 0;
9004 : }
9005 :
9006 33439 : if (state.dataSolarShading->ShadowingDaysLeft <= 0 || state.dataSysVars->DetailedSolarTimestepIntegration) {
9007 :
9008 14627 : if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
9009 : // Perform calculations.
9010 6533 : state.dataSolarShading->ShadowingDaysLeft = state.dataSolarShading->ShadowingCalcFrequency;
9011 6533 : if (state.dataGlobal->DayOfSim + state.dataSolarShading->ShadowingDaysLeft > state.dataGlobal->NumOfDayInEnvrn) {
9012 5957 : state.dataSolarShading->ShadowingDaysLeft = state.dataGlobal->NumOfDayInEnvrn - state.dataGlobal->DayOfSim + 1;
9013 : }
9014 :
9015 : // Calculate average Equation of Time, Declination Angle for this period
9016 :
9017 6533 : if (!state.dataGlobal->WarmupFlag) {
9018 108 : if (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather) {
9019 108 : DisplayString(state, "Updating Shadowing Calculations, Start Date=" + state.dataEnvrn->CurMnDyYr);
9020 : } else {
9021 0 : DisplayString(state, "Updating Shadowing Calculations, Start Date=" + state.dataEnvrn->CurMnDy);
9022 : }
9023 108 : state.dataReportFlag->DisplayPerfSimulationFlag = true;
9024 : }
9025 :
9026 6533 : PerDayOfYear = state.dataEnvrn->DayOfYear;
9027 6533 : SumDec = 0.0;
9028 6533 : SumET = 0.0;
9029 25048 : for (Count = 1; Count <= state.dataSolarShading->ShadowingDaysLeft; ++Count) {
9030 18515 : SUN3(PerDayOfYear, SinDec, EqTime);
9031 18515 : SumDec += SinDec;
9032 18515 : SumET += EqTime;
9033 18515 : ++PerDayOfYear;
9034 : }
9035 :
9036 : // Compute Period Values
9037 6533 : AvgSinSolarDeclin = SumDec / double(state.dataSolarShading->ShadowingDaysLeft);
9038 6533 : AvgCosSolarDeclin = std::sqrt(1.0 - pow_2(AvgSinSolarDeclin));
9039 6533 : AvgEqOfTime = SumET / double(state.dataSolarShading->ShadowingDaysLeft);
9040 : } else {
9041 8094 : SUN3(state.dataEnvrn->DayOfYear, AvgSinSolarDeclin, AvgEqOfTime);
9042 8094 : AvgCosSolarDeclin = std::sqrt(1.0 - pow_2(AvgSinSolarDeclin));
9043 : // trigger display of progress in the simulation every two weeks
9044 8094 : if (!state.dataGlobal->WarmupFlag && state.dataGlobal->BeginDayFlag && (state.dataGlobal->DayOfSim % 14 == 0)) {
9045 0 : state.dataReportFlag->DisplayPerfSimulationFlag = true;
9046 : }
9047 : }
9048 :
9049 14627 : CalcPerSolarBeam(state, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
9050 :
9051 : // Calculate factors for solar reflection
9052 14627 : if (state.dataSurface->CalcSolRefl) {
9053 71 : CalcBeamSolDiffuseReflFactors(state);
9054 71 : CalcBeamSolSpecularReflFactors(state);
9055 71 : if (state.dataGlobal->BeginSimFlag) CalcSkySolDiffuseReflFactors(state);
9056 : }
9057 : // Calculate daylighting coefficients
9058 14627 : CalcDayltgCoefficients(state);
9059 : }
9060 :
9061 33439 : if (!state.dataGlobal->WarmupFlag) {
9062 6018 : --state.dataSolarShading->ShadowingDaysLeft;
9063 : }
9064 :
9065 : // Recalculate daylighting coefficients if storm window has been added
9066 : // or removed from one or more windows at beginning of day
9067 35793 : if (state.dataDayltg->TotWindowsWithDayl > 0 && !state.dataGlobal->BeginSimFlag && !state.dataGlobal->BeginEnvrnFlag &&
9068 35793 : !state.dataGlobal->WarmupFlag && state.dataSurface->TotStormWin > 0 && state.dataHeatBal->StormWinChangeThisDay) {
9069 0 : CalcDayltgCoefficients(state);
9070 : }
9071 33439 : }
9072 :
9073 1340429 : void SHDRVL(EnergyPlusData &state,
9074 : int const HTSS, // Heat transfer surface number of the subsurface
9075 : int const SBSNR, // Subsurface number
9076 : int const Hour,
9077 : int const TS)
9078 : {
9079 :
9080 : // SUBROUTINE INFORMATION:
9081 : // AUTHOR Legacy Code
9082 : // DATE WRITTEN
9083 : // MODIFIED May 2002 (FCW): allow triangular windows to have reveal.
9084 : // RE-ENGINEERED Lawrie, Oct 2000
9085 :
9086 : // PURPOSE OF THIS SUBROUTINE:
9087 : // This subroutine computes the shadowing from a reveal onto a subsurface.
9088 :
9089 : // REFERENCES:
9090 : // BLAST/IBLAST code, original author George Walton
9091 :
9092 : int NVS; // Number of verticies
9093 :
9094 1340429 : int constexpr None(0); // for use with RevealStatus
9095 1340429 : int constexpr EntireWindowShadedByReveal(1); // for use with RevealStatus
9096 1340429 : int constexpr WindowShadedOnlyByReveal(2); // for use with RevealStatus
9097 :
9098 : Real64 A; // Area
9099 : Real64 R; // Depth of the reveal (m)
9100 : int I; // Loop control
9101 : int N; // Vertex number
9102 : int NS1; // Locations in homogeneous coordinate array
9103 : int NS2;
9104 : // note, below dimensions not changed because subsurface still max 4
9105 1340429 : Array1D<Real64> XVT(5); // Projected X coordinates of vertices
9106 1340429 : Array1D<Real64> YVT(5); // Projected Y coordinates of vertices
9107 : bool RevealStatusSet; // Used to control flow through this subroutine.
9108 : // Certain operations performed only if reveal status not yet set.
9109 : int RevealStatus; // Status of the reveal, takes the parameter values above
9110 :
9111 1340429 : RevealStatus = None;
9112 1340429 : RevealStatusSet = false;
9113 :
9114 1340429 : if (!state.dataSolarShading->CalcSkyDifShading) {
9115 895526 : state.dataSolarShading->SurfWinRevealStatus(Hour, TS, SBSNR) = None;
9116 : }
9117 :
9118 1340429 : R = state.dataSurface->Surface(SBSNR).Reveal;
9119 1340429 : if (R <= 0.0) {
9120 1322652 : RevealStatus = None;
9121 1322652 : RevealStatusSet = true;
9122 : }
9123 :
9124 1340429 : if (!RevealStatusSet) {
9125 :
9126 17777 : state.dataSolarShading->FRVLHC = state.dataSolarShading->LOCHCA + 1;
9127 17777 : ++state.dataSolarShading->LOCHCA;
9128 17777 : NVS = state.dataSurface->Surface(SBSNR).Sides;
9129 :
9130 : // Currently (06May02) windows are either rectangles (NVS=4) or triangles (NVS=3)
9131 :
9132 17777 : if (NVS == 4) { // Rectangular subsurface
9133 :
9134 : // Determine vertices of reveal.
9135 : // Project the subsurface up to the plane of the wall.
9136 :
9137 17777 : XVT(1) = state.dataSurface->ShadeV(SBSNR).XV(1) + R * max(state.dataSolarShading->XShadowProjection, 0.0);
9138 17777 : XVT(2) = state.dataSurface->ShadeV(SBSNR).XV(2) + R * max(state.dataSolarShading->XShadowProjection, 0.0);
9139 17777 : XVT(3) = state.dataSurface->ShadeV(SBSNR).XV(3) + R * min(state.dataSolarShading->XShadowProjection, 0.0);
9140 17777 : XVT(4) = state.dataSurface->ShadeV(SBSNR).XV(4) + R * min(state.dataSolarShading->XShadowProjection, 0.0);
9141 17777 : YVT(1) = state.dataSurface->ShadeV(SBSNR).YV(1) + R * min(state.dataSolarShading->YShadowProjection, 0.0);
9142 17777 : YVT(2) = state.dataSurface->ShadeV(SBSNR).YV(2) + R * max(state.dataSolarShading->YShadowProjection, 0.0);
9143 17777 : YVT(3) = state.dataSurface->ShadeV(SBSNR).YV(3) + R * max(state.dataSolarShading->YShadowProjection, 0.0);
9144 17777 : YVT(4) = state.dataSurface->ShadeV(SBSNR).YV(4) + R * min(state.dataSolarShading->YShadowProjection, 0.0);
9145 :
9146 : // Check for complete shadowing.
9147 :
9148 17777 : if ((XVT(2) >= XVT(3)) || (YVT(2) >= YVT(1))) {
9149 :
9150 564 : RevealStatus = EntireWindowShadedByReveal;
9151 564 : RevealStatusSet = true;
9152 :
9153 : } else {
9154 : // Re-order vertices to clockwise.
9155 :
9156 86065 : for (N = 1; N <= NVS; ++N) {
9157 68852 : state.dataSolarShading->XVS(N) = XVT(NVS + 1 - N);
9158 68852 : state.dataSolarShading->YVS(N) = YVT(NVS + 1 - N);
9159 : }
9160 :
9161 : // Transform to homogeneous coordinates
9162 :
9163 17213 : HTRANS1(state, state.dataSolarShading->FRVLHC, NVS);
9164 17213 : state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC) = -state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC);
9165 17213 : state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC) = 1.0;
9166 :
9167 17213 : if (state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC) <= 0.0) {
9168 0 : RevealStatus = EntireWindowShadedByReveal;
9169 0 : RevealStatusSet = true;
9170 : }
9171 : }
9172 :
9173 0 : } else if (NVS == 3) { // Triangular window
9174 :
9175 : // Project window to outside plane of parent surface
9176 :
9177 0 : for (N = 1; N <= 3; ++N) {
9178 0 : XVT(N) = state.dataSurface->ShadeV(SBSNR).XV(N) + R * state.dataSolarShading->XShadowProjection;
9179 0 : YVT(N) = state.dataSurface->ShadeV(SBSNR).YV(N) + R * state.dataSolarShading->YShadowProjection;
9180 : }
9181 :
9182 : // Find the overlap between the original window and the projected window
9183 : // Put XVT,YVT in clockwise order
9184 :
9185 0 : for (N = 1; N <= NVS; ++N) {
9186 0 : state.dataSolarShading->XVS(N) = XVT(NVS + 1 - N);
9187 0 : state.dataSolarShading->YVS(N) = YVT(NVS + 1 - N);
9188 : }
9189 :
9190 : // Transform to homogeneous coordinates
9191 :
9192 0 : NS1 = state.dataSolarShading->LOCHCA + 1;
9193 0 : state.dataSolarShading->LOCHCA = NS1;
9194 0 : HTRANS1(state, NS1, NVS);
9195 :
9196 : // Put XV,YV in clockwise order
9197 :
9198 0 : for (N = 1; N <= NVS; ++N) {
9199 0 : state.dataSolarShading->XVS(N) = state.dataSurface->ShadeV(SBSNR).XV(NVS + 1 - N);
9200 0 : state.dataSolarShading->YVS(N) = state.dataSurface->ShadeV(SBSNR).YV(NVS + 1 - N);
9201 : }
9202 :
9203 : // Transform to homogenous coordinates
9204 :
9205 0 : NS2 = state.dataSolarShading->LOCHCA + 1;
9206 0 : state.dataSolarShading->LOCHCA = NS2;
9207 0 : HTRANS1(state, NS2, NVS);
9208 0 : state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC) = 1.0;
9209 :
9210 : // Find overlap
9211 :
9212 0 : DeterminePolygonOverlap(state, NS1, NS2, state.dataSolarShading->FRVLHC);
9213 0 : if (state.dataSolarShading->OverlapStatus == NoOverlap) {
9214 0 : RevealStatus = EntireWindowShadedByReveal;
9215 0 : RevealStatusSet = true;
9216 : }
9217 : }
9218 : }
9219 :
9220 1340429 : if (!RevealStatusSet) {
9221 :
9222 : // Check for no shadows on window.
9223 :
9224 17213 : if (state.dataSolarShading->NSBSHC <= 1) {
9225 7797 : RevealStatus = WindowShadedOnlyByReveal;
9226 7797 : RevealStatusSet = true;
9227 : } else {
9228 : // Reduce all previous shadows to size of reveal opening.
9229 9416 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FRVLHC;
9230 9416 : MULTOL(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->FSBSHC, state.dataSolarShading->NSBSHC - 1);
9231 9416 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
9232 0 : RevealStatus = None;
9233 0 : RevealStatusSet = true;
9234 : } else {
9235 9416 : state.dataSolarShading->NRVLHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FRVLHC + 1;
9236 9416 : if (state.dataSolarShading->NRVLHC <= 1) {
9237 52 : RevealStatus = WindowShadedOnlyByReveal;
9238 52 : RevealStatusSet = true;
9239 : }
9240 : }
9241 : }
9242 : }
9243 :
9244 1340429 : if (!RevealStatusSet) {
9245 : // Compute sunlit area.
9246 9364 : A = state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC);
9247 23973 : for (I = 2; I <= state.dataSolarShading->NRVLHC; ++I) {
9248 14609 : A += state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC - 1 + I) *
9249 14609 : (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC - 1 + I));
9250 : }
9251 9364 : state.dataSolarShading->SurfSunlitArea(HTSS) = A;
9252 : }
9253 :
9254 1340429 : if ((RevealStatus == EntireWindowShadedByReveal) || (state.dataSolarShading->SurfSunlitArea(HTSS) < 0.0)) {
9255 599 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0; // Window entirely shaded by reveal.
9256 1339830 : } else if (RevealStatus == WindowShadedOnlyByReveal) {
9257 7849 : state.dataSolarShading->SurfSunlitArea(HTSS) =
9258 7849 : state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC); // Window shaded only by reveal.
9259 : }
9260 :
9261 1340429 : if (!state.dataSolarShading->CalcSkyDifShading) {
9262 895526 : state.dataSolarShading->SurfWinRevealStatus(Hour, TS, SBSNR) = RevealStatus;
9263 : }
9264 1340429 : }
9265 :
9266 3418208 : void SHDSBS(EnergyPlusData &state,
9267 : int const iHour, // Hour Index
9268 : int const CurSurf,
9269 : int const NBKS, // Number of back surfaces
9270 : int const NSBS, // Number of subsurfaces
9271 : int const HTS, // Heat transfer surface number of the general receiving surf
9272 : int const TS // Time step Index
9273 : )
9274 : {
9275 :
9276 : // SUBROUTINE INFORMATION:
9277 : // AUTHOR Legacy Code
9278 : // DATE WRITTEN
9279 : // MODIFIED FCW, Oct 2002: Surface%Area --> Surface%Area + SurfaceWindow%DividerArea
9280 : // in calculation of SunlitFracWithoutReveal (i.e., use full window area, not
9281 : // just glass area.
9282 : // TH, May 2009: Bug fixed to address part of CR 7596 - inside reveals
9283 : // causing high cooling loads
9284 : // RE-ENGINEERED Lawrie, Oct 2000
9285 :
9286 : // PURPOSE OF THIS SUBROUTINE:
9287 : // This subroutine determines the shadowing on subsurfaces and
9288 : // revises the base surface area accordingly. It also computes
9289 : // the effect of transparent subsurfaces.
9290 :
9291 : // REFERENCES:
9292 : // BLAST/IBLAST code, original author George Walton
9293 :
9294 : Real64 A; // Area
9295 : int I; // Loop control
9296 : int J; // Loop control
9297 : int K; // Window construction number
9298 : int N; // Vertex number
9299 : Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
9300 : // For windows, includes divider area
9301 : // REAL(r64) FrameAreaAdd ! Additional frame area sunlit
9302 : // REAL(r64) DividerAreaAdd ! Additional frame area sunlit
9303 : int HTSS; // Heat transfer surface number of the subsurface
9304 : int SBSNR; // Subsurface number
9305 :
9306 3418208 : if (NSBS > 0) { // Action taken only if subsurfaces present
9307 :
9308 1698856 : state.dataSolarShading->FSBSHC = state.dataSolarShading->LOCHCA + 1;
9309 :
9310 4332749 : for (I = 1; I <= NSBS; ++I) { // Do for all subsurfaces (sbs).
9311 :
9312 2633893 : SBSNR = state.dataShadowComb->ShadowComb(CurSurf).SubSurf(I);
9313 :
9314 2633893 : HTSS = SBSNR;
9315 :
9316 2633893 : K = state.dataSurface->Surface(SBSNR).Construction;
9317 :
9318 2633893 : if (!state.dataSolarShading->penumbra) {
9319 5257748 : if ((state.dataSolarShading->OverlapStatus != TooManyVertices) && (state.dataSolarShading->OverlapStatus != TooManyFigures) &&
9320 2628874 : (state.dataSolarShading->SurfSunlitArea(HTS) > 0.0)) {
9321 :
9322 : // Re-order vertices to clockwise sequential; compute homogeneous coordinates.
9323 1385295 : state.dataSolarShading->NVS = state.dataSurface->Surface(SBSNR).Sides;
9324 6926125 : for (N = 1; N <= state.dataSolarShading->NVS; ++N) {
9325 5540830 : state.dataSolarShading->XVS(N) = state.dataSurface->ShadeV(SBSNR).XV(state.dataSolarShading->NVS + 1 - N);
9326 5540830 : state.dataSolarShading->YVS(N) = state.dataSurface->ShadeV(SBSNR).YV(state.dataSolarShading->NVS + 1 - N);
9327 : }
9328 1385295 : state.dataSolarShading->LOCHCA = state.dataSolarShading->FSBSHC;
9329 1385295 : HTRANS1(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->NVS);
9330 1385295 : state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
9331 1385295 : state.dataSolarShading->HCT(state.dataSolarShading->LOCHCA) = 1.0;
9332 1385295 : state.dataSolarShading->NSBSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FSBSHC + 1;
9333 :
9334 : // Determine sunlit area of subsurface due to shadows on general receiving surface.
9335 1385295 : if (state.dataSolarShading->NGSSHC > 0) {
9336 268870 : MULTOL(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->FGSSHC - 1, state.dataSolarShading->NGSSHC);
9337 268870 : if ((state.dataSolarShading->OverlapStatus != TooManyVertices) && (state.dataSolarShading->OverlapStatus != TooManyFigures))
9338 268870 : state.dataSolarShading->NSBSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FSBSHC + 1;
9339 : }
9340 : }
9341 :
9342 5257748 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures) ||
9343 2628874 : (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0)) { // General receiving surface totally shaded.
9344 :
9345 1243579 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9346 :
9347 1243579 : if (iHour > 0 && TS > 0) state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) = 0.0;
9348 :
9349 1385295 : } else if ((state.dataSolarShading->NGSSHC <= 0) || (state.dataSolarShading->NSBSHC == 1)) { // No shadows.
9350 :
9351 1181104 : state.dataSolarShading->SurfSunlitArea(HTSS) = state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC);
9352 1181104 : state.dataSolarShading->SurfSunlitArea(HTS) -=
9353 1181104 : state.dataSolarShading->SurfSunlitArea(HTSS); // Revise sunlit area of general receiving surface.
9354 :
9355 : // TH. This is a bug. SunLitFracWithoutReveal should be a ratio of area
9356 : // IF(IHour > 0 .AND. TS > 0) SunLitFracWithoutReveal(HTSS,IHour,TS) = &
9357 : // Surface(HTSS)%NetAreaShadowCalc
9358 :
9359 : // new code fixed part of CR 7596. TH 5/29/2009
9360 1181104 : if (iHour > 0 && TS > 0)
9361 782543 : state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
9362 782543 : state.dataSolarShading->SurfSunlitArea(HTSS) / state.dataSurface->Surface(HTSS).NetAreaShadowCalc;
9363 :
9364 1181104 : SHDRVL(state, HTSS, SBSNR, iHour, TS); // Determine shadowing from reveal.
9365 :
9366 1181104 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
9367 0 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9368 :
9369 : } else { // Compute area.
9370 :
9371 204191 : A = state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC);
9372 483274 : for (J = 2; J <= state.dataSolarShading->NSBSHC; ++J) {
9373 279083 : A += state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC - 1 + J) *
9374 279083 : (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FSBSHC - 1 + J));
9375 : }
9376 204191 : state.dataSolarShading->SurfSunlitArea(HTSS) = A;
9377 204191 : if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
9378 :
9379 159325 : state.dataSolarShading->SurfSunlitArea(HTS) -=
9380 159325 : state.dataSolarShading->SurfSunlitArea(HTSS); // Revise sunlit area of general receiving surface.
9381 :
9382 159325 : if (iHour > 0 && TS > 0)
9383 112983 : state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
9384 112983 : state.dataSolarShading->SurfSunlitArea(HTSS) / state.dataSurface->Surface(HTSS).Area;
9385 :
9386 159325 : SHDRVL(state, HTSS, SBSNR, iHour, TS); // Determine shadowing from reveal.
9387 :
9388 159325 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
9389 0 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9390 :
9391 : } else { // General receiving surface totally shaded.
9392 :
9393 44866 : state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
9394 : }
9395 : }
9396 : }
9397 :
9398 : // Determine transmittance and absorptances of sunlit window.
9399 2633893 : if (state.dataConstruction->Construct(K).TransDiff > 0.0) {
9400 :
9401 2498761 : if (!state.dataSolarShading->CalcSkyDifShading) { // Overlaps calculation is only done for beam solar
9402 : // shading, not for sky diffuse solar shading
9403 :
9404 1606249 : CalcInteriorSolarOverlaps(state, iHour, NBKS, HTSS, CurSurf, TS);
9405 : }
9406 : }
9407 :
9408 : // Error checking.
9409 2633893 : SurfArea = state.dataSurface->Surface(SBSNR).NetAreaShadowCalc;
9410 2633893 : state.dataSolarShading->SurfSunlitArea(HTSS) = max(0.0, state.dataSolarShading->SurfSunlitArea(HTSS));
9411 :
9412 2633893 : state.dataSolarShading->SurfSunlitArea(HTSS) = min(state.dataSolarShading->SurfSunlitArea(HTSS), SurfArea);
9413 :
9414 : } // End of subsurface loop
9415 : }
9416 3418208 : }
9417 :
9418 26609 : void SUN3(int const JulianDayOfYear, // Julian Day Of Year
9419 : Real64 &SineOfSolarDeclination, // Sine of Solar Declination
9420 : Real64 &EquationOfTime // Equation of Time (Degrees)
9421 : )
9422 : {
9423 :
9424 : // SUBROUTINE INFORMATION:
9425 : // AUTHOR Legacy Code
9426 : // DATE WRITTEN
9427 : // MODIFIED na
9428 : // RE-ENGINEERED Linda K. Lawrie
9429 :
9430 : // PURPOSE OF THIS SUBROUTINE:
9431 : // This subroutine computes the coefficients for determining
9432 : // the solar position.
9433 :
9434 : // METHODOLOGY EMPLOYED:
9435 : // The expressions are based on least-squares fits of data on p.316 of 'Thermal
9436 : // Environmental Engineering' by Threlkeld and on p.387 of the ASHRAE Handbook
9437 : // of Fundamentals (need date of ASHRAE HOF).
9438 :
9439 : // REFERENCES:
9440 : // BLAST/IBLAST code, original author George Walton
9441 :
9442 : // Fitted coefficients of Fourier series | Sine of declination coefficients
9443 : static constexpr std::array<Real64, 9> SineSolDeclCoef = {
9444 : 0.00561800, 0.0657911, -0.392779, 0.00064440, -0.00618495, -0.00010101, -0.00007951, -0.00011691, 0.00002096};
9445 : // Fitted coefficients of Fourier Series | Equation of Time coefficients
9446 : static constexpr std::array<Real64, 9> EqOfTimeCoef = {
9447 : 0.00021971, -0.122649, 0.00762856, -0.156308, -0.0530028, -0.00388702, -0.00123978, -0.00270502, -0.00167992};
9448 :
9449 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
9450 : Real64 X; // Day of Year in Radians (Computed from Input JulianDayOfYear)
9451 : Real64 CosX; // COS(X)
9452 : Real64 SineX; // SIN(X)
9453 :
9454 26609 : X = 0.017167 * JulianDayOfYear; // Convert julian date to angle X
9455 :
9456 : // Calculate sines and cosines of X
9457 26609 : SineX = std::sin(X);
9458 26609 : CosX = std::cos(X);
9459 :
9460 26609 : SineOfSolarDeclination = SineSolDeclCoef[0] + SineSolDeclCoef[1] * SineX + SineSolDeclCoef[2] * CosX + SineSolDeclCoef[3] * (SineX * CosX * 2.0) +
9461 26609 : SineSolDeclCoef[4] * (pow_2(CosX) - pow_2(SineX)) +
9462 26609 : SineSolDeclCoef[5] * (SineX * (pow_2(CosX) - pow_2(SineX)) + CosX * (SineX * CosX * 2.0)) +
9463 26609 : SineSolDeclCoef[6] * (CosX * (pow_2(CosX) - pow_2(SineX)) - SineX * (SineX * CosX * 2.0)) +
9464 26609 : SineSolDeclCoef[7] * (2.0 * (SineX * CosX * 2.0) * (pow_2(CosX) - pow_2(SineX))) +
9465 26609 : SineSolDeclCoef[8] * (pow_2(pow_2(CosX) - pow_2(SineX)) - pow_2(SineX * CosX * 2.0));
9466 :
9467 26609 : EquationOfTime = EqOfTimeCoef[0] + EqOfTimeCoef[1] * SineX + EqOfTimeCoef[2] * CosX + EqOfTimeCoef[3] * (SineX * CosX * 2.0) +
9468 26609 : EqOfTimeCoef[4] * (pow_2(CosX) - pow_2(SineX)) +
9469 26609 : EqOfTimeCoef[5] * (SineX * (pow_2(CosX) - pow_2(SineX)) + CosX * (SineX * CosX * 2.0)) +
9470 26609 : EqOfTimeCoef[6] * (CosX * (pow_2(CosX) - pow_2(SineX)) - SineX * (SineX * CosX * 2.0)) +
9471 26609 : EqOfTimeCoef[7] * (2.0 * (SineX * CosX * 2.0) * (pow_2(CosX) - pow_2(SineX))) +
9472 26609 : EqOfTimeCoef[8] * (pow_2(pow_2(CosX) - pow_2(SineX)) - pow_2(SineX * CosX * 2.0));
9473 26609 : }
9474 :
9475 366528 : void SUN4(EnergyPlusData &state,
9476 : Real64 const CurrentTime, // Time to use in shadowing calculations
9477 : Real64 const EqOfTime, // Equation of time for current day
9478 : Real64 const SinSolarDeclin, // Sine of the Solar declination (current day)
9479 : Real64 const CosSolarDeclin // Cosine of the Solar declination (current day)
9480 : )
9481 : {
9482 :
9483 : // SUBROUTINE INFORMATION:
9484 : // AUTHOR Legacy Code
9485 : // DATE WRITTEN
9486 : // MODIFIED na
9487 : // RE-ENGINEERED Lawrie, Oct 2000
9488 :
9489 : // PURPOSE OF THIS SUBROUTINE:
9490 : // This subroutine computes solar direction cosines for a given hour. These
9491 : // cosines are used in the shadowing calculations.
9492 : // REFERENCES:
9493 : // BLAST/IBLAST code, original author George Walton
9494 :
9495 : Real64 H; // Hour angle (before noon = +) (in radians)
9496 : Real64 HrAngle; // Basic hour angle
9497 :
9498 : // Compute the hour angle
9499 366528 : HrAngle = (15.0 * (12.0 - (CurrentTime + EqOfTime)) + (state.dataEnvrn->TimeZoneMeridian - state.dataEnvrn->Longitude));
9500 366528 : H = HrAngle * Constant::DegToRadians;
9501 :
9502 : // Compute the cosine of the solar zenith angle.
9503 366528 : state.dataSolarShading->SUNCOS(3) = SinSolarDeclin * state.dataEnvrn->SinLatitude + CosSolarDeclin * state.dataEnvrn->CosLatitude * std::cos(H);
9504 366528 : state.dataSolarShading->SUNCOS(2) = 0.0;
9505 366528 : state.dataSolarShading->SUNCOS(1) = 0.0;
9506 :
9507 366528 : if (state.dataSolarShading->SUNCOS(3) < DataEnvironment::SunIsUpValue) return; // Return if sun not above horizon.
9508 :
9509 : // Compute other direction cosines.
9510 184487 : state.dataSolarShading->SUNCOS(2) = SinSolarDeclin * state.dataEnvrn->CosLatitude - CosSolarDeclin * state.dataEnvrn->SinLatitude * std::cos(H);
9511 184487 : state.dataSolarShading->SUNCOS(1) = CosSolarDeclin * std::sin(H);
9512 : }
9513 :
9514 2804678 : void WindowShadingManager(EnergyPlusData &state)
9515 : {
9516 :
9517 : // SUBROUTINE INFORMATION:
9518 : // AUTHOR Fred Winkelmann
9519 : // DATE WRITTEN December 1998
9520 : // MODIFIED November 1999 (FW)
9521 : // Aug 2001 (FW): change shading control names, change approach
9522 : // to scheduling and glare control, add movable
9523 : // insulation controls (mainly for heating reduction)
9524 : // Dec 2001 (FW): add slat angle control for blinds
9525 : // Aug 2002 (FW): add four new control types:
9526 : // OnIfHighOutsideAirTempAndHighSolarOnWindow
9527 : // OnIfHighOutsideAirTempAndHighHorizontalSolar
9528 : // OnIfHighZoneAirTempAndHighSolarOnWindow
9529 : // OnIfHighZoneAirTempAndHighHorizontalSolar
9530 : // Dec 2002 (FW): add between-glass shade/blind
9531 : // Mar 2003 (FW): allow GlareControlIsActive = .TRUE. only for daylit zones
9532 : // Apr 2003 (FW): use SNLoadCoolRate or SNLoadHeatRate only if not first time step
9533 : // (fixes problem when used first time thru and not allocated)
9534 : // May 2006 (RR): add exterior window screen
9535 : // May 2009 (BG): add EMS actuator override for shade flag and slat angle
9536 : // RE-ENGINEERED na
9537 :
9538 : // PURPOSE OF THIS SUBROUTINE:
9539 : // For windows with shading, selects the shaded construction
9540 : // that is used in the heat balance calculation, and sets
9541 : // the window shading flag, which is:
9542 : // -1: if window has no shading device
9543 : // 0: if shading device is off
9544 : // 1: if interior shade is on
9545 : // 2: if glazing is switched to darker state
9546 : // 3: if exterior shade is on
9547 : // 6: if interior blind is on
9548 : // 7: if exterior blind is on
9549 : // 8: if between-glass shade is on
9550 : // 9: if between-glass blind is on
9551 : // 10: window has interior shade that is off but may be triggered on later
9552 : // to control daylight glare
9553 : // 20: window has switchable glazing that is unswitched but may be switched later
9554 : // to control daylight glare or daylight illuminance
9555 : // 30: window has exterior shade that is off but may be triggered on later
9556 : // to control daylight glare or daylight illuminance
9557 : // 60: window has interior blind that is off but may be triggered on later
9558 : // to control daylight glare or daylight illuminance
9559 : // 70: window has exterior blind that is off but may be triggered on later
9560 : // to control daylight glare or daylight illuminance
9561 : // 80: window has between-glass shade that is off but may be triggered on later
9562 : // to control daylight glare or daylight illuminance
9563 : // 90: window has between-glass blind that is off but may be triggered on later
9564 : // to control daylight glare or daylight illuminance
9565 : // A "shading device" may be an exterior, interior or between-glass shade or blind,
9566 : // or the lower-transmitting (dark) state of switchable glazing (e.g., electrochromic).
9567 : // In all cases, the unshaded condition is represented
9568 : // by the construction given by window's Surface()%Construction and
9569 : // the shaded condition is represented by the construction given by
9570 : // the window's Surface()%ShadedConstruction
9571 : // REFERENCES:
9572 : // na
9573 :
9574 : // Using/Aliasing
9575 : using General::POLYF;
9576 : using ScheduleManager::GetCurrentScheduleValue;
9577 :
9578 : static Real64 constexpr DeltaAng(Constant::Pi / (double(Material::MaxSlatAngs) - 1.0));
9579 : static Real64 constexpr DeltaAng_inv(1.0 / DeltaAng);
9580 : static Real64 constexpr DeltaProfAng(Constant::Pi / 36.0);
9581 : int IConst; // Construction
9582 :
9583 22672022 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
9584 39783288 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
9585 19915944 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
9586 19915944 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
9587 19915944 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
9588 43139106 : for (int ISurf = firstSurfWin; ISurf <= lastSurfWin; ++ISurf) {
9589 23223162 : auto const &surfWin = state.dataSurface->SurfaceWindow(ISurf);
9590 23223162 : state.dataSurface->SurfWinExtIntShadePrevTS(ISurf) = state.dataSurface->SurfWinShadingFlag(ISurf);
9591 :
9592 23223162 : state.dataSurface->SurfWinShadingFlag(ISurf) = WinShadingType::NoShade;
9593 23223162 : state.dataSurface->SurfWinFracTimeShadingDeviceOn(ISurf) = 0.0;
9594 23223162 : if (state.dataSurface->SurfWinWindowModelType(ISurf) == WindowModel::EQL) {
9595 8109 : int EQLNum = state.dataConstruction->Construct(state.dataSurface->Surface(ISurf).Construction).EQLConsPtr;
9596 8109 : if (state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr > 0) {
9597 0 : if (state.dataWindowEquivLayer->CFS(EQLNum).L(state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr).CNTRL ==
9598 0 : state.dataWindowEquivalentLayer->lscNONE) {
9599 0 : state.dataSurface->SurfWinSlatAngThisTSDeg(ISurf) =
9600 0 : state.dataWindowEquivLayer->CFS(EQLNum).L(state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr).PHI_DEG;
9601 : } else {
9602 0 : state.dataSurface->SurfWinSlatAngThisTSDeg(ISurf) = 0.0;
9603 : }
9604 : }
9605 : }
9606 :
9607 : // Initialization of complex fenestration shading device
9608 23223162 : if (state.dataSurface->SurfWinWindowModelType(ISurf) == WindowModel::BSDF) {
9609 39540 : auto &construction = state.dataConstruction->Construct(state.dataSurface->Surface(ISurf).Construction);
9610 39540 : auto &surface_window = state.dataSurface->SurfaceWindow(ISurf);
9611 39540 : int TotLayers = construction.TotLayers;
9612 219672 : for (int Lay = 1; Lay <= TotLayers; ++Lay) {
9613 180132 : const int LayPtr = construction.LayerPoint(Lay);
9614 180132 : auto *material(state.dataMaterial->Material(LayPtr));
9615 180132 : const bool isShading = material->group == Material::Group::ComplexWindowShade;
9616 180132 : if (isShading && Lay == 1) {
9617 10143 : state.dataSurface->SurfWinShadingFlag(ISurf) = WinShadingType::ExtShade;
9618 : }
9619 180132 : if (isShading && Lay == TotLayers) {
9620 15894 : state.dataSurface->SurfWinShadingFlag(ISurf) = WinShadingType::IntShade;
9621 : }
9622 : }
9623 39540 : if (state.dataSurface->SurfWinShadingFlag(ISurf) == WinShadingType::IntShade) {
9624 15894 : auto &construction = state.dataConstruction->Construct(state.dataSurface->Surface(ISurf).Construction);
9625 15894 : const int TotLay = construction.TotLayers;
9626 15894 : int ShadingLayerPtr = construction.LayerPoint(TotLay);
9627 :
9628 15894 : ShadingLayerPtr = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(ShadingLayerPtr))->ComplexShadePtr;
9629 15894 : auto &complexShade = state.dataMaterial->ComplexShade(ShadingLayerPtr);
9630 15894 : Real64 TauShadeIR = complexShade.IRTransmittance;
9631 15894 : Real64 EpsShadeIR = complexShade.BackEmissivity;
9632 15894 : Real64 RhoShadeIR = max(0.0, 1.0 - TauShadeIR - EpsShadeIR);
9633 : // Get properties of glass next to inside shading layer
9634 15894 : int GlassLayPtr = construction.LayerPoint(TotLay - 2);
9635 15894 : Real64 EpsGlassIR = dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(GlassLayPtr))->AbsorpThermalBack;
9636 15894 : Real64 RhoGlassIR = 1 - EpsGlassIR;
9637 :
9638 15894 : Real64 EffShBlEmiss = EpsShadeIR * (1.0 + RhoGlassIR * TauShadeIR / (1.0 - RhoGlassIR * RhoShadeIR));
9639 15894 : surface_window.EffShBlindEmiss[1] = EffShBlEmiss;
9640 15894 : Real64 EffGlEmiss = EpsGlassIR * TauShadeIR / (1.0 - RhoGlassIR * RhoShadeIR);
9641 15894 : surface_window.EffGlassEmiss[1] = EffGlEmiss;
9642 : }
9643 : }
9644 :
9645 23223162 : if (state.dataSurface->Surface(ISurf).ExtBoundCond != ExternalEnvironment) continue;
9646 23195970 : if (!state.dataSurface->Surface(ISurf).HasShadeControl) {
9647 22543899 : continue;
9648 : } else {
9649 : //
9650 : }
9651 :
9652 : // Initialize switching factor (applicable only to switchable glazing) to unswitched
9653 652071 : state.dataSurface->SurfWinSwitchingFactor(ISurf) = 0.0;
9654 :
9655 652071 : IConst = state.dataSurface->Surface(ISurf).Construction;
9656 : // Vis trans at normal incidence of unswitched glass. Counting the GlazedFrac
9657 652071 : if (IConst > 0)
9658 652071 : state.dataSurface->SurfWinVisTransSelected(ISurf) =
9659 652071 : POLYF(1.0, state.dataConstruction->Construct(IConst).TransVisBeamCoef) * surfWin.glazedFrac;
9660 :
9661 : // Window has shading control
9662 : // select the active window shading control and corresponding contructions
9663 652071 : size_t indexWindowShadingControl = selectActiveWindowShadingControlIndex(state, ISurf);
9664 1304142 : if (!state.dataSurface->Surface(ISurf).windowShadingControlList.empty() &&
9665 652071 : indexWindowShadingControl <= state.dataSurface->Surface(ISurf).windowShadingControlList.size() - 1) {
9666 652071 : state.dataSurface->Surface(ISurf).activeWindowShadingControl =
9667 652071 : state.dataSurface->Surface(ISurf).windowShadingControlList[indexWindowShadingControl];
9668 : }
9669 652071 : state.dataSurface->Surface(ISurf).activeShadedConstructionPrev = state.dataSurface->Surface(ISurf).activeShadedConstruction;
9670 1304142 : if (!state.dataSurface->Surface(ISurf).shadedConstructionList.empty() &&
9671 652071 : indexWindowShadingControl <= state.dataSurface->Surface(ISurf).shadedConstructionList.size() - 1) {
9672 652071 : state.dataSurface->Surface(ISurf).activeShadedConstruction =
9673 652071 : state.dataSurface->Surface(ISurf).shadedConstructionList[indexWindowShadingControl];
9674 : }
9675 652071 : state.dataSurface->SurfWinActiveShadedConstruction(ISurf) = state.dataSurface->Surface(ISurf).activeShadedConstruction;
9676 652071 : if (!state.dataSurface->Surface(ISurf).shadedStormWinConstructionList.empty() &&
9677 0 : indexWindowShadingControl <= state.dataSurface->Surface(ISurf).shadedStormWinConstructionList.size() - 1) {
9678 0 : if (state.dataSurface->SurfWinStormWinFlag(ISurf) == 1) {
9679 0 : state.dataSurface->SurfWinActiveShadedConstruction(ISurf) =
9680 0 : state.dataSurface->Surface(ISurf).shadedStormWinConstructionList[indexWindowShadingControl];
9681 : }
9682 : }
9683 :
9684 652071 : int IShadingCtrl = state.dataSurface->Surface(ISurf).activeWindowShadingControl;
9685 652071 : int IZone = state.dataSurface->Surface(ISurf).Zone;
9686 : // Setpoint for shading
9687 652071 : Real64 SetPoint = state.dataSurface->WindowShadingControl(IShadingCtrl).SetPoint; // Control setpoint
9688 652071 : Real64 SetPoint2 = state.dataSurface->WindowShadingControl(IShadingCtrl).SetPoint2; // Second control setpoint
9689 :
9690 652071 : bool SchedAllowsControl = true; // True if control schedule is not specified or is specified and schedule value = 1
9691 652071 : int SchedulePtr = state.dataSurface->WindowShadingControl(IShadingCtrl).Schedule;
9692 652071 : if (SchedulePtr != 0) {
9693 378900 : if (state.dataSurface->WindowShadingControl(IShadingCtrl).ShadingControlIsScheduled &&
9694 189450 : GetCurrentScheduleValue(state, SchedulePtr) <= 0.0)
9695 154620 : SchedAllowsControl = false;
9696 : }
9697 :
9698 : Real64 GlareControlIsActive =
9699 775330 : (state.dataDayltg->ZoneDaylight(IZone).totRefPts > 0 && state.dataEnvrn->SunIsUp &&
9700 123259 : state.dataSurface->WindowShadingControl(IShadingCtrl).GlareControlIsActive); // True if glare control is active
9701 :
9702 652071 : Real64 SolarOnWindow = 0.0; // Direct plus diffuse solar intensity on window (W/m2)
9703 652071 : Real64 BeamSolarOnWindow = 0.0; // Direct solar intensity on window (W/m2)
9704 652071 : Real64 HorizSolar = 0.0; // Horizontal direct plus diffuse solar intensity
9705 652071 : if (state.dataEnvrn->SunIsUp) {
9706 325641 : Real64 SkySolarOnWindow = state.dataSolarShading->SurfAnisoSkyMult(ISurf) *
9707 325641 : state.dataEnvrn->DifSolarRad; // Sky diffuse solar intensity on window (W/m2)
9708 325641 : BeamSolarOnWindow = state.dataEnvrn->BeamSolarRad *
9709 325641 : state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, ISurf) *
9710 325641 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, ISurf);
9711 325641 : SolarOnWindow =
9712 325641 : BeamSolarOnWindow + SkySolarOnWindow + state.dataEnvrn->GndSolarRad * state.dataSurface->Surface(ISurf).ViewFactorGround;
9713 325641 : HorizSolar = state.dataEnvrn->BeamSolarRad * state.dataEnvrn->SOLCOS(3) + state.dataEnvrn->DifSolarRad;
9714 : }
9715 :
9716 : // Determine whether to deploy shading depending on type of control
9717 652071 : auto &thisIZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(IZone);
9718 :
9719 652071 : bool shadingOn = false;
9720 652071 : bool shadingOffButGlareControlOn = false;
9721 652071 : switch (state.dataSurface->WindowShadingControl(IShadingCtrl).shadingControlType) {
9722 20907 : case WindowShadingControlType::AlwaysOn: // 'ALWAYSON'
9723 20907 : shadingOn = true;
9724 20907 : break;
9725 0 : case WindowShadingControlType::AlwaysOff: // 'ALWAYSOFF'
9726 0 : break;
9727 116088 : case WindowShadingControlType::OnIfScheduled: // 'ONIFSCHEDULEALLOWS'
9728 116088 : if (SchedAllowsControl) shadingOn = true;
9729 116088 : break;
9730 341754 : case WindowShadingControlType::HiSolar: // 'ONIFHIGHSOLARONWINDOW'
9731 : // ! Direct plus diffuse solar intensity on window
9732 341754 : if (state.dataEnvrn->SunIsUp) {
9733 169759 : if (SolarOnWindow > SetPoint && SchedAllowsControl) {
9734 96560 : shadingOn = true;
9735 73199 : } else if (GlareControlIsActive) {
9736 31798 : shadingOffButGlareControlOn = true;
9737 : }
9738 : }
9739 341754 : break;
9740 :
9741 0 : case WindowShadingControlType::HiHorzSolar: // 'ONIFHIGHHORIZONTALSOLAR' ! Direct plus diffuse exterior horizontal solar intensity
9742 0 : if (state.dataEnvrn->SunIsUp) {
9743 0 : if (HorizSolar > SetPoint && SchedAllowsControl) {
9744 0 : shadingOn = true;
9745 0 : } else if (GlareControlIsActive) {
9746 0 : shadingOffButGlareControlOn = true;
9747 : }
9748 : }
9749 0 : break;
9750 :
9751 0 : case WindowShadingControlType::HiOutAirTemp: // 'OnIfHighOutdoorAirTemperature'
9752 0 : if (state.dataSurface->SurfOutDryBulbTemp(ISurf) > SetPoint && SchedAllowsControl) {
9753 0 : shadingOn = true;
9754 0 : } else if (GlareControlIsActive) {
9755 0 : shadingOffButGlareControlOn = true;
9756 : }
9757 0 : break;
9758 :
9759 0 : case WindowShadingControlType::HiZoneAirTemp: // 'OnIfHighZoneAirTemperature' ! Previous time step zone air temperature
9760 0 : if (thisIZoneHB.MAT > SetPoint && SchedAllowsControl) {
9761 0 : shadingOn = true;
9762 0 : } else if (GlareControlIsActive) {
9763 0 : shadingOffButGlareControlOn = true;
9764 : }
9765 0 : break;
9766 :
9767 0 : case WindowShadingControlType::OnHiOutTemp_HiSolarWindow: // 'OnIfHighOutdoorAirTempAndHighSolarOnWindow' ! Outside air temp and
9768 : // solar on window
9769 0 : if (state.dataEnvrn->SunIsUp) {
9770 0 : if (state.dataSurface->SurfOutDryBulbTemp(ISurf) > SetPoint && SolarOnWindow > SetPoint2 && SchedAllowsControl) {
9771 0 : shadingOn = true;
9772 0 : } else if (GlareControlIsActive) {
9773 0 : shadingOffButGlareControlOn = true;
9774 : }
9775 : }
9776 0 : break;
9777 :
9778 0 : case WindowShadingControlType::OnHiOutTemp_HiHorzSolar: // 'OnIfHighOutdoorAirTempAndHighHorizontalSolar' ! Outside air temp and
9779 : // horizontal solar
9780 0 : if (state.dataEnvrn->SunIsUp) {
9781 0 : if (state.dataSurface->SurfOutDryBulbTemp(ISurf) > SetPoint && HorizSolar > SetPoint2 && SchedAllowsControl) {
9782 0 : shadingOn = true;
9783 0 : } else if (GlareControlIsActive) {
9784 0 : shadingOffButGlareControlOn = true;
9785 : }
9786 : }
9787 0 : break;
9788 :
9789 0 : case WindowShadingControlType::OnHiZoneTemp_HiSolarWindow: // 'ONIFHIGHZONEAIRTEMPANDHIGHSOLARONWINDOW' ! Zone air temp and solar on
9790 : // window
9791 0 : if (state.dataEnvrn->SunIsUp) {
9792 0 : if (thisIZoneHB.MAT > SetPoint && SolarOnWindow > SetPoint2 && SchedAllowsControl) {
9793 0 : shadingOn = true;
9794 0 : } else if (GlareControlIsActive) {
9795 0 : shadingOffButGlareControlOn = true;
9796 : }
9797 : }
9798 0 : break;
9799 :
9800 0 : case WindowShadingControlType::OnHiZoneTemp_HiHorzSolar: // 'ONIFHIGHZONEAIRTEMPANDHIGHHORIZONTALSOLAR' ! Zone air temp and
9801 : // horizontal solar
9802 0 : if (state.dataEnvrn->SunIsUp) {
9803 0 : if (thisIZoneHB.MAT > SetPoint && HorizSolar > SetPoint2 && SchedAllowsControl) {
9804 0 : shadingOn = true;
9805 0 : } else if (GlareControlIsActive) {
9806 0 : shadingOffButGlareControlOn = true;
9807 : }
9808 : }
9809 0 : break;
9810 :
9811 0 : case WindowShadingControlType::HiZoneCooling:
9812 : // 'ONIFHIGHZONECOOLING' ! Previous time step zone sensible cooling rate [W]
9813 : // In the following, the check on BeginSimFlag is needed since SNLoadCoolRate (and SNLoadHeatRate,
9814 : // used in other CASEs) are not allocated at this point for the first time step of the simulation.
9815 0 : if (!state.dataGlobal->BeginSimFlag) {
9816 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > SetPoint && SchedAllowsControl) {
9817 0 : shadingOn = true;
9818 0 : } else if (GlareControlIsActive) {
9819 0 : shadingOffButGlareControlOn = true;
9820 : }
9821 : }
9822 0 : break;
9823 :
9824 167898 : case WindowShadingControlType::HiGlare:
9825 : // 'ONIFHIGHGLARE' ! Daylight glare index at first reference point in the zone.
9826 : // This type of shading control is done in DayltgInteriorIllum. Glare control is not affected
9827 : // by control schedule.
9828 167898 : if (state.dataEnvrn->SunIsUp) {
9829 84177 : shadingOffButGlareControlOn = true;
9830 : }
9831 167898 : break;
9832 :
9833 2712 : case WindowShadingControlType::MeetDaylIlumSetp:
9834 : // 'MEETDAYLIGHTILLUMINANCESETPOINT') ! Daylight illuminance test is done in DayltgInteriorIllum
9835 : // Only switchable glazing does daylight illuminance control
9836 2712 : if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9837 1330 : shadingOffButGlareControlOn = true;
9838 : }
9839 2712 : break;
9840 :
9841 2712 : case WindowShadingControlType::HiSolar_HiLumin_OffMidNight:
9842 : // 'OnIfHighSolarOrHighLuminanceTillMidnight'
9843 : // if shade is already on, then keep it on until midnight, otherwise check thresholds
9844 2712 : if (SchedAllowsControl && IS_SHADED(state.dataSurface->SurfWinExtIntShadePrevTS(ISurf))) {
9845 978 : shadingOn = true;
9846 1734 : } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9847 630 : if (SolarOnWindow > SetPoint) {
9848 14 : shadingOn = true;
9849 : } else {
9850 : // pass to DayltgInteriorIllum to check for luminance
9851 616 : shadingOn = false;
9852 616 : shadingOffButGlareControlOn = true;
9853 : }
9854 : }
9855 : // if it is the beginning of the day, then shades off
9856 2712 : if (state.dataGlobal->BeginDayFlag) {
9857 36 : shadingOn = false;
9858 36 : shadingOffButGlareControlOn = false;
9859 : }
9860 2712 : break;
9861 :
9862 0 : case WindowShadingControlType::HiSolar_HiLumin_OffSunset:
9863 : // 'OnIfHighSolarOrHighLuminanceTillSunset'
9864 : // if shade is already on, then keep it on until sunset, otherwise check thresholds
9865 0 : if (SchedAllowsControl && IS_SHADED(state.dataSurface->SurfWinExtIntShadePrevTS(ISurf))) {
9866 0 : shadingOn = true;
9867 0 : } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9868 0 : if (SolarOnWindow > SetPoint) {
9869 0 : shadingOn = true;
9870 : } else {
9871 : // pass to DayltgInteriorIllum to check for luminance
9872 0 : shadingOn = false;
9873 0 : shadingOffButGlareControlOn = true;
9874 : }
9875 : }
9876 : // if sunset, then shades off
9877 0 : if (!state.dataEnvrn->SunIsUp) {
9878 0 : shadingOn = false;
9879 0 : shadingOffButGlareControlOn = false;
9880 : }
9881 0 : break;
9882 :
9883 0 : case WindowShadingControlType::HiSolar_HiLumin_OffNextMorning:
9884 : // 'OnIfHighSolarOrHighLuminanceTillNextMorning'
9885 : // if shade is already on, then keep it on until next day when sun is up, otherwise check thresholds
9886 0 : if (SchedAllowsControl && IS_SHADED(state.dataSurface->SurfWinExtIntShadePrevTS(ISurf))) {
9887 0 : shadingOn = true;
9888 0 : } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9889 0 : if (SolarOnWindow > SetPoint) {
9890 0 : shadingOn = true;
9891 : } else {
9892 : // pass to DayltgInteriorIllum to check for luminance
9893 0 : shadingOn = false;
9894 0 : shadingOffButGlareControlOn = true;
9895 : }
9896 : }
9897 : // if next morning (identified by sun is not up in previous time step and is up now), then shades off
9898 0 : if (!state.dataEnvrn->SunIsUpPrevTS && state.dataEnvrn->SunIsUp) {
9899 0 : shadingOn = false;
9900 0 : shadingOffButGlareControlOn = false;
9901 : }
9902 0 : break;
9903 :
9904 0 : case WindowShadingControlType::OnNightLoOutTemp_OffDay: // 'OnNightIfLowOutdoorTempAndOffDay'
9905 0 : if (!state.dataEnvrn->SunIsUp && state.dataSurface->SurfOutDryBulbTemp(ISurf) < SetPoint && SchedAllowsControl) {
9906 0 : shadingOn = true;
9907 0 : } else if (GlareControlIsActive) {
9908 0 : shadingOffButGlareControlOn = true;
9909 : }
9910 0 : break;
9911 :
9912 0 : case WindowShadingControlType::OnNightLoInTemp_OffDay: // 'OnNightIfLowInsideTempAndOffDay')
9913 0 : if (!state.dataEnvrn->SunIsUp && thisIZoneHB.MAT < SetPoint && SchedAllowsControl) {
9914 0 : shadingOn = true;
9915 0 : } else if (GlareControlIsActive) {
9916 0 : shadingOffButGlareControlOn = true;
9917 : }
9918 0 : break;
9919 :
9920 0 : case WindowShadingControlType::OnNightIfHeating_OffDay: // 'OnNightIfHeatingAndOffDay'
9921 0 : if (!state.dataGlobal->BeginSimFlag) {
9922 0 : if (!state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysHeatRate > SetPoint &&
9923 : SchedAllowsControl) {
9924 0 : shadingOn = true;
9925 0 : } else if (GlareControlIsActive) {
9926 0 : shadingOffButGlareControlOn = true;
9927 : }
9928 : }
9929 0 : break;
9930 :
9931 0 : case WindowShadingControlType::OnNightLoOutTemp_OnDayCooling: // 'OnNightIfLowOutdoorTempAndOnDayIfCooling'
9932 0 : if (!state.dataGlobal->BeginSimFlag) {
9933 0 : if (!state.dataEnvrn->SunIsUp) { // Night
9934 0 : if (state.dataSurface->SurfOutDryBulbTemp(ISurf) < SetPoint && SchedAllowsControl) shadingOn = true;
9935 : } else { // Day
9936 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 && SchedAllowsControl) {
9937 0 : shadingOn = true;
9938 0 : } else if (GlareControlIsActive) {
9939 0 : shadingOffButGlareControlOn = true;
9940 : }
9941 : }
9942 : }
9943 0 : break;
9944 :
9945 0 : case WindowShadingControlType::OnNightIfHeating_OnDayCooling: // 'OnNightIfHeatingAndOnDayIfCooling'
9946 0 : if (!state.dataGlobal->BeginSimFlag) {
9947 0 : if (!state.dataEnvrn->SunIsUp) { // Night
9948 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysHeatRate > SetPoint && SchedAllowsControl)
9949 0 : shadingOn = true;
9950 : } else { // Day
9951 0 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 && SchedAllowsControl) {
9952 0 : shadingOn = true;
9953 0 : } else if (GlareControlIsActive) {
9954 0 : shadingOffButGlareControlOn = true;
9955 : }
9956 : }
9957 : }
9958 0 : break;
9959 :
9960 0 : case WindowShadingControlType::OffNight_OnDay_HiSolarWindow: // 'OffNightAndOnDayIfCoolingAndHighSolarOnWindow'
9961 0 : if (!state.dataGlobal->BeginSimFlag) {
9962 0 : if (state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 &&
9963 : SchedAllowsControl) {
9964 0 : if (SolarOnWindow > SetPoint) shadingOn = true;
9965 0 : } else if (GlareControlIsActive) {
9966 0 : shadingOffButGlareControlOn = true;
9967 : }
9968 : }
9969 0 : break;
9970 :
9971 0 : case WindowShadingControlType::OnNight_OnDay_HiSolarWindow: // 'OnNightAndOnDayIfCoolingAndHighSolarOnWindow'
9972 0 : if (!state.dataGlobal->BeginSimFlag) {
9973 0 : if (state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 &&
9974 : SchedAllowsControl) {
9975 0 : if (SolarOnWindow > SetPoint) shadingOn = true;
9976 0 : } else if (!state.dataEnvrn->SunIsUp && SchedAllowsControl) {
9977 0 : shadingOn = true;
9978 0 : } else if (GlareControlIsActive) {
9979 0 : shadingOffButGlareControlOn = true;
9980 : }
9981 : }
9982 0 : break;
9983 0 : default:
9984 0 : ShowWarningError(
9985 0 : state, format("Invalid Selection of Window Shading Control Type for Surface {}", state.dataSurface->Surface(ISurf).Name));
9986 : }
9987 :
9988 652071 : WinShadingType ShType = state.dataSurface->WindowShadingControl(IShadingCtrl).ShadingType;
9989 :
9990 652071 : state.dataSurface->SurfWinShadingFlag(ISurf) = WinShadingType::ShadeOff; // Initialize shading flag to off
9991 :
9992 652071 : if (IS_SHADED(ShType)) {
9993 652071 : if (shadingOn) {
9994 123895 : state.dataSurface->SurfWinShadingFlag(ISurf) = ShType;
9995 528176 : } else if (shadingOffButGlareControlOn) {
9996 117921 : if (ShType == WinShadingType::SwitchableGlazing)
9997 85507 : state.dataSurface->SurfWinShadingFlag(ISurf) = WinShadingType::GlassConditionallyLightened;
9998 32414 : else if (ShType == WinShadingType::IntShade)
9999 616 : state.dataSurface->SurfWinShadingFlag(ISurf) = WinShadingType::IntShadeConditionallyOff;
10000 31798 : else if (ShType == WinShadingType::ExtShade)
10001 31798 : state.dataSurface->SurfWinShadingFlag(ISurf) = WinShadingType::ExtShadeConditionallyOff;
10002 0 : else if (ShType == WinShadingType::IntBlind)
10003 0 : state.dataSurface->SurfWinShadingFlag(ISurf) = WinShadingType::IntBlindConditionallyOff;
10004 0 : else if (ShType == WinShadingType::ExtBlind)
10005 0 : state.dataSurface->SurfWinShadingFlag(ISurf) = WinShadingType::ExtBlindConditionallyOff;
10006 0 : else if (ShType == WinShadingType::BGShade)
10007 0 : state.dataSurface->SurfWinShadingFlag(ISurf) = WinShadingType::BGShadeConditionallyOff;
10008 0 : else if (ShType == WinShadingType::BGBlind)
10009 0 : state.dataSurface->SurfWinShadingFlag(ISurf) = WinShadingType::BGBlindConditionallyOff;
10010 : }
10011 : }
10012 :
10013 : // Set switching factor to fully switched if ShadingFlag = 2
10014 652071 : if (state.dataSurface->SurfWinShadingFlag(ISurf) == WinShadingType::SwitchableGlazing) {
10015 0 : state.dataSurface->SurfWinSwitchingFactor(ISurf) = 1.0;
10016 :
10017 : // Added TH 1/20/2010
10018 : // Vis trans at normal incidence of fully switched glass
10019 0 : IConst = state.dataSurface->Surface(ISurf).activeShadedConstruction;
10020 0 : state.dataSurface->SurfWinVisTransSelected(ISurf) =
10021 0 : POLYF(1.0, state.dataConstruction->Construct(IConst).TransVisBeamCoef) * surfWin.glazedFrac;
10022 : }
10023 :
10024 : // Slat angle control for blinds
10025 :
10026 652071 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = 0.0;
10027 652071 : state.dataSurface->SurfWinSlatAngThisTSDeg(ISurf) = 0.0;
10028 652071 : state.dataSurface->SurfWinSlatsBlockBeam(ISurf) = false;
10029 652071 : if (ANY_BLIND(state.dataSurface->SurfWinShadingFlag(ISurf)) ||
10030 575169 : state.dataSurface->SurfWinShadingFlag(ISurf) == WinShadingType::IntBlindConditionallyOff ||
10031 1802409 : state.dataSurface->SurfWinShadingFlag(ISurf) == WinShadingType::ExtBlindConditionallyOff ||
10032 575169 : state.dataSurface->SurfWinShadingFlag(ISurf) == WinShadingType::BGBlindConditionallyOff) {
10033 : // Blind in place or may be in place due to glare control
10034 76902 : int BlNum = state.dataSurface->SurfWinBlindNumber(ISurf);
10035 76902 : if (BlNum > 0) {
10036 76902 : Real64 InputSlatAngle = state.dataMaterial->Blind(BlNum).SlatAngle *
10037 76902 : Constant::DegToRadians; // Slat angle of associated Material:WindowBlind (rad)
10038 : Real64 SlatAng; // Slat angle this time step (rad)
10039 : Real64 PermeabilityA; // Intermediate variables in blind permeability calc
10040 : Real64 PermeabilityB;
10041 : Real64 ThetaBase; // Intermediate slat angle variable (rad)
10042 : Real64 ThetaBlock1; // Slat angles that just block beam solar (rad)
10043 : Real64 ThetaBlock2;
10044 :
10045 76902 : auto const &blind = state.dataMaterial->Blind(BlNum);
10046 76902 : Real64 ProfAng = state.dataSurface->SurfWinProfileAng(ISurf) =
10047 76902 : Dayltg::ProfileAngle(state, ISurf, state.dataEnvrn->SOLCOS, blind.SlatOrientation);
10048 :
10049 76902 : if (ProfAng > Constant::PiOvr2 || ProfAng < -Constant::PiOvr2) {
10050 0 : ProfAng = min(max(ProfAng, -Constant::PiOvr2), Constant::PiOvr2);
10051 : }
10052 76902 : int ProfAngIndex = int((ProfAng + Constant::PiOvr2) / DeltaProfAng) + 1;
10053 76902 : state.dataSurface->SurfWinProfAngIndex(ISurf) = ProfAngIndex;
10054 76902 : state.dataSurface->SurfWinProfAngInterpFac(ISurf) =
10055 76902 : (ProfAng + Constant::PiOvr2 - (ProfAngIndex - 1) * DeltaProfAng) / DeltaProfAng;
10056 :
10057 76902 : if (blind.SlatWidth > blind.SlatSeparation && BeamSolarOnWindow > 0.0) {
10058 53230 : ProfAng = state.dataSurface->SurfWinProfileAng(ISurf);
10059 53230 : Real64 ThetaBase = std::acos(std::cos(ProfAng) * blind.SlatSeparation / blind.SlatWidth);
10060 : // There are two solutions for the slat angle that just blocks beam radiation
10061 53230 : ThetaBlock1 = ProfAng + ThetaBase;
10062 53230 : ThetaBlock2 = ProfAng + Constant::Pi - ThetaBase;
10063 53230 : state.dataSolarShading->ThetaSmall = min(ThetaBlock1, ThetaBlock2);
10064 53230 : state.dataSolarShading->ThetaBig = max(ThetaBlock1, ThetaBlock2);
10065 53230 : state.dataSolarShading->ThetaMin = blind.MinSlatAngle * Constant::DegToRadians;
10066 53230 : state.dataSolarShading->ThetaMax = blind.MaxSlatAngle * Constant::DegToRadians;
10067 : }
10068 :
10069 : // TH 5/20/2010, CR 8064: Slat Width <= Slat Separation
10070 76902 : if (blind.SlatWidth <= blind.SlatSeparation && BeamSolarOnWindow > 0.0) {
10071 0 : if (state.dataSurface->WindowShadingControl(IShadingCtrl).slatAngleControl == SlatAngleControl::BlockBeamSolar) {
10072 0 : ProfAng = state.dataSurface->SurfWinProfileAng(ISurf);
10073 0 : if (std::abs(std::cos(ProfAng) * blind.SlatSeparation / blind.SlatWidth) <= 1.0) {
10074 : // set to block 100% of beam solar, not necessarily to block maximum solar (beam + diffuse)
10075 0 : ThetaBase = std::acos(std::cos(ProfAng) * blind.SlatSeparation / blind.SlatWidth);
10076 0 : state.dataSurface->SurfWinSlatsBlockBeam(ISurf) = true;
10077 : } else {
10078 : // cannot block 100% of beam solar, turn slats to be perpendicular to sun beam to block maximal beam solar
10079 0 : ThetaBase = 0.0;
10080 : }
10081 :
10082 : // There are two solutions for the slat angle that just blocks beam radiation
10083 0 : ThetaBlock1 = ProfAng + ThetaBase;
10084 0 : ThetaBlock2 = ProfAng - ThetaBase + Constant::Pi;
10085 :
10086 0 : state.dataSolarShading->ThetaSmall = min(ThetaBlock1, ThetaBlock2);
10087 0 : state.dataSolarShading->ThetaBig = max(ThetaBlock1, ThetaBlock2);
10088 0 : state.dataSolarShading->ThetaMin = blind.MinSlatAngle * Constant::DegToRadians;
10089 0 : state.dataSolarShading->ThetaMax = blind.MaxSlatAngle * Constant::DegToRadians;
10090 : }
10091 : }
10092 :
10093 76902 : switch (state.dataSurface->WindowShadingControl(IShadingCtrl).slatAngleControl) {
10094 73771 : case SlatAngleControl::Fixed: { // 'FIXEDSLATANGLE'
10095 73771 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = InputSlatAngle;
10096 73771 : if ((state.dataSurface->SurfWinSlatAngThisTS(ISurf) <= state.dataSolarShading->ThetaSmall ||
10097 5732 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) >= state.dataSolarShading->ThetaBig) &&
10098 79503 : (blind.SlatWidth > blind.SlatSeparation) && (BeamSolarOnWindow > 0.0))
10099 51887 : state.dataSurface->SurfWinSlatsBlockBeam(ISurf) = true;
10100 73771 : } break;
10101 0 : case SlatAngleControl::Scheduled: { // 'SCHEDULEDSLATANGLE'
10102 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) =
10103 0 : GetCurrentScheduleValue(state, state.dataSurface->WindowShadingControl(IShadingCtrl).SlatAngleSchedule);
10104 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) =
10105 0 : max(blind.MinSlatAngle, min(state.dataSurface->SurfWinSlatAngThisTS(ISurf), blind.MaxSlatAngle)) *
10106 : Constant::DegToRadians;
10107 0 : if ((state.dataSurface->SurfWinSlatAngThisTS(ISurf) <= state.dataSolarShading->ThetaSmall ||
10108 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) >= state.dataSolarShading->ThetaBig) &&
10109 0 : (blind.SlatWidth > blind.SlatSeparation) && (BeamSolarOnWindow > 0.0))
10110 0 : state.dataSurface->SurfWinSlatsBlockBeam(ISurf) = true;
10111 0 : } break;
10112 3131 : case SlatAngleControl::BlockBeamSolar: { // 'BLOCKBEAMSOLAR'
10113 3131 : if (BeamSolarOnWindow > 0.0) {
10114 1092 : if (blind.SlatSeparation >= blind.SlatWidth) {
10115 : // TH 5/20/2010. CR 8064.
10116 : // The following line of code assumes slats are always vertical/closed to minimize solar penetration
10117 : // The slat angle can however change if the only goal is to block maximum amount of direct beam solar
10118 : // SurfaceWindow(ISurf)%SlatAngThisTS = 0.0 ! Allows beam penetration but minimizes it
10119 :
10120 0 : if (state.dataSolarShading->ThetaSmall >= state.dataSolarShading->ThetaMin &&
10121 0 : state.dataSolarShading->ThetaSmall <= state.dataSolarShading->ThetaMax) {
10122 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = state.dataSolarShading->ThetaSmall;
10123 0 : } else if (state.dataSolarShading->ThetaBig >= state.dataSolarShading->ThetaMin &&
10124 0 : state.dataSolarShading->ThetaBig <= state.dataSolarShading->ThetaMax) {
10125 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = state.dataSolarShading->ThetaBig;
10126 0 : } else if (state.dataSolarShading->ThetaSmall < state.dataSolarShading->ThetaMin &&
10127 0 : state.dataSolarShading->ThetaBig < state.dataSolarShading->ThetaMin) {
10128 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = state.dataSolarShading->ThetaMin;
10129 0 : } else if (state.dataSolarShading->ThetaSmall > state.dataSolarShading->ThetaMax &&
10130 0 : state.dataSolarShading->ThetaBig > state.dataSolarShading->ThetaMax) {
10131 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = state.dataSolarShading->ThetaMax;
10132 : } else { // ThetaBig > ThetaMax and ThetaSmall < ThetaMin (no-block condition)
10133 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = state.dataSolarShading->ThetaMin;
10134 : }
10135 :
10136 : } else { // Usual case -- slat width greater than slat separation
10137 2184 : if (state.dataSolarShading->ThetaSmall >= state.dataSolarShading->ThetaMin &&
10138 1092 : state.dataSolarShading->ThetaSmall <= state.dataSolarShading->ThetaMax) {
10139 1071 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = state.dataSolarShading->ThetaSmall;
10140 1071 : state.dataSurface->SurfWinSlatsBlockBeam(ISurf) = true;
10141 42 : } else if (state.dataSolarShading->ThetaBig >= state.dataSolarShading->ThetaMin &&
10142 21 : state.dataSolarShading->ThetaBig <= state.dataSolarShading->ThetaMax) {
10143 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = state.dataSolarShading->ThetaBig;
10144 0 : state.dataSurface->SurfWinSlatsBlockBeam(ISurf) = true;
10145 21 : } else if (state.dataSolarShading->ThetaSmall < state.dataSolarShading->ThetaMin &&
10146 0 : state.dataSolarShading->ThetaBig < state.dataSolarShading->ThetaMin) {
10147 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = state.dataSolarShading->ThetaMin;
10148 0 : state.dataSurface->SurfWinSlatsBlockBeam(ISurf) = true;
10149 42 : } else if (state.dataSolarShading->ThetaSmall > state.dataSolarShading->ThetaMax &&
10150 21 : state.dataSolarShading->ThetaBig > state.dataSolarShading->ThetaMax) {
10151 21 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = state.dataSolarShading->ThetaMax;
10152 21 : state.dataSurface->SurfWinSlatsBlockBeam(ISurf) = true;
10153 : } else { // ThetaBig > ThetaMax and ThetaSmall < ThetaMin (no-block condition)
10154 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = state.dataSolarShading->ThetaMin;
10155 : }
10156 : }
10157 : } else {
10158 2039 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) = InputSlatAngle;
10159 : }
10160 3131 : } break;
10161 0 : default:
10162 0 : break;
10163 : }
10164 :
10165 76902 : state.dataSurface->SurfWinSlatAngThisTSDeg(ISurf) = state.dataSurface->SurfWinSlatAngThisTS(ISurf) / Constant::DegToRadians;
10166 76902 : if (state.dataSurface->SurfWinSlatAngThisTSDegEMSon(ISurf)) {
10167 0 : state.dataSurface->SurfWinSlatAngThisTSDeg(ISurf) = state.dataSurface->SurfWinSlatAngThisTSDegEMSValue(ISurf);
10168 0 : state.dataSurface->SurfWinSlatAngThisTS(ISurf) =
10169 0 : Constant::DegToRadians * state.dataSurface->SurfWinSlatAngThisTSDeg(ISurf);
10170 : }
10171 : // Air flow permeability for calculation of convective air flow between blind and glass
10172 76902 : SlatAng = state.dataSurface->SurfWinSlatAngThisTS(ISurf);
10173 76902 : PermeabilityA = std::sin(SlatAng) - blind.SlatThickness / blind.SlatSeparation;
10174 76902 : PermeabilityB =
10175 76902 : 1.0 - (std::abs(blind.SlatWidth * std::cos(SlatAng)) + blind.SlatThickness * std::sin(SlatAng)) / blind.SlatSeparation;
10176 76902 : state.dataSurface->SurfWinBlindAirFlowPermeability(ISurf) = min(1.0, max(0.0, PermeabilityA, PermeabilityB));
10177 76902 : state.dataSurface->SurfWinBlindBmBmTrans(ISurf) =
10178 76902 : Window::BlindBeamBeamTrans(ProfAng, SlatAng, blind.SlatWidth, blind.SlatSeparation, blind.SlatThickness);
10179 : // Calculate blind interpolation factors and indices.
10180 76902 : if (state.dataSurface->SurfWinMovableSlats(ISurf)) {
10181 3131 : if (SlatAng > Constant::Pi || SlatAng < 0.0) {
10182 0 : SlatAng = min(max(SlatAng, 0.0), Constant::Pi);
10183 : }
10184 3131 : Real64 SlatsAngIndex = 1 + int(SlatAng * DeltaAng_inv);
10185 3131 : state.dataSurface->SurfWinSlatsAngIndex(ISurf) = SlatsAngIndex;
10186 3131 : state.dataSurface->SurfWinSlatsAngInterpFac(ISurf) = (SlatAng - DeltaAng * (SlatsAngIndex - 1)) * DeltaAng_inv;
10187 : }
10188 : }
10189 : } // End of check if interior or exterior or between glass blind in place
10190 :
10191 : // AR: don't need to do this anymore I don't think
10192 : // CALL CalcScreenTransmittance to intialized all screens prior to HB calc's
10193 : // if (state.dataSurface->SurfWinShadingFlag(ISurf) == WinShadingType::ExtScreen && state.dataEnvrn->SunIsUp) {
10194 : // CalcScreenTransmittance(state, ISurf);
10195 : // }
10196 :
10197 : // EMS Actuator Point: override setting if ems flag on
10198 652071 : if (state.dataSurface->SurfWinShadingFlagEMSOn(ISurf)) {
10199 151217 : WinShadingType SurfWinShadingFlagEMS = findValueInEnumeration(state.dataSurface->SurfWinShadingFlagEMSValue(ISurf));
10200 151217 : if (SurfWinShadingFlagEMS != WinShadingType::Invalid) {
10201 151217 : state.dataSurface->SurfWinShadingFlag(ISurf) = SurfWinShadingFlagEMS;
10202 : } else {
10203 0 : ShowWarningError(
10204 0 : state, format("Invalid EMS value of Window Shading Control Type for Surface {}", state.dataSurface->Surface(ISurf).Name));
10205 : }
10206 : }
10207 : } // End of surface loop
10208 19867344 : }
10209 : }
10210 2804678 : }
10211 :
10212 2804678 : void CheckGlazingShadingStatusChange(EnergyPlusData &state)
10213 : {
10214 2804678 : if (state.dataGlobal->BeginSimFlag) {
10215 796 : if (state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() && state.dataWindowManager->winOpticalModel->isSimplifiedModel()) {
10216 2 : state.dataHeatBal->EnclRadAlwaysReCalc = true;
10217 : } else {
10218 5848 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
10219 10120 : for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
10220 5066 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
10221 49432 : for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
10222 44368 : auto &surf = state.dataSurface->Surface(SurfNum);
10223 88735 : if (state.dataConstruction->Construct(surf.Construction).TCFlag == 1 ||
10224 44367 : state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
10225 2 : state.dataHeatBal->EnclRadAlwaysReCalc = true;
10226 2 : break;
10227 : }
10228 : }
10229 5054 : }
10230 : }
10231 : }
10232 796 : if (state.dataHeatBal->EnclRadAlwaysReCalc) {
10233 13 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
10234 9 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
10235 : }
10236 13 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
10237 9 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
10238 : }
10239 : }
10240 : }
10241 2804678 : if (state.dataHeatBal->EnclRadAlwaysReCalc) return;
10242 :
10243 2795222 : if (state.dataGlobal->BeginEnvrnFlag || state.dataGlobal->AnyConstrOverridesInModel || state.dataGlobal->AnySurfPropOverridesInModel) {
10244 97357 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
10245 84890 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
10246 : }
10247 97357 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
10248 84890 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
10249 : }
10250 12467 : return;
10251 : }
10252 22531474 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
10253 19748719 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = false;
10254 : }
10255 22531474 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
10256 19748719 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = false;
10257 : }
10258 2782755 : if (!state.dataGlobal->AndShadingControlInModel) return;
10259 1297118 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
10260 9507761 : for (int const SurfNum : state.dataViewFactor->EnclRadInfo(enclosureNum).SurfacePtr) {
10261 8553371 : auto &surf = state.dataSurface->Surface(SurfNum);
10262 8553371 : bool surfShadingStatusChange = state.dataSurface->SurfWinExtIntShadePrevTS(SurfNum) != state.dataSurface->SurfWinShadingFlag(SurfNum) ||
10263 17050051 : surf.activeShadedConstruction != surf.activeShadedConstructionPrev ||
10264 8496680 : state.dataSurface->SurfWinMovableSlats(SurfNum);
10265 8553371 : if (surfShadingStatusChange) {
10266 62723 : state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
10267 62723 : state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
10268 62723 : break;
10269 : }
10270 : }
10271 : }
10272 : }
10273 :
10274 151217 : DataSurfaces::WinShadingType findValueInEnumeration(Real64 controlValue)
10275 : {
10276 : // This is a workaround to translate EMS Shading control numerical values
10277 : // EMS control of window shading devices involves setting the control values for shading control actuators with
10278 : // one of these values. The variable names can be used or replaced, it is the whole number values that trigger
10279 : // changes in the modeling.
10280 : // Shades and Blinds are either fully on or fully off, partial positions require multiple windows.
10281 : // the window shading control flag values follow
10282 : // -1: if window has no shading device
10283 : // 0: if shading device is off
10284 : // 1: if interior shade is on
10285 : // 2: if glazing is switched to darker state
10286 : // 3: if exterior shade is on
10287 : // 4: if exterior screen is on
10288 : // 6: if interior blind is on
10289 : // 7: if exterior blind is on
10290 : // 8: if between-glass shade is on
10291 : // 9: if between-glass blind is on
10292 : // 10: window has interior shade that is off but may be triggered on later to control daylight glare
10293 : // 20: window has switchable glazing that is unswitched but may be switched later to control daylight glare or
10294 : // daylight illuminance 30: window has exterior shade that is off but may be triggered on later to control
10295 : // daylight glare or daylight illuminance 60: window has interior blind that is off but may be triggered on later
10296 : // to control daylight glare or daylight illuminance 70: window has exterior blind that is off but may be
10297 : // triggered on later to control daylight glare or daylight illuminance 80: window has between-glass shade that is
10298 : // off but may be triggered on later to control daylight glare or daylight illuminance 90: window has
10299 : // between-glass blind that is off but may be triggered on later to control daylight glare or daylight illuminance
10300 151217 : if (controlValue == -1.0) return WinShadingType::NoShade;
10301 151217 : if (controlValue == 0.0) return WinShadingType::ShadeOff;
10302 123055 : if (controlValue == 1.0) return WinShadingType::IntShade;
10303 123055 : if (controlValue == 2.0) return WinShadingType::SwitchableGlazing;
10304 123055 : if (controlValue == 3.0) return WinShadingType::ExtShade;
10305 123055 : if (controlValue == 4.0) return WinShadingType::ExtScreen;
10306 123055 : if (controlValue == 6.0) return WinShadingType::IntBlind;
10307 0 : if (controlValue == 7.0) return WinShadingType::ExtBlind;
10308 0 : if (controlValue == 8.0) return WinShadingType::BGShade;
10309 0 : if (controlValue == 9.0) return WinShadingType::BGBlind;
10310 0 : if (controlValue == 10.0) return WinShadingType::IntShadeConditionallyOff;
10311 0 : if (controlValue == 20.0) return WinShadingType::GlassConditionallyLightened;
10312 0 : if (controlValue == 30.0) return WinShadingType::ExtShadeConditionallyOff;
10313 0 : if (controlValue == 60.0) return WinShadingType::IntBlindConditionallyOff;
10314 0 : if (controlValue == 70.0) return WinShadingType::ExtBlindConditionallyOff;
10315 0 : if (controlValue == 80.0) return WinShadingType::BGShadeConditionallyOff;
10316 0 : if (controlValue == 90.0) return WinShadingType::BGBlindConditionallyOff;
10317 0 : return WinShadingType::Invalid;
10318 : }
10319 :
10320 652071 : int selectActiveWindowShadingControlIndex(EnergyPlusData &state, int curSurface)
10321 : {
10322 : // For a given surface, determine based on the schedules which index to the window shading control list vector
10323 : // should be active
10324 652071 : int selected = 0; // presume it is the first shading control - even if it is not active it needs to be some
10325 : // shading control which is then turned off in the WindowShadingManager
10326 652071 : if (state.dataSurface->Surface(curSurface).windowShadingControlList.size() > 1) {
10327 10476 : for (std::size_t listIndex = 0; listIndex < state.dataSurface->Surface(curSurface).windowShadingControlList.size(); ++listIndex) {
10328 6996 : int wsc = state.dataSurface->Surface(curSurface).windowShadingControlList[listIndex];
10329 : // pick the first WindowShadingControl that has a non-zero schedule value
10330 6996 : if (ScheduleManager::GetCurrentScheduleValue(state, state.dataSurface->WindowShadingControl(wsc).Schedule) > 0.0) {
10331 24 : selected = listIndex;
10332 24 : break;
10333 : }
10334 : }
10335 : }
10336 652071 : return (selected);
10337 : }
10338 :
10339 4044 : void WindowGapAirflowControl(EnergyPlusData &state)
10340 : {
10341 :
10342 : // SUBROUTINE INFORMATION:
10343 : // AUTHOR Fred Winkelmann
10344 : // DATE WRITTEN February 2003
10345 : // MODIFIED June 2003, FCW: add fatal error for illegal schedule value
10346 : // RE-ENGINEERED na
10347 :
10348 : // PURPOSE OF THIS SUBROUTINE:
10349 : // For airflow windows, determines the airflow in the gap of
10350 : // double glazing and in the inner gap of triple glazing.
10351 :
10352 : // REFERENCES:
10353 : // na
10354 :
10355 : // Using/Aliasing
10356 : using ScheduleManager::GetCurrentScheduleValue;
10357 :
10358 16176 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
10359 24264 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
10360 12132 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
10361 12132 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
10362 12132 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
10363 44484 : for (int ISurf = firstSurfWin; ISurf <= lastSurfWin; ++ISurf) {
10364 :
10365 32352 : state.dataSurface->SurfWinAirflowThisTS(ISurf) = 0.0;
10366 32352 : if (state.dataSurface->SurfWinMaxAirflow(ISurf) == 0.0) continue;
10367 16176 : if (state.dataSurface->Surface(ISurf).ExtBoundCond != ExternalEnvironment) continue;
10368 16176 : switch (state.dataSurface->SurfWinAirflowControlType(ISurf)) {
10369 16176 : case WindowAirFlowControlType::MaxFlow: {
10370 16176 : state.dataSurface->SurfWinAirflowThisTS(ISurf) = state.dataSurface->SurfWinMaxAirflow(ISurf);
10371 16176 : } break;
10372 0 : case WindowAirFlowControlType::AlwaysOff: {
10373 0 : state.dataSurface->SurfWinAirflowThisTS(ISurf) = 0.0;
10374 0 : } break;
10375 0 : case WindowAirFlowControlType::Schedule: {
10376 0 : if (state.dataSurface->SurfWinAirflowHasSchedule(ISurf)) {
10377 0 : int SchedulePtr = state.dataSurface->SurfWinAirflowSchedulePtr(ISurf); // Schedule pointer
10378 0 : Real64 ScheduleMult = GetCurrentScheduleValue(state, SchedulePtr); // Multiplier value from schedule
10379 0 : if (ScheduleMult < 0.0 || ScheduleMult > 1.0) {
10380 0 : ShowFatalError(state,
10381 0 : format("Airflow schedule has a value outside the range 0.0 to 1.0 for window={}",
10382 0 : state.dataSurface->Surface(ISurf).Name));
10383 : }
10384 0 : state.dataSurface->SurfWinAirflowThisTS(ISurf) = ScheduleMult * state.dataSurface->SurfWinMaxAirflow(ISurf);
10385 : }
10386 0 : } break;
10387 0 : default:
10388 0 : break;
10389 : }
10390 : } // End of surface loop
10391 12132 : } // End of space loop
10392 : } // End of zone loop
10393 4044 : }
10394 :
10395 796 : void SkyDifSolarShading(EnergyPlusData &state)
10396 : {
10397 :
10398 : // SUBROUTINE INFORMATION:
10399 : // AUTHOR Fred Winkelmann
10400 : // DATE WRITTEN May 1999
10401 : // MODIFIED Sep 2000, FCW: add IR view factor calc
10402 : // Sep 2002, FCW: correct error in expression for ground IR view factor.
10403 : // Affects only non-vertical surfaces that are shadowed. For these surfaces
10404 : // error caused underestimate of IR from ground and shadowing surfaces.
10405 : // Dec 2002; LKL: Sky Radiance Distribution now only anisotropic
10406 : // Nov 2003: FCW: modify to do sky solar shading of shadowing surfaces
10407 : // RE-ENGINEERED na
10408 :
10409 : // PURPOSE OF THIS SUBROUTINE:
10410 : // Calculates factors that account for shading of sky diffuse
10411 : // solar radiation by shadowing surfaces such as overhangs and detached
10412 : // shades.
10413 : // Called by PerformSolarCalculations
10414 : // For each exterior heat transfer surface calculates the following
10415 : // ratio (called DifShdgRatioIsoSky in this subroutine):
10416 : // R1 = (Diffuse solar from sky dome on surface, with shading)/
10417 : // (Diffuse solar from sky dome on surface, without shading)
10418 : // To calculate the incident diffuse radiation on a surface the sky
10419 : // hemisphere is divided into source elements ("patches"). Each patch
10420 : // is assumed to have the same radiance, i.e. the sky radiance is isotropic.
10421 : // The irradiance from each patch on a surface is calculated. Then these
10422 : // irradiances are summed to get the net irradiance on a surface, which
10423 : // the denominator of R1.
10424 : // To get the numerator of R1 the same summation is done, but for each surface
10425 : // and each patch the Shadow subroutine is called to determine how much
10426 : // radiation from a patch is blocked by shading surfaces.
10427 : // Also calculated is the following ratio (called DifShdgRatioHoriz in this routine):
10428 : // R2 = (Diffuse solar from sky horizon band on surface, with shading)/
10429 : // (Diffuse solar from sky horizon band on surface, without shading)
10430 : // For this ratio only a band of sky just above the horizon is considered.
10431 : // R1 and R2 are used in SUBROUTINE AnisoSkyViewFactors, which determines the
10432 : // sky diffuse solar irradiance on each exterior heat transfer surface each
10433 : // time step. In that routine the sky radiance distribution is a superposition
10434 : // of an isotropic distribution,
10435 : // a horizon brightening distribution and a circumsolar brightening distribution,
10436 : // where the proportion of each distribution depends
10437 : // on cloud cover, sun position and other factors. R1 multiplies the irradiance
10438 : // due to the isotropic component and R2 multiplies the irradiance due to the
10439 : // horizon brightening component.
10440 : // Calculates sky and ground IR view factors assuming sky IR is isotropic and
10441 : // shadowing surfaces are opaque to IR.
10442 :
10443 : // Using/Aliasing
10444 :
10445 : Real64 Fac1WoShdg; // Intermediate calculation factor, without shading
10446 : Real64 FracIlluminated; // Fraction of surface area illuminated by a sky patch
10447 : Real64 Fac1WithShdg; // Intermediate calculation factor, with shading
10448 : Real64 SurfArea; // Surface area (m2)
10449 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WithShdgIsoSky ! Diffuse solar irradiance from isotropic
10450 : // ! sky on surface, with shading
10451 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WoShdgIsoSky ! Diffuse solar from isotropic
10452 : // ! sky on surface, without shading
10453 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WithShdgHoriz ! Diffuse solar irradiance from horizon portion
10454 : // of
10455 : // ! sky on surface, with shading
10456 : // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WoShdgHoriz ! Diffuse solar irradiance from horizon portion
10457 : // of
10458 : // ! sky on surface, without shading
10459 : // INTEGER iHour,iTS
10460 :
10461 : // Initialize Surfaces Arrays
10462 796 : bool detailedShading = state.dataSysVars->DetailedSkyDiffuseAlgorithm && state.dataSurface->ShadingTransmittanceVaries &&
10463 0 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal;
10464 796 : state.dataSolarShading->SurfSunlitArea = 0.0;
10465 796 : state.dataSolarShading->SurfWithShdgIsoSky.dimension(state.dataSurface->TotSurfaces, 0.0);
10466 796 : state.dataSolarShading->SurfWoShdgIsoSky.dimension(state.dataSurface->TotSurfaces, 0.0);
10467 796 : state.dataSolarShading->SurfWithShdgHoriz.dimension(state.dataSurface->TotSurfaces, 0.0);
10468 796 : state.dataSolarShading->SurfWoShdgHoriz.dimension(state.dataSurface->TotSurfaces, 0.0);
10469 796 : state.dataSolarShading->SurfDifShdgRatioIsoSky.allocate(state.dataSurface->TotSurfaces);
10470 796 : state.dataSolarShading->SurfDifShdgRatioHoriz.allocate(state.dataSurface->TotSurfaces);
10471 : // initialized as no shading
10472 796 : state.dataSolarShading->SurfDifShdgRatioIsoSky = 1.0;
10473 796 : state.dataSolarShading->SurfDifShdgRatioHoriz = 1.0;
10474 796 : if (detailedShading) {
10475 0 : state.dataSolarShading->SurfCurDifShdgRatioIsoSky.dimension(state.dataSurface->TotSurfaces, 1.0);
10476 0 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS.allocate(state.dataGlobal->NumOfTimeStepInHour, 24, state.dataSurface->TotSurfaces);
10477 0 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS = 1.0;
10478 0 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS.allocate(state.dataGlobal->NumOfTimeStepInHour, 24, state.dataSurface->TotSurfaces);
10479 0 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS = 1.0;
10480 : }
10481 :
10482 20128 : for (int SurfNum : state.dataSurface->AllExtSolarSurfaceList) {
10483 19332 : auto &surf = state.dataSurface->Surface(SurfNum);
10484 :
10485 : // CurrentModuleObject='Surfaces'
10486 19332 : if (detailedShading) {
10487 0 : SetupOutputVariable(state,
10488 : "Debug Surface Solar Shading Model DifShdgRatioIsoSky",
10489 : Constant::Units::None,
10490 0 : state.dataSolarShading->SurfCurDifShdgRatioIsoSky(SurfNum),
10491 : OutputProcessor::TimeStepType::Zone,
10492 : OutputProcessor::StoreType::Average,
10493 0 : surf.Name);
10494 : } else {
10495 38664 : SetupOutputVariable(state,
10496 : "Debug Surface Solar Shading Model DifShdgRatioIsoSky",
10497 : Constant::Units::None,
10498 19332 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum),
10499 : OutputProcessor::TimeStepType::Zone,
10500 : OutputProcessor::StoreType::Average,
10501 19332 : surf.Name);
10502 : }
10503 38664 : SetupOutputVariable(state,
10504 : "Debug Surface Solar Shading Model DifShdgRatioHoriz",
10505 : Constant::Units::None,
10506 19332 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum),
10507 : OutputProcessor::TimeStepType::Zone,
10508 : OutputProcessor::StoreType::Average,
10509 19332 : surf.Name);
10510 38664 : SetupOutputVariable(state,
10511 : "Debug Surface Solar Shading Model WithShdgIsoSky",
10512 : Constant::Units::None,
10513 19332 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum),
10514 : OutputProcessor::TimeStepType::Zone,
10515 : OutputProcessor::StoreType::Average,
10516 19332 : surf.Name);
10517 38664 : SetupOutputVariable(state,
10518 : "Debug Surface Solar Shading Model WoShdgIsoSky",
10519 : Constant::Units::None,
10520 19332 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum),
10521 : OutputProcessor::TimeStepType::Zone,
10522 : OutputProcessor::StoreType::Average,
10523 19332 : surf.Name);
10524 796 : }
10525 :
10526 5572 : for (int IPhi = 0; IPhi < NPhi; ++IPhi) { // Loop over patch altitude values
10527 4776 : state.dataSolarShading->SUNCOS(3) = state.dataSolarShading->sin_Phi[IPhi];
10528 :
10529 119400 : for (int ITheta = 0; ITheta < NTheta; ++ITheta) { // Loop over patch azimuth values
10530 114624 : state.dataSolarShading->SUNCOS(1) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->cos_Theta[ITheta];
10531 114624 : state.dataSolarShading->SUNCOS(2) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->sin_Theta[ITheta];
10532 :
10533 2898432 : for (int SurfNum : state.dataSurface->AllExtSolAndShadingSurfaceList) {
10534 2783808 : auto &surf = state.dataSurface->Surface(SurfNum);
10535 :
10536 : // Cosine of angle of incidence on surface of solar radiation from patch
10537 5567616 : state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS.x * surf.OutNormVec.x +
10538 2783808 : state.dataSolarShading->SUNCOS.y * surf.OutNormVec.y +
10539 2783808 : state.dataSolarShading->SUNCOS.z * surf.OutNormVec.z;
10540 114624 : }
10541 :
10542 114624 : SHADOW(state, 24, 0);
10543 :
10544 2898432 : for (int SurfNum : state.dataSurface->AllExtSolAndShadingSurfaceList) {
10545 2783808 : auto &surf = state.dataSurface->Surface(SurfNum);
10546 :
10547 2783808 : if (state.dataSolarShading->SurfSunCosTheta(SurfNum) < 0.0) continue;
10548 :
10549 1594689 : Fac1WoShdg = state.dataSolarShading->cos_Phi[IPhi] * DThetaDPhi * state.dataSolarShading->SurfSunCosTheta(SurfNum);
10550 1594689 : SurfArea = surf.NetAreaShadowCalc;
10551 1594689 : if (SurfArea > Eps) {
10552 1594689 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
10553 : } else {
10554 0 : FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / (SurfArea + Eps);
10555 : }
10556 1594689 : Fac1WithShdg = Fac1WoShdg * FracIlluminated;
10557 1594689 : state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) += Fac1WithShdg;
10558 1594689 : state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) += Fac1WoShdg;
10559 :
10560 : // Horizon region
10561 1594689 : if (IPhi == 0) {
10562 263900 : state.dataSolarShading->SurfWithShdgHoriz(SurfNum) += Fac1WithShdg;
10563 263900 : state.dataSolarShading->SurfWoShdgHoriz(SurfNum) += Fac1WoShdg;
10564 : }
10565 114624 : } // End of surface loop
10566 : } // End of Theta loop
10567 : } // End of Phi loop
10568 :
10569 20128 : for (int SurfNum : state.dataSurface->AllExtSolAndShadingSurfaceList) {
10570 :
10571 19332 : if (std::abs(state.dataSolarShading->SurfWoShdgIsoSky(SurfNum)) > Eps) {
10572 18616 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) =
10573 18616 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum));
10574 : } else {
10575 716 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) =
10576 716 : (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) + Eps);
10577 : }
10578 19332 : if (std::abs(state.dataSolarShading->SurfWoShdgHoriz(SurfNum)) > Eps) {
10579 18616 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum) =
10580 18616 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum));
10581 : } else {
10582 716 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum) =
10583 716 : (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum) + Eps);
10584 : }
10585 796 : }
10586 :
10587 : // Get IR view factors. An exterior surface can receive IR radiation from
10588 : // sky, ground or shadowing surfaces. Assume shadowing surfaces have same
10589 : // temperature as outside air (and therefore same temperature as ground),
10590 : // so that the view factor to these shadowing surfaces can be included in
10591 : // the ground view factor. Sky IR is assumed to be isotropic and shadowing
10592 : // surfaces are assumed to be opaque to IR so they totally "shade" IR from
10593 : // sky or ground.
10594 :
10595 46840 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
10596 46044 : auto &surface = state.dataSurface->Surface(SurfNum);
10597 46044 : if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm || !state.dataSurface->ShadingTransmittanceVaries ||
10598 0 : state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
10599 46044 : surface.ViewFactorSkyIR *= state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum);
10600 : } else {
10601 0 : surface.ViewFactorSkyIR *= state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(1, 1, SurfNum);
10602 : }
10603 46044 : surface.ViewFactorGroundIR = 1.0 - surface.ViewFactorSkyIR;
10604 :
10605 46044 : if (surface.SurfHasSurroundingSurfProperty) {
10606 6 : surface.ViewFactorGroundIR = 1.0 - surface.ViewFactorSkyIR - surface.ViewFactorSrdSurfs;
10607 : }
10608 : }
10609 :
10610 : // DEALLOCATE(WithShdgIsoSky)
10611 : // DEALLOCATE(WoShdgIsoSky)
10612 : // DEALLOCATE(WithShdgHoriz)
10613 : // DEALLOCATE(WoShdgHoriz)
10614 :
10615 796 : if (state.dataSysVars->DetailedSkyDiffuseAlgorithm && state.dataSurface->ShadingTransmittanceVaries &&
10616 0 : state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
10617 0 : for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
10618 0 : state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS({1, state.dataGlobal->NumOfTimeStepInHour}, {1, 24}, SurfNum) =
10619 0 : state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum);
10620 0 : state.dataSolarShading->SurfDifShdgRatioHorizHRTS({1, state.dataGlobal->NumOfTimeStepInHour}, {1, 24}, SurfNum) =
10621 0 : state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum);
10622 : }
10623 : }
10624 796 : }
10625 :
10626 916463 : void CalcWindowProfileAngles(EnergyPlusData &state)
10627 : {
10628 :
10629 : // SUBROUTINE INFORMATION:
10630 : // AUTHOR Fred Winkelmann
10631 : // DATE WRITTEN April 2002
10632 : // MODIFIED na
10633 : // RE-ENGINEERED na
10634 : // PURPOSE OF THIS SUBROUTINE:
10635 : // Called by CalcPerSolarBeam for wholly or partially sunlit exterior windows
10636 : // Calculates horizontal and vertical beam solar profile angles
10637 :
10638 : Real64 ElevSun; // Sun elevation; angle between sun and horizontal
10639 : Real64 ElevWin; // Window elevation: angle between window outward normal and horizontal
10640 : Real64 AzimWin; // Window azimuth (radians)
10641 : Real64 AzimSun; // Sun azimuth (radians)
10642 : Real64 ProfileAngHor; // Solar profile angle (radians) for horizontally oriented window elements
10643 : // such as the top and bottom of a frame.
10644 : // This is the incidence angle in a plane that is normal to the window
10645 : // and parallel to the Y-axis of the window (the axis along
10646 : // which the height of the window is measured).
10647 : Real64 ProfileAngVert; // Solar profile angle (radians) for vertically oriented elements
10648 : // such as the sides of a frame.
10649 : // This is the incidence angle in a plane that is normal to the window
10650 : // and parallel to the X-axis of the window (the axis along
10651 : // which the width of the window is measured).
10652 916463 : Vector3<Real64> WinNorm; // Unit vector normal to window
10653 916463 : Vector3<Real64> WinNormCrossBase; // Cross product of WinNorm and vector along window baseline
10654 916463 : Vector3<Real64> SunPrime; // Projection of sun vector onto plane (perpendicular to
10655 916463 : Vector3<Real64> const SolCosVec(state.dataEnvrn->SOLCOS); // Local Vector3 copy for speed (until SOLCOS mig to Vector3)
10656 : // window plane) determined by WinNorm and vector along
10657 : // baseline of window
10658 : Real64 ThWin; // Azimuth angle of WinNorm (radians)
10659 : Real64 dot1;
10660 : Real64 dot2;
10661 : Real64 dot3;
10662 :
10663 916463 : ElevSun = Constant::PiOvr2 - std::acos(SolCosVec.z);
10664 916463 : AzimSun = std::atan2(SolCosVec.x, SolCosVec.y);
10665 :
10666 916463 : Real64 const cos_ElevSun = std::cos(ElevSun);
10667 916463 : Real64 const sin_ElevSun = std::sin(ElevSun);
10668 :
10669 7241412 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
10670 12664766 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
10671 6339817 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
10672 6339817 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
10673 6339817 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
10674 13852773 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
10675 7512956 : auto &surf = state.dataSurface->Surface(SurfNum);
10676 7512956 : if (surf.ExtBoundCond != ExternalEnvironment && surf.ExtBoundCond != OtherSideCondModeledExt) continue;
10677 :
10678 7504446 : state.dataSurface->SurfWinProfileAngHor(SurfNum) = 0.0;
10679 7504446 : state.dataSurface->SurfWinProfileAngVert(SurfNum) = 0.0;
10680 7504446 : if (state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) <= 0.0) continue;
10681 :
10682 4070976 : ElevWin = Constant::PiOvr2 - surf.Tilt * Constant::DegToRadians;
10683 4070976 : AzimWin = surf.Azimuth * Constant::DegToRadians;
10684 :
10685 4070976 : ProfileAngHor = std::atan(sin_ElevSun / std::abs(cos_ElevSun * std::cos(AzimWin - AzimSun))) - ElevWin;
10686 :
10687 : // CR9280 - were having negative profile angles on west sides. commenting out previous code
10688 : // (original code) for vertical windows
10689 : // IF(ABS(ElevWin) < 0.1d0) THEN ! Near-vertical window
10690 : // ProfileAngVert = ABS(AzimWin-AzimSun)
10691 : // ELSE
10692 4070976 : WinNorm = surf.OutNormVec;
10693 4070976 : ThWin = AzimWin - Constant::PiOvr2;
10694 4070976 : Real64 const sin_Elevwin(std::sin(ElevWin));
10695 4070976 : WinNormCrossBase.x = -(sin_Elevwin * std::cos(ThWin));
10696 4070976 : WinNormCrossBase.y = sin_Elevwin * std::sin(ThWin);
10697 4070976 : WinNormCrossBase.z = std::cos(ElevWin);
10698 4070976 : SunPrime = SolCosVec - WinNormCrossBase * dot(SolCosVec, WinNormCrossBase);
10699 4070976 : dot1 = dot(WinNorm, SunPrime);
10700 4070976 : dot2 = SunPrime.magnitude();
10701 4070976 : dot3 = dot1 / dot2;
10702 4070976 : if (dot3 > 1.0) {
10703 0 : dot3 = 1.0;
10704 4070976 : } else if (dot3 < -1.0) {
10705 0 : dot3 = -1.0;
10706 : }
10707 : // ProfileAngVert =
10708 : // ABS(ACOS(DOT_PRODUCT(WinNorm,SunPrime)/SQRT(DOT_PRODUCT(SunPrime,SunPrime))))
10709 4070976 : ProfileAngVert = std::abs(std::acos(dot3));
10710 : // END IF
10711 : // Constrain to 0 to pi
10712 4070976 : if (ProfileAngVert > Constant::Pi) ProfileAngVert = Constant::TwoPi - ProfileAngVert;
10713 :
10714 4070976 : state.dataSurface->SurfWinProfileAngHor(SurfNum) = ProfileAngHor / Constant::DegToRadians;
10715 4070976 : state.dataSurface->SurfWinProfileAngVert(SurfNum) = ProfileAngVert / Constant::DegToRadians;
10716 4070976 : state.dataSurface->SurfWinTanProfileAngHor(SurfNum) = std::abs(std::tan(ProfileAngHor));
10717 4070976 : state.dataSurface->SurfWinTanProfileAngVert(SurfNum) = std::abs(std::tan(ProfileAngVert));
10718 : }
10719 6324949 : }
10720 : }
10721 916463 : }
10722 :
10723 69685 : void CalcFrameDividerShadow(EnergyPlusData &state,
10724 : int const SurfNum, // Surface number
10725 : int const FrDivNum, // Frame/divider number
10726 : int const HourNum // Hour number
10727 : )
10728 : {
10729 :
10730 : // SUBROUTINE INFORMATION:
10731 : // AUTHOR Fred Winkelmann
10732 : // DATE WRITTEN June 2000
10733 : // MODIFIED Aug 2000, FW: add effective shadowing by inside
10734 : // projections
10735 : // RE-ENGINEERED na
10736 :
10737 : // PURPOSE OF THIS SUBROUTINE:
10738 : // Called by CalcPerSolarBeam for wholly or partially sunlit exterior windows
10739 : // with a frame and/or divider. Using beam solar profile angles,
10740 : // calculates fraction of glass shaded by exterior frame and divider projections,
10741 : // The frame and divider profiles are assumed to be rectangular.
10742 : // A similar shadowing approach is used to calculate the fraction of glass area
10743 : // that produces beam solar illumination on interior frame and divider projections.
10744 : // This fraction is used in CalcWinFrameAndDividerTemps to determine the
10745 : // beam solar absorbed by inside projections. Beam solar reflected by inside projections
10746 : // is assumed to stay in the zone (as beam solar) although in actuality roughly
10747 : // half of this is reflected back onto the glass and the half that is reflected
10748 : // into the zone is diffuse.
10749 : // For multipane glazing the effect of solar absorbed by the exposed portion of
10750 : // frame or divider between the panes is not calculated. Beam solar incident on
10751 : // these portions is assumed to be transmitted into the zone unchanged.
10752 : // The shadowing of diffuse solar radiation by projections is not considered.
10753 :
10754 : Real64 ElevSun; // Sun elevation; angle between sun and horizontal
10755 : Real64 ElevWin; // Window elevation: angle between window outward normal and horizontal
10756 : Real64 AzimWin; // Window azimuth (radians)
10757 : Real64 AzimSun; // Sun azimuth (radians)
10758 : Real64 ProfileAngHor; // Solar profile angle (radians) for horizontally oriented projections
10759 : // such as the top and bottom of a frame or horizontal dividers.
10760 : // This is the incidence angle in a plane that is normal to the window
10761 : // and parallel to the Y-axis of the window (the axis along
10762 : // which the height of the window is measured).
10763 : Real64 ProfileAngVert; // Solar profile angle (radians) for vertically oriented projections
10764 : // such as the top and bottom of a frame or horizontal dividers.
10765 : // This is the incidence angle in a plane that is normal to the window
10766 : // and parallel to the X-axis of the window (the axis along
10767 : // which the width of the window is measured).
10768 : Real64 TanProfileAngHor; // Tangent of ProfileAngHor
10769 : Real64 TanProfileAngVert; // Tangent of ProfileAngVert
10770 : Real64 FrWidth; // Frame width (m)
10771 : Real64 DivWidth; // Divider width (m)
10772 : Real64 FrProjOut; // Outside frame projection (m)
10773 : Real64 DivProjOut; // Outside divider projection (m)
10774 : Real64 FrProjIn; // Inside frame projection (m)
10775 : Real64 DivProjIn; // Inside divider projection (m)
10776 : int NHorDiv; // Number of horizontal dividers
10777 : int NVertDiv; // Number of vertical dividers
10778 : Real64 GlArea; // Glazed area (m2)
10779 : Real64 Arealite; // Area of a single lite of glass (m2); glazed area, GlArea,
10780 : // if there is no divider (in which case there is only one lite).
10781 : Real64 ArealiteCol; // Area of a vertical column of lites (m2)
10782 : Real64 ArealiteRow; // Area of a horizontal row of lites (m2)
10783 : Real64 AshVDout; // Shaded area from all vertical divider outside projections (m2)
10784 : Real64 AshVDin; // Shaded area from all vertical divider inside projections (m2)
10785 : Real64 AshHDout; // Shaded area from all horizontal divider outside projections (m2)
10786 : Real64 AshHDin; // Shaded area from all horizontal divider inside projections (m2)
10787 : Real64 AshVFout; // Shaded area from outside projection of vertical sides of frame (m2)
10788 : Real64 AshVFin; // Shaded area from inside projection of vertical sides of frame (m2)
10789 : Real64 AshHFout; // Shaded area from outside projection of horizontal sides
10790 : // (top) of frame (m2)
10791 : Real64 AshHFin; // Shaded area from inside projection of horizontal sides
10792 : // (top) of frame (m2)
10793 : Real64 AshDDover; // Divider/divider shadow overlap area (m2)
10794 : Real64 AshFFover; // Frame/frame shadow overlap area (m2)
10795 : Real64 AshFVDover; // Frame/vertical divider overlap area (m2)
10796 : Real64 AshFHDover; // Frame/horizontal divider overlap area (m2)
10797 : Real64 AshFDtotOut; // Total outside projection shadow area (m2)
10798 : Real64 AshFDtotIn; // Total inside projection shadow area (m2)
10799 : Real64 FracShFDOut; // Fraction of glazing shadowed by frame and divider
10800 : // outside projections
10801 : Real64 FracShFDin; // Fraction of glazing that illuminates frame and divider
10802 : // inside projections with beam radiation
10803 :
10804 69685 : Vector3<Real64> WinNorm(3); // Window outward normal unit vector
10805 : Real64 ThWin; // Azimuth angle of WinNorm
10806 69685 : Vector3<Real64> SunPrime(3); // Projection of sun vector onto plane (perpendicular to
10807 : // window plane) determined by WinNorm and vector along
10808 : // baseline of window
10809 69685 : Vector3<Real64> WinNormCrossBase(3); // Cross product of WinNorm and vector along window baseline
10810 :
10811 108322 : if (state.dataSurface->FrameDivider(FrDivNum).FrameProjectionOut == 0.0 && state.dataSurface->FrameDivider(FrDivNum).FrameProjectionIn == 0.0 &&
10812 108322 : state.dataSurface->FrameDivider(FrDivNum).DividerProjectionOut == 0.0 && state.dataSurface->FrameDivider(FrDivNum).DividerProjectionIn == 0.0)
10813 38637 : return;
10814 :
10815 31048 : FrProjOut = state.dataSurface->FrameDivider(FrDivNum).FrameProjectionOut;
10816 31048 : FrProjIn = state.dataSurface->FrameDivider(FrDivNum).FrameProjectionIn;
10817 31048 : DivProjOut = state.dataSurface->FrameDivider(FrDivNum).DividerProjectionOut;
10818 31048 : DivProjIn = state.dataSurface->FrameDivider(FrDivNum).DividerProjectionIn;
10819 :
10820 31048 : auto &surf = state.dataSurface->Surface(SurfNum);
10821 31048 : GlArea = surf.Area;
10822 31048 : ElevWin = Constant::PiOvr2 - surf.Tilt * Constant::DegToRadians;
10823 31048 : ElevSun = Constant::PiOvr2 - std::acos(state.dataSolarShading->SUNCOS(3));
10824 31048 : AzimWin = surf.Azimuth * Constant::DegToRadians;
10825 31048 : AzimSun = std::atan2(state.dataSolarShading->SUNCOS(1), state.dataSolarShading->SUNCOS(2));
10826 :
10827 31048 : ProfileAngHor = std::atan(std::sin(ElevSun) / std::abs(std::cos(ElevSun) * std::cos(AzimWin - AzimSun))) - ElevWin;
10828 31048 : if (std::abs(ElevWin) < 0.1) { // Near-vertical window
10829 11473 : ProfileAngVert = std::abs(AzimWin - AzimSun);
10830 : } else {
10831 19575 : WinNorm = surf.OutNormVec;
10832 19575 : ThWin = AzimWin - Constant::PiOvr2;
10833 19575 : WinNormCrossBase(1) = -std::sin(ElevWin) * std::cos(ThWin);
10834 19575 : WinNormCrossBase(2) = std::sin(ElevWin) * std::sin(ThWin);
10835 19575 : WinNormCrossBase(3) = std::cos(ElevWin);
10836 19575 : SunPrime = state.dataSolarShading->SUNCOS - WinNormCrossBase * dot(state.dataSolarShading->SUNCOS, WinNormCrossBase);
10837 19575 : ProfileAngVert = std::abs(std::acos(dot(WinNorm, SunPrime) / magnitude(SunPrime)));
10838 : }
10839 : // Constrain to 0 to pi
10840 31048 : if (ProfileAngVert > Constant::Pi) ProfileAngVert = 2 * Constant::Pi - ProfileAngVert;
10841 31048 : TanProfileAngHor = std::abs(std::tan(ProfileAngHor));
10842 31048 : TanProfileAngVert = std::abs(std::tan(ProfileAngVert));
10843 :
10844 31048 : NHorDiv = state.dataSurface->FrameDivider(FrDivNum).HorDividers;
10845 31048 : NVertDiv = state.dataSurface->FrameDivider(FrDivNum).VertDividers;
10846 31048 : FrWidth = state.dataSurface->FrameDivider(FrDivNum).FrameWidth;
10847 31048 : DivWidth = state.dataSurface->FrameDivider(FrDivNum).DividerWidth;
10848 :
10849 31048 : Arealite = (surf.Height / (NHorDiv + 1.0) - DivWidth / 2.0) * (surf.Width / (NVertDiv + 1.0) - DivWidth / 2.0);
10850 31048 : if (DivProjOut > 0.0 || DivProjIn > 0.0) {
10851 10547 : ArealiteCol = (NHorDiv + 1) * Arealite;
10852 10547 : ArealiteRow = (NVertDiv + 1) * Arealite;
10853 : } else {
10854 20501 : ArealiteCol = GlArea;
10855 20501 : ArealiteRow = GlArea;
10856 : }
10857 31048 : AshVDout = 0.0;
10858 31048 : AshVDin = 0.0;
10859 31048 : AshHDout = 0.0;
10860 31048 : AshHDin = 0.0;
10861 31048 : AshVFout = 0.0;
10862 31048 : AshVFin = 0.0;
10863 31048 : AshHFout = 0.0;
10864 31048 : AshHFin = 0.0;
10865 31048 : AshDDover = 0.0;
10866 31048 : AshFFover = 0.0;
10867 31048 : AshFVDover = 0.0;
10868 31048 : AshFHDover = 0.0;
10869 :
10870 31048 : if (DivProjOut > 0.0 || DivProjIn > 0.0) {
10871 :
10872 : // Shaded area from all vertical dividers
10873 10547 : AshVDout = NVertDiv * min((surf.Height - NHorDiv * DivWidth) * DivProjOut * TanProfileAngVert, ArealiteCol);
10874 10547 : AshVDin = NVertDiv * min((surf.Height - NHorDiv * DivWidth) * DivProjIn * TanProfileAngVert, ArealiteCol);
10875 :
10876 : // Shaded area from all horizontal dividers
10877 10547 : AshHDout = NHorDiv * min((surf.Width - NVertDiv * DivWidth) * DivProjOut * TanProfileAngHor, ArealiteRow);
10878 10547 : AshHDin = NHorDiv * min((surf.Width - NVertDiv * DivWidth) * DivProjIn * TanProfileAngHor, ArealiteRow);
10879 :
10880 : // Horizontal divider/vertical divider shadow overlap
10881 10547 : AshDDover = min(DivProjOut * TanProfileAngHor * DivProjOut * TanProfileAngVert, Arealite) * NHorDiv * NVertDiv;
10882 : }
10883 :
10884 31048 : if (FrProjOut > 0.0 || FrProjIn > 0.0) {
10885 :
10886 : // Shaded area from sides of frame; to avoid complications from possible overlaps between
10887 : // shadow from side of frame and shadow from vertical divider the shaded area from side of
10888 : // frame is restricted to the area of one column of lites.
10889 31048 : AshVFout = min((surf.Height - NHorDiv * DivWidth) * FrProjOut * TanProfileAngVert, ArealiteCol);
10890 31048 : AshVFin = min((surf.Height - NHorDiv * DivWidth) * FrProjIn * TanProfileAngVert, ArealiteCol);
10891 :
10892 : // Shaded area from top or bottom of frame; to avoid complications from possible overlaps
10893 : // between shadow from top or bottom of frame and shadow from horizontal divider, the shaded
10894 : // area from the top or bottom of frame is restricted to the area of one row of lites.
10895 31048 : AshHFout = min((surf.Width - NVertDiv * DivWidth) * FrProjOut * TanProfileAngHor, ArealiteRow);
10896 31048 : AshHFin = min((surf.Width - NVertDiv * DivWidth) * FrProjIn * TanProfileAngHor, ArealiteRow);
10897 :
10898 : // Top/bottom of frame/side of frame shadow overlap
10899 31048 : AshFFover = min(FrProjOut * TanProfileAngHor * FrProjOut * TanProfileAngVert, Arealite);
10900 31048 : if (DivProjOut > 0.0) {
10901 : // Frame/vertical divider shadow overlap
10902 10547 : AshFVDover = min(FrProjOut * DivProjOut * TanProfileAngHor * TanProfileAngVert, Arealite) * NVertDiv;
10903 : // Frame/horizontal divider shadow overlap
10904 10547 : AshFHDover = min(FrProjOut * DivProjOut * TanProfileAngHor * TanProfileAngVert, Arealite) * NHorDiv;
10905 : }
10906 : }
10907 :
10908 31048 : AshFDtotOut = AshVDout + AshHDout + AshVFout + AshHFout - (AshDDover + AshFFover + AshFVDover + AshFHDover);
10909 31048 : AshFDtotIn = (AshVDin + AshHDin) * state.dataSurface->FrameDivider(FrDivNum).DividerSolAbsorp +
10910 31048 : (AshVFin + AshHFin) * state.dataSurface->FrameDivider(FrDivNum).FrameSolAbsorp;
10911 :
10912 : // Divide by the glazed area of the window
10913 31048 : FracShFDOut = AshFDtotOut / GlArea;
10914 31048 : FracShFDin = AshFDtotIn / GlArea;
10915 31048 : state.dataSurface->SurfaceWindow(SurfNum).OutProjSLFracMult[HourNum] = 1.0 - FracShFDOut;
10916 31048 : state.dataSurface->SurfaceWindow(SurfNum).InOutProjSLFracMult[HourNum] = 1.0 - (FracShFDin + FracShFDOut);
10917 146959 : }
10918 :
10919 826 : void CalcBeamSolarOnWinRevealSurface(EnergyPlusData &state)
10920 : {
10921 :
10922 : // SUBROUTINE INFORMATION:
10923 : // AUTHOR F. Winkelmann
10924 : // DATE WRITTEN April 2002
10925 : // MODIFIED:na
10926 : // RE-ENGINEERED:na
10927 :
10928 : // PURPOSE OF THIS SUBROUTINE
10929 : // Called by InitHeatGains when the sun is up.
10930 : // Calculates beam solar radiation absorbed and reflected by top, bottom,
10931 : // right and left sides of outside and inside window reveal surfaces.
10932 : // In doing this calculation, the shadowing on a reveal surface by other reveal surfaces
10933 : // is determined using the orientation of the reveal surfaces and the sun position.
10934 : // It is assumed that:
10935 : // (1) The window is an exterior window and is rectangular.
10936 : // (2) The reveal surfaces are perpendicular to the window plane.
10937 : // (3) If an exterior shade or blind is in place, there is no beam solar on
10938 : // on exterior or interior reveal surfaces.
10939 : // (3) If an interior shade or blind is in place, there is no beam solar on
10940 : // interior reveal surfaces.
10941 : // (4) The effect of window divider, if present, is ignored, including shadowing
10942 : // of divider on inside reveal surfaces.
10943 :
10944 : // In the variable names, the "subscript" 1 = outside reveal, 2 = inside reveal
10945 : // The outside reveal surfaces (top, bottom, left, right) are assumed to have the same depth
10946 : // (given by Surface%Reveal and determined from vertices of window and vertices of parent
10947 : // wall) and the same solar absorptance. The inside reveal surfaces are divided into
10948 : // two categories: (1) the bottom reveal surface, called here the "inside sill;" and
10949 : // the other reveal surfaces (left, right and top). The left, right and top inside reveal
10950 : // surfaces are assumed to have the same depth and solar absorptance.
10951 : // The depth of the outside reveal is measured from the outside surface of the glazing;
10952 : // The depth of the inside sill and the other reveal surfaces is measured from the inside
10953 : // surface of the glazing. The inside sill is
10954 : // allowed to have depth and solar absorptance values that are different from the corresponding
10955 : // values for the other inside reveal surfaces. The inside sill depth is required to be
10956 : // greater than or equal to the depth of the other inside reveal surfaces. If the inside sill
10957 : // depth is greater than zero the depth of the other inside reveal surfaces is required to
10958 : // to be greater than zero.
10959 : // The reflection of beam solar radiation from all reveal surfaces is assumed to be isotropic
10960 : // diffuse; there is no specular component. Half of the beam solar reflected from outside
10961 : // reveal surfaces is assumed to go towards the window; the other half is assumed to go back
10962 : // to the exterior environment (i.e., reflection of this outward-going component from
10963 : // other outside reveal surfaces is not considered). The half that goes towards the window
10964 : // is added to the other radiation incident on the window.
10965 : // Correspondingly, half of the beam solar reflected from inside reveal surfaces is assumed
10966 : // to go towards the window, with the other half going into the zone (this half, and the portion
10967 : // going towards the window that is reflected) is added in CalcInteriorSolarDistribution
10968 : // to the variable BTOTzone, which is the total beam solar entering the zone as beam or diffuse.
10969 : // The portion going towards the window that is not reflected is absorbed in the glazing or
10970 : // transmitted back out into the exterior environment.
10971 : // The beam solar that is absorbed by outside reveal surfaces is added to the solar absorbed
10972 : // by the outside surface of the window's parent wall; similarly, the beam solar absorbed
10973 : // by the inside reveal surfaces is added to the solar absorbed by the inside surface of the
10974 : // parent wall (and is subtracted from BTOTzone).
10975 : // The net effect of beam solar reflected from outside reveal surfaces is to INCREASE the
10976 : // the heat gain to the zone, whereas the effect of beam solar reflected from interior reveal
10977 : // surfaces is to DECREASE the heat gain to the zone since part of this reflected solar is
10978 : // transmitted back out the window.
10979 : // If the window has a frame, the absorption of reflected beam solar by the inside and outside
10980 : // surfaces of the frame is considered. The shadowing of the frame onto interior reveal
10981 : // surfaces is also considered.
10982 :
10983 : // The total glazing thickness is taken to be the sum of the thickness of the glass layers
10984 : // and between-glass gas layers. If the window has an exterior, movable, storm window glass layer
10985 : // the presence of this layer and its adjacent air gap is considered in calculating the glazing
10986 : // properties (solar transmittance, etc.). But the storm window glass is assumed to be close
10987 : // enough to the rest of the glazing that its effect on total glazing thickness and outside
10988 : // reveal depth can be ignored.
10989 :
10990 : // METHODOLOGY EMPLOYED
10991 : // na
10992 :
10993 : // REFERENCES
10994 : // na
10995 :
10996 : // USE STATEMENTS
10997 : // Using/Aliasing
10998 : using General::POLYF;
10999 :
11000 : // Locals
11001 : // SUBROUTINE ARGUMENT DEFINITIONS:na
11002 :
11003 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS
11004 :
11005 : int ConstrNum; // Construction number
11006 : int ConstrNumSh; // Shaded construction number
11007 : Real64 CosBetaBottom; // Cosine of beam solar angle of incidence on bottom reveal
11008 : Real64 CosBetaLeft; // Cosine of beam solar angle of incidence on left reveal
11009 : Real64 CosBeta; // ABS of CosBetaBottom or CosBetaLeft
11010 : Real64 d1; // Depth of outside reveal + half of glazing thickness (m)
11011 : Real64 d2; // Depth of inside sill or of inside reveal plus half of glazing thickness (m)
11012 : Real64 d2prime; // Depth of shadow cast on a reveal surface by opposite reveal (m)
11013 : Real64 d2prime2; // Depth of shadow cast by frame onto inside reveal (m)
11014 : Real64 d12; // d12 = d1 + d2 - d2prime (m)
11015 : Real64 TanAlpha; // Tangent of horizontal or vertical profile angle
11016 : Real64 TanGamma; // Tangent of vertical or horizontal profile angle
11017 : Real64 H; // Window height, width (m)
11018 : Real64 W;
11019 : Real64 L; // Window height or width (m)
11020 : Real64 A1sh; // Shadowed area of outside horizontal or vertical reveal (m2)
11021 : Real64 A2sh; // Shadowed area of inside horizontal or vertical reveal (m2)
11022 : Real64 A1ill; // Illuminated area of outside horizontal or vertical reveal (m2)
11023 : Real64 A2ill; // Illuminated area of inside horizontal or vertical reveal (m2)
11024 : Real64 SolTransGlass; // Beam solar transmittance of glazing
11025 : Real64 SolTransGlassSh; // For switchable glazing, beam solar trans in switched state
11026 : Real64 DiffReflGlass; // Diffuse back reflectance of glazing
11027 : Real64 DiffReflGlassSh; // For switchable glazing, diffuse back refl in switched state
11028 : int HorVertReveal; // Index: 1 = horizontal reveal, 2 = vertical reveal
11029 : Real64 OutsReveal; // Depth of outside reveal (from outside glazing plane to outside wall plane) (m)
11030 : Real64 InsReveal; // Depth of inside reveal (from inside glazing plane to inside wall plane (m)
11031 : Real64 InsSillDepth; // Depth of inside sill, measured from innermost face of glazing (m)
11032 : Real64 GlazingThickness; // Thickness of glazing, measured from innermost face to outermost face (m)
11033 : Real64 InsideRevealSolAbs; // Solar absorptance of inside reveal or inside sill
11034 : Real64 BmSolRefldOutsReveal; // Multiplied by beam solar gives beam solar reflected by horiz or vertical
11035 : // outside reveal surface (m2)
11036 : Real64 BmSolRefldInsReveal; // Multiplied by beam solar gives beam solar reflected by horiz or vertical
11037 : // inside reveal surface (m2)
11038 : WinShadingType ShadeFlag; // Shading flag
11039 : int FrameDivNum; // Frame/Divider number
11040 : Real64 FrameWidth; // Frame width (m)
11041 : Real64 P1; // Frame outside/inside projection plus half of glazing thickness (m)
11042 : Real64 P2;
11043 : Real64 f1; // f1=d1-P1, f2=d2-P2 (m)
11044 : Real64 f2;
11045 : Real64 L1; // Average distance of outside/inside illuminated area to frame;
11046 : Real64 L2;
11047 : // used in calculating view factor to frame (m)
11048 : Real64 FracToGlassOuts; // View factor from outside horizontal or vertical reveal to glass
11049 : Real64 FracToGlassIns; // View factor from inside horizontal or vertical reveal to glass
11050 : Real64 TanProfileAngVert; // Tangent of vertical profile angle (the profile angle appropriate for
11051 : // vertical reveal surfaces.
11052 : Real64 TanProfileAngHor; // Tangent of horizontal profile angle (the profile angle appropriate for
11053 : // horizontal reveal surfaces.
11054 :
11055 : Real64 tmp_SunlitFracWithoutReveal; // Temporary variable
11056 :
11057 56168 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
11058 110684 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
11059 55342 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
11060 55342 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
11061 55342 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
11062 140420 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
11063 : // Added TH for initialization. CR 7596 inside reveal causing high cooling loads
11064 : // for outside reveals
11065 85078 : state.dataSurface->SurfWinBmSolAbsdOutsReveal(SurfNum) = 0.0;
11066 85078 : state.dataSurface->SurfWinBmSolRefldOutsRevealReport(SurfNum) = 0.0;
11067 85078 : state.dataSurface->SurfWinBmSolRefldOutsRevealRepEnergy(SurfNum) = 0.0;
11068 85078 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) = 0.0;
11069 85078 : state.dataSurface->SurfWinOutsRevealDiffOntoFrame(SurfNum) = 0.0;
11070 : // for inside reveals
11071 85078 : state.dataSurface->SurfWinBmSolAbsdInsReveal(SurfNum) = 0.0;
11072 85078 : state.dataSurface->SurfWinBmSolAbsdInsRevealReport(SurfNum) = 0.0;
11073 85078 : state.dataSurface->SurfWinBmSolRefldInsReveal(SurfNum) = 0.0;
11074 85078 : state.dataSurface->SurfWinBmSolRefldInsRevealReport(SurfNum) = 0.0;
11075 85078 : state.dataSurface->SurfWinBmSolRefldInsRevealRepEnergy(SurfNum) = 0.0;
11076 85078 : state.dataSurface->SurfWinInsRevealDiffOntoGlazing(SurfNum) = 0.0;
11077 85078 : state.dataSurface->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) = 0.0;
11078 85078 : state.dataSurface->SurfWinInsRevealDiffOntoFrame(SurfNum) = 0.0;
11079 85078 : state.dataSurface->SurfWinInsRevealDiffOntoFrameReport(SurfNum) = 0.0;
11080 85078 : state.dataSurface->SurfWinInsRevealDiffIntoZone(SurfNum) = 0.0;
11081 85078 : state.dataSurface->SurfWinInsRevealDiffIntoZoneReport(SurfNum) = 0.0;
11082 :
11083 85078 : auto &surf = state.dataSurface->Surface(SurfNum);
11084 85078 : if ((surf.ExtBoundCond != ExternalEnvironment && surf.ExtBoundCond != OtherSideCondModeledExt)) continue;
11085 161070 : if (surf.Reveal == 0.0 && state.dataSurface->SurfWinInsideReveal(SurfNum) == 0.0 &&
11086 75992 : state.dataSurface->SurfWinInsideSillDepth(SurfNum) == 0.0)
11087 75992 : continue;
11088 9086 : if (surf.Sides != 4) continue;
11089 9086 : if (state.dataSurface->SurfWinInsideSillDepth(SurfNum) < state.dataSurface->SurfWinInsideReveal(SurfNum)) continue;
11090 :
11091 9086 : ShadeFlag = state.dataSurface->SurfWinShadingFlag(SurfNum);
11092 9086 : if ((ShadeFlag == WinShadingType::ExtShade) || (ShadeFlag == WinShadingType::ExtBlind)) continue;
11093 :
11094 9086 : if (state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) <= 0.0) continue;
11095 :
11096 4774 : tmp_SunlitFracWithoutReveal =
11097 4774 : state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
11098 :
11099 : // Calculate cosine of angle of incidence of beam solar on reveal surfaces,
11100 : // assumed to be perpendicular to window plane
11101 :
11102 4774 : CosBetaBottom = -state.dataEnvrn->SOLCOS(1) * surf.SinAzim * surf.CosTilt - state.dataEnvrn->SOLCOS(2) * surf.CosAzim * surf.CosTilt +
11103 4774 : state.dataEnvrn->SOLCOS(3) * surf.SinTilt;
11104 :
11105 4774 : CosBetaLeft = -state.dataEnvrn->SOLCOS(1) * surf.CosAzim - state.dataEnvrn->SOLCOS(2) * surf.SinAzim;
11106 :
11107 : // Note: CosBetaTop = -CosBetaBottom, CosBetaRight = -CosBetaLeft
11108 :
11109 4774 : OutsReveal = surf.Reveal;
11110 4774 : InsReveal = state.dataSurface->SurfWinInsideReveal(SurfNum);
11111 4774 : InsideRevealSolAbs = 0.0;
11112 4774 : GlazingThickness = state.dataSurface->SurfWinTotGlazingThickness(SurfNum);
11113 4774 : H = surf.Height;
11114 4774 : W = surf.Width;
11115 4774 : d1 = OutsReveal + 0.5 * GlazingThickness;
11116 4774 : ConstrNum = state.dataSurface->SurfActiveConstruction(SurfNum);
11117 4774 : ConstrNumSh = state.dataSurface->SurfWinActiveShadedConstruction(SurfNum);
11118 4774 : auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
11119 :
11120 4774 : SolTransGlass = POLYF(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum),
11121 4774 : thisConstruct.TransSolBeamCoef);
11122 4774 : TanProfileAngVert = state.dataSurface->SurfWinTanProfileAngVert(SurfNum);
11123 4774 : TanProfileAngHor = state.dataSurface->SurfWinTanProfileAngHor(SurfNum);
11124 4774 : FrameDivNum = surf.FrameDivider;
11125 4774 : FrameWidth = 0.0;
11126 4774 : if (FrameDivNum != 0) {
11127 1470 : FrameWidth = state.dataSurface->FrameDivider(FrameDivNum).FrameWidth;
11128 1470 : if (FrameWidth > 0.0) {
11129 1470 : P1 = state.dataSurface->FrameDivider(FrameDivNum).FrameProjectionOut + 0.5 * GlazingThickness;
11130 1470 : P2 = state.dataSurface->FrameDivider(FrameDivNum).FrameProjectionIn + 0.5 * GlazingThickness;
11131 1470 : if (OutsReveal + 0.5 * GlazingThickness <= P1) d1 = P1 + 0.001;
11132 : }
11133 : }
11134 : // Loop over vertical and horizontal reveal surfaces
11135 14322 : for (HorVertReveal = 1; HorVertReveal <= 2; ++HorVertReveal) {
11136 :
11137 9548 : FracToGlassOuts = 0.5;
11138 9548 : FracToGlassIns = 0.5;
11139 9548 : BmSolRefldOutsReveal = 0.0;
11140 9548 : BmSolRefldInsReveal = 0.0;
11141 9548 : A1ill = 0.0;
11142 9548 : A2ill = 0.0;
11143 :
11144 : // Added TH. 5/27/2009
11145 9548 : A1sh = 0.0;
11146 9548 : A2sh = 0.0;
11147 :
11148 9548 : if (HorVertReveal == 1) { // Vertical reveal
11149 4774 : TanAlpha = TanProfileAngHor;
11150 4774 : TanGamma = TanProfileAngVert;
11151 4774 : CosBeta = std::abs(CosBetaLeft);
11152 4774 : L = surf.Height;
11153 4774 : d2 = InsReveal + 0.5 * GlazingThickness;
11154 4774 : d2prime = d1 + d2 - W / TanGamma;
11155 4774 : InsideRevealSolAbs = state.dataSurface->SurfWinInsideRevealSolAbs(SurfNum);
11156 : } else { // Horizontal reveal
11157 4774 : InsSillDepth = state.dataSurface->SurfWinInsideSillDepth(SurfNum);
11158 4774 : TanAlpha = TanProfileAngVert;
11159 4774 : TanGamma = TanProfileAngHor;
11160 4774 : CosBeta = std::abs(CosBetaBottom);
11161 4774 : L = surf.Width;
11162 4774 : if (CosBetaBottom > 0.0) { // Bottom reveal surfaces may be illuminated
11163 4774 : d2 = InsSillDepth + 0.5 * GlazingThickness;
11164 4774 : InsideRevealSolAbs = state.dataSurface->SurfWinInsideSillSolAbs(SurfNum);
11165 : } else { // Top reveal surfaces may be illuminated
11166 0 : d2 = InsReveal + 0.5 * GlazingThickness;
11167 0 : InsideRevealSolAbs = state.dataSurface->SurfWinInsideRevealSolAbs(SurfNum);
11168 : }
11169 4774 : d2prime = d1 + d2 - H / TanGamma;
11170 : }
11171 9548 : if (d2prime < 0.0) d2prime = 0.0; // No shadow from opposing reveal
11172 9548 : d12 = d1 + d2 - d2prime;
11173 :
11174 9548 : if (FrameWidth <= 0.001) {
11175 : // Window without frame
11176 :
11177 : // Find inside and outside shadowed area of vertical or horizontal reveal surfaces
11178 : // that can be illuminated by beam solar; shadowing is by other reveal surfaces.
11179 :
11180 6608 : if (d2prime <= d2) {
11181 6608 : if (d12 * TanAlpha <= L) {
11182 6608 : A1sh = 0.5 * TanAlpha * pow_2(d1);
11183 6608 : A2sh = d2prime * L + 0.5 * TanAlpha * pow_2(d12) - A1sh;
11184 : } else { // d12*TanAlpha > L
11185 0 : if (d1 * TanAlpha <= L) {
11186 0 : A1sh = 0.5 * TanAlpha * pow_2(d1);
11187 0 : A2sh = d2 * L - 0.5 * TanAlpha * pow_2(L / TanAlpha - d1);
11188 : } else { // d1*TanAlpha > L
11189 0 : A1sh = d1 * L - (0.5 / TanAlpha) * pow_2(L);
11190 0 : A2sh = d2 * L;
11191 : }
11192 : }
11193 : } else { // d2prime > d2
11194 0 : A2sh = d2 * L;
11195 0 : if (d2prime < d1 + d2) {
11196 0 : if (d12 * TanAlpha <= L) {
11197 0 : A1sh = L * (d2prime - d2) + 0.5 * TanAlpha * pow_2(d12);
11198 : } else { // d12*TanAlpha > L
11199 0 : A1sh = d1 * L - 0.5 * pow_2(L) / TanAlpha;
11200 : }
11201 : } else { // d2prime >= d1+d2
11202 0 : A1sh = d1 * L;
11203 : }
11204 : }
11205 :
11206 : // Added TH. 5/27/2009
11207 6608 : if (A1sh < 0.0) A1sh = 0.0;
11208 6608 : if (A2sh < 0.0) A2sh = 0.0;
11209 :
11210 6608 : if (OutsReveal >= 0.001) A1ill = d1 * L - A1sh; // A1ill = 0.0 if OutsReveal < 0.001
11211 6608 : if (InsReveal >= 0.001) A2ill = d2 * L - A2sh; // A2ill = 0.0 if InsReveal < 0.001
11212 :
11213 : } else { // Window with frame; take into account shadowing
11214 : // of inside reveal surfaces by frame
11215 2940 : f1 = d1 - P1;
11216 2940 : f2 = d2 - P2;
11217 2940 : d2prime2 = FrameWidth / TanGamma;
11218 2940 : if (HorVertReveal == 1) { // Vertical reveal
11219 1470 : if (InsReveal + 0.5 * GlazingThickness <= P2) d2 = P2 + 0.001;
11220 : } else { // Horizontal
11221 1470 : if (CosBetaBottom > 0.0) { // Bottom reveal surfaces may be illuminated
11222 1470 : if (InsSillDepth + 0.5 * GlazingThickness <= P2) d2 = P2 + 0.001;
11223 : } else { // Top reveal surfaces may be illuminated
11224 0 : if (InsReveal + 0.5 * GlazingThickness <= P2) d2 = P2 + 0.001;
11225 : }
11226 : }
11227 :
11228 2940 : if (d2prime <= f2) { // Shadow from opposing reveal does not go beyond inside surface of frame
11229 :
11230 2884 : if (d12 * TanAlpha <= L) {
11231 2520 : A1sh = 0.5 * TanAlpha * pow_2(f1);
11232 2520 : L1 = f1 * (f1 * TanAlpha / (6.0 * L) + 0.5);
11233 2520 : if (d2 - (d2prime + d2prime2 + P2) >= 0.0) {
11234 2170 : A2sh = (d2prime + d2prime2) * L + 0.5 * TanAlpha * (pow_2(d1 + d2 - d2prime) - pow_2(d1 + P2 + d2prime2));
11235 2170 : L2 = d2prime2 + 0.5 * (d2 - (d2prime + d2prime2 + P2));
11236 : } else { // d2-(d2prime+d2prime2+P2) < 0. ! Inside reveal is fully shadowed by
11237 : // frame and/or opposing reveal
11238 350 : A2sh = f2 * L;
11239 350 : L2 = f2;
11240 : }
11241 : } else { // d12*TanAlpha >= L
11242 364 : if ((d1 + P2) * TanAlpha <= L) {
11243 336 : A1sh = 0.5 * TanAlpha * pow_2(f1);
11244 336 : L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
11245 336 : if ((d1 + P2 + d2prime2) * TanAlpha >= L) {
11246 14 : A2sh = f2 * L;
11247 14 : L2 = f2;
11248 : } else { // (d1+P2+d2prime2)*TanAlpha < L
11249 322 : A2sh = f2 * L - 0.5 * pow_2(L - (d1 + P2) * TanAlpha) / TanAlpha +
11250 322 : d2prime2 * (L - (d1 + P2 + d2prime2 / 2.0) * TanAlpha);
11251 322 : L2 = d2prime2 + (L / TanAlpha - (d1 + P2 + d2prime2)) / 3.0;
11252 : }
11253 : } else { // (d1+P2)*TanAlpha > L
11254 28 : L2 = f2;
11255 28 : A2sh = f2 * L;
11256 28 : if (f1 * TanAlpha <= L) {
11257 28 : A1sh = 0.5 * TanAlpha * pow_2(f1);
11258 28 : L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
11259 : } else { // f1*TanAlpha > L
11260 0 : A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
11261 0 : L1 = f1 - (L / TanAlpha) / 3.0;
11262 : }
11263 : }
11264 : }
11265 :
11266 : } else { // d2prime > f2 ! Shadow from opposing reveal goes beyond inside of frame
11267 :
11268 56 : A2sh = f2 * L;
11269 56 : L2 = f2;
11270 56 : if (d2prime >= d1 + d2) {
11271 0 : A1sh = 0.0;
11272 0 : L1 = f1;
11273 : } else { // d2prime < d1+d2
11274 56 : if (d2prime <= d2 + P1) {
11275 56 : if (f1 * TanAlpha <= L) {
11276 56 : A1sh = 0.5 * TanAlpha * pow_2(f1);
11277 56 : L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
11278 : } else { // f1*TanAlpha > L
11279 0 : A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
11280 0 : L1 = f1 - (L / TanAlpha) / 3.0;
11281 : }
11282 : } else { // d2prime > d2+P1
11283 0 : if (d12 * TanAlpha <= L) {
11284 0 : A1sh = L * (d2prime - (d2 + P1)) + 0.5 * TanAlpha * pow_2(d12);
11285 0 : L1 = (L * (f1 - d12 / 2.0) - d12 * TanAlpha * (f1 / 2 - d12 / 3.0)) / (L - d12 * TanAlpha / 2.0);
11286 : } else { // d12*TanAlpha > L
11287 0 : A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
11288 0 : L1 = f1 - (L / TanAlpha) / 3.0;
11289 : }
11290 : }
11291 : }
11292 : }
11293 :
11294 : // Added TH. 5/27/2009
11295 2940 : if (A1sh < 0.0) A1sh = 0.0;
11296 2940 : if (A2sh < 0.0) A2sh = 0.0;
11297 :
11298 2940 : if (OutsReveal >= P1 + 0.5 * GlazingThickness + 0.001) A1ill = L * f1 - A1sh;
11299 2940 : if (InsReveal >= P2 + 0.5 * GlazingThickness + 0.001) A2ill = L * f2 - A2sh;
11300 2940 : if (L1 == 0.0) {
11301 0 : FracToGlassOuts = 0.0;
11302 : } else {
11303 2940 : FracToGlassOuts = 0.5 * (1.0 - std::atan(FrameWidth / L1) / Constant::PiOvr2);
11304 : }
11305 2940 : if (L2 == 0.0) {
11306 0 : FracToGlassIns = 0.0;
11307 : } else {
11308 2940 : FracToGlassIns = 0.5 * (1.0 - std::atan(FrameWidth / L2) / Constant::PiOvr2);
11309 : }
11310 : } // End of check if window has frame
11311 :
11312 : // Added TH. 5/27/2009
11313 9548 : if (A1ill < 0.0) A1ill = 0.0;
11314 9548 : if (A2ill < 0.0) A2ill = 0.0;
11315 :
11316 : // Quantities related to outside reveal
11317 9548 : if (A1ill > Constant::OneMillionth) {
11318 :
11319 0 : state.dataSurface->SurfWinBmSolAbsdOutsReveal(SurfNum) +=
11320 0 : A1ill * state.dataSurface->SurfWinOutsideRevealSolAbs(SurfNum) * CosBeta * tmp_SunlitFracWithoutReveal;
11321 :
11322 0 : BmSolRefldOutsReveal =
11323 0 : A1ill * (1.0 - state.dataSurface->SurfWinOutsideRevealSolAbs(SurfNum)) * CosBeta * tmp_SunlitFracWithoutReveal;
11324 :
11325 0 : state.dataSurface->SurfWinBmSolRefldOutsRevealReport(SurfNum) += state.dataEnvrn->BeamSolarRad * BmSolRefldOutsReveal;
11326 0 : state.dataSurface->SurfWinBmSolRefldOutsRevealRepEnergy(SurfNum) =
11327 0 : state.dataSurface->SurfWinBmSolRefldOutsRevealReport(SurfNum) * state.dataGlobal->TimeStepZoneSec;
11328 :
11329 : // Reflected solar from outside horizontal and vertical reveal incident on glazing
11330 0 : state.dataSurface->SurfWinOutsRevealDiffOntoGlazing(SurfNum) += FracToGlassOuts * BmSolRefldOutsReveal / surf.Area;
11331 :
11332 0 : if (FrameWidth > 0.0) {
11333 : // Reflected solar from outside horizontal and vertical reveal incident on frame
11334 0 : state.dataSurface->SurfWinOutsRevealDiffOntoFrame(SurfNum) +=
11335 0 : (0.5 - FracToGlassOuts) * BmSolRefldOutsReveal / state.dataSurface->SurfWinFrameArea(SurfNum);
11336 : }
11337 :
11338 : } // End of check if A1ill > 0.0 (actually 10^-6)
11339 :
11340 : // Quantities related to inside reveal; inside reveal reflection/absorption is assumed
11341 : // to occur only if an interior shade or blind is not in place.
11342 :
11343 9548 : if (NOT_SHADED(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
11344 :
11345 8568 : if (A2ill > Constant::OneMillionth) {
11346 :
11347 1652 : DiffReflGlass = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
11348 1652 : if (ShadeFlag == WinShadingType::SwitchableGlazing) {
11349 0 : auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
11350 : SolTransGlassSh =
11351 0 : POLYF(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum),
11352 0 : thisConstructSh.TransSolBeamCoef);
11353 0 : SolTransGlass = Window::InterpSw(state.dataSurface->SurfWinSwitchingFactor(SurfNum), SolTransGlass, SolTransGlassSh);
11354 0 : DiffReflGlassSh = thisConstructSh.ReflectSolDiffBack;
11355 0 : DiffReflGlass = Window::InterpSw(state.dataSurface->SurfWinSwitchingFactor(SurfNum), DiffReflGlass, DiffReflGlassSh);
11356 : }
11357 :
11358 : // Calc beam solar sbsorbed (m2)
11359 1652 : state.dataSurface->SurfWinBmSolAbsdInsReveal(SurfNum) +=
11360 1652 : A2ill * SolTransGlass * InsideRevealSolAbs * CosBeta * tmp_SunlitFracWithoutReveal;
11361 :
11362 : // Added TH 5/26/2009 for reporting purpose - Beam solar absorbed by the inside reveal
11363 : // (W)
11364 1652 : state.dataSurface->SurfWinBmSolAbsdInsRevealReport(SurfNum) +=
11365 1652 : state.dataEnvrn->BeamSolarRad * A2ill * SolTransGlass * InsideRevealSolAbs * CosBeta * tmp_SunlitFracWithoutReveal;
11366 :
11367 : // in m2 = Area * solar transmitted fraction * inside reveal reflection fraction
11368 1652 : BmSolRefldInsReveal = A2ill * SolTransGlass * (1.0 - InsideRevealSolAbs) * CosBeta * tmp_SunlitFracWithoutReveal;
11369 :
11370 1652 : state.dataSurface->SurfWinBmSolRefldInsReveal(SurfNum) += BmSolRefldInsReveal;
11371 :
11372 1652 : state.dataSurface->SurfWinBmSolRefldInsRevealReport(SurfNum) +=
11373 1652 : state.dataEnvrn->BeamSolarRad * BmSolRefldInsReveal; // W, BeamSolarRad in W/m2
11374 1652 : state.dataSurface->SurfWinBmSolRefldInsRevealRepEnergy(SurfNum) =
11375 1652 : state.dataSurface->SurfWinBmSolRefldInsRevealReport(SurfNum) * state.dataGlobal->TimeStepZoneSec;
11376 :
11377 : // Reflected solar from inside horizontal and vertical reveal incident on glazing
11378 1652 : state.dataSurface->SurfWinInsRevealDiffOntoGlazing(SurfNum) += FracToGlassIns * BmSolRefldInsReveal / surf.Area;
11379 :
11380 : // Added TH 5/26/2009 for reporting purpose - diffuse on window glass from inside
11381 : // reveal (W)
11382 1652 : state.dataSurface->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) +=
11383 1652 : state.dataEnvrn->BeamSolarRad * FracToGlassIns * BmSolRefldInsReveal;
11384 :
11385 : // Reflected solar from inside horizontal and vertical reveal incident on frame
11386 1652 : if (FrameWidth > 0.0) {
11387 1652 : state.dataSurface->SurfWinInsRevealDiffOntoFrame(SurfNum) +=
11388 1652 : (0.5 - FracToGlassIns) * BmSolRefldInsReveal / state.dataSurface->SurfWinFrameArea(SurfNum);
11389 :
11390 : // Added TH 5/26/2009 for reporting purpose - diffuse on window frame from inside
11391 : // reveal (W)
11392 1652 : state.dataSurface->SurfWinInsRevealDiffOntoFrameReport(SurfNum) +=
11393 1652 : state.dataEnvrn->BeamSolarRad * (0.5 - FracToGlassIns) * BmSolRefldInsReveal;
11394 : }
11395 :
11396 : // Reflected solar from inside reveal going directly into zone and reflected from
11397 : // glass. Assumes half of solar reflected from inside reveal goes as diffuse radiation
11398 : // into the zone and half goes as diffuse radiation towards window.
11399 1652 : state.dataSurface->SurfWinInsRevealDiffIntoZone(SurfNum) += BmSolRefldInsReveal * (0.5 + DiffReflGlass * FracToGlassIns);
11400 :
11401 : // Added TH 5/26/2009 for reporting purpose - diffuse into zone from inside reveal (W)
11402 1652 : state.dataSurface->SurfWinInsRevealDiffIntoZoneReport(SurfNum) +=
11403 1652 : state.dataEnvrn->BeamSolarRad * BmSolRefldInsReveal * (0.5 + DiffReflGlass * FracToGlassIns);
11404 :
11405 : } // End of check if A2ill > 0.0 (actually 10^-6)
11406 :
11407 : } // End of check if interior shade or blind is in place
11408 :
11409 : } // End of loop over vertical and horizontal reveal
11410 :
11411 : } // End of surface loop
11412 55342 : }
11413 : }
11414 826 : }
11415 :
11416 2804482 : void ReportSurfaceShading(EnergyPlusData &state)
11417 : {
11418 :
11419 : // SUBROUTINE INFORMATION:
11420 : // AUTHOR Linda Lawrie
11421 : // DATE WRITTEN April 2000
11422 : // MODIFIED na
11423 : // RE-ENGINEERED na
11424 :
11425 : // PURPOSE OF THIS SUBROUTINE:
11426 : // This subroutine uses the internal variables used in the Shading
11427 : // calculations and prepares them for reporting (at timestep level).
11428 :
11429 : // METHODOLOGY EMPLOYED:
11430 : // Because all of the calculations are done on a "daily" basis in this
11431 : // module, it is difficult to formulate the values that might be useful
11432 : // for reporting. SunlitFrac was the first of these two arrays to be
11433 : // made into "two dimensions". It is not clear that both have to be
11434 : // two dimensions.
11435 :
11436 : // REFERENCES:
11437 : // na
11438 :
11439 : // Using/Aliasing
11440 : using namespace OutputReportPredefined;
11441 :
11442 : // Locals
11443 : // SUBROUTINE ARGUMENT DEFINITIONS:
11444 : // na
11445 :
11446 : // SUBROUTINE PARAMETER DEFINITIONS:
11447 : // na
11448 :
11449 : // INTERFACE BLOCK SPECIFICATIONS
11450 : // na
11451 :
11452 : // DERIVED TYPE DEFINITIONS
11453 : // na
11454 :
11455 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
11456 : int SurfNum; // Loop Counter
11457 : int RepCol; // the column of the predefined report
11458 :
11459 179402542 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
11460 176598060 : auto &surf = state.dataSurface->Surface(SurfNum);
11461 :
11462 176598060 : state.dataSurface->SurfSunlitFrac(SurfNum) =
11463 176598060 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
11464 176598060 : state.dataSurface->SurfSunlitArea(SurfNum) =
11465 176598060 : state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) * surf.Area;
11466 : }
11467 : // added for predefined reporting
11468 2804482 : RepCol = 0;
11469 2804482 : if (state.dataEnvrn->Month == 3 && state.dataEnvrn->DayOfMonth == 21) {
11470 2361 : if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
11471 20 : RepCol = state.dataOutRptPredefined->pdchSlfMar21_9;
11472 2341 : } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
11473 20 : RepCol = state.dataOutRptPredefined->pdchSlfMar21_12;
11474 2321 : } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
11475 20 : RepCol = state.dataOutRptPredefined->pdchSlfMar21_15;
11476 : }
11477 2802121 : } else if (state.dataEnvrn->Month == 6 && state.dataEnvrn->DayOfMonth == 21) {
11478 2361 : if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
11479 20 : RepCol = state.dataOutRptPredefined->pdchSlfJun21_9;
11480 2341 : } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
11481 20 : RepCol = state.dataOutRptPredefined->pdchSlfJun21_12;
11482 2321 : } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
11483 20 : RepCol = state.dataOutRptPredefined->pdchSlfJun21_15;
11484 : }
11485 2799760 : } else if (state.dataEnvrn->Month == 12 && state.dataEnvrn->DayOfMonth == 21) {
11486 192654 : if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
11487 1393 : RepCol = state.dataOutRptPredefined->pdchSlfDec21_9;
11488 191261 : } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
11489 1393 : RepCol = state.dataOutRptPredefined->pdchSlfDec21_12;
11490 189868 : } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
11491 1393 : RepCol = state.dataOutRptPredefined->pdchSlfDec21_15;
11492 : }
11493 : }
11494 2804482 : if (RepCol != 0) {
11495 431136 : for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
11496 426837 : auto &surf = state.dataSurface->Surface(SurfNum);
11497 426837 : if (surf.Class == SurfaceClass::Window) {
11498 64116 : PreDefTableEntry(state, RepCol, surf.Name, state.dataSurface->SurfSunlitFrac(SurfNum));
11499 : }
11500 : }
11501 : }
11502 2804482 : }
11503 :
11504 796 : void ReportSurfaceErrors(EnergyPlusData &state)
11505 : {
11506 :
11507 : // SUBROUTINE INFORMATION:
11508 : // AUTHOR Linda Lawrie
11509 : // DATE WRITTEN November 2004
11510 : // MODIFIED na
11511 : // RE-ENGINEERED na
11512 :
11513 : // PURPOSE OF THIS SUBROUTINE:
11514 : // This subroutine reports some recurring type errors that can get mixed up with more important
11515 : // errors in the error file.
11516 :
11517 : using namespace DataErrorTracking; // for error tracking
11518 :
11519 796 : static Array1D_string const MSG(4, {"misses", "", "within", "overlaps"});
11520 :
11521 : int Loop1;
11522 : int Loop2;
11523 : int Count;
11524 : int TotCount;
11525 796 : Array1D_bool SurfErrorReported;
11526 796 : Array1D_bool SurfErrorReported2;
11527 :
11528 796 : if (state.dataSolarShading->NumTooManyFigures + state.dataSolarShading->NumTooManyVertices + state.dataSolarShading->NumBaseSubSurround > 0) {
11529 0 : ShowMessage(state, "");
11530 0 : ShowMessage(state, "===== Recurring Surface Error Summary =====");
11531 0 : ShowMessage(state, "The following surface error messages occurred.");
11532 0 : ShowMessage(state, "");
11533 :
11534 0 : if (state.dataSolarShading->NumBaseSubSurround > 0) {
11535 0 : ShowMessage(state, "Base Surface does not surround subsurface errors occurring...");
11536 0 : ShowMessage(state,
11537 : "Check that the GlobalGeometryRules object is expressing the proper starting corner and "
11538 : "direction [CounterClockwise/Clockwise]");
11539 0 : ShowMessage(state, "");
11540 : }
11541 :
11542 0 : SurfErrorReported.dimension(state.dataSurface->TotSurfaces, false);
11543 0 : TotCount = 0;
11544 0 : for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumBaseSubSurround; ++Loop1) {
11545 0 : Count = 0;
11546 0 : if (SurfErrorReported(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1)) continue;
11547 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumBaseSubSurround; ++Loop2) {
11548 0 : if (state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1 ==
11549 0 : state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex1 &&
11550 0 : state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex == state.dataSolarShading->TrackBaseSubSurround(Loop2).MiscIndex) {
11551 0 : ++Count;
11552 : }
11553 : }
11554 0 : TotCount += Count;
11555 0 : state.dataErrTracking->TotalWarningErrors += Count - 1;
11556 0 : ShowWarningError(state,
11557 0 : format("Base surface does not surround subsurface (CHKSBS), Overlap Status={}",
11558 0 : state.dataSolarShading->cOverLapStatus(state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex)));
11559 0 : ShowContinueError(state, format(" The base surround errors occurred {} times.", Count));
11560 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumBaseSubSurround; ++Loop2) {
11561 0 : if (state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1 ==
11562 0 : state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex1 &&
11563 0 : state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex == state.dataSolarShading->TrackBaseSubSurround(Loop2).MiscIndex) {
11564 0 : ShowContinueError(state,
11565 0 : format("Surface \"{}\" {} SubSurface \"{}\"",
11566 0 : state.dataSurface->Surface(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1).Name,
11567 0 : MSG(state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex),
11568 0 : state.dataSurface->Surface(state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex2).Name));
11569 : }
11570 : }
11571 0 : SurfErrorReported(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1) = true;
11572 : }
11573 0 : if (TotCount > 0) {
11574 0 : ShowMessage(state, "");
11575 0 : ShowContinueError(state, format(" The base surround errors occurred {} times (total).", TotCount));
11576 0 : ShowMessage(state, "");
11577 : }
11578 :
11579 0 : SurfErrorReported2.allocate(state.dataSurface->TotSurfaces);
11580 0 : SurfErrorReported = false;
11581 0 : TotCount = 0;
11582 0 : if (state.dataSolarShading->NumTooManyVertices > 0) {
11583 0 : ShowMessage(state, format("Too many vertices [>={}] in shadow overlap errors occurring...", state.dataSolarShading->MaxHCV));
11584 0 : ShowMessage(state,
11585 : "These occur throughout the year and may occur several times for the same surfaces. You "
11586 : "may be able to reduce them by "
11587 : "adding Output:Diagnostics,DoNotMirrorDetachedShading;");
11588 : }
11589 0 : for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumTooManyVertices; ++Loop1) {
11590 0 : Count = 0;
11591 0 : SurfErrorReported2 = false;
11592 0 : if (SurfErrorReported(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1)) continue;
11593 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyVertices; ++Loop2) {
11594 0 : if (state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1 ==
11595 0 : state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex1) {
11596 0 : ++Count;
11597 : }
11598 : }
11599 0 : TotCount += Count;
11600 0 : state.dataErrTracking->TotalWarningErrors += Count - 1;
11601 0 : ShowMessage(state, "");
11602 0 : ShowWarningError(state, format("Too many vertices [>={}] in a shadow overlap", state.dataSolarShading->MaxHCV));
11603 0 : ShowContinueError(
11604 : state,
11605 0 : format("Overlapping figure={}, Surface Class=[{}]",
11606 0 : state.dataSurface->Surface(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1).Name,
11607 0 : cSurfaceClass(state.dataSurface->Surface(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1).Class)));
11608 0 : ShowContinueError(state, format(" This error occurred {} times.", Count));
11609 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyVertices; ++Loop2) {
11610 0 : if (state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1 ==
11611 0 : state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex1) {
11612 0 : if (SurfErrorReported2(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2)) continue;
11613 0 : ShowContinueError(
11614 : state,
11615 0 : format("Figure being Overlapped={}, Surface Class=[{}]",
11616 0 : state.dataSurface->Surface(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2).Name,
11617 0 : cSurfaceClass(state.dataSurface->Surface(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2).Class)));
11618 0 : SurfErrorReported2(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2) = true;
11619 : }
11620 : }
11621 0 : SurfErrorReported(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1) = true;
11622 : }
11623 0 : if (TotCount > 0) {
11624 0 : ShowMessage(state, "");
11625 0 : ShowContinueError(state, format(" The too many vertices errors occurred {} times (total).", TotCount));
11626 0 : ShowMessage(state, "");
11627 : }
11628 :
11629 0 : SurfErrorReported = false;
11630 0 : TotCount = 0;
11631 0 : if (state.dataSolarShading->NumTooManyFigures > 0) {
11632 0 : ShowMessage(state, format("Too many figures [>={}] in shadow overlap errors occurring...", state.dataSolarShading->MaxHCS));
11633 0 : ShowMessage(state,
11634 : "These occur throughout the year and may occur several times for the same surfaces. You "
11635 : "may be able to reduce them by "
11636 : "adding OutputDiagnostics,DoNotMirrorDetachedShading;");
11637 : }
11638 0 : for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumTooManyFigures; ++Loop1) {
11639 0 : Count = 0;
11640 0 : SurfErrorReported2 = false;
11641 0 : if (SurfErrorReported(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1)) continue;
11642 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyFigures; ++Loop2) {
11643 0 : if (state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1 == state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex1) {
11644 0 : ++Count;
11645 : }
11646 : }
11647 0 : TotCount += Count;
11648 0 : state.dataErrTracking->TotalWarningErrors += Count - 1;
11649 0 : ShowMessage(state, "");
11650 0 : ShowWarningError(state, format("Too many figures [>={}] in a shadow overlap", state.dataSolarShading->MaxHCS));
11651 0 : ShowContinueError(state,
11652 0 : format("Overlapping figure={}, Surface Class=[{}]",
11653 0 : state.dataSurface->Surface(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1).Name,
11654 0 : cSurfaceClass(state.dataSurface->Surface(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1).Class)));
11655 0 : ShowContinueError(state, format(" This error occurred {} times.", Count));
11656 0 : for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyFigures; ++Loop2) {
11657 0 : if (state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1 == state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex1) {
11658 0 : if (SurfErrorReported2(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2)) continue;
11659 0 : ShowContinueError(
11660 : state,
11661 0 : format("Figure being Overlapped={}, Surface Class=[{}]",
11662 0 : state.dataSurface->Surface(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2).Name,
11663 0 : cSurfaceClass(state.dataSurface->Surface(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2).Class)));
11664 0 : SurfErrorReported2(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2) = true;
11665 : }
11666 : }
11667 0 : SurfErrorReported(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1) = true;
11668 : }
11669 0 : if (TotCount > 0) {
11670 0 : ShowMessage(state, "");
11671 0 : ShowContinueError(state, format(" The too many figures errors occurred {} times (total).", TotCount));
11672 0 : ShowMessage(state, "");
11673 : }
11674 0 : SurfErrorReported.deallocate();
11675 0 : SurfErrorReported2.deallocate();
11676 : }
11677 796 : }
11678 :
11679 796 : void ComputeWinShadeAbsorpFactors(EnergyPlusData &state)
11680 : {
11681 :
11682 : // SUBROUTINE INFORMATION:
11683 : // AUTHOR Fred Winkelmann
11684 : // DATE WRITTEN Mar 2001
11685 : // MODIFIED Oct 2002,FCW: change ConstrNumSh =
11686 : // WindowShadingControl(WinShadeCtrlNum)%ShadedConstruction
11687 : // to Surface(SurfNum)%ShadedConstruction
11688 : // RE-ENGINEERED na
11689 :
11690 : // PURPOSE OF THIS SUBROUTINE:
11691 : // Called by InitSolarCalculations. Finds fractions that apportion radiation absorbed by a
11692 : // window shade to the two faces of the shade. For radiation incident from the left,
11693 : // ShadeAbsFacFace(1) is the fraction of radiation absorbed in the left-hand half of the
11694 : // of the shade and ShadeAbsFacFace(2) is the fraction absorbed in the right-hand half.
11695 : // The shade is assumed to be homogeneous.
11696 :
11697 : // REFERENCES: See EnergyPlus engineering documentation
11698 : // USE STATEMENTS: na
11699 :
11700 5852 : for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
11701 10124 : for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
11702 5068 : auto &thisSpace = state.dataHeatBal->space(spaceNum);
11703 5068 : int const firstSurfWin = thisSpace.WindowSurfaceFirst;
11704 5068 : int const lastSurfWin = thisSpace.WindowSurfaceLast;
11705 11285 : for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
11706 6217 : auto &surf = state.dataSurface->Surface(SurfNum);
11707 6217 : if (surf.Class == SurfaceClass::Window && surf.HasShadeControl) {
11708 151 : int WinShadeCtrlNum = surf.activeWindowShadingControl; // Window shading control number
11709 :
11710 151 : int MatNumSh = 0; // Shade layer material number
11711 151 : Real64 AbsorpEff = 0.0; // Effective absorptance of isolated shade layer (fraction of
11712 : // of incident radiation remaining after reflected portion is
11713 : // removed that is absorbed
11714 151 : if (ANY_SHADE(state.dataSurface->WindowShadingControl(WinShadeCtrlNum).ShadingType)) {
11715 71 : int const ConstrNumSh = surf.activeShadedConstruction; // Window construction number with shade
11716 71 : int TotLay = state.dataConstruction->Construct(ConstrNumSh).TotLayers; // Total layers in a construction
11717 :
11718 71 : if (state.dataSurface->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::IntShade) {
11719 49 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay); // Interior shade
11720 22 : } else if (state.dataSurface->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::ExtShade) {
11721 18 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(1); // Exterior shade
11722 4 : } else if (state.dataSurface->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::BGShade) {
11723 4 : if (state.dataConstruction->Construct(ConstrNumSh).TotGlassLayers == 2) {
11724 : // Double pane with between-glass shade
11725 2 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(3);
11726 : } else {
11727 : // Triple pane with between-glass shade
11728 2 : MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(5);
11729 : }
11730 : }
11731 71 : auto const *thisMaterialSh = dynamic_cast<const Material::MaterialChild *>(state.dataMaterial->Material(MatNumSh));
11732 71 : AbsorpEff = thisMaterialSh->AbsorpSolar / (thisMaterialSh->AbsorpSolar + thisMaterialSh->Trans + 0.0001);
11733 71 : AbsorpEff = min(max(AbsorpEff, 0.0001),
11734 : 0.999); // Constrain to avoid problems with following log eval
11735 71 : state.dataSurface->SurfWinShadeAbsFacFace1(SurfNum) = (1.0 - std::exp(0.5 * std::log(1.0 - AbsorpEff))) / AbsorpEff;
11736 71 : state.dataSurface->SurfWinShadeAbsFacFace2(SurfNum) = 1.0 - state.dataSurface->SurfWinShadeAbsFacFace1(SurfNum);
11737 : }
11738 : }
11739 : }
11740 5056 : }
11741 : }
11742 796 : }
11743 :
11744 915637 : void CalcWinTransDifSolInitialDistribution(EnergyPlusData &state)
11745 : {
11746 :
11747 : // SUBROUTINE INFORMATION:
11748 : // AUTHOR Rob Hitchcock
11749 : // DATE WRITTEN July 2007
11750 : // MODIFIED N/A
11751 : // RE-ENGINEERED N/A
11752 :
11753 : // PURPOSE OF THIS SUBROUTINE:
11754 : // This subroutine calculates the initial distribution
11755 : // of diffuse solar transmitted through exterior windows
11756 : // to individual heat transfer surfaces in each zone(or enclosure).
11757 :
11758 : // METHODOLOGY EMPLOYED:
11759 : // Apportions diffuse solar transmitted through each exterior window
11760 : // that is then absorbed, reflected, and/or transmitted
11761 : // by other heat transfer surfaces in the zone.
11762 : // Calculations use:
11763 : // 1. WinDifSolar calculated in SUBROUTINE CalcInteriorSolarDistribution,
11764 : // 2. view factors between each exterior window and
11765 : // other heat transfer surfaces in a zone
11766 : // calculated in SUBROUTINE CalcApproximateViewFactors, and
11767 : // 3. surface absorptances, reflectances, and transmittances
11768 : // determined here using revised code from SUBROUTINE InitIntSolarDistribution
11769 :
11770 : // Using/Aliasing
11771 : using ScheduleManager::GetCurrentScheduleValue;
11772 : using namespace DataViewFactorInformation;
11773 : using namespace DataWindowEquivalentLayer;
11774 :
11775 : Real64 AbsInt; // Tmp var for Inside surface short-wave absorptance
11776 : Real64 InsideDifAbsorptance; // Inside diffuse solar absorptance of a surface
11777 : Real64 InsideDifReflectance; // Inside diffuse solar reflectance of a surface
11778 : int BlNum; // Blind number
11779 : Real64 BlAbsDiffBk; // Glass layer back diffuse solar absorptance when blind in place
11780 : Real64 AbsDiffBkBl; // Blind diffuse back solar absorptance as part of glazing system
11781 :
11782 : // REAL(r64) :: DividerSolAbs ! Window divider solar absorptance
11783 : // REAL(r64) :: DividerSolRefl ! Window divider solar reflectance
11784 : // INTEGER :: MatNumGl ! Glass layer material number
11785 : // INTEGER :: MatNumSh ! Shade layer material number
11786 : // REAL(r64) :: TransGl,ReflGl,AbsGl ! Glass layer solar transmittance, reflectance, absorptance
11787 :
11788 915637 : Real64 ViewFactor = 0.0; // temp var for view factor
11789 : // Real64 ViewFactorTotal; // debug var for view factor total
11790 915637 : Real64 WinDifSolarTrans = 0.0; // debug var for WinDifSolar() [W]
11791 : // Real64 WinDifSolarDistTotl; // debug var for window total
11792 : // distributed diffuse solar [W] Real64 WinDifSolarDistAbsorbedTotl; // debug
11793 : // var for individual exterior window total distributed
11794 : // diffuse solar absorbed [W]
11795 : // Real64 WinDifSolarDistReflectedTotl; // debug var for individual exterior window total distributed
11796 : // diffuse solar reflected [W]
11797 : // Real64 WinDifSolarDistTransmittedTotl; // debug var for individual exterior window total distributed
11798 : // diffuse solar transmitted [W]
11799 915637 : Real64 WinDifSolLayAbsW = 0.0; // temp var for diffuse solar absorbed by individual glass layer [W]
11800 : // Real64 ZoneDifSolarTrans; // debug var for WinDifSolar() [W]
11801 : // Real64 ZoneDifSolarDistTotl; // debug var for zone total
11802 : // distributed diffuse solar [W] Real64 ZoneDifSolarDistAbsorbedTotl; //
11803 : // debug var for zone total distributed diffuse solar absorbed [W] Real64
11804 : // ZoneDifSolarDistReflectedTotl; // debug var for zone total distributed
11805 : // diffuse solar reflected [W] Real64 ZoneDifSolarDistTransmittedTotl; //
11806 : // debug var for zone total distributed diffuse solar transmitted [W]
11807 :
11808 915637 : Real64 DifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by surface [W]
11809 915637 : Real64 DifSolarAbs = 0.0; // temp var for diffuse solar absorbed by surface [W/m2]
11810 915637 : Real64 DifSolarReflW = 0.0; // temp var for diffuse solar reflected by surface [W]
11811 915637 : Real64 ShBlDifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by shade/blind [W]
11812 :
11813 1831274 : Array2D<Real64> SurfWinAbsSolBeamEQL(2, CFSMAXNL + 1); // absorbed exterior beam radiation by layers fraction
11814 : Array2D<Real64> SurfWinAbsSolDiffEQL(2,
11815 1831274 : CFSMAXNL + 1); // absorbed exterior diffuse radiation by layers fraction
11816 1831274 : Array2D<Real64> SurfWinAbsSolBeamBackEQL(2, CFSMAXNL + 1); // absorbed interior beam radiation by layers fraction from back
11817 1831274 : Array2D<Real64> AbsSolDiffBackEQL(2, CFSMAXNL + 1); // absorbed exterior diffuse radiation by layers fraction from back
11818 : int EQLNum; // equivalent layer fenestration index
11819 : int Lay; // equivalent layer fenestration layer index
11820 :
11821 : // Init accumulators for absorbed diffuse solar for all surfaces for later heat balance calcs
11822 915637 : state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs = 0.0;
11823 915637 : state.dataHeatBal->SurfWinInitialDifSolwinAbs = 0.0;
11824 :
11825 : // Init accumulator for total reflected diffuse solar within each zone for interreflection calcs
11826 915637 : state.dataHeatBal->EnclSolInitialDifSolReflW = 0.0;
11827 :
11828 : // Init accumulator for transmitted diffuse solar for all surfaces for reporting
11829 915637 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans = 0.0;
11830 :
11831 : // Loop over all zones doing initial distribution of diffuse solar to interior heat transfer surfaces
11832 7238521 : for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
11833 6322884 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
11834 : // Init Zone accumulators for debugging
11835 : // ZoneDifSolarTrans = 0.0;
11836 : // ZoneDifSolarDistAbsorbedTotl = 0.0;
11837 : // ZoneDifSolarDistReflectedTotl = 0.0;
11838 : // ZoneDifSolarDistTransmittedTotl = 0.0;
11839 : // Loop over all diffuse solar transmitting surfaces (i.e., exterior windows and TDDs) in the current zone
11840 60677343 : for (int const DifTransSurfNum : thisEnclosure.SurfacePtr) {
11841 : // Skip surfaces that are not exterior, except for TDD_Diffusers
11842 54354459 : auto &difTransSurf = state.dataSurface->Surface(DifTransSurfNum);
11843 54354459 : if ((difTransSurf.ExtBoundCond != ExternalEnvironment) && (difTransSurf.ExtBoundCond != OtherSideCondModeledExt) &&
11844 33301446 : (difTransSurf.OriginalClass != SurfaceClass::TDD_Diffuser))
11845 33301446 : continue;
11846 :
11847 : // Do I need to do anything special for TDDs?
11848 : // if ( SurfaceWindow( DifTransSurfNum ).OriginalClass == SurfaceClass::TDD_Diffuser )
11849 : // {
11850 : // }
11851 :
11852 : // Skip surfaces that are not exterior windows or TDD diffusers
11853 21053013 : if (difTransSurf.Class != SurfaceClass::Window && difTransSurf.OriginalClass != SurfaceClass::TDD_Diffuser) continue;
11854 :
11855 : //----------------------------------------------------------------------------------------------------------
11856 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH EXTERIOR WINDOWS AND TDDS TO INTERIOR HEAT TRANSFER
11857 : // SURFACES
11858 : //----------------------------------------------------------------------------------------------------------
11859 :
11860 : // Init transmitted solar debug vars
11861 : // ViewFactorTotal = 0.0;
11862 7503620 : WinDifSolarTrans = state.dataSurface->SurfWinDifSolar(DifTransSurfNum);
11863 : // ZoneDifSolarTrans += WinDifSolarTrans;
11864 :
11865 : // Init Exterior Window accumulators for debugging
11866 : // WinDifSolarDistAbsorbedTotl = 0.0;
11867 : // WinDifSolarDistReflectedTotl = 0.0;
11868 : // WinDifSolarDistTransmittedTotl = 0.0;
11869 :
11870 : // Loop over all heat transfer surfaces in the current zone that might receive diffuse solar
11871 106500659 : for (int const HeatTransSurfNum : thisEnclosure.SurfacePtr) {
11872 : // Skip surfaces that are not heat transfer surfaces
11873 : // Skip tubular daylighting device domes
11874 98997039 : if (state.dataSurface->Surface(HeatTransSurfNum).Class == SurfaceClass::TDD_Dome) continue;
11875 :
11876 : // View factor from current (sending) window DifTransSurfNum to current (receiving) surface
11877 : // HeatTransSurfNum
11878 : int const HTenclosureSurfNum =
11879 98997039 : state.dataSurface->Surface(HeatTransSurfNum).SolarEnclSurfIndex; // HT surface index for EnclSolInfo.SurfacePtr and F arrays
11880 98997039 : int const enclosureNum = state.dataSurface->Surface(HeatTransSurfNum).SolarEnclIndex; // index for EnclSolInfo
11881 : int const DTenclSurfNum =
11882 98997039 : state.dataSurface->Surface(DifTransSurfNum).SolarEnclSurfIndex; // Window surface index for EnclSolInfo.SurfacePtr and F arrays
11883 :
11884 98997039 : ViewFactor = state.dataViewFactor->EnclSolInfo(enclosureNum).F(HTenclosureSurfNum, DTenclSurfNum);
11885 : // debug ViewFactorTotal
11886 : // ViewFactorTotal += ViewFactor; // debug
11887 :
11888 : // Skip receiving surfaces with 0.0 view factor
11889 98997039 : if (ViewFactor <= 0.0) continue;
11890 :
11891 56918859 : Real64 const WinDifSolarTrans_Factor(WinDifSolarTrans * ViewFactor);
11892 56918859 : Real64 const win_SwitchingFactor(state.dataSurface->SurfWinSwitchingFactor(HeatTransSurfNum));
11893 56918859 : Real64 const per_HTSurfaceArea(1.0 / state.dataSurface->Surface(HeatTransSurfNum).Area);
11894 :
11895 : // Calculate diffuse solar from current exterior window absorbed and reflected by current heat
11896 : // transfer surface And calculate transmitted diffuse solar to adjacent zones through interior
11897 : // windows
11898 56918859 : int const ConstrNum = state.dataSurface->SurfActiveConstruction(HeatTransSurfNum);
11899 56918859 : if (state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) { // Interior Opaque Surface
11900 :
11901 : // Determine the inside (back) diffuse solar absorptance
11902 : // and reflectance of the current heat transfer surface
11903 49958238 : InsideDifAbsorptance = state.dataHeatBalSurf->SurfAbsSolarInt(HeatTransSurfNum);
11904 : // Inside (back) diffuse solar reflectance is assumed to be 1 - absorptance
11905 49958238 : InsideDifReflectance = 1.0 - InsideDifAbsorptance;
11906 :
11907 : // Absorbed diffuse solar [W] = current window transmitted diffuse solar [W]
11908 : // * view factor from current (sending) window DifTransSurfNum to current (receiving)
11909 : // surface HeatTransSurfNum
11910 : // * current surface inside solar absorptance
11911 49958238 : DifSolarAbsW = WinDifSolarTrans_Factor * InsideDifAbsorptance; // [W]
11912 :
11913 : // Absorbed diffuse solar [W/m2] = Absorbed diffuse solar [W]
11914 : // / current surface net area
11915 49958238 : DifSolarAbs = DifSolarAbsW * per_HTSurfaceArea;
11916 :
11917 : // Accumulate absorbed diffuse solar [W/m2] on this surface for heat balance calcs
11918 49958238 : state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs(HeatTransSurfNum) += DifSolarAbs;
11919 :
11920 : // Reflected diffuse solar [W] = current window transmitted diffuse solar
11921 : // * view factor from current (sending) window DifTransSurfNum to current (receiving)
11922 : // surface HeatTransSurfNum
11923 : // * current window inside solar reflectance
11924 49958238 : DifSolarReflW = WinDifSolarTrans_Factor * InsideDifReflectance;
11925 :
11926 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
11927 : // interreflection calcs
11928 49958238 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
11929 :
11930 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of
11931 : // energy For opaque surfaces all incident diffuse is either absorbed or reflected
11932 :
11933 : } else { // Exterior or Interior Window
11934 6960621 : int const ConstrNumSh = state.dataSurface->SurfWinActiveShadedConstruction(HeatTransSurfNum);
11935 6960621 : int TotGlassLayers = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
11936 6960621 : WinShadingType ShadeFlag = state.dataSurface->SurfWinShadingFlag(HeatTransSurfNum);
11937 :
11938 6960621 : if (state.dataSurface->SurfWinWindowModelType(HeatTransSurfNum) != WindowModel::EQL) {
11939 6957341 : if (NOT_SHADED(ShadeFlag)) { // No window shading
11940 : // Init accumulator for transmittance calc below
11941 6862966 : DifSolarAbsW = 0.0;
11942 :
11943 : // Calc diffuse solar absorbed by all window glass layers
11944 : // Note: I am assuming here that individual glass layer absorptances have been
11945 : // corrected
11946 : // to account for layer by layer transmittance and reflection effects.
11947 15836314 : for (int IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
11948 : // Calc diffuse solar absorbed from the inside by each window glass layer [W]
11949 8973348 : AbsInt = state.dataConstruction->Construct(ConstrNum).AbsDiffBack(IGlass);
11950 8973348 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).AbsDiffBack(IGlass);
11951 :
11952 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
11953 : // transmittance calc below
11954 8973348 : DifSolarAbsW += WinDifSolLayAbsW;
11955 :
11956 : // Accumulate diffuse solar absorbed from the inside by each window glass layer
11957 : // [W/m2] for heat balance calcs
11958 8973348 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
11959 : }
11960 :
11961 : // Calc diffuse solar reflected back to zone
11962 : // I don't really care if this is a window or opaque surface since I am just
11963 : // accumulating all reflected diffuse solar in a zone bucket for "interreflected"
11964 : // distribution Reflected diffuse solar [W] = current window transmitted diffuse solar
11965 : // * view factor from current (sending) window DifTransSurfNum to current
11966 : // (receiving) surface HeatTransSurfNum
11967 : // * current window inside solar reflectance
11968 6862966 : InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
11969 6862966 : DifSolarReflW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
11970 :
11971 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
11972 : // interreflection calcs
11973 6862966 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
11974 :
11975 : //------------------------------------------------------------------------------
11976 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
11977 : //------------------------------------------------------------------------------
11978 :
11979 : // If this receiving window surface (HeatTransSurfNum) is an interior window,
11980 : // calc distributed solar transmitted to adjacent zone [W]
11981 : // NOTE: This calc is here because interior windows are currently assumed to have no
11982 : // shading
11983 :
11984 : // Get the adjacent surface number for this receiving window surface
11985 6862966 : int AdjSurfNum = state.dataSurface->Surface(HeatTransSurfNum).ExtBoundCond;
11986 : // If the adjacent surface number is > 0, this is an interior window
11987 6862966 : if (AdjSurfNum > 0) { // this is an interior window surface
11988 :
11989 : // Calc diffuse solar from current exterior window
11990 : // transmitted through this interior window to adjacent zone [W]
11991 : // Transmitted diffuse solar [W] = current exterior window transmitted diffuse
11992 : // solar
11993 : // * view factor from current (sending) window DifTransSurfNum to current
11994 : // (receiving) surface HeatTransSurfNum
11995 : // - diffuse absorbed by this interior window
11996 : // - diffuse reflected by this interior window
11997 7495 : Real64 DifSolarTransThroughW = WinDifSolarTrans_Factor - DifSolarAbsW - DifSolarReflW;
11998 : // HERE 8/15/07 Note Construct(AdjConstrNum)%TransDiff could be used here since
11999 : // the "front" transmittance for an interior window in the adjacent zone is the
12000 : // correct direction as long as I use the Construct() of the Surface in the
12001 : // adjacent zone. However, the above calculation better conserves energy, although
12002 : // possibly at the expense of less accurate transmittance calcs. Preliminary tests
12003 : // showed fairly good agreement between the two DifSolarTransW calculation
12004 : // methods, but for consistency I stuck with the above. int AdjConstrNum =
12005 : // Surface(AdjSurfNum).Construction;
12006 : // DifSolarTransW = WinDifSolar(DifTransSurfNum) &
12007 : // * ViewFactor &
12008 : // * Construct(AdjConstrNum)%TransDiff
12009 :
12010 : // Get the adjacent zone index
12011 7495 : int const adjEnclosureNum = state.dataSurface->Surface(AdjSurfNum).SolarEnclIndex;
12012 :
12013 : // Call routine to distribute diffuse solar transmitted through this interior
12014 : // window into adjacent zone
12015 7495 : CalcInteriorWinTransDifSolInitialDistribution(state, adjEnclosureNum, AdjSurfNum, DifSolarTransThroughW);
12016 : }
12017 :
12018 : // Calc transmitted Window and Zone total distributed diffuse solar to check for
12019 : // conservation of energy This is not very effective since it assigns whatever
12020 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
12021 : // Should be just total less reflected
12022 6862966 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
12023 :
12024 : // Accumulate transmitted diffuse solar for reporting
12025 6862966 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
12026 :
12027 94375 : } else if (ShadeFlag == WinShadingType::SwitchableGlazing) { // Switchable glazing
12028 : // Init accumulator for transmittance calc below
12029 2226 : DifSolarAbsW = 0.0;
12030 :
12031 2226 : auto const &construct = state.dataConstruction->Construct(ConstrNum);
12032 2226 : auto const &construct_AbsDiffBack = construct.AbsDiffBack;
12033 2226 : auto const &construct_sh = state.dataConstruction->Construct(ConstrNumSh);
12034 2226 : auto const &construct_sh_AbsDiffBack = construct_sh.AbsDiffBack;
12035 6678 : for (int IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
12036 : // Calc diffuse solar absorbed in each window glass layer
12037 4452 : WinDifSolLayAbsW =
12038 : WinDifSolarTrans_Factor *
12039 4452 : Window::InterpSw(win_SwitchingFactor, construct_AbsDiffBack(IGlass), construct_sh_AbsDiffBack(IGlass));
12040 :
12041 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
12042 : // transmittance calc below
12043 4452 : DifSolarAbsW += WinDifSolLayAbsW;
12044 :
12045 : // Accumulate diffuse solar absorbed from the inside by each window glass layer
12046 : // [W/m2] for heat balance calcs
12047 4452 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
12048 : }
12049 :
12050 : // Calc diffuse solar reflected back to zone
12051 2226 : DifSolarReflW = WinDifSolarTrans_Factor *
12052 2226 : Window::InterpSw(win_SwitchingFactor, construct.ReflectSolDiffBack, construct_sh.ReflectSolDiffBack);
12053 :
12054 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12055 : // interreflection calcs
12056 2226 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
12057 :
12058 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12059 : // conservation of energy This is not very effective since it assigns whatever
12060 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
12061 : // Should be just total less reflected
12062 2226 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
12063 :
12064 : // Accumulate transmitted diffuse solar for reporting
12065 2226 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
12066 :
12067 92149 : } else if (ConstrNumSh != 0) {
12068 : // Interior, exterior or between-glass shade, screen or blind in place
12069 :
12070 : // Init accumulator for transmittance calc below
12071 78289 : DifSolarAbsW = 0.0;
12072 78289 : WinDifSolLayAbsW = 0.0;
12073 :
12074 : // First calc diffuse solar absorbed by each glass layer in this window with
12075 : // shade/blind in place
12076 78289 : auto const &construct_sh = state.dataConstruction->Construct(ConstrNumSh);
12077 78289 : auto const &construct_sh_AbsDiffBack = construct_sh.AbsDiffBack;
12078 78289 : auto const &construct_sh_BlAbsDiffBack = construct_sh.BlAbsDiffBack;
12079 :
12080 78289 : int SurfWinSlatsAngIndex = state.dataSurface->SurfWinSlatsAngIndex(HeatTransSurfNum);
12081 78289 : Real64 SurfWinSlatsAngInterpFac = state.dataSurface->SurfWinSlatsAngInterpFac(HeatTransSurfNum);
12082 :
12083 205324 : for (int IGlass = 1; IGlass <= construct_sh.TotGlassLayers; ++IGlass) {
12084 127035 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
12085 : // Calc diffuse solar absorbed in each window glass layer and shade
12086 125908 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * construct_sh_AbsDiffBack(IGlass);
12087 1127 : } else if (ANY_BLIND(ShadeFlag)) {
12088 1127 : if (state.dataSurface->SurfWinMovableSlats(HeatTransSurfNum)) {
12089 0 : BlAbsDiffBk = General::Interp(
12090 0 : construct_sh_BlAbsDiffBack(SurfWinSlatsAngIndex, IGlass),
12091 0 : construct_sh_BlAbsDiffBack(std::min(Material::MaxSlatAngs, SurfWinSlatsAngIndex + 1), IGlass),
12092 : SurfWinSlatsAngInterpFac);
12093 : } else {
12094 1127 : BlAbsDiffBk = construct_sh_BlAbsDiffBack(1, IGlass);
12095 : }
12096 : // Calc diffuse solar absorbed in each window glass layer and shade
12097 1127 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * BlAbsDiffBk;
12098 : }
12099 :
12100 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
12101 : // transmittance calc below
12102 127035 : DifSolarAbsW += WinDifSolLayAbsW;
12103 :
12104 : // Accumulate diffuse solar absorbed from the inside by each window glass layer
12105 : // [W/m2] for heat balance calcs
12106 127035 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
12107 : }
12108 :
12109 : // Next calc diffuse solar reflected back to zone from window with shade or blind on
12110 : // Diffuse back solar reflectance, bare glass or shade on
12111 78289 : InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
12112 78289 : if ((ShadeFlag == WinShadingType::IntBlind) || (ShadeFlag == WinShadingType::ExtBlind)) {
12113 : // Diffuse back solar reflectance, blind present, vs. slat angle
12114 1127 : if (state.dataSurface->SurfWinMovableSlats(HeatTransSurfNum)) {
12115 : InsideDifReflectance =
12116 0 : General::Interp(state.dataConstruction->Construct(ConstrNum).BlReflectSolDiffBack(SurfWinSlatsAngIndex),
12117 0 : state.dataConstruction->Construct(ConstrNum).BlReflectSolDiffBack(
12118 0 : std::min(Material::MaxSlatAngs, SurfWinSlatsAngIndex + 1)),
12119 : SurfWinSlatsAngInterpFac);
12120 : } else {
12121 1127 : InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).BlReflectSolDiffBack(1);
12122 : }
12123 : }
12124 78289 : DifSolarReflW = WinDifSolarTrans_Factor * InsideDifReflectance;
12125 :
12126 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12127 : // interreflection calcs
12128 78289 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
12129 :
12130 : // Now calc diffuse solar absorbed by shade/blind itself
12131 78289 : BlNum = state.dataSurface->SurfWinBlindNumber(HeatTransSurfNum);
12132 78289 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
12133 : // Calc diffuse solar absorbed by shade or screen [W]
12134 77162 : ShBlDifSolarAbsW = WinDifSolarTrans_Factor * construct_sh.AbsDiffBackShade;
12135 1127 : } else if (ANY_BLIND(ShadeFlag)) {
12136 : // Calc diffuse solar absorbed by blind [W]
12137 1127 : if (state.dataSurface->SurfWinMovableSlats(HeatTransSurfNum)) {
12138 : AbsDiffBkBl =
12139 0 : General::Interp(construct_sh.AbsDiffBackBlind(SurfWinSlatsAngIndex),
12140 0 : construct_sh.AbsDiffBackBlind(std::min(Material::MaxSlatAngs, SurfWinSlatsAngIndex + 1)),
12141 : SurfWinSlatsAngInterpFac);
12142 : } else {
12143 1127 : AbsDiffBkBl = construct_sh.AbsDiffBackBlind(1);
12144 : }
12145 1127 : ShBlDifSolarAbsW = WinDifSolarTrans_Factor * AbsDiffBkBl;
12146 : }
12147 : // Correct for divider shadowing
12148 78289 : if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
12149 37580 : ShBlDifSolarAbsW *= state.dataSurface->SurfaceWindow(HeatTransSurfNum).glazedFrac;
12150 : }
12151 :
12152 : // Accumulate diffuse solar absorbed by shade or screen [W/m2] for heat balance calcs
12153 78289 : state.dataSurface->SurfWinInitialDifSolAbsByShade(HeatTransSurfNum) += ShBlDifSolarAbsW * per_HTSurfaceArea;
12154 :
12155 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
12156 : // transmittance calc below
12157 78289 : DifSolarAbsW += ShBlDifSolarAbsW;
12158 :
12159 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12160 : // conservation of energy This is not very effective since it assigns whatever
12161 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
12162 : // Should be just total less reflected
12163 78289 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
12164 :
12165 : // Accumulate transmitted diffuse solar for reporting
12166 78289 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
12167 : } // End of shading flag check
12168 :
12169 : } else {
12170 : // SurfaceWindow(HeatTransSurfNum)%WindowModelType == WindowModel:: EQL
12171 : // ConstrNum=Surface(HeatTransSurfNum)%Construction
12172 : // call the ASHWAT fenestration model for diffuse radiation here
12173 3280 : WindowEquivalentLayer::CalcEQLOpticalProperty(state, HeatTransSurfNum, SolarArrays::DIFF, AbsSolDiffBackEQL);
12174 :
12175 3280 : EQLNum = state.dataConstruction->Construct(ConstrNum).EQLConsPtr;
12176 17262 : for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(EQLNum).NL; ++Lay) {
12177 :
12178 : // Calc diffuse solar absorbed from the inside by each layer of EQL model [W]
12179 : // WinDifSolLayAbsW = WinDifSolar(DifTransSurfNum)* ViewFactor *
12180 : // Construct(ConstrNum)%AbsDiffBack(Lay)
12181 13982 : WinDifSolLayAbsW = WinDifSolarTrans_Factor * AbsSolDiffBackEQL(2, Lay);
12182 :
12183 : // Accumulate distributed diffuse solar absorbed [W] by overall window for
12184 : // transmittance calc below
12185 13982 : DifSolarAbsW += WinDifSolLayAbsW;
12186 :
12187 : // Accumulate diffuse solar absorbed from the inside by each window layer [W/m2] for
12188 : // heat balance calcs
12189 13982 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, Lay) += WinDifSolLayAbsW * per_HTSurfaceArea;
12190 :
12191 : // ASHWAT equivalent layer model may require not the individual layer absorption but
12192 : // the flux InitialDifSolwinEQL(HeatTransSurfNum) = WinDifSolar(DifTransSurfNum)*
12193 : // ViewFactor
12194 : }
12195 :
12196 : // Calc diffuse solar reflected back to zone
12197 : // I don't really care if this is a window or opaque surface since I am just
12198 : // accumulating all reflected diffuse solar in a zone bucket for "interreflected"
12199 : // distribution Reflected diffuse solar [W] = current window transmitted diffuse solar
12200 : // * view factor from current (sending) window DifTransSurfNum to current (receiving)
12201 : // surface HeatTransSurfNum
12202 : // * current window inside solar reflectance
12203 3280 : InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
12204 3280 : DifSolarReflW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
12205 :
12206 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12207 : // interreflection calcs
12208 3280 : state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
12209 :
12210 : //------------------------------------------------------------------------------
12211 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
12212 : //------------------------------------------------------------------------------
12213 :
12214 : // If this receiving window surface (HeatTransSurfNum) is an interior window,
12215 : // calc distributed solar transmitted to adjacent zone [W]
12216 : // NOTE: This calc is here because interior windows are currently assumed to have no
12217 : // shading
12218 :
12219 : // Get the adjacent surface number for this receiving window surface
12220 3280 : int const AdjSurfNum = state.dataSurface->Surface(HeatTransSurfNum).ExtBoundCond;
12221 : // If the adjacent surface number is > 0, this is an interior window
12222 3280 : if (AdjSurfNum > 0) { // this is an interior window surface
12223 :
12224 : // Calc diffuse solar from current exterior window
12225 : // transmitted through this interior window to adjacent zone [W]
12226 : // Transmitted diffuse solar [W] = current exterior window transmitted diffuse solar
12227 : // * view factor from current (sending) window DifTransSurfNum to current
12228 : // (receiving) surface HeatTransSurfNum
12229 0 : Real64 DifSolarTransW = AbsSolDiffBackEQL(2, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1) * ViewFactor;
12230 : // int AdjConstrNum = Surface(AdjSurfNum).Construction;
12231 : // Get the adjacent zone index
12232 0 : int adjEnclosureNum = state.dataSurface->Surface(AdjSurfNum).SolarEnclIndex;
12233 : // Call routine to distribute diffuse solar transmitted through this interior window
12234 : // into adjacent zone
12235 0 : CalcInteriorWinTransDifSolInitialDistribution(state, adjEnclosureNum, AdjSurfNum, DifSolarTransW);
12236 : }
12237 :
12238 : // Calc transmitted Window and Zone total distributed diffuse solar to check for
12239 : // conservation of energy This is not very effective since it assigns whatever
12240 : // distributed diffuse solar has not been absorbed or reflected to transmitted.
12241 : // Should be just total less reflected
12242 3280 : Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
12243 :
12244 : // Accumulate transmitted diffuse solar for reporting
12245 3280 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
12246 :
12247 : } // IF (SurfaceWindow(HeatTransSurfNum)%WindowModelType /= WindowModel:: EQL) THEN
12248 :
12249 : // HERE 8/14/07 Ignore absorptance and reflectance of Frames and Dividers for now.
12250 : // I would need revised view factors that included these surface types.
12251 : // By ignoring them here, the diffuse solar is accounted for on the other surfaces
12252 :
12253 : // IF(SurfaceWindow(HeatTransSurfNum)%FrameArea > 0.0) THEN ! Window has a frame
12254 : // Note that FrameQRadInAbs is initially calculated in InitSolarHeatGains
12255 : // END IF
12256 :
12257 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerArea > 0.0) THEN ! Window has dividers
12258 : // DividerSolAbs = SurfaceWindow(HeatTransSurfNum)%DividerSolAbsorp
12259 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerType == Suspended) THEN ! Suspended
12260 : // divider; account for inside glass
12261 : // MatNumGl = Construct(ConstrNum)%LayerPoint(Construct(ConstrNum)%TotLayers)
12262 : // TransGl = dataMaterial.Material(MatNumGl)%Trans
12263 : // ReflGl = dataMaterial.Material(MatNumGl)%ReflectSolDiffBack
12264 : // AbsGl = 1.0d0-TransGl-ReflGl
12265 : // DividerSolRefl = 1.0d0-DividerSolAbs
12266 : // DividerSolAbs = AbsGl + TransGl*(DividerSolAbs +
12267 : // DividerSolRefl*AbsGl)/(1.0d0-DividerSolRefl*ReflGl)
12268 : // END IF
12269 : // Correct for interior shade transmittance
12270 : // IF(ShadeFlag == IntShadeOn) THEN
12271 : // MatNumSh = Construct(ConstrNumSh)%LayerPoint(Construct(ConstrNumSh)%TotLayers)
12272 : // DividerSolAbs = DividerSolAbs * dataMaterial.Material(MatNumSh)%Trans
12273 : // ELSE IF(ShadeFlag == WinShadingType::IntBlind) THEN
12274 : // DividerSolAbs = DividerSolAbs *
12275 : // InterpSlatAng(SurfaceWindow(HeatTransSurfNum)%SlatAngThisTS, &
12276 : // SurfaceWindow(HeatTransSurfNum)%MovableSlats,Blind(BlNum)%SolBackDiffDiffTrans)
12277 : // END IF
12278 : // Note that DividerQRadInAbs is initially calculated in InitSolarHeatGains
12279 :
12280 : // END IF ! Window has dividers
12281 :
12282 : } // opaque or window heat transfer surface
12283 :
12284 : } // HeatTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
12285 :
12286 : // Check debug var for view factors here
12287 : // ViewFactorTotal
12288 : // Check debug vars for individual transmitting surfaces here
12289 : // WinDifSolarDistTotl = WinDifSolarDistAbsorbedTotl + WinDifSolarDistReflectedTotl +
12290 : // WinDifSolarDistTransmittedTotl;
12291 : // WinDifSolarTrans
12292 :
12293 : } // DifTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
12294 :
12295 : // Check debug vars for zone totals here
12296 : // ZoneDifSolarDistTotl = ZoneDifSolarDistAbsorbedTotl + ZoneDifSolarDistReflectedTotl +
12297 : // ZoneDifSolarDistTransmittedTotl;
12298 : // ZoneDifSolarTrans
12299 : // ZoneDifSolarDistAbsorbedTotl
12300 : // ZoneDifSolarDistReflectedTotl
12301 : // ZoneDifSolarDistTransmittedTotl
12302 : // CALL DisplayString('Diffuse Solar Distribution Zone Totals')
12303 :
12304 : } // ZoneNum = 1, NumOfZones
12305 915637 : }
12306 7495 : void CalcInteriorWinTransDifSolInitialDistribution(EnergyPlusData &state,
12307 : int const IntWinEnclosureNum, // Interior Window Enclosure index number
12308 : int const IntWinSurfNum, // Interior Window Surface number
12309 : Real64 const IntWinDifSolarTransW // Diffuse Solar transmitted through Interior Window
12310 : // IntWinSurfNum from adjacent enclosure [W]
12311 : )
12312 : {
12313 :
12314 : // SUBROUTINE INFORMATION:
12315 : // AUTHOR Rob Hitchcock
12316 : // DATE WRITTEN August 2007
12317 : // MODIFIED N/A
12318 : // RE-ENGINEERED N/A
12319 :
12320 : // PURPOSE OF THIS SUBROUTINE:
12321 : // This subroutine calculates the initial distribution
12322 : // of diffuse solar transmitted through the given interior window
12323 : // to individual heat transfer surfaces in the given enclosure.
12324 : // Diffuse solar transmitted through interior windows in this enclosure
12325 : // to adjacent enclosures, is added to the EnclSolInitialDifSolReflW
12326 : // of the adjacent enclosure for subsequent interreflection calcs
12327 :
12328 : // METHODOLOGY EMPLOYED:
12329 : // Similar to method used in CalcWinTransDifSolInitialDistribution.
12330 : // Apportions diffuse solar transmitted through an interior window
12331 : // that is then absorbed, reflected, and/or transmitted
12332 : // by other heat transfer surfaces in the given enclosure.
12333 : // Calculations use:
12334 : // 1. DifSolarTransW calculated in SUBROUTINE CalcWinTransDifSolInitialDistribution,
12335 : // 2. view factors between the interior window and
12336 : // other heat transfer surfaces in the given enclosure
12337 : // calculated in SUBROUTINE CalcApproximateViewFactors, and
12338 : // 3. surface absorptances, reflectances, and transmittances
12339 : // determined here using revised code from SUBROUTINE InitIntSolarDistribution
12340 :
12341 : // Using/Aliasing
12342 : using ScheduleManager::GetCurrentScheduleValue;
12343 : using namespace DataViewFactorInformation;
12344 :
12345 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
12346 : int IGlass; // Glass layer counter
12347 : int TotGlassLayers; // Number of glass layers in a window construction
12348 : WinShadingType ShadeFlag; // Shading flag
12349 : Real64 AbsInt; // Tmp var for Inside surface short-wave absorptance
12350 : Real64 InsideDifAbsorptance; // Inside diffuse solar absorptance of a surface
12351 : Real64 InsideDifReflectance; // Inside diffuse solar reflectance of a surface
12352 : int BlNum; // Blind number
12353 : Real64 BlAbsDiffBk; // Glass layer back diffuse solar absorptance when blind in place
12354 : Real64 AbsDiffBkBl; // Blind diffuse back solar absorptance as part of glazing system
12355 :
12356 : // REAL(r64) :: DividerSolAbs ! Window divider solar absorptance
12357 : // REAL(r64) :: DividerSolRefl ! Window divider solar reflectance
12358 : // INTEGER :: MatNumGl ! Glass layer material number
12359 : // INTEGER :: MatNumSh ! Shade layer material number
12360 : // REAL(r64) :: TransGl,ReflGl,AbsGl ! Glass layer solar transmittance, reflectance, absorptance
12361 :
12362 : Real64 ViewFactor; // temp var for view factor
12363 : Real64 ViewFactorTotal; // debug var for view factor total
12364 : Real64 WinDifSolarTrans; // debug var for WinDifSolar() [W]
12365 : // Real64 WinDifSolarDistTotl; // debug var for window total distributed
12366 : // diffuse solar [W] Real64 WinDifSolarDistAbsorbedTotl( 0.0 ); // debug var
12367 : // for individual exterior window total
12368 : // distributed
12369 : // diffuse solar absorbed [W]
12370 : // Real64 WinDifSolarDistReflectedTotl( 0.0 ); // debug var for individual exterior window total
12371 : // distributed
12372 : // diffuse solar reflected [W]
12373 : // Real64 WinDifSolarDistTransmittedTotl( 0.0 ); // debug var for individual exterior window total
12374 : // distributed
12375 : // diffuse solar transmitted [W]
12376 : Real64 WinDifSolLayAbsW; // temp var for diffuse solar absorbed by individual glass layer [W]
12377 : // Real64 ZoneDifSolarTrans( 0.0 ); // debug var for WinDifSolar() [W]
12378 : // REAL(r64) :: ZoneDifSolarDistTotl ! debug var for zone total distributed diffuse solar [W]
12379 : // Real64 ZoneDifSolarDistAbsorbedTotl( 0.0 ); // debug var for zone total distributed diffuse solar
12380 : // absorbed [W] Real64 ZoneDifSolarDistReflectedTotl( 0.0 ); // debug var for zone total distributed
12381 : // diffuse solar reflected [W] Real64 ZoneDifSolarDistTransmittedTotl( 0.0 ); // debug var for zone
12382 : // total distributed diffuse solar transmitted [W]
12383 :
12384 7495 : Real64 DifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by surface [W]
12385 7495 : Real64 DifSolarAbs = 0.0; // temp var for diffuse solar absorbed by surface [W/m2]
12386 7495 : Real64 DifSolarReflW = 0.0; // temp var for diffuse solar reflected by surface [W]
12387 7495 : Real64 DifSolarTransW = 0.0; // temp var for diffuse solar transmitted through interior window surface [W]
12388 7495 : Real64 ShBlDifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by shade/blind [W]
12389 :
12390 : //-------------------------------------------------------------------------------------------------
12391 : // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO INTERIOR HEAT TRANSFER SURFACES
12392 : //-------------------------------------------------------------------------------------------------
12393 :
12394 : // Init debug vars
12395 7495 : ViewFactorTotal = 0.0;
12396 7495 : WinDifSolarTrans = IntWinDifSolarTransW;
12397 :
12398 7495 : auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(IntWinEnclosureNum);
12399 : // Loop over all heat transfer surfaces in the current zone that might receive diffuse solar
12400 7495 : Real64 InitialZoneDifSolReflW_zone(0.0);
12401 70152 : for (int const HeatTransSurfNum : thisEnclosure.SurfacePtr) {
12402 : // Skip surfaces that are not heat transfer surfaces
12403 62657 : if (!state.dataSurface->Surface(HeatTransSurfNum).HeatTransSurf) continue;
12404 : // Skip tubular daylighting device domes
12405 62657 : if (state.dataSurface->Surface(HeatTransSurfNum).Class == SurfaceClass::TDD_Dome) continue;
12406 :
12407 : // View factor from current (sending) window IntWinSurfNum to current (receiving) surface HeatTransSurfNum
12408 : int HTenclosureSurfNum =
12409 62657 : state.dataSurface->Surface(HeatTransSurfNum).SolarEnclSurfIndex; // HT surface index for EnclSolInfo.SurfacePtr and F arrays
12410 62657 : int enclosureNum = state.dataSurface->Surface(HeatTransSurfNum).SolarEnclIndex; // index for EnclSolInfo
12411 : int IntWinEnclSurfNum =
12412 62657 : state.dataSurface->Surface(IntWinSurfNum).SolarEnclSurfIndex; // Window surface index for EnclSolInfo.SurfacePtr and F arrays
12413 :
12414 62657 : ViewFactor = state.dataViewFactor->EnclSolInfo(enclosureNum).F(HTenclosureSurfNum, IntWinEnclSurfNum);
12415 : // debug ViewFactorTotal
12416 62657 : ViewFactorTotal += ViewFactor; // debug
12417 :
12418 : // Skip receiving surfaces with 0.0 view factor
12419 62657 : if (ViewFactor <= 0.0) continue;
12420 43955 : Real64 const SolarTrans_ViewFactor(IntWinDifSolarTransW * ViewFactor);
12421 :
12422 : // Calculate diffuse solar from current interior window absorbed and reflected by current heat transfer
12423 : // surface And calculate transmitted diffuse solar to adjacent zones through interior windows
12424 43955 : int const ConstrNum = state.dataSurface->SurfActiveConstruction(HeatTransSurfNum);
12425 43955 : if (state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) { // Interior Opaque Surface
12426 :
12427 : // Determine the inside (back) diffuse solar absorptance
12428 : // and reflectance of the current heat transfer surface
12429 37475 : InsideDifAbsorptance = state.dataHeatBalSurf->SurfAbsSolarInt(HeatTransSurfNum);
12430 : // Inside (back) diffuse solar reflectance is assumed to be 1 - absorptance
12431 37475 : InsideDifReflectance = 1.0 - InsideDifAbsorptance;
12432 :
12433 : // Absorbed diffuse solar [W] = current window transmitted diffuse solar [W]
12434 : // * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
12435 : // HeatTransSurfNum
12436 : // * current surface inside solar absorptance
12437 37475 : DifSolarAbsW = SolarTrans_ViewFactor * InsideDifAbsorptance; // [W]
12438 :
12439 : // Absorbed diffuse solar [W/m2] = Absorbed diffuse solar [W]
12440 : // / current surface net area
12441 37475 : DifSolarAbs = DifSolarAbsW / state.dataSurface->Surface(HeatTransSurfNum).Area;
12442 :
12443 : // Accumulate absorbed diffuse solar [W/m2] on this surface for heat balance calcs
12444 37475 : state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs(HeatTransSurfNum) += DifSolarAbs;
12445 :
12446 : // Reflected diffuse solar [W] = current window transmitted diffuse solar
12447 : // * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
12448 : // HeatTransSurfNum
12449 : // * current window inside solar reflectance
12450 37475 : DifSolarReflW = SolarTrans_ViewFactor * InsideDifReflectance;
12451 :
12452 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent interreflection
12453 : // calcs
12454 37475 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12455 :
12456 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12457 : // For opaque surfaces all incident diffuse is either absorbed or reflected
12458 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug [W]
12459 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug [W]
12460 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug [W]
12461 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug [W]
12462 :
12463 : } else { // Exterior or Interior Window
12464 :
12465 6480 : int const ConstrNumSh = state.dataSurface->SurfWinActiveShadedConstruction(HeatTransSurfNum);
12466 6480 : auto const &construction = state.dataConstruction->Construct(ConstrNum);
12467 :
12468 6480 : TotGlassLayers = construction.TotGlassLayers;
12469 6480 : ShadeFlag = state.dataSurface->SurfWinShadingFlag(HeatTransSurfNum);
12470 :
12471 6480 : if (NOT_SHADED(ShadeFlag)) { // No window shading
12472 : // Init accumulator for transmittance calc below
12473 6480 : DifSolarAbsW = 0.0;
12474 :
12475 : // Calc diffuse solar absorbed by all window glass layers
12476 : // Note: I am assuming here that individual glass layer absorptances have been corrected
12477 : // to account for layer by layer transmittance and reflection effects.
12478 12960 : for (IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
12479 : // Calc diffuse solar absorbed from the inside by each window glass layer [W]
12480 6480 : AbsInt = construction.AbsDiffBack(IGlass);
12481 6480 : WinDifSolLayAbsW = SolarTrans_ViewFactor * construction.AbsDiffBack(IGlass);
12482 :
12483 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12484 : // below
12485 6480 : DifSolarAbsW += WinDifSolLayAbsW;
12486 :
12487 : // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
12488 : // heat balance calcs
12489 6480 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) +=
12490 6480 : (WinDifSolLayAbsW / state.dataSurface->Surface(HeatTransSurfNum).Area);
12491 : }
12492 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12493 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12494 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12495 :
12496 : // Calc diffuse solar reflected back to zone
12497 : // I don't really care if this is a window or opaque surface since I am just
12498 : // accumulating all reflected diffuse solar in a zone bucket for "interreflected" distribution
12499 : // Reflected diffuse solar [W] = current window transmitted diffuse solar
12500 : // * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
12501 : // HeatTransSurfNum
12502 : // * current window inside solar reflectance
12503 6480 : DifSolarReflW = SolarTrans_ViewFactor * construction.ReflectSolDiffBack;
12504 :
12505 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12506 : // interreflection calcs
12507 6480 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12508 :
12509 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12510 :
12511 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
12512 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
12513 :
12514 : // Calc transmitted Window and Zone total distributed diffuse solar to check for conservation of
12515 : // energy This is not very effective since it assigns whatever distributed diffuse solar has not
12516 : // been absorbed or reflected to transmitted.
12517 6480 : DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
12518 :
12519 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12520 : // conservation of energy
12521 : // WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12522 : // ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12523 :
12524 : // Accumulate transmitted diffuse solar for reporting
12525 6480 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) +=
12526 6480 : (SolarTrans_ViewFactor - DifSolarReflW) / state.dataSurface->Surface(HeatTransSurfNum).Area;
12527 :
12528 : //-----------------------------------------------------------------------------------
12529 : // ADD TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
12530 : // TOTAL REFLECTED DIFFUSE SOLAR FOR SUBSEQUENT INTERREFLECTION CALCS
12531 : //-----------------------------------------------------------------------------------
12532 :
12533 : // If this receiving window surface (HeatTransSurfNum) is an interior window,
12534 : // add transmitted diffuse solar to adjacent zone total reflected distributed
12535 : // diffuse solar for subsequent interreflection calcs
12536 : // NOTE: This calc is here because interior windows are currently assumed to have no shading
12537 :
12538 : // Get the adjacent surface number for this receiving window surface
12539 6480 : int const AdjSurfNum = state.dataSurface->Surface(HeatTransSurfNum).ExtBoundCond;
12540 : // If the adjacent surface number is > 0, this is an interior window
12541 6480 : if (AdjSurfNum > 0) { // this is an interior window surface
12542 :
12543 : // Get the adjacent zone/enclosure index
12544 : // Add transmitted diffuse solar to total reflected distributed diffuse solar for each zone
12545 : // for subsequent interreflection calcs
12546 0 : state.dataHeatBal->EnclSolInitialDifSolReflW(state.dataSurface->Surface(AdjSurfNum).SolarEnclIndex) += DifSolarTransW; // [W]
12547 : }
12548 :
12549 0 : } else if (ShadeFlag == WinShadingType::SwitchableGlazing) { // Switchable glazing
12550 : // Init accumulator for transmittance calc below
12551 0 : auto const &constructionSh = state.dataConstruction->Construct(ConstrNumSh);
12552 0 : DifSolarAbsW = 0.0;
12553 :
12554 0 : for (IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
12555 : // Calc diffuse solar absorbed in each window glass layer
12556 0 : WinDifSolLayAbsW = SolarTrans_ViewFactor * InterpSw(state.dataSurface->SurfWinSwitchingFactor(HeatTransSurfNum),
12557 0 : construction.AbsDiffBack(IGlass),
12558 0 : constructionSh.AbsDiffBack(IGlass));
12559 :
12560 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12561 : // below
12562 0 : DifSolarAbsW += WinDifSolLayAbsW;
12563 :
12564 : // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
12565 : // heat balance calcs
12566 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) +=
12567 0 : (WinDifSolLayAbsW / state.dataSurface->Surface(HeatTransSurfNum).Area);
12568 : }
12569 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12570 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12571 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12572 :
12573 : // Calc diffuse solar reflected back to zone
12574 0 : DifSolarReflW = SolarTrans_ViewFactor * InterpSw(state.dataSurface->SurfWinSwitchingFactor(HeatTransSurfNum),
12575 0 : construction.ReflectSolDiffBack,
12576 0 : constructionSh.ReflectSolDiffBack);
12577 :
12578 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12579 : // interreflection calcs
12580 0 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12581 :
12582 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12583 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
12584 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
12585 :
12586 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12587 : // conservation of energy This is not very effective since it assigns whatever distributed diffuse
12588 : // solar has not been absorbed or reflected to transmitted.
12589 0 : DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
12590 : // WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12591 : // ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug
12592 : //[W]
12593 :
12594 : // Accumulate transmitted diffuse solar for reporting
12595 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) +=
12596 0 : (SolarTrans_ViewFactor - DifSolarReflW) / state.dataSurface->Surface(HeatTransSurfNum).Area;
12597 :
12598 : } else {
12599 : // Interior, exterior or between-glass shade, screen or blind in place
12600 :
12601 : // Init accumulator for transmittance calc below
12602 0 : DifSolarAbsW = 0.0;
12603 0 : WinDifSolLayAbsW = 0.0;
12604 0 : int SurfWinSlatsAngIndex = state.dataSurface->SurfWinSlatsAngIndex(HeatTransSurfNum);
12605 0 : Real64 SurfWinSlatsAngInterpFac = state.dataSurface->SurfWinSlatsAngInterpFac(HeatTransSurfNum);
12606 :
12607 : // First calc diffuse solar absorbed by each glass layer in this window with shade/blind in place
12608 0 : auto const &constructionSh = state.dataConstruction->Construct(ConstrNumSh);
12609 0 : for (IGlass = 1; IGlass <= constructionSh.TotGlassLayers; ++IGlass) {
12610 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
12611 : // Calc diffuse solar absorbed in each window glass layer and shade
12612 0 : WinDifSolLayAbsW = SolarTrans_ViewFactor * constructionSh.AbsDiffBack(IGlass);
12613 0 : } else if (ANY_BLIND(ShadeFlag)) {
12614 0 : if (state.dataSurface->SurfWinMovableSlats(HeatTransSurfNum)) {
12615 : BlAbsDiffBk =
12616 0 : General::Interp(constructionSh.BlAbsDiffBack(SurfWinSlatsAngIndex, IGlass),
12617 0 : constructionSh.BlAbsDiffBack(std::min(Material::MaxSlatAngs, SurfWinSlatsAngIndex + 1), IGlass),
12618 : SurfWinSlatsAngInterpFac);
12619 : } else {
12620 0 : BlAbsDiffBk = constructionSh.BlAbsDiffBack(1, IGlass);
12621 : }
12622 : // Calc diffuse solar absorbed in each window glass layer and shade
12623 0 : WinDifSolLayAbsW = SolarTrans_ViewFactor * BlAbsDiffBk;
12624 : }
12625 :
12626 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12627 : // below
12628 0 : DifSolarAbsW += WinDifSolLayAbsW;
12629 :
12630 : // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
12631 : // heat balance calcs
12632 0 : state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) +=
12633 0 : (WinDifSolLayAbsW / state.dataSurface->Surface(HeatTransSurfNum).Area);
12634 : }
12635 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12636 : // WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12637 : // ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
12638 :
12639 : // Next calc diffuse solar reflected back to zone from window with shade or blind on
12640 : // Diffuse back solar reflectance, bare glass or shade on
12641 0 : InsideDifReflectance = construction.ReflectSolDiffBack;
12642 0 : if ((ShadeFlag == WinShadingType::IntBlind) || (ShadeFlag == WinShadingType::ExtBlind)) {
12643 : // Diffuse back solar reflectance, blind present, vs. slat angle
12644 0 : if (state.dataSurface->SurfWinMovableSlats(HeatTransSurfNum)) {
12645 : InsideDifReflectance =
12646 0 : General::Interp(constructionSh.BlReflectSolDiffBack(SurfWinSlatsAngIndex),
12647 0 : constructionSh.BlReflectSolDiffBack(std::min(Material::MaxSlatAngs, SurfWinSlatsAngIndex + 1)),
12648 : SurfWinSlatsAngInterpFac);
12649 : } else {
12650 0 : InsideDifReflectance = constructionSh.BlReflectSolDiffBack(1);
12651 : }
12652 : }
12653 0 : DifSolarReflW = SolarTrans_ViewFactor * InsideDifReflectance;
12654 :
12655 : // Accumulate total reflected distributed diffuse solar for each zone for subsequent
12656 : // interreflection calcs
12657 0 : InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
12658 :
12659 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12660 : // WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
12661 : // ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
12662 :
12663 : // Now calc diffuse solar absorbed by shade/blind itself
12664 0 : BlNum = state.dataSurface->SurfWinBlindNumber(HeatTransSurfNum);
12665 0 : if (ANY_SHADE_SCREEN(ShadeFlag)) {
12666 : // Calc diffuse solar absorbed by shade or screen [W]
12667 0 : ShBlDifSolarAbsW = SolarTrans_ViewFactor * constructionSh.AbsDiffBackShade;
12668 0 : } else if (ANY_BLIND(ShadeFlag)) {
12669 : // Calc diffuse solar absorbed by blind [W]
12670 0 : if (state.dataSurface->SurfWinMovableSlats(HeatTransSurfNum)) {
12671 0 : AbsDiffBkBl = General::Interp(constructionSh.AbsDiffBackBlind(SurfWinSlatsAngIndex),
12672 0 : constructionSh.AbsDiffBackBlind(std::min(Material::MaxSlatAngs, SurfWinSlatsAngIndex + 1)),
12673 : SurfWinSlatsAngInterpFac);
12674 : } else {
12675 0 : AbsDiffBkBl = constructionSh.AbsDiffBackBlind(1);
12676 : }
12677 0 : ShBlDifSolarAbsW = SolarTrans_ViewFactor * AbsDiffBkBl;
12678 : }
12679 : // Correct for divider shadowing
12680 0 : if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
12681 0 : ShBlDifSolarAbsW *= state.dataSurface->SurfaceWindow(HeatTransSurfNum).glazedFrac;
12682 : }
12683 :
12684 : // Accumulate diffuse solar absorbed by shade or screen [W/m2] for heat balance calcs
12685 0 : state.dataSurface->SurfWinInitialDifSolAbsByShade(HeatTransSurfNum) +=
12686 0 : (ShBlDifSolarAbsW / state.dataSurface->Surface(HeatTransSurfNum).Area);
12687 :
12688 : // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
12689 : // below
12690 0 : DifSolarAbsW += ShBlDifSolarAbsW;
12691 :
12692 : // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
12693 : // WinDifSolarDistAbsorbedTotl += ShBlDifSolarAbsW; // debug
12694 : // ZoneDifSolarDistAbsorbedTotl += ShBlDifSolarAbsW; // debug
12695 :
12696 : // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
12697 : // conservation of energy This is not very effective since it assigns whatever distributed diffuse
12698 : // solar has not been absorbed or reflected to transmitted.
12699 0 : DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
12700 : // WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12701 : // ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
12702 :
12703 : // Accumulate transmitted diffuse solar for reporting
12704 0 : state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) +=
12705 0 : (SolarTrans_ViewFactor - DifSolarReflW) / state.dataSurface->Surface(HeatTransSurfNum).Area;
12706 :
12707 : } // End of shading flag check
12708 :
12709 : // HERE 8/14/07 Ignore absorptance and reflectance of Frames and Dividers for now.
12710 : // I would need revised view factors that included these surface types.
12711 : // By ignoring them here, the diffuse solar is accounted for on the other surfaces
12712 :
12713 : // IF(SurfaceWindow(HeatTransSurfNum)%FrameArea > 0.0) THEN ! Window has a frame
12714 : // Note that FrameQRadInAbs is initially calculated in InitSolarHeatGains
12715 : // END IF
12716 :
12717 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerArea > 0.0) THEN ! Window has dividers
12718 : // DividerSolAbs = SurfaceWindow(HeatTransSurfNum)%DividerSolAbsorp
12719 : // IF(SurfaceWindow(HeatTransSurfNum)%DividerType == Suspended) THEN ! Suspended divider;
12720 : // account for inside glass
12721 : // MatNumGl = Construct(ConstrNum)%LayerPoint(Construct(ConstrNum)%TotLayers)
12722 : // TransGl = dataMaterial.Material(MatNumGl)%Trans
12723 : // ReflGl = dataMaterial.Material(MatNumGl)%ReflectSolDiffBack
12724 : // AbsGl = 1.0d0-TransGl-ReflGl
12725 : // DividerSolRefl = 1.0d0-DividerSolAbs
12726 : // DividerSolAbs = AbsGl + TransGl*(DividerSolAbs +
12727 : // DividerSolRefl*AbsGl)/(1.0d0-DividerSolRefl*ReflGl)
12728 : // END IF
12729 : // Correct for interior shade transmittance
12730 : // IF(ShadeFlag == IntShadeOn) THEN
12731 : // MatNumSh = Construct(ConstrNumSh)%LayerPoint(Construct(ConstrNumSh)%TotLayers)
12732 : // DividerSolAbs = DividerSolAbs * dataMaterial.Material(MatNumSh)%Trans
12733 : // ELSE IF(ShadeFlag == WinShadingType::IntBlind) THEN
12734 : // DividerSolAbs = DividerSolAbs *
12735 : // InterpSlatAng(SurfaceWindow(HeatTransSurfNum)%SlatAngThisTS, &
12736 : // SurfaceWindow(HeatTransSurfNum)%MovableSlats,Blind(BlNum)%SolBackDiffDiffTrans)
12737 : // END IF
12738 : // Note that DividerQRadInAbs is initially calculated in InitSolarHeatGains
12739 :
12740 : // END IF ! Window has dividers
12741 : } // opaque or window heat transfer surface
12742 :
12743 : } // HeatTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
12744 7495 : state.dataHeatBal->EnclSolInitialDifSolReflW(IntWinEnclosureNum) += InitialZoneDifSolReflW_zone;
12745 :
12746 : // Check debug var for view factors here
12747 : // ViewFactorTotal
12748 : // Check debug vars for individual transmitting surfaces here
12749 : // WinDifSolarDistTotl = WinDifSolarDistAbsorbedTotl + WinDifSolarDistReflectedTotl +
12750 : // WinDifSolarDistTransmittedTotl; //Debug
12751 : // WinDifSolarTrans
12752 7495 : }
12753 :
12754 24 : void CalcComplexWindowOverlap(EnergyPlusData &state,
12755 : BSDFGeomDescr &Geom, // State Geometry
12756 : BSDFWindowGeomDescr const &Window, // Window Geometry
12757 : int const ISurf // Surface number of the complex fenestration
12758 : )
12759 : {
12760 : // SUBROUTINE INFORMATION:
12761 : // AUTHOR Simon Vidanovic
12762 : // DATE WRITTEN May 2012
12763 : // MODIFIED Simon Vidanovic (May 2013) - added overlaps calculations for daylighting
12764 : // RE-ENGINEERED na
12765 :
12766 : // PURPOSE OF THIS SUBROUTINE:
12767 : // For each of basis directions on back surface of the window calculates
12768 : // overlap areas. It also calculates overlap areas and reflectances for daylighting calculations
12769 :
12770 : using namespace Vectors;
12771 :
12772 : Real64 XShadowProjection; // temporary buffer
12773 : Real64 YShadowProjection; // temporary buffer
12774 :
12775 : Real64 XSp; // for calc BSDF projection direction
12776 : Real64 YSp; // for calc BSDF projection direction
12777 : Real64 ZSp; // for calc BSDF projection direction
12778 : Real64 SdotX; // temporary variable for manipulating .dot. product
12779 : Real64 SdotY; // temporary variable for manipulating .dot. product
12780 : Real64 SdotZ; // temporary variable for manipulating .dot. product
12781 : int BackSurfaceNumber; // current back surface number
12782 : int NVT; // Number of vertices of back surface
12783 : int NS1; // Number of the figure being overlapped
12784 : int NS2; // Number of the figure doing overlapping
12785 : int NS3; // Location to place results of overlap
12786 : int IRay; // Current ray of BSDF direction
12787 : int KBkSurf; // Current back surface
12788 : int N;
12789 :
12790 : // Daylighting
12791 : int IConst; // Construction number of back surface
12792 : int InsideConLay; // Construction's inside material layer number
12793 : Real64 VisibleReflectance; // Visible reflectance for inside surface material
12794 : Real64 TotAOverlap; // Total overlap area for given outgoing direction
12795 : Real64 TotARhoVisOverlap; // Total overlap area time reflectance for given outgoing direction
12796 :
12797 24 : state.dataSolarShading->XVertex.dimension(state.dataSurface->MaxVerticesPerSurface + 1, 0.0);
12798 24 : state.dataSolarShading->YVertex.dimension(state.dataSurface->MaxVerticesPerSurface + 1, 0.0);
12799 24 : state.dataSolarShading->ZVertex.dimension(state.dataSurface->MaxVerticesPerSurface + 1, 0.0);
12800 :
12801 24 : Geom.AOverlap.dimension(Window.NBkSurf, Geom.Trn.NBasis, 0.0);
12802 24 : Geom.ARhoVisOverlap.dimension(Window.NBkSurf, Geom.Trn.NBasis, 0.0);
12803 24 : Geom.AveRhoVisOverlap.dimension(Geom.Trn.NBasis, 0.0);
12804 :
12805 : // First to calculate and store coordinates of the window surface
12806 24 : state.dataSolarShading->LOCHCA = 1;
12807 24 : int BaseSurf = state.dataSurface->Surface(ISurf).BaseSurf; // Base surface number
12808 :
12809 : // Base surface contains current window surface (ISurf).
12810 : // Since that is case, below transformation should always return ZVT = 0.0
12811 : // for every possible transformation
12812 24 : CTRANS(state, ISurf, BaseSurf, NVT, state.dataSolarShading->XVertex, state.dataSolarShading->YVertex, state.dataSolarShading->ZVertex);
12813 :
12814 : // HTRANS routine is using coordinates stored in XVS and YVS in order to calculate
12815 : // surface area. Since both projections are equal to zero, then simply
12816 : // compy these values into XVS and YVS arrays
12817 120 : for (N = 1; N <= NVT; ++N) {
12818 96 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVertex(N);
12819 96 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVertex(N);
12820 : }
12821 :
12822 : // This calculates the area stored in XVS and YVS
12823 24 : HTRANS1(state, state.dataSolarShading->LOCHCA, NVT);
12824 :
12825 : // Calculation of overlap areas for each outgoing basis direction
12826 1944 : for (IRay = 1; IRay <= Geom.Trn.NBasis; ++IRay) { // basis directions loop (on back surface)
12827 : // For current basis direction calculate dot product between window surface
12828 : // and basis direction. This will be used to calculate projection of each
12829 : // of the back surfaces to window surface for given basis direciton
12830 1920 : SdotX = dot(state.dataSurface->Surface(ISurf).lcsx, Geom.sTrn(IRay));
12831 1920 : SdotY = dot(state.dataSurface->Surface(ISurf).lcsy, Geom.sTrn(IRay));
12832 1920 : SdotZ = dot(state.dataSurface->Surface(ISurf).lcsz, Geom.sTrn(IRay));
12833 1920 : XSp = -SdotX;
12834 1920 : YSp = -SdotY;
12835 1920 : ZSp = -SdotZ;
12836 :
12837 : // Projection of shadows for current basis direciton
12838 1920 : if (std::abs(ZSp) > Constant::SmallDistance) {
12839 1920 : XShadowProjection = XSp / ZSp;
12840 1920 : YShadowProjection = YSp / ZSp;
12841 1920 : if (std::abs(XShadowProjection) < 1.e-8) XShadowProjection = 0.0;
12842 1920 : if (std::abs(YShadowProjection) < 1.e-8) YShadowProjection = 0.0;
12843 : } else {
12844 0 : XShadowProjection = 0.0;
12845 0 : YShadowProjection = 0.0;
12846 : }
12847 :
12848 14244 : for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
12849 : // BaseSurf = Surface(ISurf).BaseSurf
12850 12324 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
12851 :
12852 : // Transform coordinates of back surface from general system to the
12853 : // plane of the receiving surface
12854 12324 : CTRANS(state,
12855 : BackSurfaceNumber,
12856 : BaseSurf,
12857 : NVT,
12858 12324 : state.dataSolarShading->XVertex,
12859 12324 : state.dataSolarShading->YVertex,
12860 12324 : state.dataSolarShading->ZVertex);
12861 :
12862 : // Project "shadow" from back surface along sun's rays to receiving surface. Back surface vertices
12863 : // become clockwise sequential.
12864 :
12865 61620 : for (N = 1; N <= NVT; ++N) {
12866 49296 : state.dataSolarShading->YVS(N) = state.dataSolarShading->YVertex(N) - YShadowProjection * state.dataSolarShading->ZVertex(N);
12867 49296 : state.dataSolarShading->XVS(N) = state.dataSolarShading->XVertex(N) - XShadowProjection * state.dataSolarShading->ZVertex(N);
12868 : }
12869 :
12870 : // Transform to the homogeneous coordinate system.
12871 :
12872 12324 : NS3 = state.dataSolarShading->LOCHCA + 1;
12873 12324 : state.dataSolarShading->HCT(NS3) = 0.0;
12874 12324 : HTRANS1(state, NS3, NVT);
12875 :
12876 : // Determine area of overlap of projected back surface and receiving surface.
12877 :
12878 12324 : NS1 = 1;
12879 12324 : NS2 = NS3;
12880 12324 : state.dataSolarShading->HCT(NS3) = 1.0;
12881 12324 : DeterminePolygonOverlap(state, NS1, NS2, NS3);
12882 :
12883 12324 : if (state.dataSolarShading->OverlapStatus == NoOverlap) continue; // to next back surface
12884 4624 : if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
12885 0 : break; // back surfaces DO loop
12886 :
12887 4624 : state.dataSolarShading->LOCHCA = NS3;
12888 4624 : state.dataSolarShading->HCNS(state.dataSolarShading->LOCHCA) = BackSurfaceNumber;
12889 4624 : state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
12890 :
12891 4624 : Geom.AOverlap(KBkSurf, IRay) = state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
12892 : } // DO KBkSurf = 1 , NBkSurf
12893 :
12894 : // If some of back surfaces is contained in base surface, then need to substract shadow of subsurface
12895 : // from shadow on base surface. Reson is that above shadowing algorithm is calculating shadow wihtout
12896 : // influence of subsurfaces
12897 14244 : for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
12898 12324 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
12899 : // CurBaseSurf is Current base surface number for shadow overlap calcualtions
12900 12324 : int CurBaseSurf = state.dataSurface->Surface(BackSurfaceNumber).BaseSurf;
12901 12324 : if (CurBaseSurf != BackSurfaceNumber) {
12902 : // Search if that base surface in list of back surfaces for current window
12903 : // CurBackSurface is Current back surface number for base surface
12904 2724 : int CurBackSurface = 0;
12905 5366 : for (N = 1; N <= Window.NBkSurf; ++N) {
12906 5366 : if (state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(N) == CurBaseSurf) {
12907 2724 : CurBackSurface = N;
12908 2724 : break;
12909 : }
12910 : }
12911 2724 : if (CurBackSurface != 0) {
12912 2724 : Geom.AOverlap(CurBackSurface, IRay) -= Geom.AOverlap(KBkSurf, IRay);
12913 : }
12914 : }
12915 : }
12916 :
12917 : // Calculate overlap area times reflectance. This is necessary for complex fenestration daylighting
12918 : // calculations
12919 1920 : TotAOverlap = 0.0;
12920 1920 : TotARhoVisOverlap = 0.0;
12921 14244 : for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
12922 12324 : BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
12923 12324 : IConst = state.dataSurface->Surface(BackSurfaceNumber).Construction;
12924 12324 : InsideConLay = state.dataConstruction->Construct(IConst).TotLayers;
12925 12324 : if (state.dataSurface->SurfWinWindowModelType(BackSurfaceNumber) == WindowModel::BSDF) {
12926 2724 : VisibleReflectance = state.dataConstruction->Construct(IConst).ReflectVisDiffBack;
12927 : } else {
12928 9600 : VisibleReflectance = (1.0 - dynamic_cast<Material::MaterialChild *>(state.dataMaterial->Material(InsideConLay))->AbsorpVisible);
12929 : }
12930 12324 : Geom.ARhoVisOverlap(KBkSurf, IRay) = Geom.AOverlap(KBkSurf, IRay) * VisibleReflectance;
12931 12324 : TotAOverlap += Geom.AOverlap(KBkSurf, IRay);
12932 12324 : TotARhoVisOverlap += Geom.ARhoVisOverlap(KBkSurf, IRay);
12933 : }
12934 :
12935 1920 : if (TotAOverlap != 0.0) {
12936 1920 : Geom.AveRhoVisOverlap(IRay) = TotARhoVisOverlap / TotAOverlap;
12937 : }
12938 :
12939 : } // DO IRay = 1, Geom%Trn%NBasis
12940 :
12941 : // Reset back shadowing counter since complex windows do not need it anymore
12942 24 : state.dataSolarShading->LOCHCA = 1;
12943 24 : }
12944 :
12945 2804678 : void TimestepInitComplexFenestration(EnergyPlusData &state)
12946 : {
12947 : // SUBROUTINE INFORMATION:
12948 : // AUTHOR Simon Vidanovic
12949 : // DATE WRITTEN May 2012
12950 : // MODIFIED May 2012 (Initialize complex fenestration in case of EMS)
12951 : // RE-ENGINEERED na
12952 :
12953 : // PURPOSE OF THIS SUBROUTINE:
12954 : // Performs initialization of complex fenestration. It also performs check if current surface containing
12955 : // complex fenestration have construction changed (by EMS) in which case performs addition of current states
12956 : // into complex fenestration array
12957 :
12958 : using WindowComplexManager::CheckCFSStates;
12959 :
12960 : // Locals
12961 : int iSurf; // Current surface number
12962 : int iState; // current state number
12963 : int NumOfStates; // number of states for current window
12964 :
12965 179412538 : for (iSurf = 1; iSurf <= state.dataSurface->TotSurfaces; ++iSurf) {
12966 176607860 : if (state.dataSurface->SurfWinWindowModelType(iSurf) == WindowModel::BSDF) {
12967 : // This will check complex fenestrations state and add new one if necessary (EMS case)
12968 39540 : CheckCFSStates(state, iSurf);
12969 :
12970 39540 : NumOfStates = state.dataBSDFWindow->ComplexWind(iSurf).NumStates;
12971 :
12972 : // Check for overlap areas and initialize if necessary
12973 79080 : for (iState = 1; iState <= NumOfStates; ++iState) {
12974 : // do initialization only once
12975 39540 : if (state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState).InitState) {
12976 24 : CalcComplexWindowOverlap(
12977 24 : state, state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState), state.dataBSDFWindow->ComplexWind(iSurf), iSurf);
12978 24 : state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState).InitState = false;
12979 : }
12980 : }
12981 : }
12982 : }
12983 2804678 : }
12984 :
12985 : } // namespace EnergyPlus::SolarShading
|