LCOV - code coverage report
Current view: top level - EnergyPlus - SolarShading.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 4299 6178 69.6 %
Date: 2024-08-24 18:31:18 Functions: 53 61 86.9 %

          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

Generated by: LCOV version 1.14