LCOV - code coverage report
Current view: top level - EnergyPlus - SolarShading.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 53.9 % 5976 3221
Test Date: 2025-05-22 16:09:37 Functions: 83.6 % 61 51

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <algorithm>
      50              : #include <cassert>
      51              : #include <cmath>
      52              : #include <memory>
      53              : 
      54              : // ObjexxFCL Headers
      55              : #include <ObjexxFCL/Array.functions.hh>
      56              : #include <ObjexxFCL/Vector3.hh>
      57              : #include <ObjexxFCL/member.functions.hh>
      58              : 
      59              : // EnergyPlus Headers
      60              : #include <EnergyPlus/CommandLineInterface.hh>
      61              : #include <EnergyPlus/Construction.hh>
      62              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      63              : #include <EnergyPlus/DataDaylightingDevices.hh>
      64              : #include <EnergyPlus/DataEnvironment.hh>
      65              : #include <EnergyPlus/DataErrorTracking.hh>
      66              : #include <EnergyPlus/DataHeatBalSurface.hh>
      67              : #include <EnergyPlus/DataHeatBalance.hh>
      68              : #include <EnergyPlus/DataIPShortCuts.hh>
      69              : #include <EnergyPlus/DataReportingFlags.hh>
      70              : #include <EnergyPlus/DataShadowingCombinations.hh>
      71              : #include <EnergyPlus/DataStringGlobals.hh>
      72              : #include <EnergyPlus/DataSurfaces.hh>
      73              : #include <EnergyPlus/DataSystemVariables.hh>
      74              : #include <EnergyPlus/DataViewFactorInformation.hh>
      75              : #include <EnergyPlus/DataWindowEquivalentLayer.hh>
      76              : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      77              : #include <EnergyPlus/DaylightingDevices.hh>
      78              : #include <EnergyPlus/DaylightingManager.hh>
      79              : #include <EnergyPlus/DisplayRoutines.hh>
      80              : #include <EnergyPlus/EMSManager.hh>
      81              : #include <EnergyPlus/EnergyPlusLogger.hh>
      82              : // #include <EnergyPlus/General.hh>
      83              : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
      84              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      85              : #include <EnergyPlus/OutputProcessor.hh>
      86              : #include <EnergyPlus/OutputReportPredefined.hh>
      87              : #include <EnergyPlus/PluginManager.hh>
      88              : #include <EnergyPlus/ScheduleManager.hh>
      89              : #include <EnergyPlus/SolarReflectionManager.hh>
      90              : #include <EnergyPlus/SolarShading.hh>
      91              : #include <EnergyPlus/UtilityRoutines.hh>
      92              : #include <EnergyPlus/Vectors.hh>
      93              : #include <EnergyPlus/WindowComplexManager.hh>
      94              : #include <EnergyPlus/WindowEquivalentLayer.hh>
      95              : #include <EnergyPlus/WindowManager.hh>
      96              : #include <EnergyPlus/WindowManagerExteriorData.hh>
      97              : #include <EnergyPlus/WindowModel.hh>
      98              : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      99              : #include <WCEMultiLayerOptics.hpp>
     100              : 
     101              : namespace EnergyPlus::SolarShading {
     102              : 
     103              : // MODULE INFORMATION:
     104              : //       AUTHOR         Rick Strand
     105              : //       DATE WRITTEN   March 1997
     106              : //       MODIFIED       December 1998, FCW
     107              : //       MODIFIED       July 1999, Linda Lawrie, eliminate shadefl.scr,
     108              : //                      do shadowing calculations during simulation
     109              : //       MODIFIED       June 2001, FCW, handle window blinds
     110              : //       MODIFIED       May 2004, LKL, Polygons > 4 sides (not subsurfaces)
     111              : //       MODIFIED       January 2007, LKL, Taking parameters back to original integer (HC)
     112              : //       MODIFIED       August 2011, JHK, Including Complex Fenestration optical calculations
     113              : //       MODIFIED       November 2012, BG, Timestep solar and daylighting calculations
     114              : //       RE-ENGINEERED  na
     115              : 
     116              : // PURPOSE OF THIS MODULE:
     117              : // The purpose of this module is to encompass the routines and data
     118              : // which are need to perform the solar calculations in EnergyPlus.
     119              : // This also requires that shading and geometry routines and data
     120              : // which are used by the solar calculations be included in this module.
     121              : 
     122              : // METHODOLOGY EMPLOYED:
     123              : // Many of the methods used in this module have been carried over from the
     124              : // (I)BLAST program.  As such, there is not much documentation on the
     125              : // methodology used.  The original code was written mainly by George
     126              : // Walton and requires coordinate transformations.  It calculates
     127              : // shading using an overlapping polygon approach.
     128              : 
     129              : // REFERENCES:
     130              : // TARP Manual, NIST Publication.
     131              : // Passive Solar Extension of the BLAST Program, CERL/UIUC Publication.
     132              : 
     133              : using namespace DataEnvironment;
     134              : using namespace DataHeatBalance;
     135              : using namespace DataSurfaces;
     136              : using namespace DataShadowingCombinations;
     137              : using namespace SolarReflectionManager;
     138              : using namespace DataVectorTypes;
     139              : using namespace Window;
     140              : using namespace FenestrationCommon;
     141              : using namespace SingleLayerOptics;
     142              : 
     143              : int constexpr NPhi = 6;                                // Number of altitude angle steps for sky integration
     144              : int constexpr NTheta = 24;                             // Number of azimuth angle steps for sky integration
     145              : Real64 constexpr Eps = 1.e-10;                         // Small number
     146              : Real64 constexpr DPhi = Constant::PiOvr2 / NPhi;       // Altitude step size
     147              : Real64 constexpr DTheta = 2.0 * Constant::Pi / NTheta; // Azimuth step size
     148              : Real64 constexpr DThetaDPhi = DTheta * DPhi;           // Product of DTheta and DPhi
     149              : Real64 constexpr PhiMin = 0.5 * DPhi;                  // Minimum altitude
     150              : 
     151              : Real64 constexpr HCMULT = 100000.0; // Multiplier used to change meters to .01 millimeters for homogeneous coordinates.
     152              :                                     // Homogeneous Coordinates are represented in integers (64 bit). This changes the surface coordinates from meters
     153              :                                     // to .01 millimeters -- making that the resolution for shadowing, polygon clipping, etc.
     154              : Real64 constexpr sqHCMULT = (HCMULT * HCMULT);    // Square of HCMult used in Homogeneous coordinates
     155              : Real64 constexpr sqHCMULT_fac = (0.5 / sqHCMULT); // ( 0.5 / sqHCMULT ) factor
     156              : 
     157              : // Parameters for use with the variable OverlapStatus...
     158              : int constexpr NoOverlap = 1;
     159              : int constexpr FirstSurfWithinSecond = 2;
     160              : int constexpr SecondSurfWithinFirst = 3;
     161              : int constexpr PartialOverlap = 4;
     162              : int constexpr TooManyVertices = 5;
     163              : int constexpr TooManyFigures = 6;
     164              : 
     165          119 : void InitSolarCalculations(EnergyPlusData &state)
     166              : {
     167              : 
     168              :     // SUBROUTINE INFORMATION:
     169              :     //       AUTHOR         George Walton
     170              :     //       DATE WRITTEN   September 1977
     171              :     //       MODIFIED       na
     172              :     //       RE-ENGINEERED  Mar97, RKS, Initial EnergyPlus Version
     173              : 
     174              :     // PURPOSE OF THIS SUBROUTINE:
     175              :     // This routine controls the computation of the solar flux multipliers.
     176              : 
     177              :     // METHODOLOGY EMPLOYED:
     178              :     // All shadowing calculations have been grouped under this routine to
     179              :     // allow segmentation separating it from the hourly loads calculation.
     180              : 
     181          119 :     auto &s_surf = state.dataSurface;
     182              : #ifdef EP_Count_Calls
     183              :     ++state.dataTimingsData->NumInitSolar_Calls;
     184              : #endif
     185          119 :     if (state.dataGlobal->BeginSimFlag) {
     186          114 :         if (state.files.outputControl.shd) {
     187          114 :             state.dataSolarShading->shd_stream =
     188          228 :                 std::make_unique<std::fstream>(state.dataStrGlobals->outputShdFilePath, std::ios_base::out | std::ios_base::trunc);
     189          114 :             if (!state.dataSolarShading->shd_stream) {
     190            0 :                 ShowFatalError(
     191            0 :                     state, format("InitSolarCalculations: Could not open file \"{}\" for output (write).", state.dataStrGlobals->outputShdFilePath));
     192              :             }
     193              :         } else {
     194            0 :             state.dataSolarShading->shd_stream = std::make_unique<std::iostream>(nullptr);
     195              :         }
     196              : 
     197          114 :         if (state.dataSolarShading->GetInputFlag) {
     198          111 :             checkShadingSurfaceSchedules(state);
     199          111 :             processShadowingInput(state);
     200          111 :             state.dataSolarShading->GetInputFlag = false;
     201          222 :             state.dataSolarShading->MaxHCV =
     202          111 :                 (((max(15, s_surf->MaxVerticesPerSurface) + 16) / 16) * 16) - 1; // Assure MaxHCV+1 is multiple of 16 for 128 B alignment
     203          111 :             assert((state.dataSolarShading->MaxHCV + 1) % 16 == 0);
     204              :         }
     205              : 
     206          114 :         if (state.dataSolarShading->firstTime) DisplayString(state, "Allocate Solar Module Arrays");
     207          114 :         AllocateModuleArrays(state);
     208              : 
     209          114 :         if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::FullInteriorExterior) {
     210          104 :             if (state.dataSolarShading->firstTime) DisplayString(state, "Computing Interior Solar Absorption Factors");
     211          104 :             ComputeIntSolarAbsorpFactors(state);
     212              :         }
     213              : 
     214          114 :         if (state.dataSolarShading->firstTime) DisplayString(state, "Determining Shadowing Combinations");
     215          114 :         DetermineShadowingCombinations(state);
     216          114 :         state.dataSolarShading->shd_stream.reset(); // Done writing to shd file
     217              : 
     218          114 :         if (state.dataSolarShading->firstTime) DisplayString(state, "Computing Window Shade Absorption Factors");
     219          114 :         ComputeWinShadeAbsorpFactors(state);
     220              : 
     221          114 :         if (s_surf->CalcSolRefl) {
     222            0 :             DisplayString(state, "Initializing Solar Reflection Factors");
     223            0 :             InitSolReflRecSurf(state);
     224              :         }
     225              : 
     226          114 :         if (state.dataSolarShading->firstTime) DisplayString(state, "Proceeding with Initializing Solar Calculations");
     227              :     }
     228              : 
     229          119 :     if (state.dataGlobal->BeginEnvrnFlag) {
     230          107 :         state.dataSolarShading->SurfSunCosTheta = 0.0;
     231          107 :         state.dataSolarShading->SurfSunlitArea = 0.0;
     232          107 :         s_surf->SurfSunlitArea = 0.0;
     233          107 :         s_surf->SurfSunlitFrac = 0.0;
     234          107 :         state.dataHeatBal->SurfSunlitFracHR = 0.0;
     235          107 :         state.dataHeatBal->SurfSunlitFrac = 0.0;
     236          107 :         state.dataHeatBal->SurfSunlitFracWithoutReveal = 0.0;
     237          107 :         state.dataHeatBal->SurfWinBackSurfaces = 0;
     238          107 :         state.dataHeatBal->SurfWinOverlapAreas = 0.0;
     239          107 :         state.dataHeatBal->SurfCosIncAngHR = 0.0;
     240          107 :         state.dataHeatBal->SurfCosIncAng = 0.0;
     241          107 :         state.dataSolarShading->SurfAnisoSkyMult = 1.0; // For isotropic sky; recalculated in AnisoSkyViewFactors if anisotropic radiance
     242              :         //    WithShdgIsoSky=0.0
     243              :         //    WoShdgIsoSky=0.0
     244              :         //    WithShdgHoriz=0.0
     245              :         //    WoShdgHoriz=0.0
     246              :         //    DifShdgRatioIsoSky=0.0
     247              :         //    DifShdgRatioHoriz=0.0
     248          107 :         state.dataSolarShading->SurfMultIsoSky = 0.0;
     249          107 :         state.dataSolarShading->SurfMultCircumSolar = 0.0;
     250          107 :         state.dataSolarShading->SurfMultHorizonZenith = 0.0;
     251          107 :         state.dataSolarShading->SurfWinRevealStatus = 0;
     252              : 
     253          234 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
     254          127 :             state.dataHeatBal->ZoneWinHeatGain(zoneNum) = 0.0;
     255          127 :             state.dataHeatBal->ZoneWinHeatGainRep(zoneNum) = 0.0;
     256          127 :             state.dataHeatBal->ZoneWinHeatLossRep(zoneNum) = 0.0;
     257          127 :             state.dataHeatBal->ZoneWinHeatGainRepEnergy(zoneNum) = 0.0;
     258          127 :             state.dataHeatBal->ZoneWinHeatLossRepEnergy(zoneNum) = 0.0;
     259          127 :             state.dataHeatBal->ZoneOpaqSurfInsFaceCond(zoneNum) = 0.0;
     260          127 :             state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep(zoneNum) = 0.0;
     261          127 :             state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep(zoneNum) = 0.0;
     262          127 :             state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg(zoneNum) = 0.0;
     263          127 :             state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg(zoneNum) = 0.0;
     264              :         }
     265          243 :         for (int enclNum = 1; enclNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclNum) {
     266          136 :             state.dataHeatBal->ZoneTransSolar(enclNum) = 0.0;
     267          136 :             state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclNum) = 0.0;
     268          136 :             state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclNum) = 0.0;
     269          136 :             state.dataHeatBal->EnclSolInitialDifSolReflW(enclNum) = 0.0;
     270          136 :             state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclNum) = 0.0;
     271          136 :             state.dataHeatBal->ZoneDifSolFrIntWinsRep(enclNum) = 0.0;
     272          136 :             state.dataHeatBal->ZoneTransSolarEnergy(enclNum) = 0.0;
     273          136 :             state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclNum) = 0.0;
     274          136 :             state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclNum) = 0.0;
     275          136 :             state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclNum) = 0.0;
     276          136 :             state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy(enclNum) = 0.0;
     277              :         }
     278          878 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
     279          771 :             state.dataHeatBal->SurfQRadSWOutIncident(SurfNum) = 0.0;
     280          771 :             state.dataHeatBal->SurfQRadSWOutIncidentBeam(SurfNum) = 0.0;
     281          771 :             state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = 0.0;
     282          771 :             state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) = 0.0;
     283          771 :             state.dataHeatBal->SurfIntBmIncInsSurfIntensRep(SurfNum) = 0.0;
     284          771 :             state.dataHeatBal->SurfIntBmIncInsSurfAmountRep(SurfNum) = 0.0;
     285          771 :             state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse(SurfNum) = 0.0;
     286          771 :             state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse(SurfNum) = 0.0;
     287          771 :             state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd(SurfNum) = 0.0;
     288          771 :             state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd(SurfNum) = 0.0;
     289          771 :             state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs(SurfNum) = 0.0;
     290          771 :             state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs(SurfNum) = 0.0;
     291          771 :             state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs(SurfNum) = 0.0;
     292          771 :             state.dataHeatBal->SurfCosIncidenceAngle(SurfNum) = 0.0;
     293          771 :             state.dataHeatBal->SurfSWInAbsTotalReport(SurfNum) = 0.0;
     294          771 :             state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) = 0.0;
     295          771 :             state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy(SurfNum) = 0.0;
     296          771 :             state.dataHeatBal->SurfInitialDifSolInAbsReport(SurfNum) = 0.0;
     297              :         }
     298          234 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
     299          272 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
     300          145 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
     301          145 :                 int const firstSurfWin = thisSpace.WindowSurfaceFirst;
     302          145 :                 int const lastSurfWin = thisSpace.WindowSurfaceLast;
     303          191 :                 for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
     304              : 
     305           46 :                     s_surf->SurfWinTransSolar(SurfNum) = 0.0;
     306           46 :                     s_surf->SurfWinBmSolar(SurfNum) = 0.0;
     307           46 :                     s_surf->SurfWinBmBmSolar(SurfNum) = 0.0;
     308           46 :                     s_surf->SurfWinBmDifSolar(SurfNum) = 0.0;
     309           46 :                     s_surf->SurfWinDifSolar(SurfNum) = 0.0;
     310              : 
     311           46 :                     s_surf->SurfWinTransSolarEnergy(SurfNum) = 0.0;
     312           46 :                     s_surf->SurfWinBmSolarEnergy(SurfNum) = 0.0;
     313           46 :                     s_surf->SurfWinBmBmSolarEnergy(SurfNum) = 0.0;
     314           46 :                     s_surf->SurfWinBmDifSolarEnergy(SurfNum) = 0.0;
     315              : 
     316           46 :                     s_surf->SurfWinHeatGain(SurfNum) = 0.0;
     317           46 :                     s_surf->SurfWinHeatGainRep(SurfNum) = 0.0;
     318           46 :                     s_surf->SurfWinHeatLossRep(SurfNum) = 0.0;
     319              :                 }
     320          191 :                 for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
     321           46 :                     s_surf->SurfWinGainConvGlazToZoneRep(SurfNum) = 0.0;
     322           46 :                     s_surf->SurfWinGainIRGlazToZoneRep(SurfNum) = 0.0;
     323           46 :                     s_surf->SurfWinLossSWZoneToOutWinRep(SurfNum) = 0.0;
     324           46 :                     s_surf->SurfWinGainFrameDividerToZoneRep(SurfNum) = 0.0;
     325           46 :                     s_surf->SurfWinGainConvShadeToZoneRep(SurfNum) = 0.0;
     326           46 :                     s_surf->SurfWinGainIRShadeToZoneRep(SurfNum) = 0.0;
     327           46 :                     s_surf->SurfWinGapConvHtFlowRep(SurfNum) = 0.0;
     328           46 :                     s_surf->SurfWinShadingAbsorbedSolar(SurfNum) = 0.0;
     329              : 
     330           46 :                     s_surf->SurfWinSysSolTransmittance(SurfNum) = 0.0;
     331           46 :                     s_surf->SurfWinSysSolReflectance(SurfNum) = 0.0;
     332           46 :                     s_surf->SurfWinSysSolAbsorptance(SurfNum) = 0.0;
     333              :                 }
     334          191 :                 for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
     335           46 :                     s_surf->SurfWinDifSolarEnergy(SurfNum) = 0.0;
     336           46 :                     s_surf->SurfWinHeatGainRepEnergy(SurfNum) = 0.0;
     337           46 :                     s_surf->SurfWinHeatLossRepEnergy(SurfNum) = 0.0;
     338           46 :                     s_surf->SurfWinGapConvHtFlowRepEnergy(SurfNum) = 0.0;
     339           46 :                     s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfNum) = 0.0;
     340              : 
     341           46 :                     state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfNum) = 0.0;
     342           46 :                     state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfNum) = 0.0;
     343           46 :                     state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfNum) = 0.0;
     344           46 :                     state.dataHeatBal->SurfWinInitialDifSolInTransReport(SurfNum) = 0.0;
     345              : 
     346           46 :                     s_surf->SurfWinInsideGlassCondensationFlag(SurfNum) = 0;
     347           46 :                     s_surf->SurfWinInsideFrameCondensationFlag(SurfNum) = 0;
     348           46 :                     s_surf->SurfWinInsideDividerCondensationFlag(SurfNum) = 0;
     349              :                 }
     350              :             }
     351              :         }
     352              :     }
     353              : 
     354              :     // Initialize these once
     355          833 :     for (int IPhi = 1; IPhi <= NPhi; ++IPhi) {   // Loop over patch altitude values
     356          714 :         Real64 Phi = PhiMin + (IPhi - 1) * DPhi; // 7.5,22.5,37.5,52.5,67.5,82.5 for NPhi = 6
     357          714 :         state.dataSolarShading->sin_Phi.push_back(std::sin(Phi));
     358          714 :         state.dataSolarShading->cos_Phi.push_back(std::cos(Phi));
     359              :     }
     360              : 
     361         2975 :     for (int ITheta = 1; ITheta <= NTheta; ++ITheta) { // Loop over patch azimuth values
     362         2856 :         Real64 Theta = (ITheta - 1) * DTheta;          // 0,15,30,....,330,345 for NTheta = 24
     363         2856 :         state.dataSolarShading->sin_Theta.push_back(std::sin(Theta));
     364         2856 :         state.dataSolarShading->cos_Theta.push_back(std::cos(Theta));
     365              :     }
     366              : 
     367          119 :     state.dataSolarShading->firstTime = false;
     368          119 : }
     369              : 
     370          112 : void checkShadingSurfaceSchedules(EnergyPlusData &state)
     371              : {
     372          112 :     auto &s_surf = state.dataSurface;
     373              : 
     374              :     // Shading surfaces with a transmittance schedule that is always 1.0 are marked IsTransparent during shading surface input processing
     375              :     // Now that EMS (and other types) actuators are set up, check to see if the schedule has an actuator and reset if needed
     376          158 :     for (int surfNum = s_surf->ShadingSurfaceFirst; surfNum <= s_surf->ShadingSurfaceLast; ++surfNum) {
     377           46 :         auto &thisSurface = s_surf->Surface(surfNum);
     378           46 :         if (!thisSurface.IsTransparent) continue;
     379              :         // creating some dummy bools here on purpose -- we need to do some renaming and/or consolidate these into a meaningful new global sometime
     380              :         // for now I want the logic to be as readable as possible, so creating shorthand variables makes it very clear
     381            4 :         bool const anyPlugins = size(state.dataPluginManager->plugins) > 0;
     382            4 :         bool const runningByAPI = state.dataGlobal->eplusRunningViaAPI;
     383            4 :         bool const anyEMS = state.dataGlobal->AnyEnergyManagementSystemInModel;
     384            4 :         if ((anyEMS && EMSManager::isScheduleManaged(state, thisSurface.shadowSurfSched)) || runningByAPI || anyPlugins) {
     385              :             // Transmittance schedule definitely has an actuator or may have one via python plugin or API
     386              :             // Set not transparent so it won't be skipped during shading calcs
     387            0 :             thisSurface.IsTransparent = false;
     388              :             // Also set global flags
     389            0 :             state.dataSolarShading->anyScheduledShadingSurface = true;
     390            0 :             s_surf->ShadingTransmittanceVaries = true;
     391            4 :         } else if (!thisSurface.MirroredSurf) {
     392              :             // Warning moved here from shading surface input processing (skip warning for mirrored surfaces)
     393            4 :             ShowWarningError(state,
     394            4 :                              format(R"(Shading Surface="{}", Transmittance Schedule Name="{}", is always transparent.)",
     395            2 :                                     thisSurface.Name,
     396            2 :                                     thisSurface.shadowSurfSched->Name));
     397            6 :             ShowContinueError(state, "This shading surface will be ignored.");
     398              :         }
     399              :     }
     400          112 : }
     401              : 
     402          134 : void GetShadowingInput(EnergyPlusData &state)
     403              : {
     404              :     // SUBROUTINE INFORMATION:
     405              :     //       AUTHOR         Linda K. Lawrie
     406              :     //       DATE WRITTEN   July 1999
     407              :     //       MODIFIED       B. Griffith, Nov 2012, add calculation method
     408              : 
     409              :     // PURPOSE OF THIS SUBROUTINE:
     410              :     // This subroutine gets the Shadowing Calculation object.
     411              : 
     412          134 :     auto &s_surf = state.dataSurface;
     413              : 
     414              :     // Using/Aliasing
     415              :     using DataSystemVariables::ShadingMethod;
     416              : 
     417              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     418              :     int NumItems;
     419              :     int NumNumbers;
     420              :     int NumAlphas;
     421              :     int IOStat;
     422          134 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     423          134 :     state.dataIPShortCut->rNumericArgs({1, 4}) = 0.0; // so if nothing gotten, defaults will be maintained.
     424          134 :     state.dataIPShortCut->cAlphaArgs(1) = "";
     425          134 :     state.dataIPShortCut->cAlphaArgs(2) = "";
     426          134 :     cCurrentModuleObject = "ShadowCalculation";
     427          134 :     NumItems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     428          134 :     NumAlphas = 0;
     429          134 :     NumNumbers = 0;
     430          134 :     if (NumItems > 1) {
     431            0 :         ShowWarningError(state, format("{}: More than 1 occurrence of this object found, only first will be used.", cCurrentModuleObject));
     432              :     }
     433              : 
     434          134 :     if (NumItems != 0) {
     435           46 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     436              :                                                                  cCurrentModuleObject,
     437              :                                                                  1,
     438           23 :                                                                  state.dataIPShortCut->cAlphaArgs,
     439              :                                                                  NumAlphas,
     440           23 :                                                                  state.dataIPShortCut->rNumericArgs,
     441              :                                                                  NumNumbers,
     442              :                                                                  IOStat,
     443           23 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     444           23 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     445           23 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     446           23 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     447           23 :         state.dataSolarShading->ShadowingCalcFrequency = state.dataIPShortCut->rNumericArgs(1);
     448              :     }
     449              : 
     450          134 :     if (state.dataSolarShading->ShadowingCalcFrequency <= 0) {
     451              :         //  Set to default value
     452          111 :         state.dataSolarShading->ShadowingCalcFrequency = 20;
     453              :     }
     454          134 :     if (state.dataSolarShading->ShadowingCalcFrequency > 31) {
     455            1 :         ShowWarningError(state, format("{}: suspect {}", cCurrentModuleObject, state.dataIPShortCut->cNumericFieldNames(1)));
     456            1 :         ShowContinueError(state, format("Value entered=[{:.0R}], Shadowing Calculations will be inaccurate.", state.dataIPShortCut->rNumericArgs(1)));
     457              :     }
     458              : 
     459          134 :     if (state.dataIPShortCut->rNumericArgs(2) > 199.0) {
     460           23 :         state.dataSolarShading->MaxHCS = state.dataIPShortCut->rNumericArgs(2);
     461              :     } else {
     462          111 :         state.dataSolarShading->MaxHCS = 15000;
     463              :     }
     464              : 
     465          134 :     int aNum = 1;
     466          134 :     unsigned pixelRes = 512u;
     467          134 :     if (NumAlphas >= aNum) {
     468           23 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Scheduled")) {
     469            0 :             state.dataSysVars->shadingMethod = ShadingMethod::Scheduled;
     470            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Scheduled";
     471            0 :             checkScheduledSurfacePresent(state);
     472           23 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Imported")) {
     473            0 :             if (state.dataSched->ScheduleFileShadingProcessed) {
     474            0 :                 state.dataSysVars->shadingMethod = ShadingMethod::Imported;
     475            0 :                 state.dataIPShortCut->cAlphaArgs(aNum) = "Imported";
     476              :             } else {
     477            0 :                 ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     478            0 :                 ShowContinueError(state,
     479            0 :                                   format("Value entered=\"{}\" while no Schedule:File:Shading object is defined, InternalCalculation will be used.",
     480            0 :                                          state.dataIPShortCut->cAlphaArgs(aNum)));
     481              :             }
     482           23 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "PolygonClipping")) {
     483           19 :             state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
     484           19 :             state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
     485            4 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "PixelCounting")) {
     486            4 :             state.dataSysVars->shadingMethod = ShadingMethod::PixelCounting;
     487            4 :             state.dataIPShortCut->cAlphaArgs(aNum) = "PixelCounting";
     488            4 :             if (NumNumbers >= 3) {
     489            4 :                 pixelRes = (unsigned)state.dataIPShortCut->rNumericArgs(3);
     490              :             }
     491              : #ifdef EP_NO_OPENGL
     492              :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     493              :             ShowContinueError(state, format("Value entered=\"{}\"", state.dataIPShortCut->cAlphaArgs(aNum)));
     494              :             ShowContinueError(state, "This version of EnergyPlus was not compiled to use OpenGL (required for PixelCounting)");
     495              :             ShowContinueError(state, "PolygonClipping will be used instead");
     496              :             state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
     497              :             state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
     498              : #else
     499            4 :             if (Penumbra::Penumbra::is_valid_context()) {
     500            4 :                 std::shared_ptr<EnergyPlusLogger> penumbra_logger = std::make_shared<EnergyPlusLogger>(EnergyPlusLogger::Log_level::Info);
     501            4 :                 state.dataSolarShading->LoggerContext = std::make_pair<EnergyPlusData *, std::string>(&state, "");
     502            4 :                 penumbra_logger->set_message_context(&state.dataSolarShading->LoggerContext);
     503            4 :                 state.dataSolarShading->penumbra = std::make_unique<Penumbra::Penumbra>(pixelRes, penumbra_logger);
     504            4 :             } else {
     505            0 :                 ShowWarningError(state, "No GPU found (required for PixelCounting)");
     506            0 :                 ShowContinueError(state, "PolygonClipping will be used instead");
     507            0 :                 state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
     508            0 :                 state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
     509              :             }
     510              : #endif
     511              :         } else {
     512            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     513            0 :             ShowContinueError(state, format("Value entered=\"{}\", PolygonClipping will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     514              :         }
     515              :     } else {
     516          111 :         state.dataIPShortCut->cAlphaArgs(aNum) = "PolygonClipping";
     517          111 :         state.dataSysVars->shadingMethod = ShadingMethod::PolygonClipping;
     518              :     }
     519              : 
     520          134 :     aNum++;
     521          134 :     if (NumAlphas >= aNum) {
     522           23 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Periodic")) {
     523           14 :             state.dataSysVars->DetailedSolarTimestepIntegration = false;
     524           14 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
     525            9 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Timestep")) {
     526            9 :             state.dataSysVars->DetailedSolarTimestepIntegration = true;
     527            9 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Timestep";
     528              :         } else {
     529            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     530            0 :             ShowContinueError(state, format("Value entered=\"{}\", Periodic will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     531            0 :             state.dataSysVars->DetailedSolarTimestepIntegration = false;
     532            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
     533              :         }
     534              :     } else {
     535          111 :         state.dataSysVars->DetailedSolarTimestepIntegration = false;
     536          111 :         state.dataIPShortCut->cAlphaArgs(aNum) = "Periodic";
     537              :     }
     538              : 
     539          134 :     aNum++;
     540          134 :     if (NumAlphas >= aNum) {
     541           13 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SutherlandHodgman")) {
     542            9 :             state.dataSysVars->SutherlandHodgman = true;
     543            9 :             state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
     544            4 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "ConvexWeilerAtherton")) {
     545            2 :             state.dataSysVars->SutherlandHodgman = false;
     546            2 :             state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
     547            2 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SlaterBarskyandSutherlandHodgman")) {
     548            2 :             state.dataSysVars->SutherlandHodgman = true;
     549            2 :             state.dataSysVars->SlaterBarsky = true;
     550            2 :             state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
     551            0 :         } else if (state.dataIPShortCut->lAlphaFieldBlanks(aNum)) {
     552            0 :             if (!state.dataSysVars->SutherlandHodgman) { // if already set.
     553            0 :                 state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
     554              :             } else {
     555            0 :                 if (!state.dataSysVars->SlaterBarsky) {
     556            0 :                     state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
     557              :                 } else {
     558            0 :                     state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
     559              :                 }
     560              :             }
     561              :         } else {
     562            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     563            0 :             if (!state.dataSysVars->SutherlandHodgman) {
     564            0 :                 ShowContinueError(state, format("Value entered=\"{}\", ConvexWeilerAtherton will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     565              :             } else {
     566            0 :                 if (!state.dataSysVars->SlaterBarsky) {
     567            0 :                     ShowContinueError(state, format("Value entered=\"{}\", SutherlandHodgman will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     568              :                 } else {
     569            0 :                     ShowContinueError(
     570              :                         state,
     571            0 :                         format("Value entered=\"{}\", SlaterBarskyandSutherlandHodgman will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     572              :                 }
     573              :             }
     574              :         }
     575              :     } else {
     576          121 :         if (!state.dataSysVars->SutherlandHodgman) {
     577            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "ConvexWeilerAtherton";
     578              :         } else {
     579          121 :             if (!state.dataSysVars->SlaterBarsky) {
     580          121 :                 state.dataIPShortCut->cAlphaArgs(aNum) = "SutherlandHodgman";
     581              :             } else {
     582            0 :                 state.dataIPShortCut->cAlphaArgs(aNum) = "SlaterBarskyandSutherlandHodgman";
     583              :             }
     584              :         }
     585              :     }
     586              : 
     587          134 :     aNum++;
     588          134 :     if (NumAlphas >= aNum) {
     589           13 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "SimpleSkyDiffuseModeling")) {
     590            5 :             state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
     591            5 :             state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
     592            8 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "DetailedSkyDiffuseModeling")) {
     593            8 :             state.dataSysVars->DetailedSkyDiffuseAlgorithm = true;
     594            8 :             state.dataIPShortCut->cAlphaArgs(aNum) = "DetailedSkyDiffuseModeling";
     595            0 :         } else if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     596            0 :             state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
     597            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
     598              :         } else {
     599            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     600            0 :             ShowContinueError(state, format("Value entered=\"{}\", SimpleSkyDiffuseModeling will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     601              :         }
     602              :     } else {
     603          121 :         state.dataIPShortCut->cAlphaArgs(aNum) = "SimpleSkyDiffuseModeling";
     604          121 :         state.dataSysVars->DetailedSkyDiffuseAlgorithm = false;
     605              :     }
     606              : 
     607          134 :     aNum++;
     608          134 :     if (NumAlphas >= aNum) {
     609            2 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
     610            0 :             state.dataSysVars->ReportExtShadingSunlitFrac = true;
     611            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
     612            2 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
     613            2 :             state.dataSysVars->ReportExtShadingSunlitFrac = false;
     614            2 :             state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     615              :         } else {
     616            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     617            0 :             ShowContinueError(state, format("Value entered=\"{}\", InternalCalculation will be used.", state.dataIPShortCut->cAlphaArgs(aNum)));
     618              :         }
     619              :     } else {
     620          132 :         state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     621          132 :         state.dataSysVars->ReportExtShadingSunlitFrac = false;
     622              :     }
     623              : 
     624          134 :     aNum++;
     625          134 :     if (NumAlphas >= aNum) {
     626            2 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
     627            1 :             state.dataSysVars->DisableSelfShadingWithinGroup = true;
     628            1 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
     629            1 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
     630            1 :             state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     631              :         } else {
     632            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     633            0 :             ShowContinueError(state,
     634            0 :                               format("Value entered=\"{}\", all shading effects would be considered.", state.dataIPShortCut->cAlphaArgs(aNum)));
     635              :         }
     636              :     } else {
     637          132 :         state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     638              :     }
     639              : 
     640          134 :     aNum++;
     641          134 :     if (NumAlphas >= aNum) {
     642            2 :         if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "Yes")) {
     643            0 :             state.dataSysVars->DisableSelfShadingBetweenGroup = true;
     644            0 :             state.dataIPShortCut->cAlphaArgs(aNum) = "Yes";
     645            2 :         } else if (Util::SameString(state.dataIPShortCut->cAlphaArgs(aNum), "No")) {
     646            2 :             state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     647              :         } else {
     648            0 :             ShowWarningError(state, format("{}: invalid {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaFieldNames(aNum)));
     649            0 :             ShowContinueError(state,
     650            0 :                               format("Value entered=\"{}\", all shading effects would be considered.", state.dataIPShortCut->cAlphaArgs(aNum)));
     651              :         }
     652              :     } else {
     653          132 :         state.dataIPShortCut->cAlphaArgs(aNum) = "No";
     654              :     }
     655              : 
     656          134 :     if (state.dataSysVars->DisableSelfShadingBetweenGroup && state.dataSysVars->DisableSelfShadingWithinGroup) {
     657            0 :         state.dataSysVars->DisableAllSelfShading = true;
     658          134 :     } else if (state.dataSysVars->DisableSelfShadingBetweenGroup || state.dataSysVars->DisableSelfShadingWithinGroup) {
     659            1 :         state.dataSysVars->DisableGroupSelfShading = true;
     660              :     }
     661              : 
     662          134 :     aNum++;
     663          134 :     state.dataSysVars->shadingGroupsNum = NumAlphas - (aNum - 1);
     664          134 :     state.dataSysVars->shadingGroupZoneListNames.allocate(state.dataSysVars->shadingGroupsNum);
     665          135 :     for (int numZone = 1; numZone <= state.dataSysVars->shadingGroupsNum; ++numZone) {
     666            1 :         state.dataSysVars->shadingGroupZoneListNames(numZone) = state.dataIPShortCut->cAlphaArgs(aNum - 1 + numZone);
     667              :     }
     668              : 
     669          134 :     if (!state.dataSysVars->DetailedSolarTimestepIntegration && s_surf->ShadingTransmittanceVaries &&
     670            0 :         state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
     671              : 
     672            0 :         ShowWarningError(state, "GetShadowingInput: The shading transmittance for shading devices may change throughout the year.");
     673            0 :         ShowContinueError(state,
     674            0 :                           format("Choose Shading Calculation Update Frequency Method = Timestep in the {} object to capture all shading impacts.",
     675              :                                  cCurrentModuleObject));
     676              :     }
     677          134 :     if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
     678            0 :         state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
     679              : 
     680            0 :         ShowWarningError(state, "GetShadowingInput: The shading transmittance for shading devices may change throughout the year.");
     681            0 :         ShowContinueError(state, "Simulation has been reset to use DetailedSkyDiffuseModeling. Simulation continues.");
     682            0 :         ShowContinueError(state, format("Choose DetailedSkyDiffuseModeling in the {} object to remove this warning.", cCurrentModuleObject));
     683            0 :         state.dataSysVars->DetailedSkyDiffuseAlgorithm = true;
     684            0 :         state.dataIPShortCut->cAlphaArgs(2) = "DetailedSkyDiffuseModeling";
     685            0 :         if (!state.dataSysVars->DetailedSolarTimestepIntegration && state.dataSolarShading->ShadowingCalcFrequency > 1) {
     686            0 :             ShowContinueError(state,
     687            0 :                               format("Better accuracy may be gained by setting the {} to 1 in the {} object.",
     688            0 :                                      state.dataIPShortCut->cNumericFieldNames(1),
     689              :                                      cCurrentModuleObject));
     690              :         }
     691          134 :     } else if (state.dataSysVars->DetailedSkyDiffuseAlgorithm) {
     692            8 :         if (!s_surf->ShadingTransmittanceVaries || state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
     693           16 :             ShowWarningError(state,
     694              :                              "GetShadowingInput: DetailedSkyDiffuseModeling is chosen but not needed as either the shading transmittance for "
     695              :                              "shading devices does not change throughout the year");
     696           16 :             ShowContinueError(state, " or MinimalShadowing has been chosen.");
     697           16 :             ShowContinueError(state, "Simulation should be set to use SimpleSkyDiffuseModeling, but is left at Detailed for simulation.");
     698            8 :             ShowContinueError(state, format("Choose SimpleSkyDiffuseModeling in the {} object to reduce computation time.", cCurrentModuleObject));
     699              :         }
     700              :     }
     701              : 
     702          134 :     print(state.files.eio,
     703              :           "{}",
     704              :           "! <Shadowing/Sun Position Calculations Annual Simulations>, Shading Calculation Method, "
     705              :           "Shading Calculation Update Frequency Method, Shading Calculation Update Frequency {days}, "
     706              :           "Maximum Figures in Shadow Overlap Calculations {}, Polygon Clipping Algorithm, Pixel Counting Resolution, Sky Diffuse Modeling "
     707              :           "Algorithm, Output External Shading Calculation Results, Disable "
     708              :           "Self-Shading Within Shading Zone Groups, Disable Self-Shading From Shading Zone Groups to Other Zones\n");
     709          938 :     print(state.files.eio,
     710              :           "Shadowing/Sun Position Calculations Annual Simulations,{},{},{},{},{},{},{},{},{},{}\n",
     711          134 :           state.dataIPShortCut->cAlphaArgs(1),
     712          134 :           state.dataIPShortCut->cAlphaArgs(2),
     713          134 :           state.dataSolarShading->ShadowingCalcFrequency,
     714          134 :           state.dataSolarShading->MaxHCS,
     715          134 :           state.dataIPShortCut->cAlphaArgs(3),
     716              :           pixelRes,
     717          134 :           state.dataIPShortCut->cAlphaArgs(4),
     718          134 :           state.dataIPShortCut->cAlphaArgs(5),
     719          134 :           state.dataIPShortCut->cAlphaArgs(6),
     720          134 :           state.dataIPShortCut->cAlphaArgs(7));
     721          134 : }
     722              : 
     723          114 : void processShadowingInput(EnergyPlusData &state)
     724              : {
     725              :     // all shadow input processing that needed zones and surfaces to already be read into data (part of fix for Defect #10299)
     726              : 
     727          115 :     if ((state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::PixelCounting) &&
     728            1 :         state.dataSolarShading->anyScheduledShadingSurface) {
     729            2 :         ShowSevereError(state, "The Shading Calculation Method of choice is \"PixelCounting\"; ");
     730            2 :         ShowContinueError(state, "and there is at least one shading surface of type ");
     731            2 :         ShowContinueError(state, "Shading:Site:Detailed, Shading:Building:Detailed, or Shading:Zone:Detailed, ");
     732            2 :         ShowContinueError(state, "that has an active transmittance schedule value greater than zero or may vary.");
     733            2 :         ShowContinueError(state, "With \"PixelCounting\" Shading Calculation Method, the shading surfaces will be treated as ");
     734            2 :         ShowContinueError(state, "completely opaque (transmittance = 0) during the shading calculation, ");
     735            2 :         ShowContinueError(state, "which may result in inaccurate or unexpected results.");
     736            3 :         ShowContinueError(state, "It is suggested switching to another Shading Calculation Method, such as \"PolygonClipping\".");
     737              :     }
     738              : 
     739          114 :     if (state.dataSysVars->shadingMethod == DataSystemVariables::ShadingMethod::Imported) {
     740            0 :         for (auto &surf : state.dataSurface->Surface) {
     741            0 :             if ((surf.surfExternalShadingSched = Sched::GetSchedule(state, surf.Name + "_shading")) != nullptr) {
     742            0 :                 surf.SurfSchedExternalShadingFrac = true;
     743              :             } else {
     744            0 :                 ShowWarningError(state,
     745            0 :                                  format("processShadowingInput: sunlit fraction schedule not found for {} when using ImportedShading.", surf.Name));
     746            0 :                 ShowContinueError(state, "These values are set to 1.0.");
     747              :             }
     748              :         }
     749              :     }
     750              : 
     751              :     int SurfZoneGroup, CurZoneGroup;
     752          114 :     int Found = 0;
     753          114 :     if (state.dataSysVars->DisableGroupSelfShading) {
     754            1 :         Array1D_int DisableSelfShadingGroups;
     755            1 :         int NumOfShadingGroups = state.dataSysVars->shadingGroupsNum;
     756            1 :         if (NumOfShadingGroups > 0) {
     757            1 :             DisableSelfShadingGroups.allocate(NumOfShadingGroups);
     758            2 :             for (int i = 1; i <= NumOfShadingGroups; i++) {
     759            1 :                 Found = Util::FindItemInList(
     760            1 :                     state.dataSysVars->shadingGroupZoneListNames(i), state.dataHeatBal->ZoneList, state.dataHeatBal->NumOfZoneLists);
     761            1 :                 if (Found != 0) DisableSelfShadingGroups(i) = Found;
     762              :             }
     763              : 
     764           10 :             for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; SurfNum++) {
     765            9 :                 if (state.dataSurface->Surface(SurfNum).ExtBoundCond == 0) { // Loop through all exterior surfaces
     766            9 :                     SurfZoneGroup = 0;
     767              :                     // Check the shading zone group of each exterior surface
     768           18 :                     for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups
     769            9 :                         CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop);
     770           11 :                         for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones;
     771              :                              ZoneNum++) { // Loop through all zones in the zone list
     772            9 :                             if (state.dataSurface->Surface(SurfNum).Zone == state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum)) {
     773            7 :                                 SurfZoneGroup = CurZoneGroup;
     774            7 :                                 break;
     775              :                             }
     776              :                         }
     777              :                     }
     778              :                     // if a surface is not in any zone group, no self shading is disabled for this surface
     779            9 :                     if (SurfZoneGroup != 0) {
     780              :                         // if DisableSelfShadingWithinGroup, add all zones in the same zone group to the surface's disabled zone list
     781              :                         // if DisableSelfShadingBetweenGroups, add all zones in all other zone groups to the surface's disabled zone list
     782           14 :                         for (int ZoneGroupLoop = 1; ZoneGroupLoop <= NumOfShadingGroups; ZoneGroupLoop++) { // Loop through all defined shading groups
     783            7 :                             CurZoneGroup = DisableSelfShadingGroups(ZoneGroupLoop);
     784            7 :                             if (SurfZoneGroup == CurZoneGroup && state.dataSysVars->DisableSelfShadingWithinGroup) {
     785           14 :                                 for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones;
     786              :                                      ZoneNum++) { // Loop through all zones in the zone list
     787            7 :                                     state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back(
     788            7 :                                         state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum));
     789              :                                 }
     790            0 :                             } else if (SurfZoneGroup != CurZoneGroup && state.dataSysVars->DisableSelfShadingBetweenGroup) {
     791            0 :                                 for (int ZoneNum = 1; ZoneNum <= state.dataHeatBal->ZoneList(CurZoneGroup).NumOfZones; ZoneNum++) {
     792            0 :                                     state.dataSurface->SurfShadowDisabledZoneList(SurfNum).push_back(
     793            0 :                                         state.dataHeatBal->ZoneList(CurZoneGroup).Zone(ZoneNum));
     794              :                                 }
     795              :                             }
     796              :                         }
     797              :                     }
     798              :                 }
     799              :             }
     800              :         } else {
     801            0 :             ShowFatalError(state, "No Shading groups are defined when disabling grouped self shading.");
     802              :         }
     803            1 :     }
     804          114 : }
     805              : 
     806            1 : void checkScheduledSurfacePresent(EnergyPlusData &state)
     807              : {
     808              :     // User has chosen "Scheduled" for sunlit fraction so check to see which surfaces don't have a schedule
     809            1 :     int numNotDef = 0;
     810            1 :     int constexpr maxErrMessages = 50;
     811            1 :     auto &surfData = state.dataSurface;
     812            6 :     for (int surfNum = 1; surfNum <= surfData->TotSurfaces; ++surfNum) {
     813            5 :         auto &thisSurf = surfData->Surface(surfNum);
     814            5 :         if ((thisSurf.Class == SurfaceClass::Shading || thisSurf.Class == SurfaceClass::Detached_F || thisSurf.Class == SurfaceClass::Detached_B ||
     815            4 :              thisSurf.Class == SurfaceClass::Overhang || thisSurf.Class == SurfaceClass::Fin))
     816            2 :             continue; // skip shading surfaces
     817            3 :         if (!thisSurf.SurfSchedExternalShadingFrac) {
     818            1 :             numNotDef += 1;
     819            1 :             if (numNotDef == 1) {
     820            2 :                 ShowWarningError(
     821              :                     state,
     822            2 :                     format("ShadowCalculation specified Schedule for the Shading Calculation Method but no schedule provided for {}", thisSurf.Name));
     823            2 :                 ShowContinueError(
     824              :                     state, "When Schedule is selected for the Shading Calculation Method and no schedule is provided for a particular surface,");
     825            2 :                 ShowContinueError(
     826              :                     state, "EnergyPlus will assume that the surface is not shaded.  Use SurfaceProperty:LocalEnvironment to specify a schedule");
     827            3 :                 ShowContinueError(state, "for sunlit fraction if this was not desired.  Otherwise, this surface will not be shaded at all.");
     828            0 :             } else if (numNotDef <= maxErrMessages) {
     829            0 :                 ShowWarningError(state, format("No schedule was provided for {} either.  See above error message for more details", thisSurf.Name));
     830              :             }
     831              :         }
     832              :     }
     833            1 :     if (numNotDef > maxErrMessages)
     834            0 :         ShowContinueError(state, format("This message is only shown for the first {} occurrences of this issue.", maxErrMessages));
     835            1 : }
     836              : 
     837          141 : void AllocateModuleArrays(EnergyPlusData &state)
     838              : {
     839              : 
     840              :     // SUBROUTINE INFORMATION:
     841              :     //       AUTHOR         Rick Strand
     842              :     //       DATE WRITTEN   February 1998
     843              :     //       MODIFIED       August 2005 JG - Added output variables for energy in J
     844              : 
     845              :     // PURPOSE OF THIS SUBROUTINE:
     846              :     // This routine allocates all of the arrays at the module level which
     847              :     // require allocation.
     848              : 
     849              :     // METHODOLOGY EMPLOYED:
     850              :     // Allocation is dependent on the user input file.
     851              : 
     852              :     int I;
     853              :     int NumOfLayers;
     854              : 
     855          141 :     auto &s_surf = state.dataSurface;
     856              : 
     857          141 :     state.dataSolarShading->SurfSunCosTheta.dimension(s_surf->TotSurfaces, 0.0);
     858          141 :     state.dataSolarShading->SurfSunlitArea.dimension(s_surf->TotSurfaces, 0.0);
     859          141 :     if (!state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() || !state.dataWindowManager->winOpticalModel->isSimplifiedModel()) {
     860          141 :         state.dataSolarShading->SurfWinIntBeamAbsByShadFac.allocate(s_surf->TotSurfaces);
     861          141 :         state.dataSolarShading->SurfWinExtBeamAbsByShadFac.allocate(s_surf->TotSurfaces);
     862          141 :         state.dataSolarShading->SurfWinTransBmSolar.allocate(s_surf->TotSurfaces);
     863          141 :         state.dataSolarShading->SurfWinTransDifSolar.allocate(s_surf->TotSurfaces);
     864          141 :         state.dataSolarShading->SurfWinTransDifSolarGnd.allocate(s_surf->TotSurfaces);
     865          141 :         state.dataSolarShading->SurfWinTransDifSolarSky.allocate(s_surf->TotSurfaces);
     866          141 :         state.dataSolarShading->SurfWinTransBmBmSolar.allocate(s_surf->TotSurfaces);
     867          141 :         state.dataSolarShading->SurfWinTransBmDifSolar.allocate(s_surf->TotSurfaces);
     868              :     }
     869          141 :     state.dataSolarShading->SurfAnisoSkyMult.dimension(s_surf->TotSurfaces, 1.0);
     870          141 :     state.dataSolarShading->SurfIntAbsFac.dimension(s_surf->TotSurfaces, 0.0);
     871              :     // For isotropic sky: recalculated in AnisoSkyViewFactors if anisotropic radiance
     872              :     //  ALLOCATE(WithShdgIsoSky(TotSurfaces))
     873              :     //  WithShdgIsoSky=0.0
     874              :     //  ALLOCATE(WoShdgIsoSky(TotSurfaces))
     875              :     //  WoShdgIsoSky=0.0
     876              :     //  ALLOCATE(WithShdgHoriz(TotSurfaces))
     877              :     //  WithShdgHoriz=0.0
     878              :     //  ALLOCATE(WoShdgHoriz(TotSurfaces))
     879              :     //  WoShdgHoriz=0.0
     880              :     //  ALLOCATE(DifShdgRatioIsoSky(TotSurfaces))
     881              :     //  DifShdgRatioIsoSky=0.0
     882              :     //  ALLOCATE(DifShdgRatioHoriz(TotSurfaces))
     883              :     //  DifShdgRatioHoriz=0.0
     884          141 :     state.dataSolarShading->SurfMultIsoSky.dimension(s_surf->TotSurfaces, 0.0);
     885          141 :     state.dataSolarShading->SurfMultCircumSolar.dimension(s_surf->TotSurfaces, 0.0);
     886          141 :     state.dataSolarShading->SurfMultHorizonZenith.dimension(s_surf->TotSurfaces, 0.0);
     887          141 :     state.dataSolarShading->SurfWinRevealStatus.dimension(24, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0);
     888              : 
     889              :     // Weiler-Atherton
     890          141 :     state.dataSolarShading->MAXHCArrayBounds = 2 * (s_surf->MaxVerticesPerSurface + 1);
     891          141 :     state.dataSolarShading->MAXHCArrayIncrement = s_surf->MaxVerticesPerSurface + 1;
     892          141 :     state.dataSolarShading->XTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     893          141 :     state.dataSolarShading->YTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     894          141 :     state.dataSolarShading->XVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
     895          141 :     state.dataSolarShading->XVS.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
     896          141 :     state.dataSolarShading->YVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
     897          141 :     state.dataSolarShading->YVS.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
     898          141 :     state.dataSolarShading->ZVC.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
     899              : 
     900              :     // Sutherland-Hodgman
     901          141 :     state.dataSolarShading->ATEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     902          141 :     state.dataSolarShading->BTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     903          141 :     state.dataSolarShading->CTEMP.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     904          141 :     state.dataSolarShading->XTEMP1.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     905          141 :     state.dataSolarShading->YTEMP1.dimension(2 * (s_surf->MaxVerticesPerSurface + 1), 0.0);
     906              : 
     907          141 :     s_surf->SurfSunCosHourly.allocate(Constant::iHoursInDay);
     908         3525 :     for (int hour = 1; hour <= Constant::iHoursInDay; hour++) {
     909         3384 :         s_surf->SurfSunCosHourly(hour) = 0.0;
     910              :     }
     911          141 :     s_surf->SurfSunlitArea.dimension(s_surf->TotSurfaces, 0.0);
     912          141 :     s_surf->SurfSunlitFrac.dimension(s_surf->TotSurfaces, 0.0);
     913          141 :     s_surf->SurfSkySolarInc.dimension(s_surf->TotSurfaces, 0);
     914          141 :     s_surf->SurfGndSolarInc.dimension(s_surf->TotSurfaces, 0);
     915          141 :     s_surf->SurfBmToBmReflFacObs.dimension(s_surf->TotSurfaces, 0.0);
     916          141 :     s_surf->SurfBmToDiffReflFacObs.dimension(s_surf->TotSurfaces, 0.0);
     917          141 :     s_surf->SurfBmToDiffReflFacGnd.dimension(s_surf->TotSurfaces, 0.0);
     918          141 :     s_surf->SurfSkyDiffReflFacGnd.dimension(s_surf->TotSurfaces, 0.0);
     919          141 :     s_surf->SurfOpaqAI.dimension(s_surf->TotSurfaces, 0.0);
     920          141 :     s_surf->SurfOpaqAO.dimension(s_surf->TotSurfaces, 0.0);
     921          141 :     s_surf->SurfWinTransSolar.dimension(s_surf->TotSurfaces, 0.0);
     922          141 :     s_surf->SurfWinBmSolar.dimension(s_surf->TotSurfaces, 0.0);
     923          141 :     s_surf->SurfWinBmBmSolar.dimension(s_surf->TotSurfaces, 0.0);
     924          141 :     s_surf->SurfWinBmDifSolar.dimension(s_surf->TotSurfaces, 0.0);
     925          141 :     s_surf->SurfWinDifSolar.dimension(s_surf->TotSurfaces, 0.0);
     926          141 :     s_surf->SurfWinHeatGain.dimension(s_surf->TotSurfaces, 0.0);
     927          141 :     s_surf->SurfWinHeatGainRep.dimension(s_surf->TotSurfaces, 0.0);
     928          141 :     s_surf->SurfWinHeatLossRep.dimension(s_surf->TotSurfaces, 0.0);
     929          141 :     s_surf->SurfWinGainConvGlazToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
     930          141 :     s_surf->SurfWinGainIRGlazToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
     931          141 :     s_surf->SurfWinLossSWZoneToOutWinRep.dimension(s_surf->TotSurfaces, 0.0);
     932          141 :     s_surf->SurfWinGainFrameDividerToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
     933          141 :     s_surf->SurfWinGainConvShadeToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
     934          141 :     s_surf->SurfWinGainIRShadeToZoneRep.dimension(s_surf->TotSurfaces, 0.0);
     935          141 :     s_surf->SurfWinGapConvHtFlowRep.dimension(s_surf->TotSurfaces, 0.0);
     936          141 :     s_surf->SurfWinShadingAbsorbedSolar.dimension(s_surf->TotSurfaces, 0.0);
     937          141 :     s_surf->SurfWinSysSolTransmittance.dimension(s_surf->TotSurfaces, 0.0);
     938          141 :     s_surf->SurfWinSysSolReflectance.dimension(s_surf->TotSurfaces, 0.0);
     939          141 :     s_surf->SurfWinSysSolAbsorptance.dimension(s_surf->TotSurfaces, 0.0);
     940          141 :     s_surf->SurfWinInsideGlassCondensationFlag.dimension(s_surf->TotSurfaces, 0);
     941          141 :     s_surf->SurfWinInsideFrameCondensationFlag.dimension(s_surf->TotSurfaces, 0);
     942          141 :     s_surf->SurfWinInsideDividerCondensationFlag.dimension(s_surf->TotSurfaces, 0);
     943              : 
     944          141 :     state.dataHeatBal->SurfSunlitFracHR.dimension(Constant::iHoursInDay, s_surf->TotSurfaces, 0.0);
     945          141 :     state.dataHeatBal->SurfSunlitFrac.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
     946          141 :     state.dataHeatBal->SurfSunlitFracWithoutReveal.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
     947          564 :     state.dataHeatBal->SurfWinBackSurfaces.dimension(
     948          423 :         Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, state.dataBSDFWindow->MaxBkSurf, s_surf->TotSurfaces, 0);
     949          564 :     state.dataHeatBal->SurfWinOverlapAreas.dimension(
     950          423 :         Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, state.dataBSDFWindow->MaxBkSurf, s_surf->TotSurfaces, 0.0);
     951          141 :     state.dataHeatBal->SurfCosIncAngHR.dimension(Constant::iHoursInDay, s_surf->TotSurfaces, 0.0);
     952          141 :     state.dataHeatBal->SurfCosIncAng.dimension(Constant::iHoursInDay, state.dataGlobal->TimeStepsInHour, s_surf->TotSurfaces, 0.0);
     953              : 
     954          141 :     state.dataHeatBal->ZoneTransSolar.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     955          141 :     state.dataHeatBal->ZoneBmSolFrExtWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     956          141 :     state.dataHeatBal->ZoneBmSolFrIntWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     957          141 :     state.dataHeatBal->EnclSolInitialDifSolReflW.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     958          141 :     state.dataHeatBal->ZoneDifSolFrExtWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     959          141 :     state.dataHeatBal->ZoneDifSolFrIntWinsRep.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
     960          141 :     state.dataHeatBal->ZoneWinHeatGain.dimension(state.dataGlobal->NumOfZones, 0.0);
     961          141 :     state.dataHeatBal->ZoneWinHeatGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     962          141 :     state.dataHeatBal->ZoneWinHeatLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     963          141 :     state.dataHeatBal->ZoneOpaqSurfInsFaceCond.dimension(state.dataGlobal->NumOfZones, 0.0);
     964          141 :     state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     965          141 :     state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     966          141 :     state.dataHeatBal->ZoneOpaqSurfExtFaceCond.dimension(state.dataGlobal->NumOfZones, 0.0);
     967          141 :     state.dataHeatBal->ZoneOpaqSurfExtFaceCondGainRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     968          141 :     state.dataHeatBal->ZoneOpaqSurfExtFaceCondLossRep.dimension(state.dataGlobal->NumOfZones, 0.0);
     969              : 
     970          141 :     state.dataHeatBal->SurfQRadSWOutIncident.dimension(s_surf->TotSurfaces, 0.0);
     971          141 :     state.dataHeatBal->SurfQRadSWOutIncidentBeam.dimension(s_surf->TotSurfaces, 0.0);
     972          141 :     state.dataHeatBal->SurfBmIncInsSurfIntensRep.dimension(s_surf->TotSurfaces, 0.0);
     973          141 :     state.dataHeatBal->SurfBmIncInsSurfAmountRep.dimension(s_surf->TotSurfaces, 0.0);
     974              :     //  ALLOCATE(DifIncInsSurfIntensRep(TotSurfaces))
     975              :     //  DifIncInsSurfIntensRep=0.0
     976              :     //  ALLOCATE(DifIncInsSurfAmountRep(TotSurfaces))
     977              :     //  DifIncInsSurfAmountRep=0.0
     978          141 :     state.dataHeatBal->SurfIntBmIncInsSurfIntensRep.dimension(s_surf->TotSurfaces, 0.0);
     979          141 :     state.dataHeatBal->SurfIntBmIncInsSurfAmountRep.dimension(s_surf->TotSurfaces, 0.0);
     980              :     //  ALLOCATE(IntDifIncInsSurfIntensRep(TotSurfaces))
     981              :     //  IntDifIncInsSurfIntensRep=0.0
     982              :     //  ALLOCATE(IntDifIncInsSurfAmountRep(TotSurfaces))
     983              :     //  IntDifIncInsSurfAmountRep=0.0
     984          141 :     state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse.dimension(s_surf->TotSurfaces, 0.0);
     985          141 :     state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse.dimension(s_surf->TotSurfaces, 0.0);
     986          141 :     state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd.dimension(s_surf->TotSurfaces, 0.0);
     987          141 :     state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd.dimension(s_surf->TotSurfaces, 0.0);
     988          141 :     state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs.dimension(s_surf->TotSurfaces, 0.0);
     989          141 :     state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs.dimension(s_surf->TotSurfaces, 0.0);
     990          141 :     state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs.dimension(s_surf->TotSurfaces, 0.0);
     991          141 :     state.dataHeatBal->SurfCosIncidenceAngle.dimension(s_surf->TotSurfaces, 0.0);
     992              : 
     993          141 :     state.dataHeatBal->SurfWinBSDFBeamDirectionRep.dimension(s_surf->TotSurfaces, 0);
     994          141 :     state.dataHeatBal->SurfWinBSDFBeamThetaRep.dimension(s_surf->TotSurfaces, 0.0);
     995          141 :     state.dataHeatBal->SurfWinBSDFBeamPhiRep.dimension(s_surf->TotSurfaces, 0.0);
     996          141 :     state.dataHeatBal->SurfWinQRadSWwinAbsTot.dimension(s_surf->TotSurfaces, 0.0);
     997          141 :     state.dataHeatBal->SurfWinQRadSWwinAbsLayer.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
     998          141 :     state.dataHeatBal->SurfWinFenLaySurfTempFront.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
     999          141 :     state.dataHeatBal->SurfWinFenLaySurfTempBack.dimension(s_surf->TotSurfaces, state.dataHeatBal->MaxSolidWinLayers, 0.0);
    1000              : 
    1001          141 :     state.dataHeatBal->SurfWinSWwinAbsTotalReport.dimension(s_surf->TotSurfaces, 0.0);
    1002          141 :     state.dataHeatBal->SurfInitialDifSolInAbsReport.dimension(s_surf->TotSurfaces, 0.0);
    1003          141 :     state.dataHeatBal->SurfWinInitialDifSolInTransReport.dimension(s_surf->TotSurfaces, 0.0);
    1004          141 :     state.dataHeatBal->SurfSWInAbsTotalReport.dimension(s_surf->TotSurfaces, 0.0);
    1005              : 
    1006              :     // energy
    1007          141 :     s_surf->SurfWinTransSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1008          141 :     s_surf->SurfWinBmSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1009          141 :     s_surf->SurfWinBmBmSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1010          141 :     s_surf->SurfWinBmDifSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1011              : 
    1012          141 :     s_surf->SurfWinDifSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1013          141 :     s_surf->SurfWinHeatGainRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1014          141 :     s_surf->SurfWinHeatLossRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1015          141 :     s_surf->SurfWinGapConvHtFlowRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1016          141 :     s_surf->SurfWinHeatTransferRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1017          141 :     s_surf->SurfWinShadingAbsorbedSolarEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1018              : 
    1019          141 :     state.dataHeatBal->ZoneTransSolarEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
    1020          141 :     state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
    1021          141 :     state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
    1022          141 :     state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
    1023          141 :     state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy.dimension(state.dataViewFactor->NumOfSolarEnclosures, 0.0);
    1024          141 :     state.dataHeatBal->ZoneWinHeatGainRepEnergy.dimension(state.dataGlobal->NumOfZones, 0.0);
    1025          141 :     state.dataHeatBal->ZoneWinHeatLossRepEnergy.dimension(state.dataGlobal->NumOfZones, 0.0);
    1026              : 
    1027          141 :     state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
    1028          141 :     state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
    1029          141 :     state.dataHeatBal->ZnOpqSurfExtFaceCondGnRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
    1030          141 :     state.dataHeatBal->ZnOpqSurfExtFaceCondLsRepEnrg.dimension(state.dataGlobal->NumOfZones, 0.0);
    1031              :     //  ALLOCATE(DifIncInsSurfAmountRepEnergy(TotSurfaces))
    1032              :     //  DifIncInsSurfAmountRepEnergy=0.0
    1033          141 :     state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1034          141 :     state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1035              :     //  ALLOCATE(IntDifIncInsSurfAmountRepEnergy(TotSurfaces))
    1036              :     //  IntDifIncInsSurfAmountRepEnergy=0.0
    1037          141 :     state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy.dimension(s_surf->TotSurfaces, 0.0);
    1038              : 
    1039         1153 :     for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; SurfNum++) {
    1040         1012 :         s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) = 0.0;
    1041         1012 :         s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) = 0.0;
    1042         1012 :         s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) = 0.0;
    1043         1012 :         s_surf->SurfWinBmSolRefldInsReveal(SurfNum) = 0.0;
    1044         1012 :         s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) = 0.0;
    1045         1012 :         s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) = 0.0;
    1046         1012 :         s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) = 0.0;
    1047         1012 :         s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) = 0.0;
    1048         1012 :         s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) = 0.0;
    1049         1012 :         s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) = 0.0;
    1050              :     }
    1051              : 
    1052              :     // Added report variables for inside reveal to debug CR 7596. TH 5/26/2009
    1053         1153 :     for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; SurfNum++) {
    1054         1012 :         s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) = 0.0;
    1055         1012 :         s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) = 0.0;
    1056         1012 :         s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) = 0.0;
    1057         1012 :         s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) = 0.0;
    1058              :     }
    1059              : 
    1060          141 :     DisplayString(state, "Initializing Zone and Enclosure Report Variables");
    1061          309 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    1062          168 :         std::string &thisEnclosureName = state.dataViewFactor->EnclSolInfo(enclosureNum).Name;
    1063          336 :         SetupOutputVariable(state,
    1064              :                             "Enclosure Windows Total Transmitted Solar Radiation Rate",
    1065              :                             Constant::Units::W,
    1066          168 :                             state.dataHeatBal->ZoneTransSolar(enclosureNum),
    1067              :                             OutputProcessor::TimeStepType::Zone,
    1068              :                             OutputProcessor::StoreType::Average,
    1069              :                             thisEnclosureName);
    1070          336 :         SetupOutputVariable(state,
    1071              :                             "Enclosure Exterior Windows Total Transmitted Beam Solar Radiation Rate",
    1072              :                             Constant::Units::W,
    1073          168 :                             state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum),
    1074              :                             OutputProcessor::TimeStepType::Zone,
    1075              :                             OutputProcessor::StoreType::Average,
    1076              :                             thisEnclosureName);
    1077          336 :         SetupOutputVariable(state,
    1078              :                             "Enclosure Interior Windows Total Transmitted Beam Solar Radiation Rate",
    1079              :                             Constant::Units::W,
    1080          168 :                             state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum),
    1081              :                             OutputProcessor::TimeStepType::Zone,
    1082              :                             OutputProcessor::StoreType::Average,
    1083              :                             thisEnclosureName);
    1084          336 :         SetupOutputVariable(state,
    1085              :                             "Enclosure Exterior Windows Total Transmitted Diffuse Solar Radiation Rate",
    1086              :                             Constant::Units::W,
    1087          168 :                             state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum),
    1088              :                             OutputProcessor::TimeStepType::Zone,
    1089              :                             OutputProcessor::StoreType::Average,
    1090              :                             thisEnclosureName);
    1091          336 :         SetupOutputVariable(state,
    1092              :                             "Enclosure Interior Windows Total Transmitted Diffuse Solar Radiation Rate",
    1093              :                             Constant::Units::W,
    1094          168 :                             state.dataHeatBal->ZoneDifSolFrIntWinsRep(enclosureNum),
    1095              :                             OutputProcessor::TimeStepType::Zone,
    1096              :                             OutputProcessor::StoreType::Average,
    1097              :                             thisEnclosureName);
    1098              :         // Energy variables
    1099          336 :         SetupOutputVariable(state,
    1100              :                             "Enclosure Windows Total Transmitted Solar Radiation Energy",
    1101              :                             Constant::Units::J,
    1102          168 :                             state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum),
    1103              :                             OutputProcessor::TimeStepType::Zone,
    1104              :                             OutputProcessor::StoreType::Sum,
    1105              :                             thisEnclosureName);
    1106          336 :         SetupOutputVariable(state,
    1107              :                             "Enclosure Exterior Windows Total Transmitted Beam Solar Radiation Energy",
    1108              :                             Constant::Units::J,
    1109          168 :                             state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum),
    1110              :                             OutputProcessor::TimeStepType::Zone,
    1111              :                             OutputProcessor::StoreType::Sum,
    1112              :                             thisEnclosureName);
    1113          336 :         SetupOutputVariable(state,
    1114              :                             "Enclosure Interior Windows Total Transmitted Beam Solar Radiation Energy",
    1115              :                             Constant::Units::J,
    1116          168 :                             state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclosureNum),
    1117              :                             OutputProcessor::TimeStepType::Zone,
    1118              :                             OutputProcessor::StoreType::Sum,
    1119              :                             thisEnclosureName);
    1120          336 :         SetupOutputVariable(state,
    1121              :                             "Enclosure Exterior Windows Total Transmitted Diffuse Solar Radiation Energy",
    1122              :                             Constant::Units::J,
    1123          168 :                             state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum),
    1124              :                             OutputProcessor::TimeStepType::Zone,
    1125              :                             OutputProcessor::StoreType::Sum,
    1126              :                             thisEnclosureName);
    1127          336 :         SetupOutputVariable(state,
    1128              :                             "Enclosure Interior Windows Total Transmitted Diffuse Solar Radiation Energy",
    1129              :                             Constant::Units::J,
    1130          168 :                             state.dataHeatBal->ZoneDifSolFrIntWinsRepEnergy(enclosureNum),
    1131              :                             OutputProcessor::TimeStepType::Zone,
    1132              :                             OutputProcessor::StoreType::Sum,
    1133              :                             thisEnclosureName);
    1134              :     }
    1135          300 :     for (int ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) {
    1136          318 :         SetupOutputVariable(state,
    1137              :                             "Zone Windows Total Heat Gain Rate",
    1138              :                             Constant::Units::W,
    1139          159 :                             state.dataHeatBal->ZoneWinHeatGainRep(ZoneLoop),
    1140              :                             OutputProcessor::TimeStepType::Zone,
    1141              :                             OutputProcessor::StoreType::Average,
    1142          159 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    1143          318 :         SetupOutputVariable(state,
    1144              :                             "Zone Windows Total Heat Loss Rate",
    1145              :                             Constant::Units::W,
    1146          159 :                             state.dataHeatBal->ZoneWinHeatLossRep(ZoneLoop),
    1147              :                             OutputProcessor::TimeStepType::Zone,
    1148              :                             OutputProcessor::StoreType::Average,
    1149          159 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    1150          318 :         SetupOutputVariable(state,
    1151              :                             "Zone Windows Total Heat Gain Energy",
    1152              :                             Constant::Units::J,
    1153          159 :                             state.dataHeatBal->ZoneWinHeatGainRepEnergy(ZoneLoop),
    1154              :                             OutputProcessor::TimeStepType::Zone,
    1155              :                             OutputProcessor::StoreType::Sum,
    1156          159 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    1157          318 :         SetupOutputVariable(state,
    1158              :                             "Zone Windows Total Heat Loss Energy",
    1159              :                             Constant::Units::J,
    1160          159 :                             state.dataHeatBal->ZoneWinHeatLossRepEnergy(ZoneLoop),
    1161              :                             OutputProcessor::TimeStepType::Zone,
    1162              :                             OutputProcessor::StoreType::Sum,
    1163          159 :                             state.dataHeatBal->Zone(ZoneLoop).Name);
    1164          159 :         if (state.dataGlobal->DisplayAdvancedReportVariables) {
    1165              :             // CurrentModuleObject='Zone(Advanced)'
    1166            0 :             SetupOutputVariable(state,
    1167              :                                 "Zone Opaque Surface Inside Faces Total Conduction Heat Gain Rate",
    1168              :                                 Constant::Units::W,
    1169            0 :                                 state.dataHeatBal->ZoneOpaqSurfInsFaceCondGainRep(ZoneLoop),
    1170              :                                 OutputProcessor::TimeStepType::Zone,
    1171              :                                 OutputProcessor::StoreType::Average,
    1172            0 :                                 state.dataHeatBal->Zone(ZoneLoop).Name);
    1173            0 :             SetupOutputVariable(state,
    1174              :                                 "Zone Opaque Surface Inside Faces Total Conduction Heat Loss Rate",
    1175              :                                 Constant::Units::W,
    1176            0 :                                 state.dataHeatBal->ZoneOpaqSurfInsFaceCondLossRep(ZoneLoop),
    1177              :                                 OutputProcessor::TimeStepType::Zone,
    1178              :                                 OutputProcessor::StoreType::Average,
    1179            0 :                                 state.dataHeatBal->Zone(ZoneLoop).Name);
    1180              :             // Energy variables
    1181            0 :             SetupOutputVariable(state,
    1182              :                                 "Zone Opaque Surface Inside Faces Total Conduction Heat Gain Energy",
    1183              :                                 Constant::Units::J,
    1184            0 :                                 state.dataHeatBal->ZnOpqSurfInsFaceCondGnRepEnrg(ZoneLoop),
    1185              :                                 OutputProcessor::TimeStepType::Zone,
    1186              :                                 OutputProcessor::StoreType::Sum,
    1187            0 :                                 state.dataHeatBal->Zone(ZoneLoop).Name);
    1188            0 :             SetupOutputVariable(state,
    1189              :                                 "Zone Opaque Surface Inside Faces Total Conduction Heat Loss Energy",
    1190              :                                 Constant::Units::J,
    1191            0 :                                 state.dataHeatBal->ZnOpqSurfInsFaceCondLsRepEnrg(ZoneLoop),
    1192              :                                 OutputProcessor::TimeStepType::Zone,
    1193              :                                 OutputProcessor::StoreType::Sum,
    1194            0 :                                 state.dataHeatBal->Zone(ZoneLoop).Name);
    1195              :         }
    1196              :     }
    1197              : 
    1198          141 :     DisplayString(state, "Initializing Surface (Shading) Report Variables");
    1199              :     // CurrentModuleObject='Surfaces'
    1200         1153 :     for (int SurfLoop = 1; SurfLoop <= s_surf->TotSurfaces; ++SurfLoop) {
    1201         1012 :         auto &surf = s_surf->Surface(SurfLoop);
    1202         2024 :         SetupOutputVariable(state,
    1203              :                             "Surface Outside Normal Azimuth Angle",
    1204              :                             Constant::Units::deg,
    1205         1012 :                             surf.Azimuth,
    1206              :                             OutputProcessor::TimeStepType::Zone,
    1207              :                             OutputProcessor::StoreType::Average,
    1208         1012 :                             surf.Name);
    1209         1012 :         if (surf.ExtSolar) {
    1210         1388 :             SetupOutputVariable(state,
    1211              :                                 "Surface Outside Face Sunlit Area",
    1212              :                                 Constant::Units::m2,
    1213          694 :                                 s_surf->SurfSunlitArea(SurfLoop),
    1214              :                                 OutputProcessor::TimeStepType::Zone,
    1215              :                                 OutputProcessor::StoreType::Average,
    1216          694 :                                 surf.Name);
    1217         1388 :             SetupOutputVariable(state,
    1218              :                                 "Surface Outside Face Sunlit Fraction",
    1219              :                                 Constant::Units::None,
    1220          694 :                                 s_surf->SurfSunlitFrac(SurfLoop),
    1221              :                                 OutputProcessor::TimeStepType::Zone,
    1222              :                                 OutputProcessor::StoreType::Average,
    1223          694 :                                 surf.Name);
    1224         1388 :             SetupOutputVariable(state,
    1225              :                                 "Surface Outside Face Incident Solar Radiation Rate per Area",
    1226              :                                 Constant::Units::W_m2,
    1227          694 :                                 state.dataHeatBal->SurfQRadSWOutIncident(SurfLoop),
    1228              :                                 OutputProcessor::TimeStepType::Zone,
    1229              :                                 OutputProcessor::StoreType::Average,
    1230          694 :                                 surf.Name);
    1231         1388 :             SetupOutputVariable(state,
    1232              :                                 "Surface Outside Face Incident Beam Solar Radiation Rate per Area",
    1233              :                                 Constant::Units::W_m2,
    1234          694 :                                 state.dataHeatBal->SurfQRadSWOutIncidentBeam(SurfLoop),
    1235              :                                 OutputProcessor::TimeStepType::Zone,
    1236              :                                 OutputProcessor::StoreType::Average,
    1237          694 :                                 surf.Name);
    1238         1388 :             SetupOutputVariable(state,
    1239              :                                 "Surface Outside Face Incident Sky Diffuse Solar Radiation Rate per Area",
    1240              :                                 Constant::Units::W_m2,
    1241          694 :                                 state.dataHeatBal->SurfQRadSWOutIncidentSkyDiffuse(SurfLoop),
    1242              :                                 OutputProcessor::TimeStepType::Zone,
    1243              :                                 OutputProcessor::StoreType::Average,
    1244          694 :                                 surf.Name);
    1245         1388 :             SetupOutputVariable(state,
    1246              :                                 "Surface Outside Face Incident Ground Diffuse Solar Radiation Rate per Area",
    1247              :                                 Constant::Units::W_m2,
    1248          694 :                                 state.dataHeatBal->SurfQRadSWOutIncidentGndDiffuse(SurfLoop),
    1249              :                                 OutputProcessor::TimeStepType::Zone,
    1250              :                                 OutputProcessor::StoreType::Average,
    1251          694 :                                 surf.Name);
    1252         1388 :             SetupOutputVariable(state,
    1253              :                                 "Surface Outside Face Beam Solar Incident Angle Cosine Value",
    1254              :                                 Constant::Units::None,
    1255          694 :                                 state.dataHeatBal->SurfCosIncidenceAngle(SurfLoop),
    1256              :                                 OutputProcessor::TimeStepType::Zone,
    1257              :                                 OutputProcessor::StoreType::Average,
    1258          694 :                                 surf.Name);
    1259         1388 :             SetupOutputVariable(state,
    1260              :                                 "Surface Outside Face Incident Sky Diffuse Ground Reflected Solar Radiation Rate per Area",
    1261              :                                 Constant::Units::W_m2,
    1262          694 :                                 state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflGnd(SurfLoop),
    1263              :                                 OutputProcessor::TimeStepType::Zone,
    1264              :                                 OutputProcessor::StoreType::Average,
    1265          694 :                                 surf.Name);
    1266         1388 :             SetupOutputVariable(state,
    1267              :                                 "Surface Outside Face Incident Sky Diffuse Surface Reflected Solar Radiation Rate per Area",
    1268              :                                 Constant::Units::W_m2,
    1269          694 :                                 state.dataHeatBal->SurfQRadSWOutIncSkyDiffReflObs(SurfLoop),
    1270              :                                 OutputProcessor::TimeStepType::Zone,
    1271              :                                 OutputProcessor::StoreType::Average,
    1272          694 :                                 surf.Name);
    1273         1388 :             SetupOutputVariable(state,
    1274              :                                 "Surface Outside Face Incident Beam To Beam Surface Reflected Solar Radiation Rate per Area",
    1275              :                                 Constant::Units::W_m2,
    1276          694 :                                 state.dataHeatBal->SurfQRadSWOutIncBmToBmReflObs(SurfLoop),
    1277              :                                 OutputProcessor::TimeStepType::Zone,
    1278              :                                 OutputProcessor::StoreType::Average,
    1279          694 :                                 surf.Name);
    1280         1388 :             SetupOutputVariable(state,
    1281              :                                 "Surface Outside Face Incident Beam To Diffuse Surface Reflected Solar Radiation Rate per Area",
    1282              :                                 Constant::Units::W_m2,
    1283          694 :                                 state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflObs(SurfLoop),
    1284              :                                 OutputProcessor::TimeStepType::Zone,
    1285              :                                 OutputProcessor::StoreType::Average,
    1286          694 :                                 surf.Name);
    1287         1388 :             SetupOutputVariable(state,
    1288              :                                 "Surface Outside Face Incident Beam To Diffuse Ground Reflected Solar Radiation Rate per Area",
    1289              :                                 Constant::Units::W_m2,
    1290          694 :                                 state.dataHeatBal->SurfQRadSWOutIncBmToDiffReflGnd(SurfLoop),
    1291              :                                 OutputProcessor::TimeStepType::Zone,
    1292              :                                 OutputProcessor::StoreType::Average,
    1293          694 :                                 surf.Name);
    1294         1388 :             SetupOutputVariable(state,
    1295              :                                 "Surface Anisotropic Sky Multiplier",
    1296              :                                 Constant::Units::None,
    1297          694 :                                 state.dataSolarShading->SurfAnisoSkyMult(SurfLoop),
    1298              :                                 OutputProcessor::TimeStepType::Zone,
    1299              :                                 OutputProcessor::StoreType::Average,
    1300          694 :                                 surf.Name);
    1301          694 :             SetupOutputVariable(state,
    1302              :                                 "Surface Window BSDF Beam Direction Number",
    1303              :                                 Constant::Units::None,
    1304          694 :                                 state.dataHeatBal->SurfWinBSDFBeamDirectionRep(SurfLoop),
    1305              :                                 OutputProcessor::TimeStepType::Zone,
    1306              :                                 OutputProcessor::StoreType::Average,
    1307          694 :                                 surf.Name);
    1308         1388 :             SetupOutputVariable(state,
    1309              :                                 "Surface Window BSDF Beam Theta Angle",
    1310              :                                 Constant::Units::rad,
    1311          694 :                                 state.dataHeatBal->SurfWinBSDFBeamThetaRep(SurfLoop),
    1312              :                                 OutputProcessor::TimeStepType::Zone,
    1313              :                                 OutputProcessor::StoreType::Average,
    1314          694 :                                 surf.Name);
    1315         1388 :             SetupOutputVariable(state,
    1316              :                                 "Surface Window BSDF Beam Phi Angle",
    1317              :                                 Constant::Units::rad,
    1318          694 :                                 state.dataHeatBal->SurfWinBSDFBeamPhiRep(SurfLoop),
    1319              :                                 OutputProcessor::TimeStepType::Zone,
    1320              :                                 OutputProcessor::StoreType::Average,
    1321          694 :                                 surf.Name);
    1322              :         }
    1323         1012 :         if (!surf.HeatTransSurf) continue;
    1324              : 
    1325          942 :         if (surf.Class == SurfaceClass::Window) {
    1326              :             // CurrentModuleObject='Windows/GlassDoors'
    1327           73 :             if (surf.ExtSolar) {
    1328          142 :                 SetupOutputVariable(state,
    1329              :                                     "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
    1330              :                                     Constant::Units::W,
    1331           71 :                                     state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
    1332              :                                     OutputProcessor::TimeStepType::Zone,
    1333              :                                     OutputProcessor::StoreType::Average,
    1334           71 :                                     surf.Name);
    1335          142 :                 SetupOutputVariable(state,
    1336              :                                     "Surface Window Total Glazing Layers Absorbed Shortwave Radiation Rate",
    1337              :                                     Constant::Units::W,
    1338           71 :                                     state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfLoop),
    1339              :                                     OutputProcessor::TimeStepType::Zone,
    1340              :                                     OutputProcessor::StoreType::Average,
    1341           71 :                                     surf.Name);
    1342              : 
    1343           71 :                 if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF) {
    1344            1 :                     NumOfLayers = state.dataConstruction->Construct(surf.Construction).TotSolidLayers;
    1345              :                 } else {
    1346           70 :                     NumOfLayers = state.dataConstruction->Construct(surf.Construction).TotLayers;
    1347              :                 }
    1348          222 :                 for (I = 1; I <= NumOfLayers; ++I) {
    1349          151 :                     if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF) {
    1350            9 :                         SetupOutputVariable(state,
    1351            6 :                                             format("Surface Window Total Absorbed Shortwave Radiation Rate Layer {}", I),
    1352              :                                             Constant::Units::W,
    1353            3 :                                             state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfLoop, I),
    1354              :                                             OutputProcessor::TimeStepType::Zone,
    1355              :                                             OutputProcessor::StoreType::Average,
    1356            3 :                                             surf.Name);
    1357              :                     }
    1358          151 :                     if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF || (I == 1)) {
    1359          219 :                         SetupOutputVariable(state,
    1360          146 :                                             format("Surface Window Front Face Temperature Layer {}", I),
    1361              :                                             Constant::Units::C,
    1362           73 :                                             state.dataHeatBal->SurfWinFenLaySurfTempFront(SurfLoop, I),
    1363              :                                             OutputProcessor::TimeStepType::Zone,
    1364              :                                             OutputProcessor::StoreType::Average,
    1365           73 :                                             surf.Name);
    1366              :                     }
    1367          151 :                     if (state.dataConstruction->Construct(surf.Construction).WindowTypeBSDF || (I == NumOfLayers)) {
    1368          219 :                         SetupOutputVariable(state,
    1369          146 :                                             format("Surface Window Back Face Temperature Layer {}", I),
    1370              :                                             Constant::Units::C,
    1371           73 :                                             state.dataHeatBal->SurfWinFenLaySurfTempBack(SurfLoop, I),
    1372              :                                             OutputProcessor::TimeStepType::Zone,
    1373              :                                             OutputProcessor::StoreType::Average,
    1374           73 :                                             surf.Name);
    1375              :                     }
    1376              :                 }
    1377              : 
    1378          142 :                 SetupOutputVariable(state,
    1379              :                                     "Surface Window Transmitted Solar Radiation Rate",
    1380              :                                     Constant::Units::W,
    1381           71 :                                     s_surf->SurfWinTransSolar(SurfLoop),
    1382              :                                     OutputProcessor::TimeStepType::Zone,
    1383              :                                     OutputProcessor::StoreType::Average,
    1384           71 :                                     surf.Name);
    1385          142 :                 SetupOutputVariable(state,
    1386              :                                     "Surface Window Transmitted Beam Solar Radiation Rate",
    1387              :                                     Constant::Units::W,
    1388           71 :                                     s_surf->SurfWinBmSolar(SurfLoop),
    1389              :                                     OutputProcessor::TimeStepType::Zone,
    1390              :                                     OutputProcessor::StoreType::Average,
    1391           71 :                                     surf.Name);
    1392              : 
    1393              :                 // added TH 12/9/2009
    1394          142 :                 SetupOutputVariable(state,
    1395              :                                     "Surface Window Transmitted Beam To Beam Solar Radiation Rate",
    1396              :                                     Constant::Units::W,
    1397           71 :                                     s_surf->SurfWinBmBmSolar(SurfLoop),
    1398              :                                     OutputProcessor::TimeStepType::Zone,
    1399              :                                     OutputProcessor::StoreType::Average,
    1400           71 :                                     surf.Name);
    1401          142 :                 SetupOutputVariable(state,
    1402              :                                     "Surface Window Transmitted Beam To Diffuse Solar Radiation Rate",
    1403              :                                     Constant::Units::W,
    1404           71 :                                     s_surf->SurfWinBmDifSolar(SurfLoop),
    1405              :                                     OutputProcessor::TimeStepType::Zone,
    1406              :                                     OutputProcessor::StoreType::Average,
    1407           71 :                                     surf.Name);
    1408              : 
    1409          142 :                 SetupOutputVariable(state,
    1410              :                                     "Surface Window Transmitted Diffuse Solar Radiation Rate",
    1411              :                                     Constant::Units::W,
    1412           71 :                                     s_surf->SurfWinDifSolar(SurfLoop),
    1413              :                                     OutputProcessor::TimeStepType::Zone,
    1414              :                                     OutputProcessor::StoreType::Average,
    1415           71 :                                     surf.Name);
    1416          142 :                 SetupOutputVariable(state,
    1417              :                                     "Surface Window Heat Gain Rate",
    1418              :                                     Constant::Units::W,
    1419           71 :                                     s_surf->SurfWinHeatGainRep(SurfLoop),
    1420              :                                     OutputProcessor::TimeStepType::Zone,
    1421              :                                     OutputProcessor::StoreType::Average,
    1422           71 :                                     surf.Name);
    1423          142 :                 SetupOutputVariable(state,
    1424              :                                     "Surface Window Heat Loss Rate",
    1425              :                                     Constant::Units::W,
    1426           71 :                                     s_surf->SurfWinHeatLossRep(SurfLoop),
    1427              :                                     OutputProcessor::TimeStepType::Zone,
    1428              :                                     OutputProcessor::StoreType::Average,
    1429           71 :                                     surf.Name);
    1430          142 :                 SetupOutputVariable(state,
    1431              :                                     "Surface Window Gap Convective Heat Transfer Rate",
    1432              :                                     Constant::Units::W,
    1433           71 :                                     s_surf->SurfWinGapConvHtFlowRep(SurfLoop),
    1434              :                                     OutputProcessor::TimeStepType::Zone,
    1435              :                                     OutputProcessor::StoreType::Average,
    1436           71 :                                     surf.Name);
    1437          142 :                 SetupOutputVariable(state,
    1438              :                                     "Surface Window Shading Device Absorbed Solar Radiation Rate",
    1439              :                                     Constant::Units::W,
    1440           71 :                                     s_surf->SurfWinShadingAbsorbedSolar(SurfLoop),
    1441              :                                     OutputProcessor::TimeStepType::Zone,
    1442              :                                     OutputProcessor::StoreType::Average,
    1443           71 :                                     surf.Name);
    1444          142 :                 SetupOutputVariable(state,
    1445              :                                     "Surface Window Net Heat Transfer Rate",
    1446              :                                     Constant::Units::W,
    1447           71 :                                     s_surf->SurfWinHeatGain(SurfLoop),
    1448              :                                     OutputProcessor::TimeStepType::Zone,
    1449              :                                     OutputProcessor::StoreType::Average,
    1450           71 :                                     surf.Name);
    1451              : 
    1452           71 :                 if (state.dataGlobal->DisplayAdvancedReportVariables) {
    1453              :                     // CurrentModuleObject='Windows/GlassDoors(Advanced)'
    1454            0 :                     SetupOutputVariable(state,
    1455              :                                         "Surface Window Inside Face Glazing Zone Convection Heat Gain Rate",
    1456              :                                         Constant::Units::W,
    1457            0 :                                         s_surf->SurfWinGainConvGlazToZoneRep(SurfLoop),
    1458              :                                         OutputProcessor::TimeStepType::Zone,
    1459              :                                         OutputProcessor::StoreType::Average,
    1460            0 :                                         surf.Name);
    1461            0 :                     SetupOutputVariable(state,
    1462              :                                         "Surface Window Inside Face Glazing Net Infrared Heat Transfer Rate",
    1463              :                                         Constant::Units::W,
    1464            0 :                                         s_surf->SurfWinGainIRGlazToZoneRep(SurfLoop),
    1465              :                                         OutputProcessor::TimeStepType::Zone,
    1466              :                                         OutputProcessor::StoreType::Average,
    1467            0 :                                         surf.Name);
    1468            0 :                     SetupOutputVariable(state,
    1469              :                                         "Surface Window Shortwave from Zone Back Out Window Heat Transfer Rate",
    1470              :                                         Constant::Units::W,
    1471            0 :                                         s_surf->SurfWinLossSWZoneToOutWinRep(SurfLoop),
    1472              :                                         OutputProcessor::TimeStepType::Zone,
    1473              :                                         OutputProcessor::StoreType::Average,
    1474            0 :                                         surf.Name);
    1475            0 :                     SetupOutputVariable(state,
    1476              :                                         "Surface Window Inside Face Frame and Divider Zone Heat Gain Rate",
    1477              :                                         Constant::Units::W,
    1478            0 :                                         s_surf->SurfWinGainFrameDividerToZoneRep(SurfLoop),
    1479              :                                         OutputProcessor::TimeStepType::Zone,
    1480              :                                         OutputProcessor::StoreType::Average,
    1481            0 :                                         surf.Name);
    1482            0 :                     SetupOutputVariable(state,
    1483              :                                         "Surface Window Inside Face Gap between Shade and Glazing Zone Convection Heat Gain Rate",
    1484              :                                         Constant::Units::W,
    1485            0 :                                         s_surf->SurfWinConvHeatFlowNatural(SurfLoop),
    1486              :                                         OutputProcessor::TimeStepType::Zone,
    1487              :                                         OutputProcessor::StoreType::Average,
    1488            0 :                                         surf.Name);
    1489            0 :                     SetupOutputVariable(state,
    1490              :                                         "Surface Window Inside Face Shade Zone Convection Heat Gain Rate",
    1491              :                                         Constant::Units::W,
    1492            0 :                                         s_surf->SurfWinGainConvShadeToZoneRep(SurfLoop),
    1493              :                                         OutputProcessor::TimeStepType::Zone,
    1494              :                                         OutputProcessor::StoreType::Average,
    1495            0 :                                         surf.Name);
    1496            0 :                     SetupOutputVariable(state,
    1497              :                                         "Surface Window Inside Face Shade Net Infrared Heat Transfer Rate",
    1498              :                                         Constant::Units::W,
    1499            0 :                                         s_surf->SurfWinGainIRShadeToZoneRep(SurfLoop),
    1500              :                                         OutputProcessor::TimeStepType::Zone,
    1501              :                                         OutputProcessor::StoreType::Average,
    1502            0 :                                         surf.Name);
    1503            0 :                     if (state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
    1504            0 :                         SetupOutputVariable(state,
    1505              :                                             "Surface Window Inside Face Other Convection Heat Gain Rate",
    1506              :                                             Constant::Units::W,
    1507            0 :                                             s_surf->SurfWinOtherConvHeatGain(SurfLoop),
    1508              :                                             OutputProcessor::TimeStepType::Zone,
    1509              :                                             OutputProcessor::StoreType::Average,
    1510            0 :                                             surf.Name);
    1511              :                     }
    1512              :                 }
    1513              : 
    1514              :                 // Added TH 12/23/2008 for thermochromic windows
    1515              :                 // CurrentModuleObject='Thermochromic Windows'
    1516           71 :                 if (state.dataConstruction->Construct(surf.Construction).isTCWindow) {
    1517            0 :                     SetupOutputVariable(state,
    1518              :                                         "Surface Window Thermochromic Layer Temperature",
    1519              :                                         Constant::Units::C,
    1520            0 :                                         s_surf->SurfWinTCLayerTemp(SurfLoop),
    1521              :                                         OutputProcessor::TimeStepType::Zone,
    1522              :                                         OutputProcessor::StoreType::Average,
    1523            0 :                                         surf.Name);
    1524            0 :                     SetupOutputVariable(state,
    1525              :                                         "Surface Window Thermochromic Layer Property Specification Temperature",
    1526              :                                         Constant::Units::C,
    1527            0 :                                         s_surf->SurfWinSpecTemp(SurfLoop),
    1528              :                                         OutputProcessor::TimeStepType::Zone,
    1529              :                                         OutputProcessor::StoreType::Average,
    1530            0 :                                         surf.Name);
    1531              :                 }
    1532              : 
    1533              :                 // Added TH 5/26/2009 for switchable windows to report switching factor (tinted level)
    1534              :                 // CurrentModuleObject='Switchable Windows'
    1535           71 :                 if (surf.HasShadeControl) {
    1536            8 :                     if (s_surf->WindowShadingControl(surf.activeWindowShadingControl).ShadingType == WinShadingType::SwitchableGlazing) {
    1537              :                         // IF (SurfaceWindow(SurfLoop)%ShadingFlag == WinShadingType::SwitchableGlazing) THEN  !ShadingFlag is not set to
    1538              :                         // WinShadingType::SwitchableGlazing yet!
    1539            0 :                         SetupOutputVariable(state,
    1540              :                                             "Surface Window Switchable Glazing Switching Factor",
    1541              :                                             Constant::Units::None,
    1542            0 :                                             s_surf->SurfWinSwitchingFactor(SurfLoop),
    1543              :                                             OutputProcessor::TimeStepType::Zone,
    1544              :                                             OutputProcessor::StoreType::Average,
    1545            0 :                                             surf.Name);
    1546            0 :                         SetupOutputVariable(state,
    1547              :                                             "Surface Window Switchable Glazing Visible Transmittance",
    1548              :                                             Constant::Units::None,
    1549            0 :                                             s_surf->SurfWinVisTransSelected(SurfLoop),
    1550              :                                             OutputProcessor::TimeStepType::Zone,
    1551              :                                             OutputProcessor::StoreType::Average,
    1552            0 :                                             surf.Name);
    1553              :                     }
    1554              :                 }
    1555              : 
    1556           71 :                 if (s_surf->SurfWinFrameArea(SurfLoop) > 0.0) {
    1557              :                     // CurrentModuleObject='Window Frames'
    1558           40 :                     SetupOutputVariable(state,
    1559              :                                         "Surface Window Frame Heat Gain Rate",
    1560              :                                         Constant::Units::W,
    1561           20 :                                         s_surf->SurfWinFrameHeatGain(SurfLoop),
    1562              :                                         OutputProcessor::TimeStepType::Zone,
    1563              :                                         OutputProcessor::StoreType::Average,
    1564           20 :                                         surf.Name);
    1565           40 :                     SetupOutputVariable(state,
    1566              :                                         "Surface Window Frame Heat Loss Rate",
    1567              :                                         Constant::Units::W,
    1568           20 :                                         s_surf->SurfWinFrameHeatLoss(SurfLoop),
    1569              :                                         OutputProcessor::TimeStepType::Zone,
    1570              :                                         OutputProcessor::StoreType::Average,
    1571           20 :                                         surf.Name);
    1572           40 :                     SetupOutputVariable(state,
    1573              :                                         "Surface Window Frame Inside Temperature",
    1574              :                                         Constant::Units::C,
    1575           20 :                                         s_surf->SurfWinFrameTempIn(SurfLoop),
    1576              :                                         OutputProcessor::TimeStepType::Zone,
    1577              :                                         OutputProcessor::StoreType::Average,
    1578           20 :                                         surf.Name);
    1579           40 :                     SetupOutputVariable(state,
    1580              :                                         "Surface Window Frame Outside Temperature",
    1581              :                                         Constant::Units::C,
    1582           20 :                                         s_surf->SurfWinFrameTempSurfOut(SurfLoop),
    1583              :                                         OutputProcessor::TimeStepType::Zone,
    1584              :                                         OutputProcessor::StoreType::Average,
    1585           20 :                                         surf.Name);
    1586              :                 }
    1587           71 :                 if (s_surf->SurfWinDividerArea(SurfLoop) > 0.0) {
    1588              :                     // CurrentModuleObject='Window Dividers'
    1589           40 :                     SetupOutputVariable(state,
    1590              :                                         "Surface Window Divider Heat Gain Rate",
    1591              :                                         Constant::Units::W,
    1592           20 :                                         s_surf->SurfWinDividerHeatGain(SurfLoop),
    1593              :                                         OutputProcessor::TimeStepType::Zone,
    1594              :                                         OutputProcessor::StoreType::Average,
    1595           20 :                                         surf.Name);
    1596           40 :                     SetupOutputVariable(state,
    1597              :                                         "Surface Window Divider Heat Loss Rate",
    1598              :                                         Constant::Units::W,
    1599           20 :                                         s_surf->SurfWinDividerHeatLoss(SurfLoop),
    1600              :                                         OutputProcessor::TimeStepType::Zone,
    1601              :                                         OutputProcessor::StoreType::Average,
    1602           20 :                                         surf.Name);
    1603           40 :                     SetupOutputVariable(state,
    1604              :                                         "Surface Window Divider Inside Temperature",
    1605              :                                         Constant::Units::C,
    1606           20 :                                         s_surf->SurfWinDividerTempIn(SurfLoop),
    1607              :                                         OutputProcessor::TimeStepType::Zone,
    1608              :                                         OutputProcessor::StoreType::Average,
    1609           20 :                                         surf.Name);
    1610           40 :                     SetupOutputVariable(state,
    1611              :                                         "Surface Window Divider Outside Temperature",
    1612              :                                         Constant::Units::C,
    1613           20 :                                         s_surf->SurfWinDividerTempSurfOut(SurfLoop),
    1614              :                                         OutputProcessor::TimeStepType::Zone,
    1615              :                                         OutputProcessor::StoreType::Average,
    1616           20 :                                         surf.Name);
    1617              :                 }
    1618              : 
    1619              :                 // CurrentModuleObject='Windows'
    1620              :                 // Energy
    1621          142 :                 SetupOutputVariable(state,
    1622              :                                     "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
    1623              :                                     Constant::Units::J,
    1624           71 :                                     state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
    1625              :                                     OutputProcessor::TimeStepType::Zone,
    1626              :                                     OutputProcessor::StoreType::Sum,
    1627           71 :                                     surf.Name);
    1628          142 :                 SetupOutputVariable(state,
    1629              :                                     "Surface Window Transmitted Solar Radiation Energy",
    1630              :                                     Constant::Units::J,
    1631           71 :                                     s_surf->SurfWinTransSolarEnergy(SurfLoop),
    1632              :                                     OutputProcessor::TimeStepType::Zone,
    1633              :                                     OutputProcessor::StoreType::Sum,
    1634           71 :                                     surf.Name);
    1635          142 :                 SetupOutputVariable(state,
    1636              :                                     "Surface Window Transmitted Beam Solar Radiation Energy",
    1637              :                                     Constant::Units::J,
    1638           71 :                                     s_surf->SurfWinBmSolarEnergy(SurfLoop),
    1639              :                                     OutputProcessor::TimeStepType::Zone,
    1640              :                                     OutputProcessor::StoreType::Sum,
    1641           71 :                                     surf.Name);
    1642              : 
    1643              :                 // added TH 12/9/2009
    1644          142 :                 SetupOutputVariable(state,
    1645              :                                     "Surface Window Transmitted Beam To Beam Solar Radiation Energy",
    1646              :                                     Constant::Units::J,
    1647           71 :                                     s_surf->SurfWinBmBmSolarEnergy(SurfLoop),
    1648              :                                     OutputProcessor::TimeStepType::Zone,
    1649              :                                     OutputProcessor::StoreType::Sum,
    1650           71 :                                     surf.Name);
    1651          142 :                 SetupOutputVariable(state,
    1652              :                                     "Surface Window Transmitted Beam To Diffuse Solar Radiation Energy",
    1653              :                                     Constant::Units::J,
    1654           71 :                                     s_surf->SurfWinBmDifSolarEnergy(SurfLoop),
    1655              :                                     OutputProcessor::TimeStepType::Zone,
    1656              :                                     OutputProcessor::StoreType::Sum,
    1657           71 :                                     surf.Name);
    1658              : 
    1659          142 :                 SetupOutputVariable(state,
    1660              :                                     "Surface Window Transmitted Diffuse Solar Radiation Energy",
    1661              :                                     Constant::Units::J,
    1662           71 :                                     s_surf->SurfWinDifSolarEnergy(SurfLoop),
    1663              :                                     OutputProcessor::TimeStepType::Zone,
    1664              :                                     OutputProcessor::StoreType::Sum,
    1665           71 :                                     surf.Name);
    1666          142 :                 SetupOutputVariable(state,
    1667              :                                     "Surface Window Heat Gain Energy",
    1668              :                                     Constant::Units::J,
    1669           71 :                                     s_surf->SurfWinHeatGainRepEnergy(SurfLoop),
    1670              :                                     OutputProcessor::TimeStepType::Zone,
    1671              :                                     OutputProcessor::StoreType::Sum,
    1672           71 :                                     surf.Name);
    1673          142 :                 SetupOutputVariable(state,
    1674              :                                     "Surface Window Heat Loss Energy",
    1675              :                                     Constant::Units::J,
    1676           71 :                                     s_surf->SurfWinHeatLossRepEnergy(SurfLoop),
    1677              :                                     OutputProcessor::TimeStepType::Zone,
    1678              :                                     OutputProcessor::StoreType::Sum,
    1679           71 :                                     surf.Name);
    1680          142 :                 SetupOutputVariable(state,
    1681              :                                     "Surface Window Gap Convective Heat Transfer Energy",
    1682              :                                     Constant::Units::J,
    1683           71 :                                     s_surf->SurfWinGapConvHtFlowRepEnergy(SurfLoop),
    1684              :                                     OutputProcessor::TimeStepType::Zone,
    1685              :                                     OutputProcessor::StoreType::Sum,
    1686           71 :                                     surf.Name);
    1687          142 :                 SetupOutputVariable(state,
    1688              :                                     "Surface Window Shading Device Absorbed Solar Radiation Energy",
    1689              :                                     Constant::Units::J,
    1690           71 :                                     s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfLoop),
    1691              :                                     OutputProcessor::TimeStepType::Zone,
    1692              :                                     OutputProcessor::StoreType::Sum,
    1693           71 :                                     surf.Name);
    1694          142 :                 SetupOutputVariable(state,
    1695              :                                     "Surface Window Net Heat Transfer Energy",
    1696              :                                     Constant::Units::J,
    1697           71 :                                     s_surf->SurfWinHeatTransferRepEnergy(SurfLoop),
    1698              :                                     OutputProcessor::TimeStepType::Zone,
    1699              :                                     OutputProcessor::StoreType::Sum,
    1700           71 :                                     surf.Name);
    1701              : 
    1702          142 :                 SetupOutputVariable(state,
    1703              :                                     "Surface Window System Solar Transmittance",
    1704              :                                     Constant::Units::None,
    1705           71 :                                     s_surf->SurfWinSysSolTransmittance(SurfLoop),
    1706              :                                     OutputProcessor::TimeStepType::Zone,
    1707              :                                     OutputProcessor::StoreType::Average,
    1708           71 :                                     surf.Name);
    1709          142 :                 SetupOutputVariable(state,
    1710              :                                     "Surface Window System Solar Reflectance",
    1711              :                                     Constant::Units::None,
    1712           71 :                                     s_surf->SurfWinSysSolReflectance(SurfLoop),
    1713              :                                     OutputProcessor::TimeStepType::Zone,
    1714              :                                     OutputProcessor::StoreType::Average,
    1715           71 :                                     surf.Name);
    1716          142 :                 SetupOutputVariable(state,
    1717              :                                     "Surface Window System Solar Absorptance",
    1718              :                                     Constant::Units::None,
    1719           71 :                                     s_surf->SurfWinSysSolAbsorptance(SurfLoop),
    1720              :                                     OutputProcessor::TimeStepType::Zone,
    1721              :                                     OutputProcessor::StoreType::Average,
    1722           71 :                                     surf.Name);
    1723           71 :                 SetupOutputVariable(state,
    1724              :                                     "Surface Window Inside Face Glazing Condensation Status",
    1725              :                                     Constant::Units::None,
    1726           71 :                                     s_surf->SurfWinInsideGlassCondensationFlag(SurfLoop),
    1727              :                                     OutputProcessor::TimeStepType::Zone,
    1728              :                                     OutputProcessor::StoreType::Average,
    1729           71 :                                     surf.Name);
    1730           71 :                 SetupOutputVariable(state,
    1731              :                                     "Surface Window Inside Face Frame Condensation Status",
    1732              :                                     Constant::Units::None,
    1733           71 :                                     s_surf->SurfWinInsideFrameCondensationFlag(SurfLoop),
    1734              :                                     OutputProcessor::TimeStepType::Zone,
    1735              :                                     OutputProcessor::StoreType::Average,
    1736           71 :                                     surf.Name);
    1737           71 :                 SetupOutputVariable(state,
    1738              :                                     "Surface Window Inside Face Divider Condensation Status",
    1739              :                                     Constant::Units::None,
    1740           71 :                                     s_surf->SurfWinInsideDividerCondensationFlag(SurfLoop),
    1741              :                                     OutputProcessor::TimeStepType::Zone,
    1742              :                                     OutputProcessor::StoreType::Average,
    1743           71 :                                     surf.Name);
    1744              : 
    1745              :                 // Outside reveal report variables
    1746              :                 // IF (Surface(SurfLoop)%Reveal > 0.0) THEN
    1747          142 :                 SetupOutputVariable(state,
    1748              :                                     "Surface Window Outside Reveal Reflected Beam Solar Radiation Rate",
    1749              :                                     Constant::Units::W,
    1750           71 :                                     s_surf->SurfWinBmSolRefldOutsRevealReport(SurfLoop),
    1751              :                                     OutputProcessor::TimeStepType::Zone,
    1752              :                                     OutputProcessor::StoreType::Average,
    1753           71 :                                     surf.Name);
    1754              :                 // Energy
    1755          142 :                 SetupOutputVariable(state,
    1756              :                                     "Surface Window Outside Reveal Reflected Beam Solar Radiation Energy",
    1757              :                                     Constant::Units::J,
    1758           71 :                                     s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfLoop),
    1759              :                                     OutputProcessor::TimeStepType::Zone,
    1760              :                                     OutputProcessor::StoreType::Sum,
    1761           71 :                                     surf.Name);
    1762              :                 // ENDIF
    1763              : 
    1764              :                 // Inside reveal report variables
    1765           71 :                 if (s_surf->SurfWinInsideReveal(SurfLoop) > 0.0 || s_surf->SurfWinInsideSillDepth(SurfLoop) > 0.0) {
    1766            0 :                     SetupOutputVariable(state,
    1767              :                                         "Surface Window Inside Reveal Reflected Beam Solar Radiation Rate",
    1768              :                                         Constant::Units::W,
    1769            0 :                                         s_surf->SurfWinBmSolRefldInsRevealReport(SurfLoop),
    1770              :                                         OutputProcessor::TimeStepType::Zone,
    1771              :                                         OutputProcessor::StoreType::Average,
    1772            0 :                                         surf.Name);
    1773              :                     // Energy
    1774            0 :                     SetupOutputVariable(state,
    1775              :                                         "Surface Window Inside Reveal Reflected Beam Solar Radiation Energy",
    1776              :                                         Constant::Units::J,
    1777            0 :                                         s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfLoop),
    1778              :                                         OutputProcessor::TimeStepType::Zone,
    1779              :                                         OutputProcessor::StoreType::Sum,
    1780            0 :                                         surf.Name);
    1781              : 
    1782              :                     // Added report variables for inside reveal to debug CR 7596. TH 5/26/2009
    1783              :                     // All reflected solar by the inside reveal is turned into diffuse
    1784            0 :                     SetupOutputVariable(state,
    1785              :                                         "Surface Window Inside Reveal Absorbed Beam Solar Radiation Rate",
    1786              :                                         Constant::Units::W,
    1787            0 :                                         s_surf->SurfWinBmSolAbsdInsRevealReport(SurfLoop),
    1788              :                                         OutputProcessor::TimeStepType::Zone,
    1789              :                                         OutputProcessor::StoreType::Average,
    1790            0 :                                         surf.Name);
    1791            0 :                     SetupOutputVariable(state,
    1792              :                                         "Surface Window Inside Reveal Reflected Diffuse Zone Solar Radiation Rate",
    1793              :                                         Constant::Units::W,
    1794            0 :                                         s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfLoop),
    1795              :                                         OutputProcessor::TimeStepType::Zone,
    1796              :                                         OutputProcessor::StoreType::Average,
    1797            0 :                                         surf.Name);
    1798            0 :                     SetupOutputVariable(state,
    1799              :                                         "Surface Window Inside Reveal Reflected Diffuse Frame Solar Radiation Rate",
    1800              :                                         Constant::Units::W,
    1801            0 :                                         s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfLoop),
    1802              :                                         OutputProcessor::TimeStepType::Zone,
    1803              :                                         OutputProcessor::StoreType::Average,
    1804            0 :                                         surf.Name);
    1805            0 :                     SetupOutputVariable(state,
    1806              :                                         "Surface Window Inside Reveal Reflected Diffuse Glazing Solar Radiation Rate",
    1807              :                                         Constant::Units::W,
    1808            0 :                                         s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfLoop),
    1809              :                                         OutputProcessor::TimeStepType::Zone,
    1810              :                                         OutputProcessor::StoreType::Average,
    1811            0 :                                         surf.Name);
    1812              :                 }
    1813              : 
    1814              :                 //     Output blind report variables only when blinds are used
    1815           71 :                 auto &surfShade = s_surf->surfShades(SurfLoop);
    1816           71 :                 if (surfShade.blind.matNum > 0) {
    1817              :                     // CurrentModuleObject='Window Blinds'
    1818           16 :                     SetupOutputVariable(state,
    1819              :                                         "Surface Window Blind Beam to Beam Solar Transmittance",
    1820              :                                         Constant::Units::None,
    1821            8 :                                         s_surf->SurfWinBlTsolBmBm(SurfLoop),
    1822              :                                         OutputProcessor::TimeStepType::Zone,
    1823              :                                         OutputProcessor::StoreType::Average,
    1824            8 :                                         surf.Name);
    1825           16 :                     SetupOutputVariable(state,
    1826              :                                         "Surface Window Blind Beam to Diffuse Solar Transmittance",
    1827              :                                         Constant::Units::None,
    1828            8 :                                         s_surf->SurfWinBlTsolBmDif(SurfLoop),
    1829              :                                         OutputProcessor::TimeStepType::Zone,
    1830              :                                         OutputProcessor::StoreType::Average,
    1831            8 :                                         surf.Name);
    1832           16 :                     SetupOutputVariable(state,
    1833              :                                         "Surface Window Blind Diffuse to Diffuse Solar Transmittance",
    1834              :                                         Constant::Units::None,
    1835            8 :                                         s_surf->SurfWinBlTsolDifDif(SurfLoop),
    1836              :                                         OutputProcessor::TimeStepType::Zone,
    1837              :                                         OutputProcessor::StoreType::Average,
    1838            8 :                                         surf.Name);
    1839           16 :                     SetupOutputVariable(state,
    1840              :                                         "Surface Window Blind and Glazing System Beam Solar Transmittance",
    1841              :                                         Constant::Units::None,
    1842            8 :                                         s_surf->SurfWinBlGlSysTsolBmBm(SurfLoop),
    1843              :                                         OutputProcessor::TimeStepType::Zone,
    1844              :                                         OutputProcessor::StoreType::Average,
    1845            8 :                                         surf.Name);
    1846           16 :                     SetupOutputVariable(state,
    1847              :                                         "Surface Window Blind and Glazing System Diffuse Solar Transmittance",
    1848              :                                         Constant::Units::None,
    1849            8 :                                         s_surf->SurfWinBlGlSysTsolDifDif(SurfLoop),
    1850              :                                         OutputProcessor::TimeStepType::Zone,
    1851              :                                         OutputProcessor::StoreType::Average,
    1852            8 :                                         surf.Name);
    1853              :                 }
    1854              : 
    1855              :                 //     Output screen report variables only when screens are used
    1856           71 :                 if (s_surf->SurfaceWindow(SurfLoop).screenNum > 0) {
    1857              :                     // CurrentModuleObject='Window Screens'
    1858            0 :                     SetupOutputVariable(state,
    1859              :                                         "Surface Window Screen Beam to Beam Solar Transmittance",
    1860              :                                         Constant::Units::None,
    1861            0 :                                         s_surf->SurfWinScTsolBmBm(SurfLoop),
    1862              :                                         OutputProcessor::TimeStepType::Zone,
    1863              :                                         OutputProcessor::StoreType::Average,
    1864            0 :                                         surf.Name);
    1865            0 :                     SetupOutputVariable(state,
    1866              :                                         "Surface Window Screen Beam to Diffuse Solar Transmittance",
    1867              :                                         Constant::Units::None,
    1868            0 :                                         s_surf->SurfWinScTsolBmDif(SurfLoop),
    1869              :                                         OutputProcessor::TimeStepType::Zone,
    1870              :                                         OutputProcessor::StoreType::Average,
    1871            0 :                                         surf.Name);
    1872            0 :                     SetupOutputVariable(state,
    1873              :                                         "Surface Window Screen Diffuse to Diffuse Solar Transmittance",
    1874              :                                         Constant::Units::None,
    1875            0 :                                         s_surf->SurfWinScTsolDifDif(SurfLoop),
    1876              :                                         OutputProcessor::TimeStepType::Zone,
    1877              :                                         OutputProcessor::StoreType::Average,
    1878            0 :                                         surf.Name);
    1879            0 :                     SetupOutputVariable(state,
    1880              :                                         "Surface Window Screen and Glazing System Beam Solar Transmittance",
    1881              :                                         Constant::Units::None,
    1882            0 :                                         s_surf->SurfWinScGlSysTsolBmBm(SurfLoop),
    1883              :                                         OutputProcessor::TimeStepType::Zone,
    1884              :                                         OutputProcessor::StoreType::Average,
    1885            0 :                                         surf.Name);
    1886            0 :                     SetupOutputVariable(state,
    1887              :                                         "Surface Window Screen and Glazing System Diffuse Solar Transmittance",
    1888              :                                         Constant::Units::None,
    1889            0 :                                         s_surf->SurfWinScGlSysTsolDifDif(SurfLoop),
    1890              :                                         OutputProcessor::TimeStepType::Zone,
    1891              :                                         OutputProcessor::StoreType::Average,
    1892            0 :                                         surf.Name);
    1893              :                 }
    1894              : 
    1895              :                 // CurrentModuleObject='Windows'
    1896          142 :                 SetupOutputVariable(state,
    1897              :                                     "Surface Window Solar Horizontal Profile Angle",
    1898              :                                     Constant::Units::deg,
    1899           71 :                                     s_surf->SurfWinProfileAngHor(SurfLoop),
    1900              :                                     OutputProcessor::TimeStepType::Zone,
    1901              :                                     OutputProcessor::StoreType::Average,
    1902           71 :                                     surf.Name);
    1903          142 :                 SetupOutputVariable(state,
    1904              :                                     "Surface Window Solar Vertical Profile Angle",
    1905              :                                     Constant::Units::deg,
    1906           71 :                                     s_surf->SurfWinProfileAngVert(SurfLoop),
    1907              :                                     OutputProcessor::TimeStepType::Zone,
    1908              :                                     OutputProcessor::StoreType::Average,
    1909           71 :                                     surf.Name);
    1910          142 :                 SetupOutputVariable(state,
    1911              :                                     "Surface Window Glazing Beam to Beam Solar Transmittance",
    1912              :                                     Constant::Units::None,
    1913           71 :                                     s_surf->SurfWinGlTsolBmBm(SurfLoop),
    1914              :                                     OutputProcessor::TimeStepType::Zone,
    1915              :                                     OutputProcessor::StoreType::Average,
    1916           71 :                                     surf.Name);
    1917          142 :                 SetupOutputVariable(state,
    1918              :                                     "Surface Window Glazing Beam to Diffuse Solar Transmittance",
    1919              :                                     Constant::Units::None,
    1920           71 :                                     s_surf->SurfWinGlTsolBmDif(SurfLoop),
    1921              :                                     OutputProcessor::TimeStepType::Zone,
    1922              :                                     OutputProcessor::StoreType::Average,
    1923           71 :                                     surf.Name);
    1924          142 :                 SetupOutputVariable(state,
    1925              :                                     "Surface Window Glazing Diffuse to Diffuse Solar Transmittance",
    1926              :                                     Constant::Units::None,
    1927           71 :                                     s_surf->SurfWinGlTsolDifDif(SurfLoop),
    1928              :                                     OutputProcessor::TimeStepType::Zone,
    1929              :                                     OutputProcessor::StoreType::Average,
    1930           71 :                                     surf.Name);
    1931           71 :                 SetupOutputVariable(state,
    1932              :                                     "Surface Window Model Solver Iteration Count",
    1933              :                                     Constant::Units::None,
    1934           71 :                                     s_surf->SurfWinWindowCalcIterationsRep(SurfLoop),
    1935              :                                     OutputProcessor::TimeStepType::Zone,
    1936              :                                     OutputProcessor::StoreType::Average,
    1937           71 :                                     surf.Name);
    1938              :             } else { // Not ExtSolar
    1939            2 :                 if (state.dataGlobal->DisplayAdvancedReportVariables) {
    1940              :                     // CurrentModuleObject='InteriorWindows(Advanced)'
    1941            0 :                     if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
    1942            0 :                         SetupOutputVariable(state,
    1943              :                                             "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
    1944              :                                             Constant::Units::W,
    1945            0 :                                             state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
    1946              :                                             OutputProcessor::TimeStepType::Zone,
    1947              :                                             OutputProcessor::StoreType::Average,
    1948            0 :                                             surf.Name);
    1949              :                     }
    1950            0 :                     SetupOutputVariable(state,
    1951              :                                         "Surface Window Total Glazing Layers Absorbed Shortwave Radiation Rate",
    1952              :                                         Constant::Units::W,
    1953            0 :                                         state.dataHeatBal->SurfWinSWwinAbsTotalReport(SurfLoop),
    1954              :                                         OutputProcessor::TimeStepType::Zone,
    1955              :                                         OutputProcessor::StoreType::Average,
    1956            0 :                                         surf.Name);
    1957              : 
    1958            0 :                     if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
    1959            0 :                         SetupOutputVariable(state,
    1960              :                                             "Surface Window Transmitted Solar Radiation Rate",
    1961              :                                             Constant::Units::W,
    1962            0 :                                             s_surf->SurfWinTransSolar(SurfLoop),
    1963              :                                             OutputProcessor::TimeStepType::Zone,
    1964              :                                             OutputProcessor::StoreType::Average,
    1965            0 :                                             surf.Name);
    1966              :                     }
    1967            0 :                     SetupOutputVariable(state,
    1968              :                                         "Surface Window Transmitted Beam Solar Radiation Rate",
    1969              :                                         Constant::Units::W,
    1970            0 :                                         s_surf->SurfWinBmSolar(SurfLoop),
    1971              :                                         OutputProcessor::TimeStepType::Zone,
    1972              :                                         OutputProcessor::StoreType::Average,
    1973            0 :                                         surf.Name);
    1974              : 
    1975              :                     // added TH 12/9/2009
    1976            0 :                     SetupOutputVariable(state,
    1977              :                                         "Surface Window Transmitted Beam To Beam Solar Radiation Rate",
    1978              :                                         Constant::Units::W,
    1979            0 :                                         s_surf->SurfWinBmBmSolar(SurfLoop),
    1980              :                                         OutputProcessor::TimeStepType::Zone,
    1981              :                                         OutputProcessor::StoreType::Average,
    1982            0 :                                         surf.Name);
    1983            0 :                     SetupOutputVariable(state,
    1984              :                                         "Surface Window Transmitted Beam To Diffuse Solar Radiation Rate",
    1985              :                                         Constant::Units::W,
    1986            0 :                                         s_surf->SurfWinBmDifSolar(SurfLoop),
    1987              :                                         OutputProcessor::TimeStepType::Zone,
    1988              :                                         OutputProcessor::StoreType::Average,
    1989            0 :                                         surf.Name);
    1990              : 
    1991            0 :                     SetupOutputVariable(state,
    1992              :                                         "Surface Window Transmitted Diffuse Solar Radiation Rate",
    1993              :                                         Constant::Units::W,
    1994            0 :                                         s_surf->SurfWinDifSolar(SurfLoop),
    1995              :                                         OutputProcessor::TimeStepType::Zone,
    1996              :                                         OutputProcessor::StoreType::Average,
    1997            0 :                                         surf.Name);
    1998            0 :                     SetupOutputVariable(state,
    1999              :                                         "Surface Window Heat Gain Rate",
    2000              :                                         Constant::Units::W,
    2001            0 :                                         s_surf->SurfWinHeatGainRep(SurfLoop),
    2002              :                                         OutputProcessor::TimeStepType::Zone,
    2003              :                                         OutputProcessor::StoreType::Average,
    2004            0 :                                         surf.Name);
    2005            0 :                     SetupOutputVariable(state,
    2006              :                                         "Surface Window Heat Loss Rate",
    2007              :                                         Constant::Units::W,
    2008            0 :                                         s_surf->SurfWinHeatLossRep(SurfLoop),
    2009              :                                         OutputProcessor::TimeStepType::Zone,
    2010              :                                         OutputProcessor::StoreType::Average,
    2011            0 :                                         surf.Name);
    2012            0 :                     SetupOutputVariable(state,
    2013              :                                         "Surface Window Gap Convective Heat Transfer Rate",
    2014              :                                         Constant::Units::W,
    2015            0 :                                         s_surf->SurfWinGapConvHtFlowRep(SurfLoop),
    2016              :                                         OutputProcessor::TimeStepType::Zone,
    2017              :                                         OutputProcessor::StoreType::Average,
    2018            0 :                                         surf.Name);
    2019            0 :                     SetupOutputVariable(state,
    2020              :                                         "Surface Window Shading Device Absorbed Solar Radiation Rate",
    2021              :                                         Constant::Units::W,
    2022            0 :                                         s_surf->SurfWinShadingAbsorbedSolar(SurfLoop),
    2023              :                                         OutputProcessor::TimeStepType::Zone,
    2024              :                                         OutputProcessor::StoreType::Average,
    2025            0 :                                         surf.Name);
    2026            0 :                     if (s_surf->SurfWinFrameArea(SurfLoop) > 0.0) {
    2027            0 :                         SetupOutputVariable(state,
    2028              :                                             "Surface Window Frame Heat Gain Rate",
    2029              :                                             Constant::Units::W,
    2030            0 :                                             s_surf->SurfWinFrameHeatGain(SurfLoop),
    2031              :                                             OutputProcessor::TimeStepType::Zone,
    2032              :                                             OutputProcessor::StoreType::Average,
    2033            0 :                                             surf.Name);
    2034            0 :                         SetupOutputVariable(state,
    2035              :                                             "Surface Window Frame Heat Loss Rate",
    2036              :                                             Constant::Units::W,
    2037            0 :                                             s_surf->SurfWinFrameHeatLoss(SurfLoop),
    2038              :                                             OutputProcessor::TimeStepType::Zone,
    2039              :                                             OutputProcessor::StoreType::Average,
    2040            0 :                                             surf.Name);
    2041            0 :                         SetupOutputVariable(state,
    2042              :                                             "Surface Window Frame Inside Temperature",
    2043              :                                             Constant::Units::C,
    2044            0 :                                             s_surf->SurfWinFrameTempIn(SurfLoop),
    2045              :                                             OutputProcessor::TimeStepType::Zone,
    2046              :                                             OutputProcessor::StoreType::Average,
    2047            0 :                                             surf.Name);
    2048            0 :                         SetupOutputVariable(state,
    2049              :                                             "Surface Window Frame Outside Temperature",
    2050              :                                             Constant::Units::C,
    2051            0 :                                             s_surf->SurfWinFrameTempSurfOut(SurfLoop),
    2052              :                                             OutputProcessor::TimeStepType::Zone,
    2053              :                                             OutputProcessor::StoreType::Average,
    2054            0 :                                             surf.Name);
    2055              :                     }
    2056            0 :                     if (s_surf->SurfWinDividerArea(SurfLoop) > 0.0) {
    2057            0 :                         SetupOutputVariable(state,
    2058              :                                             "Surface Window Divider Heat Gain Rate",
    2059              :                                             Constant::Units::W,
    2060            0 :                                             s_surf->SurfWinDividerHeatGain(SurfLoop),
    2061              :                                             OutputProcessor::TimeStepType::Zone,
    2062              :                                             OutputProcessor::StoreType::Average,
    2063            0 :                                             surf.Name);
    2064            0 :                         SetupOutputVariable(state,
    2065              :                                             "Surface Window Divider Heat Loss Rate",
    2066              :                                             Constant::Units::W,
    2067            0 :                                             s_surf->SurfWinDividerHeatLoss(SurfLoop),
    2068              :                                             OutputProcessor::TimeStepType::Zone,
    2069              :                                             OutputProcessor::StoreType::Average,
    2070            0 :                                             surf.Name);
    2071            0 :                         SetupOutputVariable(state,
    2072              :                                             "Surface Window Divider Inside Temperature",
    2073              :                                             Constant::Units::C,
    2074            0 :                                             s_surf->SurfWinDividerTempIn(SurfLoop),
    2075              :                                             OutputProcessor::TimeStepType::Zone,
    2076              :                                             OutputProcessor::StoreType::Average,
    2077            0 :                                             surf.Name);
    2078            0 :                         SetupOutputVariable(state,
    2079              :                                             "Surface Window Divider Outside Temperature",
    2080              :                                             Constant::Units::C,
    2081            0 :                                             s_surf->SurfWinDividerTempSurfOut(SurfLoop),
    2082              :                                             OutputProcessor::TimeStepType::Zone,
    2083              :                                             OutputProcessor::StoreType::Average,
    2084            0 :                                             surf.Name);
    2085              :                     }
    2086              :                     // Energy
    2087              : 
    2088            0 :                     if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
    2089            0 :                         SetupOutputVariable(state,
    2090              :                                             "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
    2091              :                                             Constant::Units::J,
    2092            0 :                                             state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
    2093              :                                             OutputProcessor::TimeStepType::Zone,
    2094              :                                             OutputProcessor::StoreType::Sum,
    2095            0 :                                             surf.Name);
    2096              :                     }
    2097              : 
    2098            0 :                     if (surf.OriginalClass != SurfaceClass::TDD_Diffuser) {
    2099            0 :                         SetupOutputVariable(state,
    2100              :                                             "Surface Window Transmitted Solar Radiation Energy",
    2101              :                                             Constant::Units::J,
    2102            0 :                                             s_surf->SurfWinTransSolarEnergy(SurfLoop),
    2103              :                                             OutputProcessor::TimeStepType::Zone,
    2104              :                                             OutputProcessor::StoreType::Sum,
    2105            0 :                                             surf.Name);
    2106              :                     }
    2107            0 :                     SetupOutputVariable(state,
    2108              :                                         "Surface Window Transmitted Beam Solar Radiation Energy",
    2109              :                                         Constant::Units::J,
    2110            0 :                                         s_surf->SurfWinBmSolarEnergy(SurfLoop),
    2111              :                                         OutputProcessor::TimeStepType::Zone,
    2112              :                                         OutputProcessor::StoreType::Sum,
    2113            0 :                                         surf.Name);
    2114              : 
    2115            0 :                     SetupOutputVariable(state,
    2116              :                                         "Surface Window Transmitted Beam To Beam Solar Radiation Energy",
    2117              :                                         Constant::Units::J,
    2118            0 :                                         s_surf->SurfWinBmBmSolarEnergy(SurfLoop),
    2119              :                                         OutputProcessor::TimeStepType::Zone,
    2120              :                                         OutputProcessor::StoreType::Sum,
    2121            0 :                                         surf.Name);
    2122            0 :                     SetupOutputVariable(state,
    2123              :                                         "Surface Window Transmitted Beam To Diffuse Solar Radiation Energy",
    2124              :                                         Constant::Units::J,
    2125            0 :                                         s_surf->SurfWinBmDifSolarEnergy(SurfLoop),
    2126              :                                         OutputProcessor::TimeStepType::Zone,
    2127              :                                         OutputProcessor::StoreType::Sum,
    2128            0 :                                         surf.Name);
    2129              : 
    2130            0 :                     SetupOutputVariable(state,
    2131              :                                         "Surface Window Transmitted Diffuse Solar Radiation Energy",
    2132              :                                         Constant::Units::J,
    2133            0 :                                         s_surf->SurfWinDifSolarEnergy(SurfLoop),
    2134              :                                         OutputProcessor::TimeStepType::Zone,
    2135              :                                         OutputProcessor::StoreType::Sum,
    2136            0 :                                         surf.Name);
    2137            0 :                     SetupOutputVariable(state,
    2138              :                                         "Surface Window Heat Gain Energy",
    2139              :                                         Constant::Units::J,
    2140            0 :                                         s_surf->SurfWinHeatGainRepEnergy(SurfLoop),
    2141              :                                         OutputProcessor::TimeStepType::Zone,
    2142              :                                         OutputProcessor::StoreType::Sum,
    2143            0 :                                         surf.Name);
    2144            0 :                     SetupOutputVariable(state,
    2145              :                                         "Surface Window Heat Loss Energy",
    2146              :                                         Constant::Units::J,
    2147            0 :                                         s_surf->SurfWinHeatLossRepEnergy(SurfLoop),
    2148              :                                         OutputProcessor::TimeStepType::Zone,
    2149              :                                         OutputProcessor::StoreType::Sum,
    2150            0 :                                         surf.Name);
    2151            0 :                     SetupOutputVariable(state,
    2152              :                                         "Surface Window Gap Convective Heat Transfer Energy",
    2153              :                                         Constant::Units::J,
    2154            0 :                                         s_surf->SurfWinGapConvHtFlowRepEnergy(SurfLoop),
    2155              :                                         OutputProcessor::TimeStepType::Zone,
    2156              :                                         OutputProcessor::StoreType::Sum,
    2157            0 :                                         surf.Name);
    2158            0 :                     SetupOutputVariable(state,
    2159              :                                         "Surface Window Shading Device Absorbed Solar Radiation Energy",
    2160              :                                         Constant::Units::J,
    2161            0 :                                         s_surf->SurfWinShadingAbsorbedSolarEnergy(SurfLoop),
    2162              :                                         OutputProcessor::TimeStepType::Zone,
    2163              :                                         OutputProcessor::StoreType::Sum,
    2164            0 :                                         surf.Name);
    2165              : 
    2166            0 :                     SetupOutputVariable(state,
    2167              :                                         "Surface Window System Solar Transmittance",
    2168              :                                         Constant::Units::None,
    2169            0 :                                         s_surf->SurfWinSysSolTransmittance(SurfLoop),
    2170              :                                         OutputProcessor::TimeStepType::Zone,
    2171              :                                         OutputProcessor::StoreType::Average,
    2172            0 :                                         surf.Name);
    2173            0 :                     SetupOutputVariable(state,
    2174              :                                         "Surface Window System Solar Reflectance",
    2175              :                                         Constant::Units::None,
    2176            0 :                                         s_surf->SurfWinSysSolReflectance(SurfLoop),
    2177              :                                         OutputProcessor::TimeStepType::Zone,
    2178              :                                         OutputProcessor::StoreType::Average,
    2179            0 :                                         surf.Name);
    2180            0 :                     SetupOutputVariable(state,
    2181              :                                         "Surface Window System Solar Absorptance",
    2182              :                                         Constant::Units::None,
    2183            0 :                                         s_surf->SurfWinSysSolAbsorptance(SurfLoop),
    2184              :                                         OutputProcessor::TimeStepType::Zone,
    2185              :                                         OutputProcessor::StoreType::Average,
    2186            0 :                                         surf.Name);
    2187            0 :                     SetupOutputVariable(state,
    2188              :                                         "Surface Window Inside Face Glazing Condensation Status",
    2189              :                                         Constant::Units::None,
    2190            0 :                                         s_surf->SurfWinInsideGlassCondensationFlag(SurfLoop),
    2191              :                                         OutputProcessor::TimeStepType::Zone,
    2192              :                                         OutputProcessor::StoreType::Average,
    2193            0 :                                         surf.Name);
    2194            0 :                     SetupOutputVariable(state,
    2195              :                                         "Surface Window Inside Face Frame Condensation Status",
    2196              :                                         Constant::Units::None,
    2197            0 :                                         s_surf->SurfWinInsideFrameCondensationFlag(SurfLoop),
    2198              :                                         OutputProcessor::TimeStepType::Zone,
    2199              :                                         OutputProcessor::StoreType::Average,
    2200            0 :                                         surf.Name);
    2201            0 :                     SetupOutputVariable(state,
    2202              :                                         "Surface Window Inside Face Divider Condensation Status",
    2203              :                                         Constant::Units::None,
    2204            0 :                                         s_surf->SurfWinInsideDividerCondensationFlag(SurfLoop),
    2205              :                                         OutputProcessor::TimeStepType::Zone,
    2206              :                                         OutputProcessor::StoreType::Average,
    2207            0 :                                         surf.Name);
    2208            0 :                     SetupOutputVariable(state,
    2209              :                                         "Surface Window Outside Reveal Reflected Beam Solar Radiation Rate",
    2210              :                                         Constant::Units::W,
    2211            0 :                                         s_surf->SurfWinBmSolRefldOutsRevealReport(SurfLoop),
    2212              :                                         OutputProcessor::TimeStepType::Zone,
    2213              :                                         OutputProcessor::StoreType::Average,
    2214            0 :                                         surf.Name);
    2215            0 :                     SetupOutputVariable(state,
    2216              :                                         "Surface Window Inside Reveal Reflected Beam Solar Radiation Rate",
    2217              :                                         Constant::Units::W,
    2218            0 :                                         s_surf->SurfWinBmSolRefldInsRevealReport(SurfLoop),
    2219              :                                         OutputProcessor::TimeStepType::Zone,
    2220              :                                         OutputProcessor::StoreType::Average,
    2221            0 :                                         surf.Name);
    2222              :                     // Energy
    2223            0 :                     SetupOutputVariable(state,
    2224              :                                         "Surface Window Outside Reveal Reflected Beam Solar Radiation Energy",
    2225              :                                         Constant::Units::J,
    2226            0 :                                         s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfLoop),
    2227              :                                         OutputProcessor::TimeStepType::Zone,
    2228              :                                         OutputProcessor::StoreType::Sum,
    2229            0 :                                         surf.Name);
    2230            0 :                     SetupOutputVariable(state,
    2231              :                                         "Surface Window Inside Reveal Reflected Beam Solar Radiation Energy",
    2232              :                                         Constant::Units::J,
    2233            0 :                                         s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfLoop),
    2234              :                                         OutputProcessor::TimeStepType::Zone,
    2235              :                                         OutputProcessor::StoreType::Sum,
    2236            0 :                                         surf.Name);
    2237              : 
    2238              :                     //     Output blind report variables only when blinds are used
    2239            0 :                     auto &surfShade = s_surf->surfShades(SurfLoop);
    2240            0 :                     if (surfShade.blind.matNum > 0) {
    2241            0 :                         SetupOutputVariable(state,
    2242              :                                             "Surface Window Blind Beam to Beam Solar Transmittance",
    2243              :                                             Constant::Units::None,
    2244            0 :                                             s_surf->SurfWinBlTsolBmBm(SurfLoop),
    2245              :                                             OutputProcessor::TimeStepType::Zone,
    2246              :                                             OutputProcessor::StoreType::Average,
    2247            0 :                                             surf.Name);
    2248            0 :                         SetupOutputVariable(state,
    2249              :                                             "Surface Window Blind Beam to Diffuse Solar Transmittance",
    2250              :                                             Constant::Units::None,
    2251            0 :                                             s_surf->SurfWinBlTsolBmDif(SurfLoop),
    2252              :                                             OutputProcessor::TimeStepType::Zone,
    2253              :                                             OutputProcessor::StoreType::Average,
    2254            0 :                                             surf.Name);
    2255            0 :                         SetupOutputVariable(state,
    2256              :                                             "Surface Window Blind Diffuse to Diffuse Solar Transmittance",
    2257              :                                             Constant::Units::None,
    2258            0 :                                             s_surf->SurfWinBlTsolDifDif(SurfLoop),
    2259              :                                             OutputProcessor::TimeStepType::Zone,
    2260              :                                             OutputProcessor::StoreType::Average,
    2261            0 :                                             surf.Name);
    2262            0 :                         SetupOutputVariable(state,
    2263              :                                             "Surface Window Blind and Glazing System Beam Solar Transmittance",
    2264              :                                             Constant::Units::None,
    2265            0 :                                             s_surf->SurfWinBlGlSysTsolBmBm(SurfLoop),
    2266              :                                             OutputProcessor::TimeStepType::Zone,
    2267              :                                             OutputProcessor::StoreType::Average,
    2268            0 :                                             surf.Name);
    2269            0 :                         SetupOutputVariable(state,
    2270              :                                             "Surface Window Blind and Glazing System Diffuse Solar Transmittance",
    2271              :                                             Constant::Units::None,
    2272            0 :                                             s_surf->SurfWinBlGlSysTsolDifDif(SurfLoop),
    2273              :                                             OutputProcessor::TimeStepType::Zone,
    2274              :                                             OutputProcessor::StoreType::Average,
    2275            0 :                                             surf.Name);
    2276              :                     }
    2277              : 
    2278              :                     //     Output screen report variables only when screens are used
    2279            0 :                     if (s_surf->SurfaceWindow(SurfLoop).screenNum > 0) {
    2280            0 :                         SetupOutputVariable(state,
    2281              :                                             "Surface Window Screen Beam to Beam Solar Transmittance",
    2282              :                                             Constant::Units::None,
    2283            0 :                                             s_surf->SurfWinScTsolBmBm(SurfLoop),
    2284              :                                             OutputProcessor::TimeStepType::Zone,
    2285              :                                             OutputProcessor::StoreType::Average,
    2286            0 :                                             surf.Name);
    2287            0 :                         SetupOutputVariable(state,
    2288              :                                             "Surface Window Screen Beam to Diffuse Solar Transmittance",
    2289              :                                             Constant::Units::None,
    2290            0 :                                             s_surf->SurfWinScTsolBmDif(SurfLoop),
    2291              :                                             OutputProcessor::TimeStepType::Zone,
    2292              :                                             OutputProcessor::StoreType::Average,
    2293            0 :                                             surf.Name);
    2294            0 :                         SetupOutputVariable(state,
    2295              :                                             "Surface Window Screen Diffuse to Diffuse Solar Transmittance",
    2296              :                                             Constant::Units::None,
    2297            0 :                                             s_surf->SurfWinScTsolDifDif(SurfLoop),
    2298              :                                             OutputProcessor::TimeStepType::Zone,
    2299              :                                             OutputProcessor::StoreType::Average,
    2300            0 :                                             surf.Name);
    2301            0 :                         SetupOutputVariable(state,
    2302              :                                             "Surface Window Screen and Glazing System Beam Solar Transmittance",
    2303              :                                             Constant::Units::None,
    2304            0 :                                             s_surf->SurfWinScGlSysTsolBmBm(SurfLoop),
    2305              :                                             OutputProcessor::TimeStepType::Zone,
    2306              :                                             OutputProcessor::StoreType::Average,
    2307            0 :                                             surf.Name);
    2308            0 :                         SetupOutputVariable(state,
    2309              :                                             "Surface Window Screen and Glazing System Diffuse Solar Transmittance",
    2310              :                                             Constant::Units::None,
    2311            0 :                                             s_surf->SurfWinScGlSysTsolDifDif(SurfLoop),
    2312              :                                             OutputProcessor::TimeStepType::Zone,
    2313              :                                             OutputProcessor::StoreType::Average,
    2314            0 :                                             surf.Name);
    2315              :                     }
    2316              : 
    2317            0 :                     SetupOutputVariable(state,
    2318              :                                         "Surface Window Solar Horizontal Profile Angle",
    2319              :                                         Constant::Units::deg,
    2320            0 :                                         s_surf->SurfWinProfileAngHor(SurfLoop),
    2321              :                                         OutputProcessor::TimeStepType::Zone,
    2322              :                                         OutputProcessor::StoreType::Average,
    2323            0 :                                         surf.Name);
    2324            0 :                     SetupOutputVariable(state,
    2325              :                                         "Surface Window Solar Vertical Profile Angle",
    2326              :                                         Constant::Units::deg,
    2327            0 :                                         s_surf->SurfWinProfileAngVert(SurfLoop),
    2328              :                                         OutputProcessor::TimeStepType::Zone,
    2329              :                                         OutputProcessor::StoreType::Average,
    2330            0 :                                         surf.Name);
    2331            0 :                     SetupOutputVariable(state,
    2332              :                                         "Surface Window Glazing Beam to Beam Solar Transmittance",
    2333              :                                         Constant::Units::None,
    2334            0 :                                         s_surf->SurfWinGlTsolBmBm(SurfLoop),
    2335              :                                         OutputProcessor::TimeStepType::Zone,
    2336              :                                         OutputProcessor::StoreType::Average,
    2337            0 :                                         surf.Name);
    2338            0 :                     SetupOutputVariable(state,
    2339              :                                         "Surface Window Glazing Beam to Diffuse Solar Transmittance",
    2340              :                                         Constant::Units::None,
    2341            0 :                                         s_surf->SurfWinGlTsolBmDif(SurfLoop),
    2342              :                                         OutputProcessor::TimeStepType::Zone,
    2343              :                                         OutputProcessor::StoreType::Average,
    2344            0 :                                         surf.Name);
    2345            0 :                     SetupOutputVariable(state,
    2346              :                                         "Surface Window Glazing Diffuse to Diffuse Solar Transmittance",
    2347              :                                         Constant::Units::None,
    2348            0 :                                         s_surf->SurfWinGlTsolDifDif(SurfLoop),
    2349              :                                         OutputProcessor::TimeStepType::Zone,
    2350              :                                         OutputProcessor::StoreType::Average,
    2351            0 :                                         surf.Name);
    2352            0 :                     SetupOutputVariable(state,
    2353              :                                         "Surface Window Model Solver Iteration Count",
    2354              :                                         Constant::Units::None,
    2355            0 :                                         s_surf->SurfWinWindowCalcIterationsRep(SurfLoop),
    2356              :                                         OutputProcessor::TimeStepType::Zone,
    2357              :                                         OutputProcessor::StoreType::Average,
    2358            0 :                                         surf.Name);
    2359              :                 }
    2360              :             } // end non extsolar reporting as advanced variables
    2361              :         }     // Window Reporting
    2362          942 :         if (surf.Class == SurfaceClass::Window && surf.ExtBoundCond > 0 && surf.ExtBoundCond != SurfLoop) { // Interzone window
    2363              :                                                                                                             // CurrentModuleObject='InterzoneWindows'
    2364            0 :             SetupOutputVariable(state,
    2365              :                                 "Surface Window Transmitted Beam Solar Radiation Rate",
    2366              :                                 Constant::Units::W,
    2367            0 :                                 s_surf->SurfWinBmSolTransThruIntWinRep(SurfLoop),
    2368              :                                 OutputProcessor::TimeStepType::Zone,
    2369              :                                 OutputProcessor::StoreType::Average,
    2370            0 :                                 surf.Name);
    2371              :             // energy
    2372            0 :             SetupOutputVariable(state,
    2373              :                                 "Surface Window Transmitted Beam Solar Radiation Energy",
    2374              :                                 Constant::Units::J,
    2375            0 :                                 s_surf->SurfWinBmSolTransThruIntWinRepEnergy(SurfLoop),
    2376              :                                 OutputProcessor::TimeStepType::Zone,
    2377              :                                 OutputProcessor::StoreType::Sum,
    2378            0 :                                 surf.Name);
    2379              :         }
    2380          942 :         if (surf.Class == SurfaceClass::TDD_Dome && surf.ExtSolar) {
    2381              :             // CurrentModuleObject='TDD Domes'
    2382            4 :             SetupOutputVariable(state,
    2383              :                                 "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
    2384              :                                 Constant::Units::W,
    2385            2 :                                 state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
    2386              :                                 OutputProcessor::TimeStepType::Zone,
    2387              :                                 OutputProcessor::StoreType::Average,
    2388            2 :                                 surf.Name);
    2389            4 :             SetupOutputVariable(state,
    2390              :                                 "Surface Window Transmitted Solar Radiation Rate",
    2391              :                                 Constant::Units::W,
    2392            2 :                                 s_surf->SurfWinTransSolar(SurfLoop),
    2393              :                                 OutputProcessor::TimeStepType::Zone,
    2394              :                                 OutputProcessor::StoreType::Average,
    2395            2 :                                 surf.Name);
    2396              :             // energy
    2397            4 :             SetupOutputVariable(state,
    2398              :                                 "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
    2399              :                                 Constant::Units::J,
    2400            2 :                                 state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
    2401              :                                 OutputProcessor::TimeStepType::Zone,
    2402              :                                 OutputProcessor::StoreType::Sum,
    2403            2 :                                 surf.Name);
    2404            4 :             SetupOutputVariable(state,
    2405              :                                 "Surface Window Transmitted Solar Radiation Energy",
    2406              :                                 Constant::Units::J,
    2407            2 :                                 s_surf->SurfWinTransSolarEnergy(SurfLoop),
    2408              :                                 OutputProcessor::TimeStepType::Zone,
    2409              :                                 OutputProcessor::StoreType::Sum,
    2410            2 :                                 surf.Name);
    2411              :         }
    2412          942 :         if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    2413              :             // CurrentModuleObject='TDD Diffusers'
    2414            4 :             SetupOutputVariable(state,
    2415              :                                 "Surface Outside Face Incident Solar Radiation Rate per Area",
    2416              :                                 Constant::Units::W_m2,
    2417            2 :                                 state.dataHeatBal->SurfQRadSWOutIncident(SurfLoop),
    2418              :                                 OutputProcessor::TimeStepType::Zone,
    2419              :                                 OutputProcessor::StoreType::Average,
    2420            2 :                                 surf.Name);
    2421            4 :             SetupOutputVariable(state,
    2422              :                                 "Surface Window Total Glazing Layers Absorbed Solar Radiation Rate",
    2423              :                                 Constant::Units::W,
    2424            2 :                                 state.dataHeatBal->SurfWinQRadSWwinAbsTot(SurfLoop),
    2425              :                                 OutputProcessor::TimeStepType::Zone,
    2426              :                                 OutputProcessor::StoreType::Average,
    2427            2 :                                 surf.Name);
    2428            4 :             SetupOutputVariable(state,
    2429              :                                 "Surface Window Transmitted Solar Radiation Rate",
    2430              :                                 Constant::Units::W,
    2431            2 :                                 s_surf->SurfWinTransSolar(SurfLoop),
    2432              :                                 OutputProcessor::TimeStepType::Zone,
    2433              :                                 OutputProcessor::StoreType::Average,
    2434            2 :                                 surf.Name);
    2435              :             // energy
    2436            4 :             SetupOutputVariable(state,
    2437              :                                 "Surface Window Total Glazing Layers Absorbed Solar Radiation Energy",
    2438              :                                 Constant::Units::J,
    2439            2 :                                 state.dataHeatBal->SurfWinQRadSWwinAbsTotEnergy(SurfLoop),
    2440              :                                 OutputProcessor::TimeStepType::Zone,
    2441              :                                 OutputProcessor::StoreType::Sum,
    2442            2 :                                 surf.Name);
    2443            4 :             SetupOutputVariable(state,
    2444              :                                 "Surface Window Transmitted Solar Radiation Energy",
    2445              :                                 Constant::Units::J,
    2446            2 :                                 s_surf->SurfWinTransSolarEnergy(SurfLoop),
    2447              :                                 OutputProcessor::TimeStepType::Zone,
    2448              :                                 OutputProcessor::StoreType::Sum,
    2449            2 :                                 surf.Name);
    2450              :         }
    2451              :     }
    2452              : 
    2453         1153 :     for (int SurfLoop = 1; SurfLoop <= s_surf->TotSurfaces; ++SurfLoop) {
    2454         1012 :         auto &surf = s_surf->Surface(SurfLoop);
    2455         1012 :         if (!surf.HeatTransSurf) continue;
    2456              :         // CurrentModuleObject='Surfaces'
    2457         1884 :         SetupOutputVariable(state,
    2458              :                             "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Rate per Area",
    2459              :                             Constant::Units::W_m2,
    2460          942 :                             state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfLoop),
    2461              :                             OutputProcessor::TimeStepType::Zone,
    2462              :                             OutputProcessor::StoreType::Average,
    2463          942 :                             surf.Name);
    2464         1884 :         SetupOutputVariable(state,
    2465              :                             "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Rate",
    2466              :                             Constant::Units::W,
    2467          942 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfLoop),
    2468              :                             OutputProcessor::TimeStepType::Zone,
    2469              :                             OutputProcessor::StoreType::Average,
    2470          942 :                             surf.Name);
    2471         1884 :         SetupOutputVariable(state,
    2472              :                             "Surface Inside Face Interior Windows Incident Beam Solar Radiation Rate per Area",
    2473              :                             Constant::Units::W_m2,
    2474          942 :                             state.dataHeatBal->SurfIntBmIncInsSurfIntensRep(SurfLoop),
    2475              :                             OutputProcessor::TimeStepType::Zone,
    2476              :                             OutputProcessor::StoreType::Average,
    2477          942 :                             surf.Name);
    2478         1884 :         SetupOutputVariable(state,
    2479              :                             "Surface Inside Face Interior Windows Incident Beam Solar Radiation Rate",
    2480              :                             Constant::Units::W,
    2481          942 :                             state.dataHeatBal->SurfIntBmIncInsSurfAmountRep(SurfLoop),
    2482              :                             OutputProcessor::TimeStepType::Zone,
    2483              :                             OutputProcessor::StoreType::Average,
    2484          942 :                             surf.Name);
    2485         1884 :         SetupOutputVariable(state,
    2486              :                             "Surface Inside Face Initial Transmitted Diffuse Absorbed Solar Radiation Rate",
    2487              :                             Constant::Units::W,
    2488          942 :                             state.dataHeatBal->SurfInitialDifSolInAbsReport(SurfLoop),
    2489              :                             OutputProcessor::TimeStepType::Zone,
    2490              :                             OutputProcessor::StoreType::Average,
    2491          942 :                             surf.Name);
    2492         1884 :         SetupOutputVariable(state,
    2493              :                             "Surface Inside Face Initial Transmitted Diffuse Transmitted Out Window Solar Radiation Rate",
    2494              :                             Constant::Units::W,
    2495          942 :                             state.dataHeatBal->SurfWinInitialDifSolInTransReport(SurfLoop),
    2496              :                             OutputProcessor::TimeStepType::Zone,
    2497              :                             OutputProcessor::StoreType::Average,
    2498          942 :                             surf.Name);
    2499         1884 :         SetupOutputVariable(state,
    2500              :                             "Surface Inside Face Absorbed Shortwave Radiation Rate",
    2501              :                             Constant::Units::W,
    2502          942 :                             state.dataHeatBal->SurfSWInAbsTotalReport(SurfLoop),
    2503              :                             OutputProcessor::TimeStepType::Zone,
    2504              :                             OutputProcessor::StoreType::Average,
    2505          942 :                             surf.Name);
    2506              :         // energy
    2507         1884 :         SetupOutputVariable(state,
    2508              :                             "Surface Inside Face Exterior Windows Incident Beam Solar Radiation Energy",
    2509              :                             Constant::Units::J,
    2510          942 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfLoop),
    2511              :                             OutputProcessor::TimeStepType::Zone,
    2512              :                             OutputProcessor::StoreType::Sum,
    2513          942 :                             surf.Name);
    2514         1884 :         SetupOutputVariable(state,
    2515              :                             "Surface Inside Face Interior Windows Incident Beam Solar Radiation Energy",
    2516              :                             Constant::Units::J,
    2517          942 :                             state.dataHeatBal->SurfIntBmIncInsSurfAmountRepEnergy(SurfLoop),
    2518              :                             OutputProcessor::TimeStepType::Zone,
    2519              :                             OutputProcessor::StoreType::Sum,
    2520          942 :                             surf.Name);
    2521              :     }
    2522          141 : }
    2523              : 
    2524        71212 : void AnisoSkyViewFactors(EnergyPlusData &state)
    2525              : {
    2526              : 
    2527              :     // SUBROUTINE INFORMATION:
    2528              :     //       AUTHOR         Fred Winkelmann
    2529              :     //       DATE WRITTEN   April 1999
    2530              :     //       MODIFIED       LKL; Dec 2002 -- Anisotropic is only sky radiance option
    2531              :     //       RE-ENGINEERED  na
    2532              : 
    2533              :     // PURPOSE OF THIS SUBROUTINE:
    2534              :     // Calculates view factor multiplier, SurfAnisoSkyMult, for diffuse
    2535              :     // sky irradiance on exterior surfaces taking into account
    2536              :     // anisotropic radiance of the sky. Called by InitSurfaceHeatBalance
    2537              :     // In this case the diffuse sky irradiance on a surface is given by
    2538              :     //  SurfAnisoSkyMult(SurfNum) * DifSolarRad
    2539              :     // SurfAnisoSkyMult accounts not only for the sky radiance distribution but
    2540              :     // also for the effects of shading of sky diffuse radiation by
    2541              :     // shadowing surfaces such as overhangs. It does not account for reflection
    2542              :     // of sky diffuse radiation from shadowing surfaces.
    2543              :     // Based on an empirical model described in
    2544              :     // R. Perez, P. Ineichen, R. Seals, J. Michalsky and R. Stewart,
    2545              :     // "Modeling Daylight Availability and Irradiance Components from Direct
    2546              :     // and Global Irradiance," Solar Energy 44, 271-289, 1990.
    2547              :     // In this model the radiance of the sky consists of three distributions
    2548              :     // that are superimposed:
    2549              : 
    2550              :     // (1) An isotropic distribution that covers the entire sky dome;
    2551              :     // (2) A circumsolar brightening centered around the position of the sun;
    2552              :     // (3) A horizon brightening
    2553              :     // The circumsolar brightening is assumed to be concentrated at a point
    2554              :     // source at the center of the sun although this region actually begins at the
    2555              :     // periphery of the solar disk and falls off in intensity with increasing
    2556              :     // angular distance from the periphery.
    2557              :     // The horizon brightening is assumed to be concentrated at the horizon and
    2558              :     // to be independent of azimuth. In actuality, for clear skies, the horizon
    2559              :     // brightening is highest at the horizon and decreases in intensity away from
    2560              :     // the horizon. For overcast skies the horizon brightening has a negative value
    2561              :     // since for such skies the sky radiance increases rather than decreases away
    2562              :     // from the horizon.
    2563              :     // The F11R, F12R, etc. values were provided by R. Perez, private communication,
    2564              :     // 5/21/99. These values have higher precision than those listed in the above
    2565              :     // paper.
    2566              : 
    2567              :     // Using/Aliasing
    2568              : 
    2569              :     // Locals
    2570              :     // SUBROUTINE PARAMETER DEFINITIONS:
    2571              :     static constexpr std::array<Real64, 7> EpsilonLimit = {
    2572              :         1.065, 1.23, 1.5, 1.95, 2.8, 4.5, 6.2}; // Upper limit of bins of the sky clearness parameter, Epsilon
    2573              :     // Circumsolar brightening coefficients; index corresponds to range of Epsilon, the sky clearness parameter
    2574              :     static constexpr std::array<Real64, 8> F11R = {-0.0083117, 0.1299457, 0.3296958, 0.5682053, 0.8730280, 1.1326077, 1.0601591, 0.6777470};
    2575              :     static constexpr std::array<Real64, 8> F12R = {0.5877285, 0.6825954, 0.4868735, 0.1874525, -0.3920403, -1.2367284, -1.5999137, -0.3272588};
    2576              :     static constexpr std::array<Real64, 8> F13R = {-0.0620636, -0.1513752, -0.2210958, -0.2951290, -0.3616149, -0.4118494, -0.3589221, -0.2504286};
    2577              :     // Horizon/zenith brightening coefficient array; index corresponds to range of Epsilon, the sky clearness parameter
    2578              :     static constexpr std::array<Real64, 8> F21R = {-0.0596012, -0.0189325, 0.0554140, 0.1088631, 0.2255647, 0.2877813, 0.2642124, 0.1561313};
    2579              :     static constexpr std::array<Real64, 8> F22R = {0.0721249, 0.0659650, -0.0639588, -0.1519229, -0.4620442, -0.8230357, -1.1272340, -1.3765031};
    2580              :     static constexpr std::array<Real64, 8> F23R = {-0.0220216, -0.0288748, -0.0260542, -0.0139754, 0.0012448, 0.0558651, 0.1310694, 0.2506212};
    2581              : 
    2582              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2583              : 
    2584              :     Real64 CosZenithAng;           // Cosine of solar zenith angle
    2585              :     Real64 ZenithAng;              // Solar zenith angle (radians)
    2586              :     Real64 ZenithAngDeg;           // Solar zenith angle (degrees)
    2587              :     Real64 F1;                     // Circumsolar brightening coefficient
    2588              :     Real64 F2;                     // Horizon/zenith brightening coefficient
    2589              :     Real64 Epsilon;                // Sky clearness parameter
    2590              :     Real64 Delta;                  // Sky brightness parameter
    2591              :     Real64 CosIncAngBeamOnSurface; // Cosine of incidence angle of beam solar on surface
    2592              :     int EpsilonBin;                // Sky clearness (Epsilon) bin index
    2593              :     Real64 AirMass;                // Relative air mass
    2594              :     Real64 AirMassH;               // Intermediate variable for relative air mass calculation
    2595              :     Real64 CircumSolarFac;         // Ratio of cosine of incidence angle to cosine of zenith angle
    2596              :     Real64 KappaZ3;                // Intermediate variable
    2597              :     Real64 ViewFactorSkyGeom;      // Geometrical sky view factor
    2598        71212 :     Real64 constexpr cosine_tolerance(0.0001);
    2599              : 
    2600        71212 :     auto &s_surf = state.dataSurface;
    2601              : 
    2602              : #ifdef EP_Count_Calls
    2603              :     ++state.dataTimingsData->NumAnisoSky_Calls;
    2604              : #endif
    2605              : 
    2606        71212 :     CosZenithAng = state.dataEnvrn->SOLCOS(3);
    2607        71212 :     ZenithAng = std::acos(CosZenithAng);
    2608        71212 :     ZenithAngDeg = ZenithAng / Constant::DegToRad;
    2609              : 
    2610        71212 :     state.dataSolarShading->SurfAnisoSkyMult = 0.0;
    2611              : 
    2612              :     //           Relative air mass
    2613        71212 :     AirMassH = (1.0 - 0.1 * state.dataEnvrn->Elevation / 1000.0);
    2614        71212 :     if (ZenithAngDeg <= 75.0) {
    2615        56901 :         AirMass = AirMassH / CosZenithAng;
    2616              :     } else {
    2617        14311 :         AirMass = AirMassH / (CosZenithAng + 0.15 * std::pow(93.9 - ZenithAngDeg, -1.253));
    2618              :     }
    2619        71212 :     KappaZ3 = 1.041 * pow_3(ZenithAng);
    2620        71212 :     Epsilon = ((state.dataEnvrn->BeamSolarRad + state.dataEnvrn->DifSolarRad) / state.dataEnvrn->DifSolarRad + KappaZ3) / (1.0 + KappaZ3);
    2621        71212 :     Delta = state.dataEnvrn->DifSolarRad * AirMass / 1353.0; // 1353 is average extraterrestrial irradiance (W/m2)
    2622              :     //           Circumsolar (F1) and horizon/zenith (F2) brightening coefficients
    2623       487897 :     for (EpsilonBin = 0; EpsilonBin < 8; ++EpsilonBin) {
    2624       487897 :         if (EpsilonBin == 7) break;
    2625       460196 :         if (Epsilon < EpsilonLimit[EpsilonBin]) break;
    2626              :     }
    2627        71212 :     F1 = max(0.0, F11R[EpsilonBin] + F12R[EpsilonBin] * Delta + F13R[EpsilonBin] * ZenithAng);
    2628        71212 :     F2 = F21R[EpsilonBin] + F22R[EpsilonBin] * Delta + F23R[EpsilonBin] * ZenithAng;
    2629              : 
    2630       462398 :     for (int SurfNum : s_surf->AllExtSolarSurfaceList) {
    2631              : 
    2632       391186 :         CosIncAngBeamOnSurface = state.dataEnvrn->SOLCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
    2633       391186 :                                  state.dataEnvrn->SOLCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
    2634       391186 :                                  state.dataEnvrn->SOLCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
    2635              : 
    2636              :         // So I believe this should only be a diagnostic error...the calcs should always be within -1,+1; it's just round-off that we need to trap
    2637              :         // for
    2638       391186 :         if (CosIncAngBeamOnSurface > 1.0) {
    2639            0 :             if (CosIncAngBeamOnSurface > (1.0 + cosine_tolerance)) {
    2640            0 :                 ShowSevereError(state, "Cosine of incident angle of beam solar on surface out of range...too high");
    2641            0 :                 ShowContinueError(state, "This is a diagnostic error that should not be encountered under normal circumstances");
    2642            0 :                 ShowContinueError(state, format("Occurs on surface: {}", s_surf->Surface(SurfNum).Name));
    2643            0 :                 ShowContinueError(state, format("Current value = {} ... should be within [-1, +1]", CosIncAngBeamOnSurface));
    2644            0 :                 ShowFatalError(state, "Anisotropic solar calculation causes fatal error");
    2645              :             }
    2646            0 :             CosIncAngBeamOnSurface = 1.0;
    2647       391186 :         } else if (CosIncAngBeamOnSurface < -1.0) {
    2648            0 :             if (CosIncAngBeamOnSurface < (-1.0 - cosine_tolerance)) {
    2649            0 :                 ShowSevereError(state, "Cosine of incident angle of beam solar on surface out of range...too low");
    2650            0 :                 ShowContinueError(state, "This is a diagnostic error that should not be encountered under normal circumstances");
    2651            0 :                 ShowContinueError(state, format("Occurs on surface: {}", s_surf->Surface(SurfNum).Name));
    2652            0 :                 ShowContinueError(state, format("Current value = {} ... should be within [-1, +1]", CosIncAngBeamOnSurface));
    2653            0 :                 ShowFatalError(state, "Anisotropic solar calculation causes fatal error");
    2654              :             }
    2655            0 :             CosIncAngBeamOnSurface = -1.0;
    2656              :         }
    2657              : 
    2658       391186 :         ViewFactorSkyGeom = s_surf->Surface(SurfNum).ViewFactorSky;
    2659       391186 :         state.dataSolarShading->SurfMultIsoSky(SurfNum) = ViewFactorSkyGeom * (1.0 - F1);
    2660              :         //           0.0871557 below corresponds to a zenith angle of 85 deg
    2661       391186 :         CircumSolarFac = max(0.0, CosIncAngBeamOnSurface) / max(0.0871557, CosZenithAng);
    2662              :         //           For near-horizontal roofs, model has an inconsistency that gives sky diffuse
    2663              :         //           irradiance significantly different from DifSolarRad when zenith angle is
    2664              :         //           above 85 deg. The following forces irradiance to be very close to DifSolarRad
    2665              :         //           in this case.
    2666       391186 :         if (CircumSolarFac > 0.0 && CosZenithAng < 0.0871557 && s_surf->Surface(SurfNum).Tilt < 2.0) CircumSolarFac = 1.0;
    2667       391186 :         state.dataSolarShading->SurfMultCircumSolar(SurfNum) = F1 * CircumSolarFac;
    2668       391186 :         state.dataSolarShading->SurfMultHorizonZenith(SurfNum) = F2 * s_surf->Surface(SurfNum).SinTilt;
    2669              : 
    2670       391186 :         if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm || !s_surf->ShadingTransmittanceVaries ||
    2671            0 :             state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    2672       391186 :             state.dataSolarShading->SurfAnisoSkyMult(SurfNum) =
    2673       391186 :                 state.dataSolarShading->SurfMultIsoSky(SurfNum) * state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) +
    2674       391186 :                 state.dataSolarShading->SurfMultCircumSolar(SurfNum) *
    2675       391186 :                     state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) +
    2676       391186 :                 state.dataSolarShading->SurfMultHorizonZenith(SurfNum) * state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum);
    2677              :         } else {
    2678            0 :             state.dataSolarShading->SurfAnisoSkyMult(SurfNum) =
    2679            0 :                 state.dataSolarShading->SurfMultIsoSky(SurfNum) *
    2680            0 :                     state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum) +
    2681            0 :                 state.dataSolarShading->SurfMultCircumSolar(SurfNum) *
    2682            0 :                     state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) +
    2683            0 :                 state.dataSolarShading->SurfMultHorizonZenith(SurfNum) *
    2684            0 :                     state.dataSolarShading->SurfDifShdgRatioHorizHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum);
    2685            0 :             state.dataSolarShading->SurfCurDifShdgRatioIsoSky(SurfNum) =
    2686            0 :                 state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(state.dataGlobal->TimeStep, state.dataGlobal->HourOfDay, SurfNum);
    2687              :         }
    2688       391186 :         state.dataSolarShading->SurfAnisoSkyMult(SurfNum) = max(0.0, state.dataSolarShading->SurfAnisoSkyMult(SurfNum)); // make sure not negative.
    2689              :     }
    2690        71212 : }
    2691              : 
    2692           43 : void CHKBKS(EnergyPlusData &state,
    2693              :             int const NBS, // Surface Number of the potential back surface
    2694              :             int const NRS  // Surface Number of the potential shadow receiving surface
    2695              : )
    2696              : {
    2697              : 
    2698              :     // SUBROUTINE INFORMATION:
    2699              :     //       AUTHOR         Legacy Code
    2700              :     //       DATE WRITTEN
    2701              :     //       MODIFIED       Nov 2001, FW: Reverse subroutine arguments NRS and NBS to
    2702              :     //                                    correspond to how CHKBKS is called
    2703              :     //                      Jan 2002, FW: change error message
    2704              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    2705              :     //       Sep 2020: Revised the vector computation method to reliably produce CVec,
    2706              :     //                 and simplified the warning messages.
    2707              : 
    2708              :     // PURPOSE OF THIS SUBROUTINE:
    2709              :     // Determines whether a any vertices of the back surface are in front of the receiving surface;
    2710              :     // if so, gives severe error.  Only base heat transfer surfaces are checked.
    2711              : 
    2712              :     // METHODOLOGY EMPLOYED:
    2713              :     // na
    2714              : 
    2715              :     // REFERENCES:
    2716              :     // BLAST/IBLAST code, original author George Walton
    2717              : 
    2718              :     // Using/Aliasing
    2719              :     using namespace Vectors;
    2720              : 
    2721              :     int N;       // Loop Control (vertex counter)
    2722              :     int NVRS;    // Number of vertices of the receiving surface
    2723              :     int NVBS;    // Number of vertices of the back surface
    2724              :     Real64 DOTP; // Dot product of C and D
    2725              : 
    2726              :     // Object Data
    2727           43 :     Vector CVec(0.0); // Vector perpendicular to surface at vertex 1
    2728           43 :     Vector DVec(0.0); // Vector from vertex 1 of first surface to vertex 'n' of second surface
    2729              : 
    2730           43 :     auto &s_surf = state.dataSurface;
    2731              : 
    2732           43 :     NVRS = s_surf->Surface(NRS).Sides;
    2733           43 :     NVBS = s_surf->Surface(NBS).Sides;
    2734              : 
    2735              :     // SEE IF ANY VERTICES OF THE back surface ARE IN FRONT OF THE receiving surface
    2736              : 
    2737          133 :     for (N = 2; N < NVRS; N++) {
    2738          180 :         CVec += cross(s_surf->Surface(NRS).Vertex(N) - s_surf->Surface(NRS).Vertex(1),
    2739          270 :                       s_surf->Surface(NRS).Vertex((N + 1)) - s_surf->Surface(NRS).Vertex(1));
    2740              :     }
    2741           43 :     CVec /= (NVRS >= 3 ? NVRS : 3);
    2742              : 
    2743          171 :     for (N = 1; N <= NVBS; ++N) {
    2744          144 :         DVec = s_surf->Surface(NBS).Vertex(N) - s_surf->Surface(NRS).Vertex(1);
    2745          144 :         DOTP = dot(CVec, DVec);
    2746          144 :         if (DOTP > 0.0009) {
    2747           32 :             ShowSevereError(state, "Problem in interior solar distribution calculation (CHKBKS)");
    2748           16 :             ShowContinueError(state, format("   Solar Distribution = FullInteriorExterior will not work in Zone={}", s_surf->Surface(NRS).ZoneName));
    2749           32 :             ShowContinueError(state,
    2750           32 :                               format("   because one or more of vertices, such as Vertex {} of back surface={}, is in front of receiving surface={}",
    2751              :                                      N,
    2752           16 :                                      s_surf->Surface(NBS).Name,
    2753           16 :                                      s_surf->Surface(NRS).Name));
    2754           16 :             ShowContinueError(state, format("   (Dot Product indicator={:20.4F})", DOTP));
    2755           32 :             ShowContinueError(state,
    2756              :                               "   Check surface geometry; if OK, use Solar Distribution = FullExterior instead. Use Output:Diagnostics, "
    2757              :                               "DisplayExtraWarnings; for more details.");
    2758           16 :             if (!state.dataGlobal->DisplayExtraWarnings) break;
    2759              :         }
    2760              :     }
    2761           43 : }
    2762              : 
    2763         2568 : void CHKGSS(EnergyPlusData &state,
    2764              :             int const NRS,     // Surface number of the potential shadow receiving surface
    2765              :             int const NSS,     // Surface number of the potential shadow casting surface
    2766              :             Real64 const ZMIN, // Lowest point of the receiving surface
    2767              :             bool &CannotShade  // TRUE if shadow casting surface cannot shade receiving surface.
    2768              : )
    2769              : {
    2770              : 
    2771              :     // SUBROUTINE INFORMATION:
    2772              :     //       AUTHOR         Legacy Code
    2773              :     //       DATE WRITTEN
    2774              :     //       MODIFIED       na
    2775              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    2776              : 
    2777              :     // PURPOSE OF THIS SUBROUTINE:
    2778              :     // Determines the possible shadowing combinations.  The
    2779              :     // routine checks detached shadowing or base heat transfer surfaces
    2780              :     // for the possibility that they cannot shade a given base heat transfer surface.
    2781              : 
    2782              :     // METHODOLOGY EMPLOYED:
    2783              :     // Shadowing is not possible if:
    2784              :     // 1.  The lowest point of the shadow receiving surface (receiving surface)
    2785              :     //     Is higher than the highest point of the shadow casting surface (s.s.)
    2786              :     // 2.  The shadow casting surface Faces up (e.g. A flat roof)
    2787              :     // 3.  The shadow casting surface Is behind the receiving surface
    2788              :     // 4.  The receiving surface is behind the shadow casting surface
    2789              : 
    2790              :     // REFERENCES:
    2791              :     // BLAST/IBLAST code, original author George Walton
    2792              : 
    2793              :     // Using/Aliasing
    2794              :     using namespace Vectors;
    2795              : 
    2796              :     // Object Data
    2797              : 
    2798         2568 :     CannotShade = true;
    2799              : 
    2800         2568 :     auto &s_surf = state.dataSurface;
    2801              : 
    2802              :     // see if no point of shadow casting surface is above low point of receiving surface
    2803              : 
    2804         2568 :     auto const &surface_C = s_surf->Surface(NSS);
    2805         3262 :     if (surface_C.OutNormVec(3) > 0.9999) return; // Shadow Casting Surface is horizontal and facing upward
    2806         2062 :     auto const &vertex_C = surface_C.Vertex;
    2807         2062 :     Real64 ZMAX(vertex_C(1).z);
    2808         8282 :     for (int i = 2, e = surface_C.Sides; i <= e; ++i) {
    2809         6220 :         ZMAX = std::max(ZMAX, vertex_C(i).z);
    2810              :     }
    2811         2062 :     if (ZMAX <= ZMIN) return;
    2812              : 
    2813              :     // SEE IF ANY VERTICES OF THE Shadow Casting Surface ARE ABOVE THE PLANE OF THE receiving surface
    2814              : 
    2815         1368 :     auto const &surface_R = s_surf->Surface(NRS);
    2816         1368 :     auto const &vertex_R = surface_R.Vertex;
    2817         1368 :     Vector const &vertex_R_2 = vertex_R(2);
    2818         1368 :     Vector const AVec = (vertex_R(1) - vertex_R_2); // Vector from vertex 2 to vertex 1 of receiving surface
    2819         1368 :     Vector const BVec = (vertex_R(3) - vertex_R_2); // Vector from vertex 2 to vertex 3 of receiving surface
    2820              : 
    2821         1368 :     Vector const CVec = cross(BVec, AVec); // Vector perpendicular to surface at vertex 2
    2822              : 
    2823         1368 :     int const NVSS = surface_C.Sides; // Number of vertices of the shadow casting surface
    2824         1368 :     Real64 DOTP(0.0);                 // Dot Product
    2825         5725 :     for (int I = 1; I <= NVSS; ++I) {
    2826         4662 :         DOTP = dot(CVec, vertex_C(I) - vertex_R_2);
    2827         4662 :         if (DOTP > state.dataSolarShading->TolValue) break; // DO loop
    2828              :     }
    2829              : 
    2830              :     // SEE IF ANY VERTICES OF THE receiving surface ARE ABOVE THE PLANE OF THE S.S.
    2831              : 
    2832         1368 :     if (DOTP > state.dataSolarShading->TolValue) {
    2833              : 
    2834          305 :         Vector const &vertex_C_2 = vertex_C(2);
    2835          305 :         Vector const AVec(vertex_C(1) - vertex_C_2);
    2836          305 :         Vector const BVec(vertex_C(3) - vertex_C_2);
    2837              : 
    2838          305 :         Vector const CVec(cross(BVec, AVec));
    2839              : 
    2840          305 :         int const NVRS = surface_R.Sides; // Number of vertices of the receiving surface
    2841         1097 :         for (int I = 1; I <= NVRS; ++I) {
    2842          918 :             DOTP = dot(CVec, vertex_R(I) - vertex_C_2);
    2843          918 :             if (DOTP > state.dataSolarShading->TolValue) {
    2844          126 :                 CannotShade = false;
    2845          126 :                 break; // DO loop
    2846              :             }
    2847              :         }
    2848          305 :     }
    2849         1368 : }
    2850              : 
    2851           70 : void CHKSBS(EnergyPlusData &state,
    2852              :             int const HTS,   // Heat transfer surface number of the general receiving surf
    2853              :             int const GRSNR, // Surface number of general receiving surface
    2854              :             int const SBSNR  // Surface number of subsurface
    2855              : )
    2856              : {
    2857              : 
    2858              :     // SUBROUTINE INFORMATION:
    2859              :     //       AUTHOR         Legacy Code
    2860              :     //       DATE WRITTEN
    2861              :     //       MODIFIED       na
    2862              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    2863              : 
    2864              :     // PURPOSE OF THIS SUBROUTINE:
    2865              :     // Checks that a subsurface is completely
    2866              :     // enclosed by its base surface.
    2867              : 
    2868              :     // REFERENCES:
    2869              :     // BLAST/IBLAST code, original author George Walton
    2870              : 
    2871              :     // 3D Planar Polygons
    2872              :     // In 3D applications, one sometimes wants to test a point and polygon that are in the same plane.
    2873              :     // For example, one may have the intersection point of a ray with the plane of a polyhedron's face,
    2874              :     // and want to test if it is inside the face.  Or one may want to know if the base of a 3D perpendicular
    2875              :     // dropped from a point is inside a planar polygon.
    2876              : 
    2877              :     // 3D inclusion is easily determined by projecting the point and polygon into 2D.  To do this, one simply
    2878              :     // ignores one of the 3D coordinates and uses the other two.  To optimally select the coordinate to ignore,
    2879              :     // compute a normal vector to the plane, and select the coordinate with the largest absolute value [Snyder & Barr, 1987].
    2880              :     // This gives the projection of the polygon with maximum area, and results in robust computations.
    2881              :     // John M. Snyder & Alan H. Barr, "Ray Tracing Complex Models Containing Surface Tessellations",
    2882              :     // Computer Graphics 21(4), 119-126 (1987) [also in the Proceedings of SIGGRAPH 1987]
    2883              :     //--- using adapted routine from Triangulation code -- EnergyPlus.
    2884              : 
    2885              :     // MSG - for error message
    2886           70 :     static Array1D_string const MSG(4, {"misses", "", "within", "overlaps"});
    2887              : 
    2888              :     int N;   // Loop Control
    2889              :     int NVT; // Number of vertices
    2890              :     int NS1; // Number of the figure being overlapped
    2891              :     int NS2; // Number of the figure doing overlapping
    2892              :     int NS3; // Location to place results of overlap
    2893              : 
    2894              :     bool inside;
    2895              : 
    2896              :     bool Out;
    2897              :     Real64 X1; // ,SX,SY,SZ
    2898              :     Real64 Y1;
    2899              :     Real64 Z1;
    2900              :     Real64 X2;
    2901              :     Real64 Y2;
    2902              :     Real64 Z2;
    2903              :     Real64 BX;
    2904              :     Real64 BY;
    2905              :     Real64 BZ;
    2906              :     Real64 BMAX;
    2907              :     //  INTEGER M
    2908              : 
    2909           70 :     auto &s_surf = state.dataSurface;
    2910              : 
    2911           70 :     if (state.dataSolarShading->CHKSBSOneTimeFlag) {
    2912           33 :         state.dataSolarShading->XVT.allocate(s_surf->MaxVerticesPerSurface + 1);
    2913           33 :         state.dataSolarShading->YVT.allocate(s_surf->MaxVerticesPerSurface + 1);
    2914           33 :         state.dataSolarShading->ZVT.allocate(s_surf->MaxVerticesPerSurface + 1);
    2915           33 :         state.dataSolarShading->XVT = 0.0;
    2916           33 :         state.dataSolarShading->YVT = 0.0;
    2917           33 :         state.dataSolarShading->ZVT = 0.0;
    2918           33 :         state.dataSolarShading->CHKSBSOneTimeFlag = false;
    2919              :     }
    2920              : 
    2921           70 :     NS1 = 1;
    2922           70 :     NS2 = 2;
    2923           70 :     NS3 = 3;
    2924           70 :     state.dataSolarShading->HCT(1) = 0.0;
    2925           70 :     state.dataSolarShading->HCT(2) = 0.0;
    2926              : 
    2927              :     // Put coordinates of base surface into clockwise sequence on the x'-y' plane.
    2928              : 
    2929           70 :     state.dataSolarShading->XVT = 0.0;
    2930           70 :     state.dataSolarShading->YVT = 0.0;
    2931           70 :     state.dataSolarShading->ZVT = 0.0;
    2932           70 :     state.dataSolarShading->XVS = 0.0;
    2933           70 :     state.dataSolarShading->YVS = 0.0;
    2934           70 :     CTRANS(state, GRSNR, HTS, NVT, state.dataSolarShading->XVT, state.dataSolarShading->YVT, state.dataSolarShading->ZVT);
    2935          350 :     for (N = 1; N <= NVT; ++N) {
    2936          280 :         state.dataSolarShading->XVS(N) = state.dataSolarShading->XVT(NVT + 1 - N);
    2937          280 :         state.dataSolarShading->YVS(N) = state.dataSolarShading->YVT(NVT + 1 - N);
    2938              :     }
    2939              : 
    2940           70 :     HTRANS1(state, NS2, NVT);
    2941              : 
    2942              :     // Put coordinates of the subsurface into clockwise sequence.
    2943              : 
    2944           70 :     state.dataSolarShading->NVS = s_surf->Surface(SBSNR).Sides;
    2945          350 :     for (N = 1; N <= state.dataSolarShading->NVS; ++N) {
    2946          280 :         state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(state.dataSolarShading->NVS + 1 - N);
    2947          280 :         state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(state.dataSolarShading->NVS + 1 - N);
    2948              :     }
    2949           70 :     HTRANS1(state, NS1, state.dataSolarShading->NVS);
    2950              : 
    2951              :     // Determine the overlap condition.
    2952              : 
    2953           70 :     DeterminePolygonOverlap(state, NS1, NS2, NS3);
    2954              : 
    2955              :     // Print error condition if necessary.
    2956              : 
    2957           70 :     if (state.dataSolarShading->OverlapStatus != FirstSurfWithinSecond) {
    2958            0 :         Out = false;
    2959              :         // C                            COMPUTE COMPONENTS OF VECTOR
    2960              :         // C                            NORMAL TO BASE SURFACE.
    2961            0 :         X1 = s_surf->Surface(GRSNR).Vertex(1).x - s_surf->Surface(GRSNR).Vertex(2).x; // XV(1,GRSNR)-XV(2,GRSNR)
    2962            0 :         Y1 = s_surf->Surface(GRSNR).Vertex(1).y - s_surf->Surface(GRSNR).Vertex(2).y; // YV(1,GRSNR)-YV(2,GRSNR)
    2963            0 :         Z1 = s_surf->Surface(GRSNR).Vertex(1).z - s_surf->Surface(GRSNR).Vertex(2).z; // ZV(1,GRSNR)-ZV(2,GRSNR)
    2964            0 :         X2 = s_surf->Surface(GRSNR).Vertex(3).x - s_surf->Surface(GRSNR).Vertex(2).x; // XV(3,GRSNR)-XV(2,GRSNR)
    2965            0 :         Y2 = s_surf->Surface(GRSNR).Vertex(3).y - s_surf->Surface(GRSNR).Vertex(2).y; // YV(3,GRSNR)-YV(2,GRSNR)
    2966            0 :         Z2 = s_surf->Surface(GRSNR).Vertex(3).z - s_surf->Surface(GRSNR).Vertex(2).z; // ZV(3,GRSNR)-ZV(2,GRSNR)
    2967            0 :         BX = Y1 * Z2 - Y2 * Z1;
    2968            0 :         BY = Z1 * X2 - Z2 * X1;
    2969            0 :         BZ = X1 * Y2 - X2 * Y1;
    2970              :         // C                            FIND LARGEST COMPONENT.
    2971            0 :         BMAX = max(std::abs(BX), std::abs(BY), std::abs(BZ));
    2972              :         // C
    2973            0 :         if (std::abs(BX) == BMAX) {
    2974              :             //        write(outputfiledebug,*) ' looking bx-bmax',bmax
    2975            0 :             for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
    2976            0 :                 inside = polygon_contains_point(
    2977            0 :                     s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), true, false, false);
    2978            0 :                 if (!inside) {
    2979            0 :                     Out = true;
    2980              :                     //            do m=1,surface(grsnr)%sides
    2981              :                     //            write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
    2982              :                     //            write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
    2983              :                     //            enddo
    2984              :                     //            EXIT
    2985              :                 }
    2986              :                 //          Y1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(NV(GRSNR),GRSNR)-YV(N,SBSNR)
    2987              :                 //          Z1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(NV(GRSNR),GRSNR)-ZV(N,SBSNR)
    2988              :                 //          DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
    2989              :                 //            Y2 = Y1
    2990              :                 //            Z2 = Z1
    2991              :                 //            Y1 = Surface(GRSNR)%Vertex(M)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(M,GRSNR)-YV(N,SBSNR)
    2992              :                 //            Z1 = Surface(GRSNR)%Vertex(M)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(M,GRSNR)-ZV(N,SBSNR)
    2993              :                 //            SX = Y1*Z2-Y2*Z1
    2994              :                 //            IF(SX*BX.LT.-1.0d-6) THEN
    2995              :                 //              OUT=.TRUE.
    2996              :                 //              write(outputfiledebug,*) 'sx*bx=',sx*bx
    2997              :                 //              write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
    2998              :                 //              write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
    2999              :                 //            endif
    3000              :                 //          ENDDO
    3001              :                 //          IF (OUT) EXIT
    3002              :             }
    3003            0 :         } else if (std::abs(BY) == BMAX) {
    3004              :             //        write(outputfiledebug,*) ' looking by-bmax',bmax
    3005            0 :             for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
    3006            0 :                 inside = polygon_contains_point(
    3007            0 :                     s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), false, true, false);
    3008            0 :                 if (!inside) {
    3009            0 :                     Out = true;
    3010              :                     //            do m=1,surface(grsnr)%sides
    3011              :                     //            write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
    3012              :                     //            write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
    3013              :                     //            enddo
    3014              :                     //            EXIT
    3015              :                 }
    3016              :                 //          Z1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(NV(GRSNR),GRSNR)-ZV(N,SBSNR)
    3017              :                 //          X1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%X-Surface(SBSNR)%Vertex(N)%X !XV(NV(GRSNR),GRSNR)-XV(N,SBSNR)
    3018              :                 //          DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
    3019              :                 //            Z2 = Z1
    3020              :                 //            X2 = X1
    3021              :                 //            Z1 = Surface(GRSNR)%Vertex(M)%Z-Surface(SBSNR)%Vertex(N)%Z !ZV(M,GRSNR)-ZV(N,SBSNR)
    3022              :                 //            X1 = Surface(GRSNR)%Vertex(M)%X-Surface(SBSNR)%Vertex(N)%X !XV(M,GRSNR)-XV(N,SBSNR)
    3023              :                 //            SY = Z1*X2-Z2*X1
    3024              :                 //            IF(SY*BY.LT.-1.0d-6) THEN
    3025              :                 //              OUT=.TRUE.
    3026              :                 //              write(outputfiledebug,*) 'sy*by=',sy*by
    3027              :                 //              write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
    3028              :                 //              write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
    3029              :                 //            ENDIF
    3030              :                 //          ENDDO
    3031              :                 //          IF (OUT) EXIT
    3032              :             }
    3033              :         } else {
    3034              :             //        write(outputfiledebug,*) ' looking bz-bmax',bmax
    3035            0 :             for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) { // NV(SBSNR)
    3036            0 :                 inside = polygon_contains_point(
    3037            0 :                     s_surf->Surface(GRSNR).Sides, s_surf->Surface(GRSNR).Vertex, s_surf->Surface(SBSNR).Vertex(N), false, false, true);
    3038            0 :                 if (!inside) {
    3039            0 :                     Out = true;
    3040              :                     //            do m=1,surface(grsnr)%sides
    3041              :                     //            write(outputfiledebug,*) 'grsnr,side=',m,surface(grsnr)%vertex
    3042              :                     //            write(outputfiledebug,*) 'point outside=',surface(sbsnr)%vertex(n)
    3043              :                     //            enddo
    3044              :                     //            EXIT
    3045              :                 }
    3046              :                 //          X1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%X-Surface(SBSNR)%Vertex(N)%X !XV(NV(GRSNR),GRSNR)-XV(N,SBSNR)
    3047              :                 //          Y1 = Surface(GRSNR)%Vertex(Surface(GRSNR)%Sides)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(NV(GRSNR),GRSNR)-YV(N,SBSNR)
    3048              :                 //          DO M=1,Surface(GRSNR)%Sides !NV(GRSNR)
    3049              :                 //            X2 = X1
    3050              :                 //            Y2 = Y1
    3051              :                 //            X1 = Surface(GRSNR)%Vertex(M)%X-Surface(SBSNR)%Vertex(N)%X !XV(M,GRSNR)-XV(N,SBSNR)
    3052              :                 //            Y1 = Surface(GRSNR)%Vertex(M)%Y-Surface(SBSNR)%Vertex(N)%Y !YV(M,GRSNR)-YV(N,SBSNR)
    3053              :                 //            SZ = X1*Y2-X2*Y1
    3054              :                 //            IF(SZ*BZ.LT.-1.0d-6) THEN
    3055              :                 //              OUT=.TRUE.
    3056              :                 //              write(outputfiledebug,*) 'sz*bz=',sz*bz
    3057              :                 //              write(outputfiledebug,*) 'grsnr=',surface(grsnr)%vertex(m)
    3058              :                 //              write(outputfiledebug,*) 'sbsnr=',surface(sbsnr)%vertex(n)
    3059              :                 //            ENDIF
    3060              :                 //          ENDDO
    3061              :                 //          IF (OUT) EXIT
    3062              :             }
    3063              :         }
    3064              :         //    CALL ShowWarningError(state, 'Base surface does not surround subsurface (CHKSBS), Overlap Status='//  &
    3065              :         //                           TRIM(cOverLapStatus(OverlapStatus)))
    3066              :         //    CALL ShowContinueError(state, 'Surface "'//TRIM(Surface(GRSNR)%Name)//'" '//TRIM(MSG(OverlapStatus))//  &
    3067              :         //                     ' SubSurface "'//TRIM(Surface(SBSNR)%Name)//'"')
    3068              :         //    IF (FirstSurroundError) THEN
    3069              :         //      CALL ShowWarningError(state, 'Base Surface does not surround subsurface errors occurring...'//  &
    3070              :         //                     'Check that the SurfaceGeometry object is expressing the proper starting corner and '//  &
    3071              :         //                     'direction [CounterClockwise/Clockwise]')
    3072              :         //      FirstSurroundError=.FALSE.
    3073              :         //    ENDIF
    3074            0 :         if (Out) {
    3075            0 :             state.dataSolarShading->TrackBaseSubSurround.redimension(++state.dataSolarShading->NumBaseSubSurround);
    3076            0 :             state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).SurfIndex1 = GRSNR;
    3077            0 :             state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).SurfIndex2 = SBSNR;
    3078            0 :             state.dataSolarShading->TrackBaseSubSurround(state.dataSolarShading->NumBaseSubSurround).MiscIndex =
    3079            0 :                 state.dataSolarShading->OverlapStatus;
    3080              :             //    CALL ShowRecurringWarningErrorAtEnd(state, 'Base surface does not surround subsurface (CHKSBS), Overlap Status='//  &
    3081              :             //                       TRIM(cOverLapStatus(OverlapStatus)), &
    3082              :             //                       TrackBaseSubSurround(GRSNR)%ErrIndex1)
    3083              :             //    CALL ShowRecurringContinueErrorAtEnd(state, 'Surface "'//TRIM(Surface(GRSNR)%Name)//'" '//TRIM(MSG(OverlapStatus))//  &
    3084              :             //                       ' SubSurface "'//TRIM(Surface(SBSNR)%Name)//'"',  &
    3085              :             //                      TrackBaseSubSurround(SBSNR)%ErrIndex2)
    3086            0 :             if (state.dataSolarShading->shd_stream) {
    3087            0 :                 *state.dataSolarShading->shd_stream << "==== Base does not Surround subsurface details ====\n";
    3088            0 :                 *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(GRSNR).Name << ' '
    3089            0 :                                                     << state.dataSolarShading->cOverLapStatus(state.dataSolarShading->OverlapStatus) << '\n';
    3090            0 :                 *state.dataSolarShading->shd_stream << "Surface#=" << std::setw(5) << GRSNR << " NSides=" << std::setw(5)
    3091            0 :                                                     << s_surf->Surface(GRSNR).Sides << '\n';
    3092            0 :                 *state.dataSolarShading->shd_stream << std::fixed << std::setprecision(2);
    3093            0 :                 for (N = 1; N <= s_surf->Surface(GRSNR).Sides; ++N) {
    3094            0 :                     Vector const &v(s_surf->Surface(GRSNR).Vertex(N));
    3095            0 :                     *state.dataSolarShading->shd_stream << "Vertex " << std::setw(5) << N << "=(" << std::setw(15) << v.x << ',' << std::setw(15)
    3096            0 :                                                         << v.y << ',' << std::setw(15) << v.z << ")\n";
    3097              :                 }
    3098            0 :                 *state.dataSolarShading->shd_stream << "SubSurface=" << s_surf->Surface(SBSNR).Name << '\n';
    3099            0 :                 *state.dataSolarShading->shd_stream << "Surface#=" << std::setw(5) << SBSNR << " NSides=" << std::setw(5)
    3100            0 :                                                     << s_surf->Surface(SBSNR).Sides << '\n';
    3101            0 :                 for (N = 1; N <= s_surf->Surface(SBSNR).Sides; ++N) {
    3102            0 :                     Vector const &v(s_surf->Surface(SBSNR).Vertex(N));
    3103            0 :                     *state.dataSolarShading->shd_stream << "Vertex " << std::setw(5) << N << "=(" << std::setw(15) << v.x << ',' << std::setw(15)
    3104            0 :                                                         << v.y << ',' << std::setw(15) << v.z << ")\n";
    3105              :                 }
    3106            0 :                 *state.dataSolarShading->shd_stream << "================================\n";
    3107              :             }
    3108              :         }
    3109              :     }
    3110           70 : }
    3111              : 
    3112            6 : bool polygon_contains_point(int const nsides,            // number of sides (vertices)
    3113              :                             Array1D<Vector> &polygon_3d, // points of polygon
    3114              :                             Vector const &point_3d,      // point to be tested
    3115              :                             bool const ignorex,
    3116              :                             bool const ignorey,
    3117              :                             bool const ignorez)
    3118              : {
    3119              : 
    3120              :     // Function information:
    3121              :     //       Author         Linda Lawrie
    3122              :     //       Date written   October 2005
    3123              :     //       Modified       na
    3124              :     //       Re-engineered  na
    3125              : 
    3126              :     // Purpose of this function:
    3127              :     // Determine if a point is inside a simple 2d polygon.  For a simple polygon (one whose
    3128              :     // boundary never crosses itself).  The polygon does not need to be convex.
    3129              : 
    3130              :     // References:
    3131              :     // M Shimrat, Position of Point Relative to Polygon, ACM Algorithm 112,
    3132              :     // Communications of the ACM, Volume 5, Number 8, page 434, August 1962.
    3133              : 
    3134              :     // Use statements:
    3135              :     // Using/Aliasing
    3136              :     using namespace DataVectorTypes;
    3137              : 
    3138              :     // return value, true=inside, false = not inside
    3139              : 
    3140            6 :     EP_SIZE_CHECK(polygon_3d, nsides);
    3141              : 
    3142              :     int ip1;
    3143              : 
    3144              :     // Object Data
    3145            6 :     Array1D<Vector_2d> polygon(nsides);
    3146            6 :     Vector_2d point;
    3147              : 
    3148            6 :     bool inside = false;
    3149            6 :     if (ignorex) {
    3150           10 :         for (int i = 1; i <= nsides; ++i) {
    3151            8 :             polygon(i).x = polygon_3d(i).y;
    3152            8 :             polygon(i).y = polygon_3d(i).z;
    3153              :         }
    3154            2 :         point.x = point_3d.y;
    3155            2 :         point.y = point_3d.z;
    3156            4 :     } else if (ignorey) {
    3157           10 :         for (int i = 1; i <= nsides; ++i) {
    3158            8 :             polygon(i).x = polygon_3d(i).x;
    3159            8 :             polygon(i).y = polygon_3d(i).z;
    3160              :         }
    3161            2 :         point.x = point_3d.x;
    3162            2 :         point.y = point_3d.z;
    3163            2 :     } else if (ignorez) {
    3164           10 :         for (int i = 1; i <= nsides; ++i) {
    3165            8 :             polygon(i).x = polygon_3d(i).x;
    3166            8 :             polygon(i).y = polygon_3d(i).y;
    3167              :         }
    3168            2 :         point.x = point_3d.x;
    3169            2 :         point.y = point_3d.y;
    3170              :     } else { // Illegal
    3171            0 :         assert(false);
    3172              :         point.x = point.y = 0.0; // Elim possibly used uninitialized warnings
    3173              :     }
    3174              : 
    3175           30 :     for (int i = 1; i <= nsides; ++i) {
    3176              : 
    3177           24 :         if (i < nsides) {
    3178           18 :             ip1 = i + 1;
    3179              :         } else {
    3180            6 :             ip1 = 1;
    3181              :         }
    3182              : 
    3183           24 :         if ((polygon(i).y < point.y && point.y <= polygon(ip1).y) || (point.y <= polygon(i).y && polygon(ip1).y < point.y)) {
    3184            6 :             if ((point.x - polygon(i).x) - (point.y - polygon(i).y) * (polygon(ip1).x - polygon(i).x) / (polygon(ip1).y - polygon(i).y) < 0) {
    3185            3 :                 inside = !inside;
    3186              :             }
    3187              :         }
    3188              :     }
    3189              : 
    3190            6 :     return inside;
    3191            6 : }
    3192              : 
    3193          104 : void ComputeIntSolarAbsorpFactors(EnergyPlusData &state)
    3194              : {
    3195              : 
    3196              :     // SUBROUTINE INFORMATION:
    3197              :     //       AUTHOR         Legacy Code
    3198              :     //       MODIFIED       B. Griffith, Oct 2010, deal with no floor case
    3199              :     //                      L. Lawrie, Mar 2012, relax >154 tilt even further (>120 considered non-wall by ASHRAE)
    3200              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3201              : 
    3202              :     // PURPOSE OF THIS SUBROUTINE:
    3203              :     // This routine computes the fractions of diffusely transmitted
    3204              :     // solar energy absorbed by each zone surface.
    3205              : 
    3206              :     // METHODOLOGY EMPLOYED:
    3207              :     // It is assumed that all transmitted solar energy is incident
    3208              :     // on the floors of the zone (or enclosure).  The fraction directly absorbed in
    3209              :     // the floor is given by 'ISABSF'.  It is proportional to the
    3210              :     // area * solar absorptance.  The remaining solar energy is then
    3211              :     // distributed uniformly around the room according to
    3212              :     // area*absorptance product
    3213              : 
    3214              :     // REFERENCES:
    3215              :     // BLAST/IBLAST code, original author George Walton
    3216              : 
    3217              :     using namespace DataWindowEquivalentLayer;
    3218              : 
    3219              :     Real64 AreaSum;       // Intermediate calculation value
    3220              :     int Lay;              // Window glass layer number
    3221              :     Real64 AbsDiffTotWin; // Sum of a window's glass layer solar absorptances
    3222              :     Real64 TestFractSum;
    3223              :     Real64 HorizAreaSum;
    3224              : 
    3225          104 :     auto &s_surf = state.dataSurface;
    3226              : 
    3227          236 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    3228          132 :         auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
    3229              : 
    3230          132 :         AreaSum = 0.0;
    3231          132 :         TestFractSum = 0.0;
    3232          844 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    3233          712 :             if (state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType == StandardZone && s_surf->Surface(SurfNum).CosTilt < -0.5) {
    3234          145 :                 AreaSum += s_surf->Surface(SurfNum).Area;
    3235              :             }
    3236              :         }
    3237              : 
    3238          132 :         HorizAreaSum = AreaSum;
    3239              : 
    3240          132 :         if ((thisEnclosure.FloorArea <= 0.0) && (HorizAreaSum > 0.0)) {
    3241              :             // fill floor area even though surfs not called "Floor", they are roughly horizontal and face upwards.
    3242            0 :             thisEnclosure.FloorArea = HorizAreaSum;
    3243            0 :             ShowWarningError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
    3244            0 :             ShowContinueError(state, format("...Enclosure=\"{}\" has no floor, but has approximate horizontal surfaces.", thisEnclosure.Name));
    3245            0 :             ShowContinueError(state, format("...these Tilt > 120 degrees, (area=[{:.2R}] m2) will be used.", HorizAreaSum));
    3246              :         }
    3247              : 
    3248              :         // Compute ISABSF
    3249              : 
    3250          844 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    3251              : 
    3252              :             // only horizontal surfaces. !      !CR 8229, relaxed from -0.99 to -0.5  (Tilt > 154)
    3253              :             // only horizontal surfaces. !      !CR8769 use ASHRAE std of >120, -0.9 to -0.5  (Tilt > 120)
    3254          857 :             if ((state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType != StandardZone || s_surf->Surface(SurfNum).CosTilt < -0.5) &&
    3255          145 :                 (state.dataHeatBal->Zone(s_surf->Surface(SurfNum).Zone).OfType == StandardZone || s_surf->Surface(SurfNum).ExtBoundCond > 0)) {
    3256              : 
    3257          145 :                 int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
    3258          145 :                 auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    3259              :                 // last minute V3.1
    3260          145 :                 if (thisConstruct.TransDiff <= 0.0) { // Opaque surface
    3261          143 :                     if (AreaSum > 0.0)
    3262          143 :                         state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * thisConstruct.InsideAbsorpSolar / AreaSum;
    3263              :                 } else { // Window (floor windows are assumed to have no shading device and no divider,
    3264              :                     // and assumed to be non-switchable)
    3265            2 :                     AbsDiffTotWin = 0.0;
    3266            2 :                     if (!state.dataConstruction->Construct(s_surf->Surface(SurfNum).Construction).WindowTypeEQL) {
    3267            6 :                         for (Lay = 1; Lay <= thisConstruct.TotGlassLayers; ++Lay) {
    3268            4 :                             AbsDiffTotWin += thisConstruct.AbsDiffBack(Lay);
    3269              :                         }
    3270              :                     } else {
    3271            0 :                         for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(thisConstruct.EQLConsPtr).NL; ++Lay) {
    3272            0 :                             AbsDiffTotWin += thisConstruct.AbsDiffBackEQL(Lay);
    3273              :                         }
    3274              :                     }
    3275            2 :                     if (AreaSum > 0.0) state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * AbsDiffTotWin / AreaSum;
    3276              :                 }
    3277              :             }
    3278              :             // CR 8229  test ISABSF for problems
    3279          712 :             TestFractSum += state.dataSolarShading->SurfIntAbsFac(SurfNum);
    3280              :         }
    3281              : 
    3282          132 :         if (TestFractSum <= 0.0) {
    3283            9 :             if (thisEnclosure.ExtWindowArea > 0.0) { // we have a problem, the sun has no floor to go to
    3284            3 :                 if (thisEnclosure.FloorArea <= 0.0) {
    3285            0 :                     ShowSevereError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
    3286            0 :                     ShowContinueError(state, format("but Zone or Enclosure =\"{}\" does not appear to have any floor surfaces.", thisEnclosure.Name));
    3287            0 :                     ShowContinueError(state, "Solar gains will be spread evenly on all surfaces in the zone, and the simulation continues...");
    3288              :                 } else { // Floor Area > 0 but still can't absorb
    3289            6 :                     ShowSevereError(state, "ComputeIntSolarAbsorpFactors: Solar distribution model is set to place solar gains on the zone floor,");
    3290            3 :                     ShowContinueError(state, format("but Zone or Enclosure =\"{}\" floor cannot absorb any solar gains. ", thisEnclosure.Name));
    3291            6 :                     ShowContinueError(state, "Check the solar absorptance of the inside layer of the floor surface construction/material.");
    3292            9 :                     ShowContinueError(state, "Solar gains will be spread evenly on all surfaces in the zone, and the simulation continues...");
    3293              :                 }
    3294              : 
    3295              :                 // try again but use an even spread across all the surfaces in the zone, regardless of horizontal
    3296              :                 //  so as to not lose solar energy
    3297            3 :                 AreaSum = 0.0;
    3298            3 :                 for (int SurfNum : thisEnclosure.SurfacePtr) {
    3299            0 :                     AreaSum += s_surf->Surface(SurfNum).Area;
    3300              :                 }
    3301              : 
    3302            3 :                 for (int const SurfNum : thisEnclosure.SurfacePtr) {
    3303            0 :                     int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
    3304            0 :                     auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    3305            0 :                     if (thisConstruct.TransDiff <= 0.0) { // Opaque surface
    3306            0 :                         if (AreaSum > 0.0)
    3307            0 :                             state.dataSolarShading->SurfIntAbsFac(SurfNum) =
    3308            0 :                                 s_surf->Surface(SurfNum).Area * thisConstruct.InsideAbsorpSolar / AreaSum;
    3309              :                     } else { // Window (floor windows are assumed to have no shading device and no divider,
    3310              :                         // and assumed to be non-switchable)
    3311            0 :                         AbsDiffTotWin = 0.0;
    3312            0 :                         if (!state.dataConstruction->Construct(s_surf->Surface(SurfNum).Construction).WindowTypeEQL) {
    3313            0 :                             for (Lay = 1; Lay <= thisConstruct.TotGlassLayers; ++Lay) {
    3314            0 :                                 AbsDiffTotWin += thisConstruct.AbsDiffBack(Lay);
    3315              :                             }
    3316              :                         } else {
    3317            0 :                             for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(thisConstruct.EQLConsPtr).NL; ++Lay) {
    3318            0 :                                 AbsDiffTotWin += thisConstruct.AbsDiffBackEQL(Lay);
    3319              :                             }
    3320              :                         }
    3321              : 
    3322            0 :                         if (AreaSum > 0.0) state.dataSolarShading->SurfIntAbsFac(SurfNum) = s_surf->Surface(SurfNum).Area * AbsDiffTotWin / AreaSum;
    3323              :                     }
    3324              :                 }
    3325              :             }
    3326              :         }
    3327              : 
    3328              :     } // enclosure loop
    3329          104 : }
    3330              : 
    3331        11826 : void CLIP(EnergyPlusData &state, int const NVT, Array1D<Real64> &XVT, Array1D<Real64> &YVT, Array1D<Real64> &ZVT)
    3332              : {
    3333              : 
    3334              :     // SUBROUTINE INFORMATION:
    3335              :     //       AUTHOR         Legacy Code
    3336              :     //       DATE WRITTEN
    3337              :     //       MODIFIED       na
    3338              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3339              : 
    3340              :     // PURPOSE OF THIS SUBROUTINE:
    3341              :     // This subroutine 'clips' the shadow casting surface polygon so that
    3342              :     // none of it lies below the plane of the receiving surface polygon.  This
    3343              :     // prevents the casting of 'false' shadows.
    3344              : 
    3345              :     // REFERENCES:
    3346              :     // BLAST/IBLAST code, original author George Walton
    3347              : 
    3348        11826 :     int NABOVE(0);    // Number of vertices of shadow casting surface. above the plane of receiving surface
    3349        11826 :     int NEXT(0);      // First vertex above plane of receiving surface
    3350        11826 :     int NON(0);       // Number of vertices of shadow casting surface. on plane of receiving surface
    3351        11826 :     Real64 XIN(0.0);  // X of entry point of shadow casting surface. into plane of receiving surface
    3352        11826 :     Real64 XOUT(0.0); // X of exit point of shadow casting surface. from plane of receiving surface
    3353        11826 :     Real64 YIN(0.0);  // Y of entry point of shadow casting surface. into plane of receiving surface
    3354        11826 :     Real64 YOUT(0.0); // Y of exit point of shadow casting surface. from plane of receiving surface
    3355              :     //  INTEGER NVS      ! Number of vertices of the shadow/clipped surface
    3356              : 
    3357              :     // Determine if the shadow casting surface. is above, below, or intersects with the plane of the receiving surface
    3358              : 
    3359        11826 :     state.dataSolarShading->NumVertInShadowOrClippedSurface = state.dataSolarShading->NVS;
    3360        59098 :     for (int N = 1; N <= NVT; ++N) {
    3361        47272 :         Real64 const ZVT_N(ZVT(N));
    3362        47272 :         if (ZVT_N > 0.0) {
    3363        33104 :             ++NABOVE;
    3364        14168 :         } else if (ZVT_N == 0.0) {
    3365         6998 :             ++NON;
    3366              :         }
    3367              :     }
    3368              : 
    3369        11826 :     if (NABOVE + NON == NVT) { // Rename the unclipped shadow casting surface.
    3370              : 
    3371         8241 :         state.dataSolarShading->NVS = NVT;
    3372         8241 :         state.dataSolarShading->NumVertInShadowOrClippedSurface = NVT;
    3373        41173 :         for (int N = 1; N <= NVT; ++N) {
    3374        32932 :             state.dataSolarShading->XVC(N) = XVT(N);
    3375        32932 :             state.dataSolarShading->YVC(N) = YVT(N);
    3376        32932 :             state.dataSolarShading->ZVC(N) = ZVT(N);
    3377              :         }
    3378              : 
    3379         3585 :     } else if (NABOVE == 0) { // Totally submerged shadow casting surface.
    3380              : 
    3381            0 :         state.dataSolarShading->NVS = 0;
    3382            0 :         state.dataSolarShading->NumVertInShadowOrClippedSurface = 0;
    3383              : 
    3384              :     } else { // Remove (clip) that portion of the shadow casting surface. which is below the receiving surface
    3385              : 
    3386         3585 :         state.dataSolarShading->NVS = NABOVE + 2;
    3387         3585 :         state.dataSolarShading->NumVertInShadowOrClippedSurface = NABOVE + 2;
    3388         3585 :         Real64 ZVT_N, ZVT_P(ZVT(1));
    3389         3585 :         XVT(NVT + 1) = XVT(1);
    3390         3585 :         YVT(NVT + 1) = YVT(1);
    3391         3585 :         ZVT(NVT + 1) = ZVT_P;
    3392        17925 :         for (int N = 1, P = 2; N <= NVT; ++N, ++P) {
    3393        14340 :             ZVT_N = ZVT_P;
    3394        14340 :             ZVT_P = ZVT(P);
    3395        14340 :             if (ZVT_N >= 0.0 && ZVT_P < 0.0) { // Line enters plane of receiving surface
    3396         3585 :                 Real64 const ZVT_fac(1.0 / (ZVT_P - ZVT_N));
    3397         3585 :                 XIN = (ZVT_P * XVT(N) - ZVT_N * XVT(P)) * ZVT_fac;
    3398         3585 :                 YIN = (ZVT_P * YVT(N) - ZVT_N * YVT(P)) * ZVT_fac;
    3399        14340 :             } else if (ZVT_N <= 0.0 && ZVT_P > 0.0) { // Line exits plane of receiving surface
    3400         3585 :                 NEXT = N + 1;
    3401         3585 :                 Real64 const ZVT_fac(1.0 / (ZVT_P - ZVT_N));
    3402         3585 :                 XOUT = (ZVT_P * XVT(N) - ZVT_N * XVT(P)) * ZVT_fac;
    3403         3585 :                 YOUT = (ZVT_P * YVT(N) - ZVT_N * YVT(P)) * ZVT_fac;
    3404              :             }
    3405              :         }
    3406              : 
    3407              :         // Renumber the vertices of the clipped shadow casting surface. so they are still counter-clockwise sequential.
    3408              : 
    3409         3585 :         state.dataSolarShading->XVC(1) = XOUT; //? Verify that the IN and OUT values were ever set?
    3410         3585 :         state.dataSolarShading->YVC(1) = YOUT;
    3411         3585 :         state.dataSolarShading->ZVC(1) = 0.0;
    3412         3585 :         state.dataSolarShading->XVC(state.dataSolarShading->NVS) = XIN;
    3413         3585 :         state.dataSolarShading->YVC(state.dataSolarShading->NVS) = YIN;
    3414         3585 :         state.dataSolarShading->ZVC(state.dataSolarShading->NVS) = 0.0;
    3415        10755 :         for (int N = 1; N <= NABOVE; ++N) {
    3416         7170 :             if (NEXT > NVT) NEXT = 1;
    3417         7170 :             state.dataSolarShading->XVC(N + 1) = XVT(NEXT);
    3418         7170 :             state.dataSolarShading->YVC(N + 1) = YVT(NEXT);
    3419         7170 :             state.dataSolarShading->ZVC(N + 1) = ZVT(NEXT);
    3420         7170 :             ++NEXT;
    3421              :         }
    3422              :     }
    3423        11826 : }
    3424              : 
    3425        29799 : void CTRANS(EnergyPlusData &state,
    3426              :             int const NS,         // Surface number whose vertex coordinates are being transformed
    3427              :             int const NGRS,       // Base surface number for surface NS
    3428              :             int &NVT,             // Number of vertices for surface NS
    3429              :             Array1D<Real64> &XVT, // XYZ coordinates of vertices of NS in plane of NGRS
    3430              :             Array1D<Real64> &YVT,
    3431              :             Array1D<Real64> &ZVT)
    3432              : {
    3433              : 
    3434              :     // SUBROUTINE INFORMATION:
    3435              :     //       AUTHOR         Legacy Code
    3436              :     //       DATE WRITTEN
    3437              :     //       MODIFIED       na
    3438              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3439              : 
    3440              :     // PURPOSE OF THIS SUBROUTINE:
    3441              :     // Transforms the general coordinates of the vertices
    3442              :     // of surface NS to coordinates in the plane of the receiving surface NGRS.
    3443              :     // See subroutine 'CalcCoordinateTransformation' SurfaceGeometry Module.
    3444              : 
    3445              :     // REFERENCES:
    3446              :     // BLAST/IBLAST code, original author George Walton
    3447              :     // NECAP subroutine 'SHADOW'
    3448              : 
    3449              :     Real64 Xdif; // Intermediate Result
    3450              :     Real64 Ydif; // Intermediate Result
    3451              :     Real64 Zdif; // Intermediate Result
    3452              : 
    3453        29799 :     auto &s_surf = state.dataSurface;
    3454              : 
    3455              :     // Tuned
    3456        29799 :     auto const &surface = s_surf->Surface(NS);
    3457        29799 :     auto const &base_surface = s_surf->Surface(NGRS);
    3458        29799 :     auto const &base_lcsx = base_surface.lcsx;
    3459        29799 :     auto const &base_lcsy = base_surface.lcsy;
    3460        29799 :     auto const &base_lcsz = base_surface.lcsz;
    3461        29799 :     Real64 const base_X0 = s_surf->X0(NGRS);
    3462        29799 :     Real64 const base_Y0 = s_surf->Y0(NGRS);
    3463        29799 :     Real64 const base_Z0 = s_surf->Z0(NGRS);
    3464              : 
    3465        29799 :     NVT = surface.Sides;
    3466              : 
    3467              :     // Perform transformation
    3468       148963 :     for (int N = 1; N <= NVT; ++N) {
    3469       119164 :         auto const &vertex = surface.Vertex(N);
    3470              : 
    3471       119164 :         Xdif = vertex.x - base_X0;
    3472       119164 :         Ydif = vertex.y - base_Y0;
    3473       119164 :         Zdif = vertex.z - base_Z0;
    3474              : 
    3475       119164 :         if (std::abs(Xdif) <= 1.E-15) Xdif = 0.0;
    3476       119164 :         if (std::abs(Ydif) <= 1.E-15) Ydif = 0.0;
    3477       119164 :         if (std::abs(Zdif) <= 1.E-15) Zdif = 0.0;
    3478              : 
    3479       119164 :         XVT(N) = base_lcsx.x * Xdif + base_lcsx.y * Ydif + base_lcsx.z * Zdif;
    3480       119164 :         YVT(N) = base_lcsy.x * Xdif + base_lcsy.y * Ydif + base_lcsy.z * Zdif;
    3481       119164 :         ZVT(N) = base_lcsz.x * Xdif + base_lcsz.y * Ydif + base_lcsz.z * Zdif;
    3482              :     }
    3483        29799 : }
    3484              : 
    3485            0 : void HTRANS(EnergyPlusData &state,
    3486              :             int const I,          // Mode selector: 0 - Compute H.C. of sides
    3487              :             int const NS,         // Figure Number
    3488              :             int const NumVertices // Number of vertices
    3489              : )
    3490              : {
    3491              : 
    3492              :     // SUBROUTINE INFORMATION:
    3493              :     //       AUTHOR         Legacy Code
    3494              :     //       DATE WRITTEN
    3495              :     //       MODIFIED       na
    3496              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3497              : 
    3498              :     // PURPOSE OF THIS SUBROUTINE:
    3499              :     // This subroutine sets up the homogeneous coordinates.
    3500              :     // This routine converts the cartesian coordinates of a surface
    3501              :     // or shadow polygon to homogeneous coordinates.  It also
    3502              :     // computes the area of the polygon.
    3503              : 
    3504              :     // METHODOLOGY EMPLOYED:
    3505              :     // Note: Original legacy code used integer arithmetic (tests in subroutines
    3506              :     // INCLOS and INTCPT are sensitive to round-off error).  However, porting to Fortran 77
    3507              :     // (BLAST/IBLAST) required some variables to become REAL(r64) instead.
    3508              : 
    3509              :     // Notes on homogeneous coordinates:
    3510              :     // A point (X,Y) is represented by a 3-element vector
    3511              :     // (W*X,W*Y,W), where W may be any REAL(r64) number except 0.  a line
    3512              :     // is also represented by a 3-element vector (A,B,C).  The
    3513              :     // directed line (A,B,C) from point (W*X1,W*Y1,W) to point
    3514              :     // (V*X2,V*Y2,V) is given by (A,B,C) = (W*X1,W*Y1,W) cross
    3515              :     // (V*X2,V*Y2,V).  The sequence of the cross product is a
    3516              :     // convention to determine sign.  The condition that a point lie
    3517              :     // on a line is that (A,B,C) dot (W*X,W*Y,W) = 0.  'Normalize'
    3518              :     // the representation of a point by setting W to 1.  Then if
    3519              :     // (A,B,C) dot (X,Y,1) > 0.0, The point is to the left of the
    3520              :     // line, and if it is less than zero, the point is to the right
    3521              :     // of the line.  The intercept of two lines is given by
    3522              :     // (W*X,W*Y,W) = (A1,B1,C1) cross (A2,B2,C3).
    3523              : 
    3524              :     // REFERENCES:
    3525              :     // BLAST/IBLAST code, original author George Walton
    3526              :     // W. M. Newman & R. F. Sproull, 'Principles of Interactive Computer Graphics', Appendix II, McGraw-Hill, 1973.
    3527              :     // 'CRC Math Tables', 22 ED, 'Analytic Geometry', P.369
    3528              : 
    3529              :     // Using/Aliasing
    3530              : 
    3531              :     // Locals
    3532              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    3533              :     //                1 - Compute H.C. of vertices & sides
    3534              : 
    3535            0 :     if (NS > 2 * state.dataSolarShading->MaxHCS) {
    3536            0 :         ShowFatalError(state, format("Solar Shading: HTrans: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
    3537              :     }
    3538              : 
    3539            0 :     state.dataSolarShading->HCNV(NS) = NumVertices;
    3540              : 
    3541              :     // Tuned Linear indexing
    3542              : 
    3543            0 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    3544            0 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    3545            0 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
    3546            0 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
    3547            0 :     int const l1(state.dataSolarShading->HCX.index(NS, 1));
    3548            0 :     if (I != 0) { // Transform vertices of figure ns.
    3549              : 
    3550              :         // See comment at top of module regarding HCMULT
    3551            0 :         int l(l1);
    3552            0 :         for (int N = 1; N <= NumVertices; ++N, ++l) { // [ l ] == ( NS, N )
    3553            0 :             state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XVS(N) * HCMULT);
    3554            0 :             state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YVS(N) * HCMULT);
    3555              :         }
    3556              :     }
    3557              : 
    3558              :     // Establish extra point for finding lines between points.
    3559              : 
    3560            0 :     int l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
    3561            0 :     Int64 HCX_m = state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]; // [ l ] == ( NS, NumVertices + 1 ), [ l1 ] == ( NS, 1 )
    3562            0 :     Int64 HCY_m = state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]; // [ l ] == ( NS, NumVertices + 1 ), [ l1 ] == ( NS, 1 )
    3563              : 
    3564              :     // Determine lines between points.
    3565            0 :     l = l1;
    3566            0 :     int m = l1 + 1u;
    3567              :     Int64 HCX_l;
    3568              :     Int64 HCY_l;
    3569            0 :     Real64 SUM = 0.0;                                  // Sum variable
    3570            0 :     for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
    3571            0 :         HCX_l = HCX_m;
    3572            0 :         HCY_l = HCY_m;
    3573            0 :         HCX_m = state.dataSolarShading->HCX[m];
    3574            0 :         HCY_m = state.dataSolarShading->HCY[m];
    3575            0 :         state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
    3576            0 :         state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
    3577            0 :         SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
    3578              :     }
    3579              : 
    3580              :     // Compute area of polygon.
    3581              :     //  SUM=0.0D0
    3582              :     //  DO N = 1, NumVertices
    3583              :     //    SUM = SUM + HCX(N,NS)*HCY(N+1,NS) - HCY(N,NS)*HCX(N+1,NS) ! Since HCX and HCY integerized, value of SUM should be ok
    3584              :     //  END DO
    3585            0 :     state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
    3586              :     //  HCAREA(NS)=0.5d0*SUM*(kHCMULT)
    3587            0 : }
    3588              : 
    3589        34858 : void HTRANS0(EnergyPlusData &state,
    3590              :              int const NS,         // Figure Number
    3591              :              int const NumVertices // Number of vertices
    3592              : )
    3593              : {
    3594              :     // Using/Aliasing
    3595              : 
    3596              :     // Locals
    3597              : 
    3598        34858 :     if (NS > 2 * state.dataSolarShading->MaxHCS) {
    3599            0 :         ShowFatalError(state, format("Solar Shading: HTrans0: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
    3600              :     }
    3601              : 
    3602        34858 :     state.dataSolarShading->HCNV(NS) = NumVertices;
    3603              : 
    3604              :     // Tuned Linear indexing
    3605              : 
    3606        34858 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    3607        34858 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    3608        34858 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
    3609        34858 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
    3610              : 
    3611        34858 :     int const l1 = state.dataSolarShading->HCX.index(NS, 1);
    3612              : 
    3613        34858 :     int l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
    3614        34858 :     Int64 HCX_m = state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]; // [ l1 ] == ( NS, 1 )
    3615        34858 :     Int64 HCY_m = state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]; // [ l1 ] == ( NS, 1 )
    3616              : 
    3617        34858 :     l = l1;
    3618        34858 :     int m = l1 + 1u;
    3619              :     Int64 HCX_l;
    3620              :     Int64 HCY_l;
    3621        34858 :     Real64 SUM(0.0);
    3622       149503 :     for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
    3623       114645 :         HCX_l = HCX_m;
    3624       114645 :         HCY_l = HCY_m;
    3625       114645 :         HCX_m = state.dataSolarShading->HCX[m];
    3626       114645 :         HCY_m = state.dataSolarShading->HCY[m];
    3627       114645 :         state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
    3628       114645 :         state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
    3629       114645 :         SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
    3630              :     }
    3631              : 
    3632        34858 :     state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
    3633        34858 : }
    3634              : 
    3635        38197 : void HTRANS1(EnergyPlusData &state,
    3636              :              int const NS,         // Figure Number
    3637              :              int const NumVertices // Number of vertices
    3638              : )
    3639              : {
    3640              :     // Using/Aliasing
    3641              : 
    3642        38197 :     if (NS > 2 * state.dataSolarShading->MaxHCS) {
    3643            0 :         ShowFatalError(state, format("Solar Shading: HTrans1: Too many Figures (>{})", state.dataSolarShading->MaxHCS));
    3644              :     }
    3645              : 
    3646        38197 :     state.dataSolarShading->HCNV(NS) = NumVertices;
    3647              : 
    3648              :     // Tuned Linear indexing
    3649              : 
    3650        38197 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    3651        38197 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    3652        38197 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
    3653        38197 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
    3654              : 
    3655        38197 :     int const l1 = state.dataSolarShading->HCX.index(NS, 1);
    3656              : 
    3657              :     // only in HTRANS1
    3658        38197 :     int l = l1;
    3659       190953 :     for (int N = 1; N <= NumVertices; ++N, ++l) { // [ l ] == ( NS, N )
    3660       152756 :         state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XVS(N) * HCMULT);
    3661       152756 :         state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YVS(N) * HCMULT);
    3662              :     }
    3663              : 
    3664        38197 :     l = state.dataSolarShading->HCX.index(NS, NumVertices + 1);
    3665        38197 :     Int64 HCX_m(state.dataSolarShading->HCX[l] = state.dataSolarShading->HCX[l1]); // [ l1 ] == ( NS, 1 )
    3666        38197 :     Int64 HCY_m(state.dataSolarShading->HCY[l] = state.dataSolarShading->HCY[l1]);
    3667              : 
    3668        38197 :     l = l1;
    3669        38197 :     int m = l1 + 1u;
    3670              :     Int64 HCX_l;
    3671              :     Int64 HCY_l;
    3672        38197 :     Real64 SUM = 0.0;
    3673       190953 :     for (int N = 1; N <= NumVertices; ++N, ++l, ++m) { // [ l ] == ( NS, N ), [ m ] == ( NS, N + 1 )
    3674       152756 :         HCX_l = HCX_m;
    3675       152756 :         HCY_l = HCY_m;
    3676       152756 :         HCX_m = state.dataSolarShading->HCX[m];
    3677       152756 :         HCY_m = state.dataSolarShading->HCY[m];
    3678       152756 :         state.dataSolarShading->HCA[l] = HCY_l - HCY_m;
    3679       152756 :         state.dataSolarShading->HCB[l] = HCX_m - HCX_l;
    3680       152756 :         SUM += state.dataSolarShading->HCC[l] = (HCY_m * HCX_l) - (HCX_m * HCY_l);
    3681              :     }
    3682              : 
    3683        38197 :     state.dataSolarShading->HCAREA(NS) = SUM * sqHCMULT_fac;
    3684        38197 : }
    3685              : 
    3686            0 : void INCLOS(EnergyPlusData &state,
    3687              :             int const N1,            // Figure number of figure 1
    3688              :             int const N1NumVert,     // Number of vertices of figure 1
    3689              :             int const N2,            // Figure number of figure 2
    3690              :             int const N2NumVert,     // Number of vertices of figure 2
    3691              :             int &NumVerticesOverlap, // Number of vertices which overlap
    3692              :             int &NIN                 // Number of vertices of figure 1 within figure 2
    3693              : )
    3694              : {
    3695              : 
    3696              :     // SUBROUTINE INFORMATION:
    3697              :     //       AUTHOR         Legacy Code
    3698              :     //       DATE WRITTEN
    3699              :     //       MODIFIED       na
    3700              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3701              : 
    3702              :     // PURPOSE OF THIS SUBROUTINE:
    3703              :     // This subroutine determines which vertices of figure N1 lie within figure N2.
    3704              : 
    3705              :     // METHODOLOGY EMPLOYED:
    3706              :     // For vertex N of figure N1 to lie within figure N2, it must be
    3707              :     // on or to the right of all sides of figure N2, assuming
    3708              :     // figure N2 is convex.
    3709              : 
    3710              :     // REFERENCES:
    3711              :     // BLAST/IBLAST code, original author George Walton
    3712              : 
    3713              :     int K;              // Vertex number of the overlap
    3714              :     int M;              // Side number of figure N2
    3715              :     int N;              // Vertex number of figure N1
    3716              :     bool CycleMainLoop; // Sets when to cycle main loop
    3717              :     Real64 HFunct;
    3718              : 
    3719            0 :     NIN = 0;
    3720              : 
    3721            0 :     for (N = 1; N <= N1NumVert; ++N) {
    3722              : 
    3723            0 :         CycleMainLoop = false;
    3724              : 
    3725              :         // Eliminate cases where vertex N is to the left of side M.
    3726              : 
    3727            0 :         for (M = 1; M <= N2NumVert; ++M) {
    3728            0 :             HFunct = state.dataSolarShading->HCX(N1, N) * state.dataSolarShading->HCA(N2, M) +
    3729            0 :                      state.dataSolarShading->HCY(N1, N) * state.dataSolarShading->HCB(N2, M) + state.dataSolarShading->HCC(N2, M);
    3730            0 :             if (HFunct > 0.0) {
    3731            0 :                 CycleMainLoop = true; // Set to cycle to the next value of N
    3732            0 :                 break;                // M DO loop
    3733              :             }
    3734              :         }
    3735              : 
    3736            0 :         if (CycleMainLoop) continue;
    3737            0 :         ++NIN;
    3738              : 
    3739              :         // Check for duplication of previously determined points.
    3740              : 
    3741            0 :         if (NumVerticesOverlap != 0) {
    3742            0 :             for (K = 1; K <= NumVerticesOverlap; ++K) {
    3743            0 :                 if ((state.dataSolarShading->XTEMP(K) == state.dataSolarShading->HCX(N1, N)) &&
    3744            0 :                     (state.dataSolarShading->YTEMP(K) == state.dataSolarShading->HCY(N1, N))) {
    3745            0 :                     CycleMainLoop = true; // Set to cycle to the next value of N
    3746            0 :                     break;                // K DO loop
    3747              :                 }
    3748              :             }
    3749            0 :             if (CycleMainLoop) continue;
    3750              :         }
    3751              : 
    3752              :         // Record enclosed vertices in temporary arrays.
    3753              : 
    3754            0 :         ++NumVerticesOverlap;
    3755            0 :         state.dataSolarShading->XTEMP(NumVerticesOverlap) = state.dataSolarShading->HCX(N1, N);
    3756            0 :         state.dataSolarShading->YTEMP(NumVerticesOverlap) = state.dataSolarShading->HCY(N1, N);
    3757              :     }
    3758            0 : }
    3759              : 
    3760            0 : void INTCPT(EnergyPlusData &state,
    3761              :             int const NV1, // Number of vertices of figure NS1
    3762              :             int const NV2, // Number of vertices of figure NS2
    3763              :             int &NV3,      // Number of vertices of figure NS3
    3764              :             int const NS1, // Number of the figure being overlapped
    3765              :             int const NS2  // Number of the figure doing overlapping
    3766              : )
    3767              : {
    3768              : 
    3769              :     // SUBROUTINE INFORMATION:
    3770              :     //       AUTHOR         Legacy Code
    3771              :     //       DATE WRITTEN
    3772              :     //       MODIFIED       na
    3773              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    3774              : 
    3775              :     // PURPOSE OF THIS SUBROUTINE:
    3776              :     // This subroutine determines all intercepts between the sides of figure NS1
    3777              :     // and the sides of figure NS2.
    3778              : 
    3779              :     // METHODOLOGY EMPLOYED:
    3780              :     // The requirements for intersection are that the end points of
    3781              :     // line N lie on both sides of line M and vice versa.  Also
    3782              :     // eliminate cases where the end point of one line lies exactly
    3783              :     // on the other to reduce duplication with the enclosed points.
    3784              : 
    3785              :     // REFERENCES:
    3786              :     // BLAST/IBLAST code, original author George Walton
    3787              : 
    3788              :     Real64 W;        // Normalization factor
    3789              :     Real64 XUntrunc; // Untruncated X coordinate
    3790              :     Real64 YUntrunc; // Untruncated Y coordinate
    3791              :     Int64 I1;        // Intermediate result for testing intersection
    3792              :     Int64 I2;        // Intermediate result for testing intersection
    3793              :     int K;
    3794              :     int KK;
    3795              :     int M; // Side number of figure NS2
    3796              :     int N; // Side number of figure NS1
    3797              : 
    3798            0 :     for (N = 1; N <= NV1; ++N) {
    3799            0 :         for (M = 1; M <= NV2; ++M) {
    3800              : 
    3801              :             // Eliminate cases where sides N and M do not intersect.
    3802              : 
    3803            0 :             I1 = state.dataSolarShading->HCA(NS1, N) * state.dataSolarShading->HCX(NS2, M) +
    3804            0 :                  state.dataSolarShading->HCB(NS1, N) * state.dataSolarShading->HCY(NS2, M) + state.dataSolarShading->HCC(NS1, N);
    3805            0 :             I2 = state.dataSolarShading->HCA(NS1, N) * state.dataSolarShading->HCX(NS2, M + 1) +
    3806            0 :                  state.dataSolarShading->HCB(NS1, N) * state.dataSolarShading->HCY(NS2, M + 1) + state.dataSolarShading->HCC(NS1, N);
    3807            0 :             if (I1 >= 0 && I2 >= 0) continue;
    3808            0 :             if (I1 <= 0 && I2 <= 0) continue;
    3809              : 
    3810            0 :             I1 = state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCX(NS1, N) +
    3811            0 :                  state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCY(NS1, N) + state.dataSolarShading->HCC(NS2, M);
    3812            0 :             I2 = state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCX(NS1, N + 1) +
    3813            0 :                  state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCY(NS1, N + 1) + state.dataSolarShading->HCC(NS2, M);
    3814            0 :             if (I1 >= 0 && I2 >= 0) continue;
    3815            0 :             if (I1 <= 0 && I2 <= 0) continue;
    3816              : 
    3817              :             // Determine the point of intersection and record in the temporary array.
    3818              : 
    3819            0 :             KK = NV3;
    3820            0 :             ++NV3;
    3821            0 :             W = state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCA(NS1, N) -
    3822            0 :                 state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCB(NS1, N);
    3823            0 :             XUntrunc = (state.dataSolarShading->HCC(NS2, M) * state.dataSolarShading->HCB(NS1, N) -
    3824            0 :                         state.dataSolarShading->HCB(NS2, M) * state.dataSolarShading->HCC(NS1, N)) /
    3825              :                        W;
    3826            0 :             YUntrunc = (state.dataSolarShading->HCA(NS2, M) * state.dataSolarShading->HCC(NS1, N) -
    3827            0 :                         state.dataSolarShading->HCC(NS2, M) * state.dataSolarShading->HCA(NS1, N)) /
    3828              :                        W;
    3829            0 :             if (NV3 > isize(state.dataSolarShading->XTEMP)) {
    3830            0 :                 state.dataSolarShading->XTEMP.redimension(isize(state.dataSolarShading->XTEMP) + 10, 0.0);
    3831            0 :                 state.dataSolarShading->YTEMP.redimension(isize(state.dataSolarShading->YTEMP) + 10, 0.0);
    3832              :             }
    3833            0 :             state.dataSolarShading->XTEMP(NV3) = nint64(XUntrunc);
    3834            0 :             state.dataSolarShading->YTEMP(NV3) = nint64(YUntrunc);
    3835              : 
    3836              :             // Eliminate near-duplicate points.
    3837              : 
    3838            0 :             if (KK != 0) {
    3839            0 :                 Real64 const x(state.dataSolarShading->XTEMP(NV3));
    3840            0 :                 Real64 const y(state.dataSolarShading->YTEMP(NV3));
    3841            0 :                 for (K = 1; K <= KK; ++K) {
    3842            0 :                     if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
    3843            0 :                     if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
    3844            0 :                     NV3 = KK;
    3845            0 :                     break; // K DO loop
    3846              :                 }
    3847              :             }
    3848              :         }
    3849              :     }
    3850            0 : }
    3851              : 
    3852         2349 : inline bool neq(Real64 a, Real64 b)
    3853              : {
    3854         2349 :     return std::abs(a - b) > 2.0;
    3855              : }
    3856              : 
    3857         3486 : inline bool d_eq(Real64 a, Real64 b)
    3858              : {
    3859         3486 :     return std::abs(a - b) < 2.0;
    3860              : }
    3861              : 
    3862          737 : void CLIPLINE(Real64 &x0, Real64 &x1, Real64 &y0, Real64 &y1, Real64 maxX, Real64 minX, Real64 maxY, Real64 minY, bool &visible)
    3863              : {
    3864              : 
    3865              :     // Line segment clipping
    3866              :     // Reference:
    3867              :     // Liang, Y.D., Barsky, B.A., Slater, M.
    3868              :     // 2D line and polygon clipping based on space subdivision.
    3869              :     // The Visual Computer 10, 407–422 (1994).
    3870              : 
    3871              :     // Tweaked via microbenchmarking to improve efficiency
    3872              : 
    3873          737 :     bool rev = false;
    3874          737 :     if (x0 > x1) { // reverse for efficiency
    3875          311 :         std::swap(x0, x1);
    3876          311 :         std::swap(y0, y1);
    3877          311 :         rev = true;
    3878              :     }
    3879              : 
    3880          737 :     if (x0 > maxX || x1 < minX) {
    3881              :         // Both points are outside the clip window, so they can't cross it
    3882           52 :         return;
    3883              :     }
    3884              : 
    3885              :     // defining variables
    3886          685 :     Real64 const dx = x1 - x0; // >= 0
    3887          685 :     Real64 const dy = y1 - y0;
    3888              : 
    3889          685 :     Real64 const q1 = x0 - minX;
    3890          685 :     Real64 const q2 = maxX - x0;
    3891          685 :     Real64 const q3 = y0 - minY;
    3892          685 :     Real64 const q4 = maxY - y0;
    3893              : 
    3894          685 :     Real64 u1 = 0;
    3895          685 :     Real64 u2 = 1;
    3896              : 
    3897          685 :     if ((dx == 0 && (q1 < 0 || q2 < 0)) || (dy == 0 && (q3 < 0 || q4 < 0))) {
    3898              :         // Line is parallel to clipping window
    3899           98 :         return;
    3900              :     }
    3901          587 :     if (dx != 0) {
    3902          520 :         Real64 const r1 = q1 / -dx;
    3903          520 :         if (r1 > u1) {
    3904          138 :             u1 = r1;
    3905              :         }
    3906          520 :         Real64 const r2 = q2 / dx;
    3907          520 :         if (r2 < u2) {
    3908          136 :             u2 = r2;
    3909              :         }
    3910              :     }
    3911          587 :     if (dy != 0) {
    3912          341 :         Real64 const r3 = q3 / -dy;
    3913          341 :         Real64 const r4 = q4 / dy;
    3914          341 :         if (dy > 0) {
    3915          173 :             if (r3 > u1) {
    3916           54 :                 u1 = r3;
    3917              :             }
    3918          173 :             if (r4 < u2) {
    3919           16 :                 u2 = r4;
    3920              :             }
    3921              :         } else {
    3922          168 :             if (r4 > u1) {
    3923           16 :                 u1 = r4;
    3924              :             }
    3925          168 :             if (r3 < u2) {
    3926           55 :                 u2 = r3;
    3927              :             }
    3928              :         }
    3929              :     }
    3930              : 
    3931          587 :     if (u1 > u2) { // reject
    3932              :         // Line is outside the clipping window
    3933            4 :         return;
    3934              :     }
    3935              : 
    3936          583 :     visible = true;
    3937              : 
    3938          583 :     Real64 const xn0 = x0 + dx * u1;
    3939          583 :     Real64 const yn0 = y0 + dy * u1;
    3940              : 
    3941          583 :     Real64 const xn1 = x0 + dx * u2;
    3942          583 :     Real64 const yn1 = y0 + dy * u2;
    3943              : 
    3944          583 :     if (rev) {
    3945          229 :         x0 = xn1;
    3946          229 :         y0 = yn1;
    3947          229 :         x1 = xn0;
    3948          229 :         y1 = yn0;
    3949              :     } else {
    3950          354 :         x0 = xn0;
    3951          354 :         y0 = yn0;
    3952          354 :         x1 = xn1;
    3953          354 :         y1 = yn1;
    3954              :     }
    3955              : }
    3956              : 
    3957          157 : void CLIPRECT(EnergyPlusData &state, int const NS2, int const NV1, int &NV3)
    3958              : {
    3959              :     // Polygon clipping by line segment clipping for rectangles
    3960              :     // Reference:
    3961              :     // Slater, M., Barsky, B.A.
    3962              :     // 2D line and polygon clipping based on space subdivision.
    3963              :     // The Visual Computer 10, 407–422 (1994).
    3964          157 :     bool INTFLAG = false;
    3965          157 :     int l = state.dataSolarShading->HCA.index(NS2, 1);
    3966              :     Real64 maxX, minX, maxY, minY;
    3967          157 :     if (state.dataSolarShading->HCX[l] > state.dataSolarShading->HCX[l + 2]) {
    3968          157 :         maxX = state.dataSolarShading->HCX[l];
    3969          157 :         minX = state.dataSolarShading->HCX[l + 2];
    3970              :     } else {
    3971            0 :         maxX = state.dataSolarShading->HCX[l + 2];
    3972            0 :         minX = state.dataSolarShading->HCX[l];
    3973              :     }
    3974          157 :     if (state.dataSolarShading->HCY[l] > state.dataSolarShading->HCY[l + 2]) {
    3975          157 :         maxY = state.dataSolarShading->HCY[l];
    3976          157 :         minY = state.dataSolarShading->HCY[l + 2];
    3977              :     } else {
    3978            0 :         maxY = state.dataSolarShading->HCY[l + 2];
    3979            0 :         minY = state.dataSolarShading->HCY[l];
    3980              :     }
    3981              : 
    3982              :     Real64 arrx[20]; // Temp array for output X
    3983              :     Real64 arry[20]; // Temp array for output Y
    3984          157 :     int arrc = 0;    // Number of items in output
    3985              : 
    3986          797 :     for (int j = 0; j < NV1; ++j) {
    3987          640 :         Real64 x_1 = state.dataSolarShading->XTEMP[j];
    3988          640 :         Real64 y_1 = state.dataSolarShading->YTEMP[j];
    3989          640 :         Real64 x_2 = state.dataSolarShading->XTEMP[(j + 1) % NV1];
    3990          640 :         Real64 y_2 = state.dataSolarShading->YTEMP[(j + 1) % NV1];
    3991          640 :         Real64 x1 = x_1, x2 = x_2, y1 = y_1, y2 = y_2;
    3992              : 
    3993          640 :         bool visible = false;
    3994          640 :         CLIPLINE(x_1, x_2, y_1, y_2, maxX, minX, maxY, minY, visible);
    3995          640 :         if (visible) {
    3996          514 :             if ((x_1 != x1 || y_1 != y1) || (x_2 != x2 || y_2 != y2)) {
    3997          274 :                 INTFLAG = true;
    3998              :             }
    3999              :             // if line on edge, or inside, add both points
    4000          514 :             if (arrc == 0 || ((neq(arrx[arrc - 1], x_1) || neq(arry[arrc - 1], y_1)) && (neq(arrx[0], x_1) || neq(arry[0], y_1)))) {
    4001          213 :                 arrx[arrc] = x_1;
    4002          213 :                 arry[arrc] = y_1;
    4003          213 :                 arrc += 1;
    4004          213 :                 if ((neq(x_1, x_2) || neq(y_1, y_2)) && (neq(arrx[0], x_2) || neq(arry[0], y_2))) {
    4005          183 :                     arrx[arrc] = x_2;
    4006          183 :                     arry[arrc] = y_2;
    4007          183 :                     arrc += 1;
    4008              :                 }
    4009          301 :             } else if ((neq(arrx[arrc - 1], x_2) || neq(arry[arrc - 1], y_2)) && (neq(arrx[0], x_2) || neq(arry[0], y_2))) {
    4010          136 :                 arrx[arrc] = x_2;
    4011          136 :                 arry[arrc] = y_2;
    4012          136 :                 arrc += 1;
    4013              :             }
    4014              :         }
    4015              :     }
    4016          157 :     NV3 = arrc;
    4017              : 
    4018              :     // Re-populate XTEMP/YTEMP
    4019          157 :     if (NV3 > 1) {
    4020          147 :         int LastEdgeIndex = -1, incr = 0;
    4021          147 :         double cornerXs[4] = {minX, minX, maxX, maxX};
    4022          147 :         double cornerYs[4] = {minY, maxY, maxY, minY};
    4023          147 :         Real64 edges[4] = {minX, maxY, maxX, minY};
    4024              :         Real64 LastEdgeX, LastEdgeY;
    4025          826 :         for (int i = 0; i <= arrc; i++) {
    4026          679 :             int k = i % arrc;
    4027              : 
    4028          679 :             Real64 currX = arrx[k], currY = arry[k];
    4029              : 
    4030          679 :             int edgeCount = 0, EdgeIndex = -1;
    4031         3395 :             for (int m = 0; m < 4; m++) {
    4032         2716 :                 if (m % 2 == 0 && d_eq(currX, edges[m])) { // MinX or MaxX
    4033          486 :                     edgeCount++;
    4034          486 :                     EdgeIndex = m;
    4035         2230 :                 } else if (m % 2 == 1 && d_eq(currY, edges[m])) {
    4036          501 :                     edgeCount++;
    4037          501 :                     EdgeIndex = m;
    4038              :                 }
    4039              :             }
    4040          679 :             if (edgeCount == 0) { // On inside
    4041           77 :                 if (i != arrc) {
    4042           77 :                     state.dataSolarShading->XTEMP[incr] = currX;
    4043           77 :                     state.dataSolarShading->YTEMP[incr] = currY;
    4044           77 :                     incr++;
    4045              :                 }
    4046           77 :                 continue;
    4047          602 :             } else if (edgeCount > 1) { // On corner
    4048          385 :                 if (d_eq(currX, minX)) {
    4049          250 :                     if (d_eq(currY, minY)) {
    4050            8 :                         EdgeIndex = 3;
    4051              :                     } else {
    4052          242 :                         EdgeIndex = 0;
    4053              :                     }
    4054              :                 } else {
    4055          135 :                     if (d_eq(currY, maxY)) {
    4056          131 :                         EdgeIndex = 1;
    4057              :                     } else {
    4058            4 :                         EdgeIndex = 2;
    4059              :                     }
    4060              :                 }
    4061              :             }
    4062          602 :             if ((LastEdgeIndex > -1 && EdgeIndex > -1) && LastEdgeIndex != EdgeIndex) {
    4063          386 :                 int jumpCount = 0;
    4064          386 :                 if ((EdgeIndex == 0 && LastEdgeIndex == 3) || (EdgeIndex - LastEdgeIndex == 1)) {
    4065          237 :                     jumpCount = 1;
    4066          149 :                 } else if (EdgeIndex % 2 == LastEdgeIndex % 2) {
    4067              :                     // Clockwise double jump
    4068          112 :                     jumpCount = 2;
    4069           37 :                 } else if ((EdgeIndex == 3 && LastEdgeIndex == 0) || (LastEdgeIndex - EdgeIndex == 1)) {
    4070              :                     // Clockwise triple jump
    4071           37 :                     jumpCount = 3;
    4072              :                 }
    4073          386 :                 if (jumpCount > 0) {
    4074              :                     Real64 cornerX;
    4075              :                     Real64 cornerY;
    4076          386 :                     int startIndex = (LastEdgeIndex + 1) % 4;
    4077          386 :                     int added = 0;
    4078          958 :                     for (int i1 = startIndex, j1 = 0; j1 < jumpCount; i1 = (i1 + 1) % 4, j1++) {
    4079          572 :                         cornerX = cornerXs[i1];
    4080          572 :                         cornerY = cornerYs[i1];
    4081          572 :                         if (cornerX == LastEdgeX && cornerY == LastEdgeY) continue; // skip if jump started on corner
    4082              : 
    4083          308 :                         bool insideFlag = true;
    4084          979 :                         for (int j = 0; j < NV1; ++j) {
    4085          921 :                             if ((state.dataSolarShading->ATEMP[j] * cornerX) + (cornerY * state.dataSolarShading->BTEMP[j]) +
    4086          921 :                                     state.dataSolarShading->CTEMP[j] >
    4087              :                                 0.0) {
    4088          250 :                                 insideFlag = false;
    4089          250 :                                 break;
    4090              :                             }
    4091              :                         }
    4092              : 
    4093          366 :                         if (insideFlag &&
    4094           58 :                             (incr == 0 ||
    4095          144 :                              ((neq(cornerX, state.dataSolarShading->XTEMP[incr - 1]) || neq(cornerY, state.dataSolarShading->YTEMP[incr - 1])) &&
    4096           84 :                               (neq(cornerX, state.dataSolarShading->XTEMP[0]) || neq(cornerY, state.dataSolarShading->YTEMP[0]))))) {
    4097           56 :                             state.dataSolarShading->XTEMP[incr] = cornerX;
    4098           56 :                             state.dataSolarShading->YTEMP[incr] = cornerY;
    4099           56 :                             incr++;
    4100           56 :                             added++;
    4101              :                         }
    4102              :                     }
    4103          386 :                     if (jumpCount > 2 && (added == jumpCount && edgeCount == 1)) {
    4104            0 :                         if (i != arrc) {
    4105            0 :                             state.dataSolarShading->XTEMP[incr] = currX;
    4106            0 :                             state.dataSolarShading->YTEMP[incr] = currY;
    4107            0 :                             incr++;
    4108              :                         }
    4109            0 :                         break;
    4110              :                     }
    4111              :                 }
    4112              :             }
    4113          602 :             if (i != arrc) {
    4114          455 :                 state.dataSolarShading->XTEMP[incr] = currX;
    4115          455 :                 state.dataSolarShading->YTEMP[incr] = currY;
    4116          455 :                 incr++;
    4117              :             }
    4118          602 :             LastEdgeIndex = EdgeIndex;
    4119          602 :             LastEdgeX = currX;
    4120          602 :             LastEdgeY = currY;
    4121              :         }
    4122          147 :         NV3 = incr;
    4123              : 
    4124              :     } else {
    4125           10 :         if (NV3 == 1) {
    4126            0 :             state.dataSolarShading->XTEMP[0] = arrx[0];
    4127            0 :             state.dataSolarShading->YTEMP[0] = arry[0];
    4128              :         }
    4129           10 :         if (NV3 == 0) {
    4130           10 :             double cornerXs[4] = {minX, minX, maxX, maxX};
    4131           10 :             double cornerYs[4] = {minY, maxY, maxY, minY};
    4132           10 :             Real64 cornerX = cornerXs[0];
    4133           10 :             Real64 cornerY = cornerYs[0];
    4134           10 :             bool insideFlag = true;
    4135           50 :             for (int j = 0; j < NV1; ++j) {
    4136           40 :                 if ((state.dataSolarShading->ATEMP[j] * cornerX) + (cornerY * state.dataSolarShading->BTEMP[j]) + state.dataSolarShading->CTEMP[j] >=
    4137              :                     0.0) {
    4138            0 :                     insideFlag = false;
    4139            0 :                     break;
    4140              :                 }
    4141              :             }
    4142           10 :             if (insideFlag) {
    4143           50 :                 for (int i1 = 0; i1 < 4; i1++) {
    4144           40 :                     state.dataSolarShading->XTEMP[i1] = cornerXs[i1];
    4145           40 :                     state.dataSolarShading->YTEMP[i1] = cornerYs[i1];
    4146              :                 }
    4147           10 :                 NV3 = 4;
    4148           10 :                 INTFLAG = true;
    4149              :             }
    4150              :         }
    4151              :     }
    4152              : 
    4153              :     // update homogeneous edges A,B,C
    4154          157 :     if (NV3 > 0) {
    4155          157 :         Real64 const X_0(state.dataSolarShading->XTEMP[0]);
    4156          157 :         Real64 const Y_0(state.dataSolarShading->YTEMP[0]);
    4157          157 :         Real64 XP_0 = X_0, XP_1;
    4158          157 :         Real64 YP_0 = Y_0, YP_1;
    4159          628 :         for (int P = 0; P < NV3 - 1; ++P) {
    4160          471 :             XP_1 = state.dataSolarShading->XTEMP[P + 1];
    4161          471 :             YP_1 = state.dataSolarShading->YTEMP[P + 1];
    4162              : 
    4163          471 :             state.dataSolarShading->ATEMP[P] = YP_0 - YP_1;
    4164          471 :             state.dataSolarShading->BTEMP[P] = XP_1 - XP_0;
    4165          471 :             state.dataSolarShading->CTEMP[P] = XP_0 * YP_1 - YP_0 * XP_1;
    4166          471 :             XP_0 = XP_1;
    4167          471 :             YP_0 = YP_1;
    4168              :         }
    4169              : 
    4170          157 :         state.dataSolarShading->ATEMP[NV3 - 1] = YP_1 - Y_0;
    4171          157 :         state.dataSolarShading->BTEMP[NV3 - 1] = X_0 - XP_1;
    4172          157 :         state.dataSolarShading->CTEMP[NV3 - 1] = XP_1 * Y_0 - YP_1 * X_0;
    4173              :     }
    4174              : 
    4175              :     // Determine overlap status
    4176          157 :     if (NV3 < 3) { // Determine overlap status
    4177            0 :         state.dataSolarShading->OverlapStatus = NoOverlap;
    4178          157 :     } else if (!INTFLAG) {
    4179           12 :         state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
    4180              :     }
    4181          157 : }
    4182              : 
    4183        20917 : void CLIPPOLY(EnergyPlusData &state,
    4184              :               int const NS1, // Figure number of figure 1 (The subject polygon)
    4185              :               int const NS2, // Figure number of figure 2 (The clipping polygon)
    4186              :               int const NV1, // Number of vertices of figure 1
    4187              :               int const NV2, // Number of vertices of figure 2
    4188              :               int &NV3       // Number of vertices of figure 3
    4189              : )
    4190              : {
    4191              : 
    4192              :     // SUBROUTINE INFORMATION:
    4193              :     //       AUTHOR         Tyler Hoyt
    4194              :     //       DATE WRITTEN   May 4, 2010
    4195              :     //       MODIFIED       na
    4196              :     //       RE-ENGINEERED  na
    4197              : 
    4198              :     // PURPOSE OF THIS SUBROUTINE:
    4199              :     // Populate global arrays XTEMP and YTEMP with the vertices
    4200              :     // of the overlap between NS1 and NS2, and determine relevant
    4201              :     // overlap status.
    4202              : 
    4203              :     // METHODOLOGY EMPLOYED:
    4204              :     // The Sutherland-Hodgman algorithm for polygon clipping is employed.
    4205              : 
    4206              :     using General::SafeDivide;
    4207              : 
    4208              :     typedef Array2D<Int64>::size_type size_type;
    4209              :     bool INTFLAG; // For overlap status
    4210              :     int S;        // Test vertex
    4211              :     int KK;       // Duplicate test index
    4212              :     int NVOUT;    // Current output length for loops
    4213              :     int NVTEMP;
    4214              : 
    4215              :     Real64 W; // Normalization factor
    4216              :     Real64 HFunct;
    4217              : 
    4218        20917 :     auto &s_surf = state.dataSurface;
    4219              : 
    4220              : #ifdef EP_Count_Calls
    4221              :     ++state.dataTimingsData->NumClipPoly_Calls;
    4222              : #endif
    4223              :     // Tuned Linear indexing
    4224              : 
    4225        20917 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    4226        20917 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    4227        20917 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
    4228        20917 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
    4229              : 
    4230              :     // Populate the arrays with the original polygon
    4231       104901 :     for (size_type j = 0, l = state.dataSolarShading->HCX.index(NS1, 1), e = NV1; j < e; ++j, ++l) {
    4232        83984 :         state.dataSolarShading->XTEMP[j] = state.dataSolarShading->HCX[l]; // [ l ] == ( NS1, j+1 )
    4233        83984 :         state.dataSolarShading->YTEMP[j] = state.dataSolarShading->HCY[l];
    4234        83984 :         state.dataSolarShading->ATEMP[j] = state.dataSolarShading->HCA[l];
    4235        83984 :         state.dataSolarShading->BTEMP[j] = state.dataSolarShading->HCB[l];
    4236        83984 :         state.dataSolarShading->CTEMP[j] = state.dataSolarShading->HCC[l];
    4237              :     }
    4238              : 
    4239        20917 :     NVOUT = NV1; // First point-loop is the length of the subject polygon.
    4240        20917 :     INTFLAG = false;
    4241        20917 :     NVTEMP = 0;
    4242        20917 :     KK = 0;
    4243              : 
    4244              :     // Check if clipping polygon is rectangle
    4245        20917 :     if (state.dataSysVars->SlaterBarsky) {
    4246          422 :         int l1 = state.dataSolarShading->HCA.index(NS2, 1);
    4247          844 :         bool rectFlag = ((NV2 == 4) && (((((state.dataSolarShading->HCX[l1] == state.dataSolarShading->HCX[l1 + 1] &&
    4248          157 :                                             state.dataSolarShading->HCY[l1] != state.dataSolarShading->HCY[l1 + 1]) &&
    4249          157 :                                            ((state.dataSolarShading->HCY[l1 + 2] == state.dataSolarShading->HCY[l1 + 1] &&
    4250          157 :                                              state.dataSolarShading->HCY[l1 + 3] == state.dataSolarShading->HCY[l1]))) &&
    4251          157 :                                           state.dataSolarShading->HCX[l1 + 2] == state.dataSolarShading->HCX[l1 + 3]) ||
    4252          265 :                                          ((((state.dataSolarShading->HCY[l1] == state.dataSolarShading->HCY[l1 + 1] &&
    4253           24 :                                              state.dataSolarShading->HCX[l1] != state.dataSolarShading->HCX[l1 + 1]) &&
    4254           24 :                                             (state.dataSolarShading->HCX[l1 + 2] == state.dataSolarShading->HCX[l1 + 1] &&
    4255            0 :                                              state.dataSolarShading->HCX[l1 + 3] == state.dataSolarShading->HCX[l1])) &&
    4256            0 :                                            (state.dataSolarShading->HCY[l1 + 2] == state.dataSolarShading->HCY[l1 + 3]))))));
    4257          422 :         if (rectFlag) {
    4258          157 :             CLIPRECT(state, NS2, NV1, NV3);
    4259          157 :             return;
    4260              :         }
    4261              :     }
    4262              : 
    4263        20760 :     int l = state.dataSolarShading->HCA.index(NS2, 1);
    4264        88491 :     for (int E = 1; E <= NV2; ++E, ++l) { // Loop over edges of the clipping polygon
    4265       377790 :         for (int P = 1; P <= NVOUT; ++P) {
    4266       304257 :             state.dataSolarShading->XTEMP1(P) = state.dataSolarShading->XTEMP(P);
    4267       304257 :             state.dataSolarShading->YTEMP1(P) = state.dataSolarShading->YTEMP(P);
    4268              :         }
    4269        73533 :         S = NVOUT;
    4270        73533 :         Real64 const HCA_E(state.dataSolarShading->HCA[l]);
    4271        73533 :         Real64 const HCB_E(state.dataSolarShading->HCB[l]);
    4272        73533 :         Real64 const HCC_E(state.dataSolarShading->HCC[l]);
    4273        73533 :         Real64 XTEMP1_S(state.dataSolarShading->XTEMP1(S));
    4274        73533 :         Real64 YTEMP1_S(state.dataSolarShading->YTEMP1(S));
    4275       377790 :         for (int P = 1; P <= NVOUT; ++P) {
    4276       304257 :             Real64 const XTEMP1_P(state.dataSolarShading->XTEMP1(P));
    4277       304257 :             Real64 const YTEMP1_P(state.dataSolarShading->YTEMP1(P));
    4278       304257 :             HFunct = XTEMP1_P * HCA_E + YTEMP1_P * HCB_E + HCC_E;
    4279              :             // S is constant within this block
    4280       304257 :             if (HFunct <= 0.0) { // Vertex is not in the clipping plane
    4281       222766 :                 HFunct = XTEMP1_S * HCA_E + YTEMP1_S * HCB_E + HCC_E;
    4282       222766 :                 if (HFunct > 0.0) { // Test vertex is in the clipping plane
    4283              : 
    4284              :                     // Find/store the intersection of the clip edge and the line connecting S and P
    4285        30580 :                     KK = NVTEMP;
    4286        30580 :                     ++NVTEMP;
    4287        30580 :                     Real64 const ATEMP_S(state.dataSolarShading->ATEMP(S));
    4288        30580 :                     Real64 const BTEMP_S(state.dataSolarShading->BTEMP(S));
    4289        30580 :                     Real64 const CTEMP_S(state.dataSolarShading->CTEMP(S));
    4290        30580 :                     W = HCB_E * ATEMP_S - HCA_E * BTEMP_S;
    4291        30580 :                     if (W != 0.0) {
    4292        30580 :                         Real64 const W_inv(1.0 / W);
    4293        30580 :                         state.dataSolarShading->XTEMP(NVTEMP) = nint64((HCC_E * BTEMP_S - HCB_E * CTEMP_S) * W_inv);
    4294        30580 :                         state.dataSolarShading->YTEMP(NVTEMP) = nint64((HCA_E * CTEMP_S - HCC_E * ATEMP_S) * W_inv);
    4295              :                     } else {
    4296            0 :                         state.dataSolarShading->XTEMP(NVTEMP) = SafeDivide(HCC_E * BTEMP_S - HCB_E * CTEMP_S, W);
    4297            0 :                         state.dataSolarShading->YTEMP(NVTEMP) = SafeDivide(HCA_E * CTEMP_S - HCC_E * ATEMP_S, W);
    4298              :                     }
    4299        30580 :                     INTFLAG = true;
    4300              : 
    4301        30580 :                     if (E == NV2) { // Remove near-duplicates on last edge
    4302         6024 :                         if (KK != 0) {
    4303         3585 :                             Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
    4304         3585 :                             Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
    4305         8189 :                             for (int K = 1; K <= KK; ++K) {
    4306         4604 :                                 if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
    4307          141 :                                 if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
    4308            0 :                                 NVTEMP = KK;
    4309            0 :                                 break; // K loop
    4310              :                             }
    4311              :                         }
    4312              :                     }
    4313              :                 }
    4314              : 
    4315       222766 :                 KK = NVTEMP;
    4316       222766 :                 ++NVTEMP;
    4317       222766 :                 if (NVTEMP > state.dataSolarShading->MAXHCArrayBounds) {
    4318            0 :                     int const NewArrayBounds(state.dataSolarShading->MAXHCArrayBounds + state.dataSolarShading->MAXHCArrayIncrement);
    4319            0 :                     state.dataSolarShading->XTEMP.redimension(NewArrayBounds, 0.0);
    4320            0 :                     state.dataSolarShading->YTEMP.redimension(NewArrayBounds, 0.0);
    4321            0 :                     state.dataSolarShading->XTEMP1.redimension(NewArrayBounds, 0.0);
    4322            0 :                     state.dataSolarShading->YTEMP1.redimension(NewArrayBounds, 0.0);
    4323            0 :                     state.dataSolarShading->ATEMP.redimension(NewArrayBounds, 0.0);
    4324            0 :                     state.dataSolarShading->BTEMP.redimension(NewArrayBounds, 0.0);
    4325            0 :                     state.dataSolarShading->CTEMP.redimension(NewArrayBounds, 0.0);
    4326            0 :                     state.dataSolarShading->MAXHCArrayBounds = NewArrayBounds;
    4327              :                 }
    4328              : 
    4329       222766 :                 state.dataSolarShading->XTEMP(NVTEMP) = XTEMP1_P;
    4330       222766 :                 state.dataSolarShading->YTEMP(NVTEMP) = YTEMP1_P;
    4331              : 
    4332       222766 :                 if (E == NV2) { // Remove near-duplicates on last edge
    4333        50965 :                     if (KK != 0) {
    4334        41120 :                         Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
    4335        41120 :                         Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
    4336       120257 :                         for (int K = 1; K <= KK; ++K) {
    4337        83665 :                             if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
    4338        21028 :                             if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
    4339         4528 :                             NVTEMP = KK;
    4340         4528 :                             break; // K loop
    4341              :                         }
    4342              :                     }
    4343              :                 }
    4344              : 
    4345              :             } else {
    4346        81491 :                 HFunct = XTEMP1_S * HCA_E + YTEMP1_S * HCB_E + HCC_E;
    4347        81491 :                 if (HFunct <= 0.0) {                                        // Test vertex is not in the clipping plane
    4348        30580 :                     if (NVTEMP < 2 * (s_surf->MaxVerticesPerSurface + 1)) { // avoid assigning to element outside of XTEMP array size
    4349        30580 :                         KK = NVTEMP;
    4350        30580 :                         ++NVTEMP;
    4351        30580 :                         Real64 const ATEMP_S(state.dataSolarShading->ATEMP(S));
    4352        30580 :                         Real64 const BTEMP_S(state.dataSolarShading->BTEMP(S));
    4353        30580 :                         Real64 const CTEMP_S(state.dataSolarShading->CTEMP(S));
    4354        30580 :                         W = HCB_E * ATEMP_S - HCA_E * BTEMP_S;
    4355        30580 :                         if (W != 0.0) {
    4356        30580 :                             Real64 const W_inv(1.0 / W);
    4357        30580 :                             state.dataSolarShading->XTEMP(NVTEMP) = nint64((HCC_E * BTEMP_S - HCB_E * CTEMP_S) * W_inv);
    4358        30580 :                             state.dataSolarShading->YTEMP(NVTEMP) = nint64((HCA_E * CTEMP_S - HCC_E * ATEMP_S) * W_inv);
    4359              :                         } else {
    4360            0 :                             state.dataSolarShading->XTEMP(NVTEMP) = SafeDivide(HCC_E * BTEMP_S - HCB_E * CTEMP_S, W);
    4361            0 :                             state.dataSolarShading->YTEMP(NVTEMP) = SafeDivide(HCA_E * CTEMP_S - HCC_E * ATEMP_S, W);
    4362              :                         }
    4363        30580 :                         INTFLAG = true;
    4364              : 
    4365        30580 :                         if (E == NV2) { // Remove near-duplicates on last edge
    4366         6024 :                             if (KK != 0) {
    4367         3350 :                                 Real64 const x(state.dataSolarShading->XTEMP(NVTEMP));
    4368         3350 :                                 Real64 const y(state.dataSolarShading->YTEMP(NVTEMP));
    4369        11212 :                                 for (int K = 1; K <= KK; ++K) {
    4370         8062 :                                     if (std::abs(x - state.dataSolarShading->XTEMP(K)) > 2.0) continue;
    4371         1537 :                                     if (std::abs(y - state.dataSolarShading->YTEMP(K)) > 2.0) continue;
    4372          200 :                                     NVTEMP = KK;
    4373          200 :                                     break; // K loop
    4374              :                                 }
    4375              :                             }
    4376              :                         }
    4377              :                     }
    4378              :                 }
    4379              :             }
    4380       304257 :             S = P;
    4381       304257 :             XTEMP1_S = XTEMP1_P;
    4382       304257 :             YTEMP1_S = YTEMP1_P;
    4383              :         } // end loop over points of subject polygon
    4384              : 
    4385        73533 :         NVOUT = NVTEMP;
    4386        73533 :         if (NVOUT == 0) break; // Added to avoid array bounds violation of XTEMP1 and YTEMP1 and wasted looping
    4387        67731 :         NVTEMP = 0;
    4388              : 
    4389        67731 :         if (E != NV2) {
    4390        52773 :             if (NVOUT > 2) { // Compute HC values for edges of output polygon
    4391        52773 :                 Real64 const X_1(state.dataSolarShading->XTEMP(1));
    4392        52773 :                 Real64 const Y_1(state.dataSolarShading->YTEMP(1));
    4393        52773 :                 Real64 X_P(X_1), X_P1;
    4394        52773 :                 Real64 Y_P(Y_1), Y_P1;
    4395       220913 :                 for (int P = 1; P < NVOUT; ++P) {
    4396       168140 :                     X_P1 = state.dataSolarShading->XTEMP(P + 1);
    4397       168140 :                     Y_P1 = state.dataSolarShading->YTEMP(P + 1);
    4398       168140 :                     state.dataSolarShading->ATEMP(P) = Y_P - Y_P1;
    4399       168140 :                     state.dataSolarShading->BTEMP(P) = X_P1 - X_P;
    4400       168140 :                     state.dataSolarShading->CTEMP(P) = X_P * Y_P1 - Y_P * X_P1;
    4401       168140 :                     X_P = X_P1;
    4402       168140 :                     Y_P = Y_P1;
    4403              :                 }
    4404        52773 :                 state.dataSolarShading->ATEMP(NVOUT) = Y_P1 - Y_1;
    4405        52773 :                 state.dataSolarShading->BTEMP(NVOUT) = X_1 - X_P1;
    4406        52773 :                 state.dataSolarShading->CTEMP(NVOUT) = X_P1 * Y_1 - Y_P1 * X_1;
    4407              :             }
    4408              :         }
    4409              : 
    4410              :     } // end loop over edges in NS2
    4411              : 
    4412        20760 :     NV3 = NVOUT;
    4413              : 
    4414        20760 :     if (NV3 < 3) { // Determine overlap status
    4415         6406 :         state.dataSolarShading->OverlapStatus = NoOverlap;
    4416        14354 :     } else if (!INTFLAG) {
    4417         1557 :         state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
    4418              :     }
    4419              : }
    4420              : 
    4421         5346 : void MULTOL(EnergyPlusData &state,
    4422              :             int const NNN,   // argument
    4423              :             int const LOC0,  // Location in the homogeneous coordinate array
    4424              :             int const NRFIGS // Number of figures overlapped
    4425              : )
    4426              : {
    4427              : 
    4428              :     // SUBROUTINE INFORMATION:
    4429              :     //       AUTHOR         Legacy Code
    4430              :     //       DATE WRITTEN
    4431              :     //       MODIFIED       na
    4432              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    4433              : 
    4434              :     // PURPOSE OF THIS SUBROUTINE:
    4435              :     // This subroutine determines the overlaps of figure 'NS2' with previous figures
    4436              :     // 'LOC0+1' through 'LOC0+NRFIGS'.  For example, if NS2
    4437              :     // is a shadow, overlap with previous shadows.
    4438              : 
    4439              :     // REFERENCES:
    4440              :     // BLAST/IBLAST code, original author George Walton
    4441              : 
    4442              :     int I;   // Loop Control
    4443              :     int NS1; // Number of the figure being overlapped
    4444              :     int NS2; // Number of the figure doing overlapping
    4445              :     int NS3; // Location to place results of overlap
    4446              : 
    4447         5346 :     state.dataSolarShading->maxNumberOfFigures = max(state.dataSolarShading->maxNumberOfFigures, NRFIGS);
    4448              : 
    4449         5346 :     NS2 = NNN;
    4450        12252 :     for (I = 1; I <= NRFIGS; ++I) {
    4451         6906 :         NS1 = LOC0 + I;
    4452         6906 :         NS3 = state.dataSolarShading->LOCHCA + 1;
    4453              : 
    4454         6906 :         DeterminePolygonOverlap(state, NS1, NS2, NS3); // Find overlap of figure NS2 on figure NS1.
    4455              : 
    4456              :         // Process overlap cases:
    4457              : 
    4458         6906 :         if (state.dataSolarShading->OverlapStatus == NoOverlap) continue;
    4459              : 
    4460         5302 :         if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) break;
    4461              : 
    4462         5302 :         state.dataSolarShading->LOCHCA = NS3; // Increment h.c. arrays pointer.
    4463              :     }
    4464         5346 : }
    4465              : 
    4466            0 : void ORDER(EnergyPlusData &state,
    4467              :            int const NV3, // Number of vertices of figure NS3
    4468              :            int const NS3  // Location to place results of overlap
    4469              : )
    4470              : {
    4471              : 
    4472              :     // SUBROUTINE INFORMATION:
    4473              :     //       AUTHOR         Legacy Code
    4474              :     //       DATE WRITTEN
    4475              :     //       MODIFIED       na
    4476              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    4477              : 
    4478              :     // PURPOSE OF THIS SUBROUTINE:
    4479              :     // This subroutine sorts the vertices found by inclosure and
    4480              :     // intercept in to clockwise order so that the overlap polygon
    4481              :     // may be used in computing subsequent overlaps.
    4482              : 
    4483              :     // METHODOLOGY EMPLOYED:
    4484              :     // The slopes of the lines from the left-most vertex to all
    4485              :     // others are found.  The slopes are sorted into descending
    4486              :     // sequence.  This sequence puts the vertices in clockwise order.
    4487              : 
    4488              :     // REFERENCES:
    4489              :     // BLAST/IBLAST code, original author George Walton
    4490              : 
    4491              :     Real64 DELTAX; // Difference between X coordinates of two vertices
    4492              :     Real64 DELTAY; // Difference between Y coordinates of two vertices
    4493              :     Real64 SAVES;  // Temporary location for exchange of variables
    4494              :     Real64 SAVEX;  // Temporary location for exchange of variables
    4495              :     Real64 SAVEY;  // Temporary location for exchange of variables
    4496              :     Real64 XMIN;   // X coordinate of left-most vertex
    4497              :     Real64 YXMIN;
    4498              :     int I;   // Sort index
    4499              :     int IM1; // Sort control
    4500              :     int J;   // Sort index
    4501              :     int M;   // Number of slopes to be sorted
    4502              :     int N;   // Vertex number
    4503              :     int P;   // Location of first slope to be sorted
    4504              : 
    4505            0 :     auto &s_surf = state.dataSurface;
    4506              : 
    4507            0 :     if (state.dataSolarShading->ORDERFirstTimeFlag) {
    4508            0 :         state.dataSolarShading->SLOPE.allocate(max(10, s_surf->MaxVerticesPerSurface + 1));
    4509            0 :         state.dataSolarShading->ORDERFirstTimeFlag = false;
    4510              :     }
    4511              :     // Determine left-most vertex.
    4512              : 
    4513            0 :     XMIN = state.dataSolarShading->XTEMP(1);
    4514            0 :     YXMIN = state.dataSolarShading->YTEMP(1);
    4515            0 :     for (N = 2; N <= NV3; ++N) {
    4516            0 :         if (state.dataSolarShading->XTEMP(N) >= XMIN) continue;
    4517            0 :         XMIN = state.dataSolarShading->XTEMP(N);
    4518            0 :         YXMIN = state.dataSolarShading->YTEMP(N);
    4519              :     }
    4520              : 
    4521              :     // Determine slopes from left-most vertex to all others.  Identify
    4522              :     // first and second or last points as they occur.
    4523              : 
    4524            0 :     P = 1;
    4525            0 :     M = 0;
    4526            0 :     for (N = 1; N <= NV3; ++N) {
    4527              : 
    4528            0 :         DELTAX = state.dataSolarShading->XTEMP(N) - XMIN;
    4529            0 :         DELTAY = state.dataSolarShading->YTEMP(N) - YXMIN;
    4530              : 
    4531            0 :         if (std::abs(DELTAX) > 0.5) {
    4532              : 
    4533            0 :             ++M;
    4534            0 :             state.dataSolarShading->SLOPE(M) = DELTAY / DELTAX;
    4535            0 :             state.dataSolarShading->XTEMP(M) = state.dataSolarShading->XTEMP(N);
    4536            0 :             state.dataSolarShading->YTEMP(M) = state.dataSolarShading->YTEMP(N);
    4537              : 
    4538            0 :         } else if (DELTAY > 0.5) {
    4539              : 
    4540            0 :             P = 2;
    4541            0 :             state.dataSolarShading->HCX(NS3, 2) = nint64(state.dataSolarShading->XTEMP(N));
    4542            0 :             state.dataSolarShading->HCY(NS3, 2) = nint64(state.dataSolarShading->YTEMP(N));
    4543              : 
    4544            0 :         } else if (DELTAY < -0.5) {
    4545              : 
    4546            0 :             state.dataSolarShading->HCX(NS3, NV3) = nint64(state.dataSolarShading->XTEMP(N));
    4547            0 :             state.dataSolarShading->HCY(NS3, NV3) = nint64(state.dataSolarShading->YTEMP(N));
    4548              : 
    4549              :         } else {
    4550              : 
    4551            0 :             state.dataSolarShading->HCX(NS3, 1) = nint64(XMIN);
    4552            0 :             state.dataSolarShading->HCY(NS3, 1) = nint64(YXMIN);
    4553              :         }
    4554              :     }
    4555              : 
    4556              :     // Sequence the temporary arrays in order of decreasing slopes.(bubble sort)
    4557              : 
    4558            0 :     if (M != 1) {
    4559              : 
    4560            0 :         for (I = 2; I <= M; ++I) {
    4561            0 :             IM1 = I - 1;
    4562            0 :             for (J = 1; J <= IM1; ++J) {
    4563            0 :                 if (state.dataSolarShading->SLOPE(I) <= state.dataSolarShading->SLOPE(J)) continue;
    4564            0 :                 SAVEX = state.dataSolarShading->XTEMP(I);
    4565            0 :                 SAVEY = state.dataSolarShading->YTEMP(I);
    4566            0 :                 SAVES = state.dataSolarShading->SLOPE(I);
    4567            0 :                 state.dataSolarShading->XTEMP(I) = state.dataSolarShading->XTEMP(J);
    4568            0 :                 state.dataSolarShading->YTEMP(I) = state.dataSolarShading->YTEMP(J);
    4569            0 :                 state.dataSolarShading->SLOPE(I) = state.dataSolarShading->SLOPE(J);
    4570            0 :                 state.dataSolarShading->XTEMP(J) = SAVEX;
    4571            0 :                 state.dataSolarShading->YTEMP(J) = SAVEY;
    4572            0 :                 state.dataSolarShading->SLOPE(J) = SAVES;
    4573              :             }
    4574              :         }
    4575              :     }
    4576              : 
    4577              :     // Place sequenced points in the homogeneous coordinate arrays.
    4578              : 
    4579            0 :     for (N = 1; N <= M; ++N) {
    4580            0 :         state.dataSolarShading->HCX(NS3, N + P) = nint64(state.dataSolarShading->XTEMP(N));
    4581            0 :         state.dataSolarShading->HCY(NS3, N + P) = nint64(state.dataSolarShading->YTEMP(N));
    4582              :     }
    4583            0 : }
    4584              : 
    4585        20917 : void DeterminePolygonOverlap(EnergyPlusData &state,
    4586              :                              int const NS1, // Number of the figure being overlapped
    4587              :                              int const NS2, // Number of the figure doing overlapping
    4588              :                              int const NS3  // Location to place results of overlap
    4589              : )
    4590              : {
    4591              : 
    4592              :     // SUBROUTINE INFORMATION:
    4593              :     //       AUTHOR         Legacy Code
    4594              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    4595              : 
    4596              :     // PURPOSE OF THIS SUBROUTINE:
    4597              :     // This subroutine computes the possible overlap of two polygons.
    4598              :     // It uses homogeneous coordinate techniques to determine the overlap area
    4599              :     // between two convex polygons.  Results are stored in the homogeneous coordinate (HC) arrays.
    4600              : 
    4601              :     // METHODOLOGY EMPLOYED:
    4602              :     // The vertices defining the overlap between fig.1 and fig.2
    4603              :     // consist of: the vertices of fig.1 enclosed by fig.2 (A)
    4604              :     // plus the vertices of fig.2 enclosed by fig.1 (B)
    4605              :     // plus the intercepts of fig.1 and fig.2 (C & D)
    4606              : 
    4607              :     //                               +----------------------+
    4608              :     //                               !                      !
    4609              :     //                               !         FIG.2        !
    4610              :     //                               !                      !
    4611              :     //                +--------------C----------A           !
    4612              :     //                !              !         /            !
    4613              :     //                !              !        /             !
    4614              :     //                !              B-------D--------------+
    4615              :     //                !    FIG.1            /
    4616              :     //                !                    /
    4617              :     //                +-------------------+
    4618              : 
    4619              :     // REFERENCES:
    4620              :     // BLAST/IBLAST code, original author George Walton
    4621              : 
    4622              : #ifdef EP_Count_Calls
    4623              :     ++state.dataTimingsData->NumDetPolyOverlap_Calls;
    4624              : #endif
    4625              : 
    4626              :     // Check for exceeding array limits.
    4627        20917 :     if (NS3 > state.dataSolarShading->MaxHCS) {
    4628              : 
    4629            0 :         state.dataSolarShading->OverlapStatus = TooManyFigures;
    4630              : 
    4631            0 :         if (!state.dataSolarShading->TooManyFiguresMessage && !state.dataGlobal->DisplayExtraWarnings) {
    4632            0 :             ShowWarningError(state,
    4633            0 :                              format("DeterminePolygonOverlap: Too many figures [>{}]  detected in an overlap calculation. Use "
    4634              :                                     "Output:Diagnostics,DisplayExtraWarnings; for more details.",
    4635            0 :                                     state.dataSolarShading->MaxHCS));
    4636            0 :             state.dataSolarShading->TooManyFiguresMessage = true;
    4637              :         }
    4638              : 
    4639            0 :         if (state.dataGlobal->DisplayExtraWarnings) {
    4640            0 :             state.dataSolarShading->TrackTooManyFigures.redimension(++state.dataSolarShading->NumTooManyFigures);
    4641            0 :             state.dataSolarShading->TrackTooManyFigures(state.dataSolarShading->NumTooManyFigures).SurfIndex1 =
    4642            0 :                 state.dataSolarShading->CurrentShadowingSurface;
    4643            0 :             state.dataSolarShading->TrackTooManyFigures(state.dataSolarShading->NumTooManyFigures).SurfIndex2 =
    4644            0 :                 state.dataSolarShading->CurrentSurfaceBeingShadowed;
    4645              :         }
    4646              : 
    4647            0 :         return;
    4648              :     }
    4649              : 
    4650        20917 :     state.dataSolarShading->OverlapStatus = PartialOverlap;
    4651        20917 :     int NV1 = state.dataSolarShading->HCNV(NS1); // Number of vertices of figure NS1
    4652        20917 :     int NV2 = state.dataSolarShading->HCNV(NS2); // Number of vertices of figure NS2
    4653        20917 :     int NV3 = 0;                                 // Number of vertices of figure NS3 (the overlap of NS1 and NS2)
    4654        20917 :     int NIN1 = 0;                                // Number of vertices of NS1 within NS2
    4655        20917 :     int NIN2 = 0;                                // Number of vertices of NS2 within NS1
    4656              : 
    4657        20917 :     if (!state.dataSysVars->SutherlandHodgman) {
    4658            0 :         INCLOS(state, NS1, NV1, NS2, NV2, NV3, NIN1); // Find vertices of NS1 within NS2.
    4659              : 
    4660            0 :         if (NIN1 >= NV1) {
    4661              : 
    4662            0 :             state.dataSolarShading->OverlapStatus = FirstSurfWithinSecond;
    4663              : 
    4664              :         } else {
    4665              : 
    4666            0 :             INCLOS(state, NS2, NV2, NS1, NV1, NV3, NIN2); // Find vertices of NS2 within NS1.
    4667              : 
    4668            0 :             if (NIN2 >= NV2) {
    4669              : 
    4670            0 :                 state.dataSolarShading->OverlapStatus = SecondSurfWithinFirst;
    4671              : 
    4672              :             } else {
    4673              : 
    4674            0 :                 INTCPT(state, NV1, NV2, NV3, NS1, NS2); // Find intercepts of NS1 & NS2.
    4675              : 
    4676            0 :                 if (NV3 < 3) { // Overlap must have 3 or more vertices
    4677            0 :                     state.dataSolarShading->OverlapStatus = NoOverlap;
    4678            0 :                     return;
    4679              :                 }
    4680              :             }
    4681              :         }
    4682              : 
    4683              :     } else {
    4684              :         // simple polygon clipping
    4685        20917 :         CLIPPOLY(state, NS1, NS2, NV1, NV2, NV3);
    4686              :     }
    4687              : 
    4688        20917 :     if (NV3 < state.dataSolarShading->MaxHCV) {
    4689              : 
    4690        20917 :         if (!state.dataSysVars->SutherlandHodgman) {
    4691            0 :             ORDER(state, NV3, NS3); // Put vertices in clockwise order.
    4692              :         } else {
    4693        20917 :             assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    4694        20917 :             int l = state.dataSolarShading->HCX.index(NS3, 1);
    4695        79830 :             for (int N = 1; N <= NV3; ++N, ++l) {
    4696        58913 :                 state.dataSolarShading->HCX[l] = nint64(state.dataSolarShading->XTEMP(N)); // [ l ] == ( N, NS3 )
    4697        58913 :                 state.dataSolarShading->HCY[l] = nint64(state.dataSolarShading->YTEMP(N));
    4698              :             }
    4699              :         }
    4700              : 
    4701        20917 :         HTRANS0(state, NS3, NV3); // Determine h.c. values of sides.
    4702              :         // Skip overlaps of negligible area.
    4703              : 
    4704        20917 :         if (std::abs(state.dataSolarShading->HCAREA(NS3)) * HCMULT < std::abs(state.dataSolarShading->HCAREA(NS1))) {
    4705         6406 :             state.dataSolarShading->OverlapStatus = NoOverlap;
    4706              :         } else {
    4707        14511 :             if (state.dataSolarShading->HCAREA(NS1) * state.dataSolarShading->HCAREA(NS2) > 0.0) {
    4708         2221 :                 state.dataSolarShading->HCAREA(NS3) = -state.dataSolarShading->HCAREA(NS3); // Determine sign of area of overlap
    4709              :             }
    4710        14511 :             Real64 const HCT_1 = state.dataSolarShading->HCT(NS1);
    4711        14511 :             Real64 const HCT_2 = state.dataSolarShading->HCT(NS2);
    4712        14511 :             if (HCT_2 == 1.0 || HCT_1 == 1.0) {
    4713        13851 :                 state.dataSolarShading->HCT(NS3) = HCT_1 * HCT_2;
    4714              :             } else {
    4715              :                 // Determine transmission of overlap which corrects for prior shadows
    4716              :                 // The resulting transmission of overlapping shadows is HCT_1 * HCT_2
    4717              :                 // Shadows with HCT_1 and HCT_2 have already been applied in the overlapping area
    4718              :                 // so the correction is the difference between (HCT_1+HCT_2) and (HCT_1*HCT_2)
    4719          660 :                 state.dataSolarShading->HCT(NS3) = (HCT_1 + HCT_2) - HCT_1 * HCT_2;
    4720              :             }
    4721              :         }
    4722              : 
    4723              :     } else {
    4724              : 
    4725            0 :         state.dataSolarShading->OverlapStatus = TooManyVertices;
    4726              : 
    4727            0 :         if (!state.dataSolarShading->TooManyVerticesMessage && !state.dataGlobal->DisplayExtraWarnings) {
    4728            0 :             ShowWarningError(state,
    4729            0 :                              format("DeterminePolygonOverlap: Too many vertices [>{}] detected in an overlap calculation. Use "
    4730              :                                     "Output:Diagnostics,DisplayExtraWarnings; for more details.",
    4731            0 :                                     state.dataSolarShading->MaxHCV));
    4732            0 :             state.dataSolarShading->TooManyVerticesMessage = true;
    4733              :         }
    4734              : 
    4735            0 :         if (state.dataGlobal->DisplayExtraWarnings) {
    4736            0 :             state.dataSolarShading->TrackTooManyVertices.redimension(++state.dataSolarShading->NumTooManyVertices);
    4737            0 :             state.dataSolarShading->TrackTooManyVertices(state.dataSolarShading->NumTooManyVertices).SurfIndex1 =
    4738            0 :                 state.dataSolarShading->CurrentShadowingSurface;
    4739            0 :             state.dataSolarShading->TrackTooManyVertices(state.dataSolarShading->NumTooManyVertices).SurfIndex2 =
    4740            0 :                 state.dataSolarShading->CurrentSurfaceBeingShadowed;
    4741              :         }
    4742              :     }
    4743              : }
    4744              : 
    4745         1838 : void CalcPerSolarBeam(EnergyPlusData &state,
    4746              :                       Real64 const AvgEqOfTime,       // Average value of Equation of Time for period
    4747              :                       Real64 const AvgSinSolarDeclin, // Average value of Sine of Solar Declination for period
    4748              :                       Real64 const AvgCosSolarDeclin  // Average value of Cosine of Solar Declination for period
    4749              : )
    4750              : {
    4751              : 
    4752              :     // SUBROUTINE INFORMATION:
    4753              :     //       AUTHOR         Legacy Code
    4754              :     //       DATE WRITTEN
    4755              :     //       MODIFIED       BG, Nov 2012 - Timestep solar.  DetailedSolarTimestepIntegration
    4756              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    4757              : 
    4758              :     // PURPOSE OF THIS SUBROUTINE:
    4759              :     // This subroutine manages computation of solar gain multipliers for beam radiation.  These
    4760              :     // are calculated for a period of days depending on the input "Shadowing Calculations".
    4761              : 
    4762              :     // REFERENCES:
    4763              :     // BLAST/IBLAST code, original author George Walton
    4764              : 
    4765              :     // Using/Aliasing
    4766              : 
    4767              :     using WindowComplexManager::InitComplexWindows;
    4768              :     using WindowComplexManager::UpdateComplexWindows;
    4769              : 
    4770              :     int iHour; // Hour index number
    4771              :     int TS;    // TimeStep Loop Countergit
    4772              : 
    4773         1838 :     auto &s_surf = state.dataSurface;
    4774              : 
    4775         1838 :     if (state.dataSolarShading->InitComplexOnce) InitComplexWindows(state);
    4776         1838 :     state.dataSolarShading->InitComplexOnce = false;
    4777              : 
    4778         1838 :     if (state.dataGlobal->KickOffSizing || state.dataGlobal->KickOffSimulation) return; // Skip solar calcs for these Initialization steps.
    4779              : 
    4780              : #ifdef EP_Count_Calls
    4781              :     ++state.dataTimingsData->NumCalcPerSolBeam_Calls;
    4782              : #endif
    4783              : 
    4784              :     // Initialize some values for the appropriate period
    4785         1576 :     if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    4786          549 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    4787          689 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    4788          363 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
    4789          363 :                 int firstSurf = thisSpace.OpaqOrIntMassSurfaceFirst;
    4790          363 :                 int lastSurf = thisSpace.OpaqOrIntMassSurfaceLast;
    4791         2264 :                 for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4792         1901 :                     s_surf->SurfOpaqAO(surfNum) = 0.0;
    4793              :                 }
    4794          363 :                 firstSurf = thisSpace.HTSurfaceFirst;
    4795          363 :                 lastSurf = thisSpace.HTSurfaceLast;
    4796         2375 :                 for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4797         2012 :                     state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
    4798              :                 }
    4799         9075 :                 for (int hour = 1; hour <= 24; ++hour) {
    4800        57000 :                     for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4801        48288 :                         state.dataHeatBal->SurfSunlitFracHR(hour, surfNum) = 0.0;
    4802        48288 :                         state.dataHeatBal->SurfCosIncAngHR(hour, surfNum) = 0.0;
    4803              :                     }
    4804              :                 }
    4805         9075 :                 for (int hour = 1; hour <= 24; ++hour) {
    4806        54264 :                     for (int timestep = 1; timestep <= state.dataGlobal->TimeStepsInHour; ++timestep) {
    4807       295800 :                         for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4808       250248 :                             state.dataHeatBal->SurfSunlitFrac(hour, timestep, surfNum) = 0.0;
    4809       250248 :                             state.dataHeatBal->SurfCosIncAng(hour, timestep, surfNum) = 0.0;
    4810       250248 :                             state.dataHeatBal->SurfSunlitFracWithoutReveal(hour, timestep, surfNum) = 0.0;
    4811              :                         }
    4812              :                     }
    4813              :                 }
    4814         9075 :                 for (int hour = 1; hour <= 24; ++hour) {
    4815        54264 :                     for (int timestep = 1; timestep <= state.dataGlobal->TimeStepsInHour; ++timestep) {
    4816       956592 :                         for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
    4817      5916000 :                             for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4818      5004960 :                                 state.dataHeatBal->SurfWinBackSurfaces(hour, timestep, backSurfNum, surfNum) = 0.0;
    4819      5004960 :                                 state.dataHeatBal->SurfWinOverlapAreas(hour, timestep, backSurfNum, surfNum) = 0.0;
    4820              :                             }
    4821              :                         }
    4822              :                     } // for (timestep)
    4823              :                 }     // for (hour)
    4824              :             }         // for (spaceNum)
    4825              :         }             // for (zoneNum)
    4826              : 
    4827         2278 :         for (auto &e : s_surf->SurfaceWindow) {
    4828         2055 :             std::fill(e.OutProjSLFracMult.begin(), e.OutProjSLFracMult.end(), 1.0);
    4829         2055 :             std::fill(e.InOutProjSLFracMult.begin(), e.InOutProjSLFracMult.end(), 1.0);
    4830              :         }
    4831              :     } else {
    4832         2705 :         for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    4833         2704 :             for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    4834         1352 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
    4835         1352 :                 int const firstSurf = thisSpace.HTSurfaceFirst;
    4836         1352 :                 int const lastSurf = thisSpace.HTSurfaceLast;
    4837         5418 :                 for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4838         4066 :                     state.dataSolarShading->SurfSunCosTheta(surfNum) = 0.0;
    4839         4066 :                     s_surf->SurfOpaqAO(surfNum) = 0.0;
    4840         4066 :                     state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
    4841         4066 :                     state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
    4842         4066 :                     state.dataHeatBal->SurfSunlitFracHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
    4843         4066 :                     state.dataHeatBal->SurfCosIncAngHR(state.dataGlobal->HourOfDay, surfNum) = 0.0;
    4844         4066 :                     state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, surfNum) = 0.0;
    4845              :                 }
    4846        28392 :                 for (int backSurfNum = 1; backSurfNum <= state.dataBSDFWindow->MaxBkSurf; ++backSurfNum) {
    4847       108360 :                     for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    4848        81320 :                         state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0;
    4849        81320 :                         state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, backSurfNum, surfNum) = 0.0;
    4850              :                     }
    4851              :                 }
    4852              :             }
    4853              :         }
    4854              : 
    4855         5434 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
    4856         4081 :             s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;
    4857         4081 :             s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay] = 1.0;
    4858              :         }
    4859              :     }
    4860              : 
    4861         1576 :     if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    4862         5575 :         for (iHour = 1; iHour <= 24; ++iHour) { // Do for all hours
    4863        34560 :             for (TS = 1; TS <= state.dataGlobal->TimeStepsInHour; ++TS) {
    4864        29208 :                 FigureSunCosines(state, iHour, TS, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
    4865              :             }
    4866              :         }
    4867              :     } else {
    4868         1353 :         FigureSunCosines(state, state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
    4869              :     }
    4870              :     // Initialize/update the Complex Fenestration geometry and optical properties
    4871         1576 :     UpdateComplexWindows(state);
    4872         1576 :     if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    4873         5575 :         for (iHour = 1; iHour <= 24; ++iHour) { // Do for all hours.
    4874        34560 :             for (TS = 1; TS <= state.dataGlobal->TimeStepsInHour; ++TS) {
    4875        29208 :                 FigureSolarBeamAtTimestep(state, iHour, TS);
    4876              :             } // TimeStep Loop
    4877              :         }     // Hour Loop
    4878              :     } else {
    4879         1353 :         FigureSolarBeamAtTimestep(state, state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    4880              :     }
    4881              : }
    4882              : 
    4883        30561 : void FigureSunCosines(EnergyPlusData &state,
    4884              :                       int const iHour,
    4885              :                       int const iTimeStep,
    4886              :                       Real64 const EqOfTime,       // value of Equation of Time for period
    4887              :                       Real64 const SinSolarDeclin, // value of Sine of Solar Declination for period
    4888              :                       Real64 const CosSolarDeclin  // value of Cosine of Solar Declination for period
    4889              : )
    4890              : {
    4891              : 
    4892              :     // SUBROUTINE INFORMATION:
    4893              :     //       AUTHOR         B. Griffith
    4894              :     //       DATE WRITTEN   October 2012
    4895              :     //       MODIFIED       na
    4896              :     //       RE-ENGINEERED  na
    4897              : 
    4898              :     // PURPOSE OF THIS SUBROUTINE:
    4899              :     // Determine solar position.  Default for sun below horizon.
    4900              : 
    4901              :     // METHODOLOGY EMPLOYED:
    4902              :     // Given hour, timestep, equation of time, solar declination sine, and solar declination cosine,
    4903              :     // determine sun directions for use elsewhere
    4904              : 
    4905              :     // Using/Aliasing
    4906              : 
    4907              :     Real64 CurrentTime; // Current Time for passing to Solar Position Routine
    4908              : 
    4909        30561 :     auto &s_surf = state.dataSurface;
    4910              : 
    4911        30561 :     if (state.dataGlobal->TimeStepsInHour != 1) {
    4912        30249 :         CurrentTime = double(iHour - 1) + double(iTimeStep) * (state.dataGlobal->TimeStepZone);
    4913              :     } else {
    4914          312 :         CurrentTime = double(iHour) + state.dataEnvrn->TS1TimeOffset;
    4915              :     }
    4916        30561 :     SUN4(state, CurrentTime, EqOfTime, SinSolarDeclin, CosSolarDeclin);
    4917              : 
    4918              :     // Save hourly values for use in DaylightingManager
    4919        30561 :     if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    4920        29208 :         if (iTimeStep == state.dataGlobal->TimeStepsInHour) s_surf->SurfSunCosHourly(iHour) = state.dataSolarShading->SUNCOS;
    4921              :     } else {
    4922         1353 :         s_surf->SurfSunCosHourly(iHour) = state.dataSolarShading->SUNCOS;
    4923              :     }
    4924              :     // Save timestep values for use in WindowComplexManager
    4925        30561 :     state.dataBSDFWindow->SUNCOSTS(iTimeStep, iHour) = state.dataSolarShading->SUNCOS;
    4926        30561 : }
    4927              : 
    4928        30582 : void FigureSolarBeamAtTimestep(EnergyPlusData &state, int const iHour, int const iTimeStep)
    4929              : {
    4930              : 
    4931              :     // SUBROUTINE INFORMATION:
    4932              :     //       AUTHOR         B.Griffith, derived from CalcPerSolarBeam, Legacy and Lawrie.
    4933              :     //       DATE WRITTEN   October 2012
    4934              :     //       MODIFIED       na
    4935              :     //       RE-ENGINEERED  na
    4936              : 
    4937              :     // PURPOSE OF THIS SUBROUTINE:
    4938              :     // This subroutine computes solar gain multipliers for beam solar
    4939              : 
    4940              :     using DataSystemVariables::ShadingMethod;
    4941              : 
    4942              :     Real64 SurfArea;        // Surface area. For walls, includes all window frame areas.
    4943              :     Real64 Fac1WoShdg;      // Intermediate calculation factor, without shading
    4944              :     Real64 Fac1WithShdg;    // Intermediate calculation factor, with shading
    4945              :     Real64 FracIlluminated; // Fraction of surface area illuminated by a sky patch
    4946              : 
    4947        30582 :     auto &s_surf = state.dataSurface;
    4948              : 
    4949              :     // Recover the sun direction from the array stored in previous loop
    4950        30582 :     state.dataSolarShading->SUNCOS = state.dataBSDFWindow->SUNCOSTS(iTimeStep, iHour);
    4951              : 
    4952        30582 :     state.dataSolarShading->SurfSunCosTheta = 0.0;
    4953              : 
    4954        30582 :     if (state.dataSolarShading->SUNCOS(3) < DataEnvironment::SunIsUpValue) return;
    4955              : 
    4956       144356 :     for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
    4957       258554 :         state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
    4958       129277 :                                                            state.dataSolarShading->SUNCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
    4959       129277 :                                                            state.dataSolarShading->SUNCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
    4960       129277 :         if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    4961       127565 :             if (iTimeStep == state.dataGlobal->TimeStepsInHour)
    4962        24614 :                 state.dataHeatBal->SurfCosIncAngHR(iHour, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
    4963              :         } else {
    4964         1712 :             state.dataHeatBal->SurfCosIncAngHR(iHour, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
    4965              :         }
    4966       129277 :         state.dataHeatBal->SurfCosIncAng(iHour, iTimeStep, SurfNum) = state.dataSolarShading->SurfSunCosTheta(SurfNum);
    4967              :     }
    4968              : 
    4969        30157 :     if ((state.dataSysVars->shadingMethod == ShadingMethod::Scheduled || state.dataSysVars->shadingMethod == ShadingMethod::Imported) &&
    4970        30157 :         !state.dataGlobal->DoingSizing && state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather) {
    4971           10 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
    4972            9 :             auto &surf = s_surf->Surface(SurfNum);
    4973            9 :             if (surf.SurfSchedExternalShadingFrac) {
    4974            1 :                 state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = surf.surfExternalShadingSched->getHrTsVal(state, iHour, iTimeStep);
    4975              :             } else {
    4976            8 :                 state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 1.0;
    4977              :             }
    4978              :         }
    4979              :     } else {
    4980        15078 :         SHADOW(state, iHour, iTimeStep); // Determine sunlit areas and solar multipliers for all surfaces.
    4981       144346 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
    4982       129268 :             if (s_surf->Surface(SurfNum).Area >= 1.e-10) {
    4983       129268 :                 SurfArea = s_surf->Surface(SurfNum).NetAreaShadowCalc;
    4984       129268 :                 if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    4985       127556 :                     if (iTimeStep == state.dataGlobal->TimeStepsInHour)
    4986        24614 :                         state.dataHeatBal->SurfSunlitFracHR(iHour, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
    4987              :                 } else {
    4988         1712 :                     state.dataHeatBal->SurfSunlitFracHR(iHour, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
    4989              :                 }
    4990       129268 :                 state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
    4991       129268 :                 if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) < 1.e-5)
    4992        85366 :                     state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 0.0;
    4993              :             }
    4994              :             // Added check
    4995       129268 :             if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) > 1.0) {
    4996            0 :                 state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) = 1.0;
    4997              :             }
    4998              :         }
    4999              :     }
    5000              :     //   Note -- if not the below, values are set in SkyDifSolarShading routine (constant for simulation)
    5001        15096 :     if (state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
    5002           17 :         state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
    5003          148 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
    5004          131 :             state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) = 0.;
    5005          131 :             state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) = 0.;
    5006          131 :             state.dataSolarShading->SurfWithShdgHoriz(SurfNum) = 0.;
    5007          131 :             state.dataSolarShading->SurfWoShdgHoriz(SurfNum) = 0.;
    5008              :         }
    5009              : 
    5010          119 :         for (int IPhi = 0; IPhi < NPhi; ++IPhi) { // Loop over patch altitude values
    5011          102 :             state.dataSolarShading->SUNCOS(3) = state.dataSolarShading->sin_Phi[IPhi];
    5012              : 
    5013         2550 :             for (int ITheta = 0; ITheta < NTheta; ++ITheta) { // Loop over patch azimuth values
    5014         2448 :                 state.dataSolarShading->SUNCOS(1) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->cos_Theta[ITheta];
    5015         2448 :                 state.dataSolarShading->SUNCOS(2) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->sin_Theta[ITheta];
    5016              : 
    5017        21312 :                 for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
    5018        37728 :                     state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS(1) * s_surf->Surface(SurfNum).OutNormVec(1) +
    5019        18864 :                                                                        state.dataSolarShading->SUNCOS(2) * s_surf->Surface(SurfNum).OutNormVec(2) +
    5020        18864 :                                                                        state.dataSolarShading->SUNCOS(3) * s_surf->Surface(SurfNum).OutNormVec(3);
    5021              :                 }
    5022              : 
    5023         2448 :                 SHADOW(state, iHour, iTimeStep); // Determine sunlit areas and solar multipliers for all surfaces.
    5024              : 
    5025        21312 :                 for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
    5026              : 
    5027        18864 :                     if (state.dataSolarShading->SurfSunCosTheta(SurfNum) < 0.0) continue;
    5028              : 
    5029         8526 :                     Fac1WoShdg = state.dataSolarShading->cos_Phi[IPhi] * DThetaDPhi * state.dataSolarShading->SurfSunCosTheta(SurfNum);
    5030         8526 :                     SurfArea = s_surf->Surface(SurfNum).NetAreaShadowCalc;
    5031         8526 :                     if (SurfArea > Eps) {
    5032         8526 :                         FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
    5033              :                     } else {
    5034            0 :                         FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / (SurfArea + Eps);
    5035              :                     }
    5036         8526 :                     Fac1WithShdg = Fac1WoShdg * FracIlluminated;
    5037         8526 :                     state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) += Fac1WithShdg;
    5038         8526 :                     state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) += Fac1WoShdg;
    5039              : 
    5040              :                     // Horizon region
    5041         8526 :                     if (IPhi == 0) {
    5042         1421 :                         state.dataSolarShading->SurfWithShdgHoriz(SurfNum) += Fac1WithShdg;
    5043         1421 :                         state.dataSolarShading->SurfWoShdgHoriz(SurfNum) += Fac1WoShdg;
    5044              :                     }
    5045              :                 } // End of surface loop
    5046              :             }     // End of Theta loop
    5047              :         }         // End of Phi loop
    5048              : 
    5049          148 :         for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
    5050              :             // Original conditions:
    5051              :             // if (!s_surf->Surface(SurfNum).IsShadowing &&
    5052              :             //    (!s_surf->Surface(SurfNum).HeatTransSurf || !s_surf->Surface(SurfNum).ExtSolar))
    5053              :             //    continue;
    5054              : 
    5055          131 :             if (std::abs(state.dataSolarShading->SurfWoShdgIsoSky(SurfNum)) > Eps) {
    5056           95 :                 state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(iTimeStep, iHour, SurfNum) =
    5057           95 :                     (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum));
    5058              :             } else {
    5059           36 :                 state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(iTimeStep, iHour, SurfNum) =
    5060           36 :                     (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) + Eps);
    5061              :             }
    5062          131 :             if (std::abs(state.dataSolarShading->SurfWoShdgHoriz(SurfNum)) > Eps) {
    5063           95 :                 state.dataSolarShading->SurfDifShdgRatioHorizHRTS(iTimeStep, iHour, SurfNum) =
    5064           95 :                     (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum));
    5065              :             } else {
    5066           36 :                 state.dataSolarShading->SurfDifShdgRatioHorizHRTS(iTimeStep, iHour, SurfNum) =
    5067           36 :                     (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum) + Eps);
    5068              :             }
    5069              :         }
    5070              : 
    5071              :         //  ! Get IR view factors. An exterior surface can receive IR radiation from
    5072              :         //  ! sky, ground or shadowing surfaces. Assume shadowing surfaces have same
    5073              :         //  ! temperature as outside air (and therefore same temperature as ground),
    5074              :         //  ! so that the view factor to these shadowing surfaces can be included in
    5075              :         //  ! the ground view factor. Sky IR is assumed to be isotropic and shadowing
    5076              :         //  ! surfaces are assumed to be opaque to IR so they totally "shade" IR from
    5077              :         //  ! sky or ground.
    5078              : 
    5079              :         //  DO SurfNum = 1,TotSurfaces
    5080              :         //    Surface(SurfNum)%ViewFactorSkyIR = Surface(SurfNum)%ViewFactorSkyIR * DifShdgRatioIsoSky(SurfNum,IHOUR,TS)
    5081              :         //    Surface(SurfNum)%ViewFactorGroundIR = 1.0 - Surface(SurfNum)%ViewFactorSkyIR
    5082              :         //  END DO
    5083              : 
    5084              :     } // test for shading surfaces
    5085              : 
    5086        15102 :     for (int SurfNum : s_surf->AllExtSolWinWithFrameSurfaceList) {
    5087              :         // For exterior windows with frame/divider that are partially or fully sunlit,
    5088              :         // correct SunlitFrac due to shadowing of frame and divider projections onto window glass.
    5089              :         // Note: if SunlitFrac = 0.0 the window is either completely shaded or the sun is in back
    5090              :         // of the window; in either case, frame/divider shadowing doesn't have to be done.
    5091              : 
    5092           23 :         if (state.dataHeatBal->SurfSunlitFrac(iHour, iTimeStep, SurfNum) > 0.0) {
    5093           17 :             CalcFrameDividerShadow(state, SurfNum, s_surf->Surface(SurfNum).FrameDivider, iHour);
    5094              :         }
    5095              :     }
    5096              : }
    5097              : 
    5098          133 : void DetermineShadowingCombinations(EnergyPlusData &state)
    5099              : {
    5100              : 
    5101              :     // SUBROUTINE INFORMATION:
    5102              :     //       AUTHOR         From Legacy Code
    5103              :     //       DATE WRITTEN
    5104              :     //       MODIFIED       LKL; March 2002 -- another missing translation from BLAST's routine
    5105              :     //                      FCW; Jan 2003 -- removed line that prevented beam solar through interior windows
    5106              :     //       RE-ENGINEERED  Rick Strand; 1998
    5107              :     //                      Linda Lawrie; Oct 2000
    5108              : 
    5109              :     // PURPOSE OF THIS SUBROUTINE:
    5110              :     // This routine prepares a list of heat transfer surfaces and
    5111              :     // their possible shadowers which is used to direct the hourly
    5112              :     // calculation of shadows and sunlit areas.
    5113              : 
    5114              :     // METHODOLOGY EMPLOYED:
    5115              :     // As appropriate surfaces are identified, they are placed into the
    5116              :     // ShadowComb data structure (module level) with the accompanying lists
    5117              :     // of other surface numbers.
    5118              : 
    5119              :     // REFERENCES:
    5120              :     // BLAST/IBLAST code, original author George Walton
    5121              : 
    5122              :     // Using/Aliasing
    5123              :     using namespace DataErrorTracking;
    5124              : 
    5125          133 :     Array1D_int GSS;             // List of shadowing surfaces numbers for a receiving surface
    5126          133 :     Array1D_int BKS;             // List of back surface numbers for a receiving surface
    5127          133 :     Array1D_int SBS;             // List of subsurfaces for a receiving surface
    5128              :     bool CannotShade;            // TRUE if subsurface cannot shade receiving surface
    5129              :     bool HasWindow;              // TRUE if a window is present on receiving surface
    5130              :     Real64 ZMIN;                 // Lowest point on the receiving surface
    5131              :     int BackSurfaceNumber;       // Back surface number
    5132              :     int HTS;                     // Heat transfer surface number for a receiving surface
    5133              :     int GRSNR;                   // Receiving surface number
    5134              :     int GSSNR;                   // Shadowing surface number
    5135              :     int SBSNR;                   // Subsurface number
    5136              :     int NBKS;                    // Number of back surfaces for a receiving surface
    5137              :     int NGSS;                    // Number of shadowing surfaces for a receiving surface
    5138              :     int NSBS;                    // Number of subsurfaces for a receiving surface
    5139              :     bool ShadowingSurf;          // True if a receiving surface is a shadowing surface
    5140          133 :     Array1D_bool CastingSurface; // tracking during setup of ShadowComb
    5141              : 
    5142          133 :     auto &s_surf = state.dataSurface;
    5143              : 
    5144              : #ifdef EP_Count_Calls
    5145              :     ++state.dataTimingsData->NumDetShadowCombs_Calls;
    5146              : #endif
    5147              : 
    5148          133 :     state.dataShadowComb->ShadowComb.dimension(s_surf->TotSurfaces, ShadowingCombinations{}); // Set all elements to default constructed state
    5149              : 
    5150          133 :     CastingSurface.dimension(s_surf->TotSurfaces, false);
    5151              : 
    5152          133 :     state.dataSolarShading->HCA.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
    5153          133 :     state.dataSolarShading->HCB.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
    5154          133 :     state.dataSolarShading->HCC.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
    5155          133 :     state.dataSolarShading->HCX.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
    5156          133 :     state.dataSolarShading->HCY.dimension(2 * state.dataSolarShading->MaxHCS, state.dataSolarShading->MaxHCV + 1, 0);
    5157          133 :     state.dataSolarShading->HCAREA.dimension(2 * state.dataSolarShading->MaxHCS, 0.0);
    5158          133 :     state.dataSolarShading->HCNS.dimension(2 * state.dataSolarShading->MaxHCS, 0);
    5159          133 :     state.dataSolarShading->HCNV.dimension(2 * state.dataSolarShading->MaxHCS, 0);
    5160          133 :     state.dataSolarShading->HCT.dimension(2 * state.dataSolarShading->MaxHCS, 0.0);
    5161              : 
    5162          133 :     GSS.dimension(state.dataSolarShading->MaxGSS, 0);
    5163          133 :     BKS.dimension(state.dataSolarShading->MaxGSS, 0);
    5164          133 :     SBS.dimension(state.dataSolarShading->MaxGSS, 0);
    5165              : 
    5166          133 :     state.dataSolarShading->penumbraIDs.clear();
    5167              : 
    5168          133 :     HTS = 0;
    5169              : 
    5170              :     // Check every surface as a possible shadow receiving surface ("RS" = receiving surface).
    5171          133 :     if (state.dataEnvrn->IgnoreSolarRadiation) {
    5172            0 :         return;
    5173              :     }
    5174              : 
    5175         1110 :     for (GRSNR = 1; GRSNR <= s_surf->TotSurfaces; ++GRSNR) { // Loop through all surfaces (looking for potential receiving surfaces)...
    5176              : 
    5177          977 :         ShadowingSurf = s_surf->Surface(GRSNR).IsShadowing;
    5178          977 :         NGSS = 0;
    5179          977 :         NSBS = 0;
    5180          977 :         NBKS = 0;
    5181              : 
    5182          977 :         if (!ShadowingSurf && !s_surf->Surface(GRSNR).HeatTransSurf) continue;
    5183          975 :         HTS = GRSNR;
    5184              : 
    5185              : #ifndef EP_NO_OPENGL
    5186          975 :         if (state.dataSolarShading->penumbra) {
    5187            0 :             bool skipSurface = s_surf->Surface(GRSNR).MirroredSurf;
    5188              :             // Penumbra doesn't need mirrored surfaces TODO: Don't bother creating them in the first place?
    5189              : 
    5190              :             // Skip interior surfaces if the other side has already been added to penumbra
    5191            0 :             if (s_surf->Surface(GRSNR).ExtBoundCond > 0) {
    5192            0 :                 if (s_surf->SurfPenumbraID(s_surf->Surface(GRSNR).ExtBoundCond) >= 0) {
    5193            0 :                     s_surf->SurfPenumbraID(GRSNR) = s_surf->SurfPenumbraID(s_surf->Surface(GRSNR).ExtBoundCond);
    5194            0 :                     skipSurface = true;
    5195              :                 }
    5196              :             }
    5197              : 
    5198            0 :             if (!skipSurface) {
    5199              :                 // Add surfaces to penumbra...
    5200            0 :                 Penumbra::Polygon poly;
    5201              : 
    5202            0 :                 if (s_surf->Surface(GRSNR).Reveal > 0.0) {
    5203            0 :                     Real64 R = s_surf->Surface(GRSNR).Reveal;
    5204            0 :                     auto &norm = s_surf->Surface(GRSNR).NewellSurfaceNormalVector;
    5205            0 :                     auto &v = s_surf->Surface(GRSNR).Vertex;
    5206            0 :                     for (unsigned i = 0; i < v.size(); ++i) {
    5207            0 :                         poly.push_back(v[i].x);
    5208            0 :                         poly.push_back(v[i].y);
    5209            0 :                         poly.push_back(v[i].z);
    5210              : 
    5211            0 :                         Vector vPrev;
    5212            0 :                         if (i == 0) {
    5213            0 :                             vPrev = v[v.size() - 1];
    5214              :                         } else {
    5215            0 :                             vPrev = v[i - 1];
    5216              :                         }
    5217              : 
    5218            0 :                         Penumbra::Polygon rPoly; // Reveal surface
    5219            0 :                         rPoly.push_back(v[i].x);
    5220            0 :                         rPoly.push_back(v[i].y);
    5221            0 :                         rPoly.push_back(v[i].z);
    5222              : 
    5223            0 :                         rPoly.push_back(v[i].x + norm.x * R);
    5224            0 :                         rPoly.push_back(v[i].y + norm.y * R);
    5225            0 :                         rPoly.push_back(v[i].z + norm.z * R);
    5226              : 
    5227            0 :                         rPoly.push_back(vPrev.x + norm.x * R);
    5228            0 :                         rPoly.push_back(vPrev.y + norm.y * R);
    5229            0 :                         rPoly.push_back(vPrev.z + norm.z * R);
    5230              : 
    5231            0 :                         rPoly.push_back(vPrev.x);
    5232            0 :                         rPoly.push_back(vPrev.y);
    5233            0 :                         rPoly.push_back(vPrev.z);
    5234              : 
    5235            0 :                         Penumbra::Surface rSurf(rPoly, fmt::format("{} reveal {}", s_surf->Surface(GRSNR).Name, i));
    5236            0 :                         state.dataSolarShading->penumbra->add_surface(rSurf);
    5237            0 :                     }
    5238              :                 } else {
    5239            0 :                     for (auto const &v : s_surf->Surface(GRSNR).Vertex) {
    5240            0 :                         poly.push_back(v.x);
    5241            0 :                         poly.push_back(v.y);
    5242            0 :                         poly.push_back(v.z);
    5243              :                     }
    5244              :                 }
    5245            0 :                 Penumbra::Surface pSurf(poly, s_surf->Surface(GRSNR).Name);
    5246              : 
    5247              :                 // Punch holes for subsurfaces
    5248            0 :                 if (s_surf->Surface(GRSNR).BaseSurf == GRSNR) { // Only look for subsurfaces on base surfaces
    5249            0 :                     for (int subSurface = 1; subSurface <= s_surf->TotSurfaces; ++subSurface) {
    5250            0 :                         if (s_surf->Surface(subSurface).BaseSurf != GRSNR) continue; // Ignore subsurfaces of other surfaces
    5251            0 :                         if (!s_surf->Surface(subSurface).HeatTransSurf) continue;    // Skip non heat transfer subsurfaces
    5252            0 :                         if (subSurface == GRSNR) continue;                           // Surface itself cannot be its own subsurface
    5253              : 
    5254            0 :                         Penumbra::Polygon subPoly;
    5255            0 :                         if (s_surf->Surface(subSurface).Reveal > 0.0) {
    5256            0 :                             Real64 R = s_surf->Surface(subSurface).Reveal;
    5257            0 :                             auto &norm = s_surf->Surface(subSurface).NewellSurfaceNormalVector;
    5258            0 :                             for (auto const &v : s_surf->Surface(subSurface).Vertex) {
    5259            0 :                                 subPoly.push_back(v.x + norm.x * R);
    5260            0 :                                 subPoly.push_back(v.y + norm.y * R);
    5261            0 :                                 subPoly.push_back(v.z + norm.z * R);
    5262              :                             }
    5263              :                         } else {
    5264            0 :                             for (auto const &v : s_surf->Surface(subSurface).Vertex) {
    5265            0 :                                 subPoly.push_back(v.x);
    5266            0 :                                 subPoly.push_back(v.y);
    5267            0 :                                 subPoly.push_back(v.z);
    5268              :                             }
    5269              :                         }
    5270              : 
    5271            0 :                         pSurf.add_hole(subPoly);
    5272            0 :                     }
    5273              :                 }
    5274            0 :                 s_surf->SurfPenumbraID(GRSNR) = state.dataSolarShading->penumbra->add_surface(pSurf);
    5275            0 :                 state.dataSolarShading->penumbraIDs.push_back(s_surf->SurfPenumbraID(GRSNR));
    5276            0 :             }
    5277              :         }
    5278              : #endif
    5279              : 
    5280          975 :         if (!ShadowingSurf && !s_surf->Surface(GRSNR).ExtSolar) continue; // Skip surfaces with no external solar
    5281              : 
    5282          671 :         if (!ShadowingSurf && s_surf->Surface(GRSNR).BaseSurf != GRSNR) { // Skip subsurfaces (SBS)
    5283           70 :             continue;
    5284              :         }
    5285              : 
    5286              :         // Get the lowest point of receiving surface
    5287          601 :         ZMIN = minval(s_surf->Surface(GRSNR).Vertex, &Vector::z);
    5288              : 
    5289              :         // Check every surface as a possible shadow casting surface ("SS" = shadow sending)
    5290          601 :         NGSS = 0;
    5291          601 :         if (state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) { // Except when doing simplified exterior shadowing.
    5292              : 
    5293         5489 :             for (GSSNR = 1; GSSNR <= s_surf->TotSurfaces; ++GSSNR) { // Loop through all surfaces, looking for ones that could shade GRSNR
    5294              : 
    5295         5094 :                 if (GSSNR == GRSNR) continue; // Receiving surface cannot shade itself
    5296         4699 :                 if ((s_surf->Surface(GSSNR).HeatTransSurf) && (s_surf->Surface(GSSNR).BaseSurf == GRSNR))
    5297           63 :                     continue; // A heat transfer subsurface of a receiving surface
    5298              :                 // cannot shade the receiving surface
    5299         4636 :                 if (ShadowingSurf) {
    5300              :                     // If receiving surf is a shadowing surface exclude matching shadow surface as sending surface
    5301              :                     // IF((GSSNR == GRSNR+1 .AND. Surface(GSSNR)%Name(1:3) == 'Mir').OR. &
    5302              :                     //   (GSSNR == GRSNR-1 .AND. Surface(GRSNR)%Name(1:3) == 'Mir')) CYCLE
    5303         1817 :                     if (((GSSNR == GRSNR + 1) && s_surf->Surface(GSSNR).MirroredSurf) ||
    5304          893 :                         ((GSSNR == GRSNR - 1) && s_surf->Surface(GRSNR).MirroredSurf))
    5305           62 :                         continue;
    5306              :                 }
    5307              : 
    5308         4574 :                 if (s_surf->Surface(GSSNR).BaseSurf == GRSNR) { // Shadowing subsurface of receiving surface
    5309              : 
    5310            0 :                     ++NGSS;
    5311            0 :                     if (NGSS > state.dataSolarShading->MaxGSS) {
    5312            0 :                         GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
    5313              :                     }
    5314            0 :                     GSS(NGSS) = GSSNR;
    5315              : 
    5316         8720 :                 } else if ((s_surf->Surface(GSSNR).BaseSurf == 0) ||
    5317         4146 :                            ((s_surf->Surface(GSSNR).BaseSurf == GSSNR) &&
    5318         3614 :                             ((s_surf->Surface(GSSNR).ExtBoundCond == ExternalEnvironment) ||
    5319         1474 :                              s_surf->Surface(GSSNR).ExtBoundCond ==
    5320              :                                  OtherSideCondModeledExt))) { // Detached shadowing surface or | any other base surface
    5321              :                     // exposed to outside environment
    5322              : 
    5323         2568 :                     CHKGSS(state, GRSNR, GSSNR, ZMIN, CannotShade); // Check to see if this can shade the receiving surface
    5324         2568 :                     if (!CannotShade) {                             // Update the shadowing surface data if shading is possible
    5325          126 :                         ++NGSS;
    5326          126 :                         if (NGSS > state.dataSolarShading->MaxGSS) {
    5327            0 :                             GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
    5328              :                         }
    5329          126 :                         GSS(NGSS) = GSSNR;
    5330              :                     }
    5331              :                 }
    5332              : 
    5333              :             }    // ...end of surfaces DO loop (GSSNR)
    5334              :         } else { // Simplified Distribution -- still check for Shading Subsurfaces
    5335              : 
    5336         1483 :             for (GSSNR = 1; GSSNR <= s_surf->TotSurfaces; ++GSSNR) { // Loop through all surfaces (looking for surfaces which could shade GRSNR) ...
    5337              : 
    5338         1277 :                 if (GSSNR == GRSNR) continue; // Receiving surface cannot shade itself
    5339         1071 :                 if ((s_surf->Surface(GSSNR).HeatTransSurf) && (s_surf->Surface(GSSNR).BaseSurf == GRSNR))
    5340            7 :                     continue;                                   // Skip heat transfer subsurfaces of receiving surface
    5341         1064 :                 if (s_surf->Surface(GSSNR).BaseSurf == GRSNR) { // Shadowing subsurface of receiving surface
    5342            0 :                     ++NGSS;
    5343            0 :                     if (NGSS > state.dataSolarShading->MaxGSS) {
    5344            0 :                         GSS.redimension(state.dataSolarShading->MaxGSS *= 2, 0);
    5345              :                     }
    5346            0 :                     GSS(NGSS) = GSSNR;
    5347              :                 }
    5348              :             }
    5349              : 
    5350              :         } // ...end of check for simplified solar distribution
    5351              : 
    5352              :         // Check every surface as a receiving subsurface of the receiving surface
    5353          601 :         NSBS = 0;
    5354          601 :         HasWindow = false;
    5355              :         // legacy: IF (OSENV(HTS) > 10) WINDOW=.TRUE. -->Note: WINDOW was set true for roof ponds, solar walls, or other zones
    5356         6972 :         for (SBSNR = 1; SBSNR <= s_surf->TotSurfaces; ++SBSNR) { // Loop through the surfaces yet again (looking for subsurfaces of GRSNR)...
    5357              : 
    5358         6371 :             if (!s_surf->Surface(SBSNR).HeatTransSurf) continue;    // Skip non heat transfer subsurfaces
    5359         5819 :             if (SBSNR == GRSNR) continue;                           // Surface itself cannot be its own subsurface
    5360         5280 :             if (s_surf->Surface(SBSNR).BaseSurf != GRSNR) continue; // Ignore subsurfaces of other surfaces and other surfaces
    5361              : 
    5362           70 :             if (state.dataConstruction->Construct(s_surf->Surface(SBSNR).Construction).TransDiff > 0.0) HasWindow = true; // Check for window
    5363           70 :             CHKSBS(state, HTS, GRSNR, SBSNR); // Check that the receiving surface completely encloses the subsurface;
    5364              :             // severe error if not
    5365           70 :             ++NSBS;
    5366           70 :             if (NSBS > state.dataSolarShading->MaxSBS) {
    5367            0 :                 SBS.redimension(state.dataSolarShading->MaxSBS *= 2, 0);
    5368              :             }
    5369           70 :             SBS(NSBS) = SBSNR;
    5370              : 
    5371              :         } // ...end of surfaces DO loop (SBSNR)
    5372              : 
    5373              :         // Check every surface as a back surface
    5374          601 :         NBKS = 0;
    5375              :         //                                        Except for simplified
    5376              :         //                                        interior solar distribution,
    5377          601 :         if ((state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) &&
    5378              :             (HasWindow)) { // For full interior solar distribution | and a window present on base surface (GRSNR)
    5379              : 
    5380           76 :             for (BackSurfaceNumber = 1; BackSurfaceNumber <= s_surf->TotSurfaces;
    5381              :                  ++BackSurfaceNumber) { // Loop through surfaces yet again, looking for back surfaces to GRSNR
    5382              : 
    5383           69 :                 if (!s_surf->Surface(BackSurfaceNumber).HeatTransSurf) continue;    // Skip non-heat transfer surfaces
    5384           69 :                 if (s_surf->Surface(BackSurfaceNumber).BaseSurf == GRSNR) continue; // Skip subsurfaces of this GRSNR
    5385           55 :                 if (BackSurfaceNumber == GRSNR) continue;                           // A back surface cannot be GRSNR itself
    5386           55 :                 if (s_surf->Surface(BackSurfaceNumber).SolarEnclIndex != s_surf->Surface(GRSNR).SolarEnclIndex)
    5387           14 :                     continue; // Skip if back surface not in same solar enclosure
    5388              : 
    5389           41 :                 if (s_surf->Surface(BackSurfaceNumber).Class == SurfaceClass::IntMass) continue;
    5390              : 
    5391              :                 // Following line removed 1/27/03 by FCW. Was in original code that didn't do beam solar transmitted through
    5392              :                 // interior windows. Was removed to allow such beam solar but then somehow was put back in.
    5393              :                 // IF (Surface(BackSurfaceNumber)%BaseSurf /= BackSurfaceNumber) CYCLE ! Not for subsurfaces of Back Surface
    5394              : 
    5395           41 :                 if (!state.dataSolarShading->penumbra) {
    5396           41 :                     CHKBKS(state, BackSurfaceNumber, GRSNR); // CHECK FOR CONVEX ZONE; severe error if not
    5397              :                 }
    5398           41 :                 ++NBKS;
    5399           41 :                 if (NBKS > state.dataSolarShading->MaxBKS) {
    5400            0 :                     BKS.redimension(state.dataSolarShading->MaxBKS *= 2, 0);
    5401              :                 }
    5402           41 :                 BKS(NBKS) = BackSurfaceNumber;
    5403              : 
    5404              :             } // ...end of surfaces DO loop (BackSurfaceNumber)
    5405              :         }
    5406              : 
    5407              :         // Put this into the ShadowComb data structure
    5408          601 :         state.dataShadowComb->ShadowComb(GRSNR).UseThisSurf = true;
    5409          601 :         state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf = NGSS;
    5410          601 :         state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf = NBKS;
    5411          601 :         state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf = NSBS;
    5412          601 :         state.dataSolarShading->MaxDim = max(state.dataSolarShading->MaxDim, NGSS, NBKS, NSBS);
    5413              : 
    5414          601 :         state.dataShadowComb->ShadowComb(GRSNR).GenSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf});
    5415          601 :         state.dataShadowComb->ShadowComb(GRSNR).GenSurf(0) = 0;
    5416          601 :         if (state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf > 0) {
    5417           89 :             state.dataShadowComb->ShadowComb(GRSNR).GenSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf}) = GSS({1, NGSS});
    5418              :         }
    5419              : 
    5420          601 :         state.dataShadowComb->ShadowComb(GRSNR).BackSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf});
    5421          601 :         state.dataShadowComb->ShadowComb(GRSNR).BackSurf(0) = 0;
    5422          601 :         if (state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf > 0) {
    5423            7 :             state.dataShadowComb->ShadowComb(GRSNR).BackSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf}) = BKS({1, NBKS});
    5424              :         }
    5425              : 
    5426          601 :         state.dataShadowComb->ShadowComb(GRSNR).SubSurf.allocate({0, state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf});
    5427          601 :         state.dataShadowComb->ShadowComb(GRSNR).SubSurf(0) = 0;
    5428          601 :         if (state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf > 0) {
    5429           65 :             state.dataShadowComb->ShadowComb(GRSNR).SubSurf({1, state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf}) = SBS({1, NSBS});
    5430              :         }
    5431              : 
    5432              :     } // ...end of surfaces (GRSNR) DO loop
    5433              : 
    5434          133 :     GSS.deallocate();
    5435          133 :     SBS.deallocate();
    5436          133 :     BKS.deallocate();
    5437              : 
    5438          133 :     if (!state.dataSolarShading->penumbra) {
    5439          133 :         if (state.dataSolarShading->shd_stream) {
    5440          114 :             *state.dataSolarShading->shd_stream << "Shadowing Combinations\n";
    5441          114 :             if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
    5442           41 :                 *state.dataSolarShading->shd_stream
    5443           41 :                     << "..Solar Distribution=Minimal Shadowing, Detached Shading will not be used in shadowing calculations\n";
    5444           73 :             } else if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullExterior) {
    5445           63 :                 if (s_surf->CalcSolRefl) {
    5446            0 :                     *state.dataSolarShading->shd_stream << "..Solar Distribution=FullExteriorWithReflectionsFromExteriorSurfaces\n";
    5447              :                 } else {
    5448           63 :                     *state.dataSolarShading->shd_stream << "..Solar Distribution=FullExterior\n";
    5449              :                 }
    5450           10 :             } else if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
    5451           10 :                 if (s_surf->CalcSolRefl) {
    5452            0 :                     *state.dataSolarShading->shd_stream << "..Solar Distribution=FullInteriorAndExteriorWithReflectionsFromExteriorSurfaces\n";
    5453              :                 } else {
    5454           10 :                     *state.dataSolarShading->shd_stream << "..Solar Distribution=FullInteriorAndExterior\n";
    5455              :                 }
    5456              :             } else {
    5457              :             }
    5458              : 
    5459          114 :             *state.dataSolarShading->shd_stream << "..In the following, only the first 10 reference surfaces will be shown.\n";
    5460          114 :             *state.dataSolarShading->shd_stream << "..But all surfaces are used in the calculations.\n";
    5461              : 
    5462          943 :             for (int HTSnum : s_surf->AllSurfaceListReportOrder) {
    5463          829 :                 *state.dataSolarShading->shd_stream << "==================================\n";
    5464          829 :                 if (state.dataShadowComb->ShadowComb(HTSnum).UseThisSurf) {
    5465          484 :                     if (s_surf->Surface(HTSnum).IsConvex) {
    5466          960 :                         *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
    5467          960 :                                                             << " is used as Receiving Surface in calculations and is convex.\n";
    5468              :                     } else {
    5469            8 :                         *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
    5470            8 :                                                             << " is used as Receiving Surface in calculations and is non-convex.\n";
    5471            4 :                         if (state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf > 0) {
    5472            2 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    5473            0 :                                 ShowWarningError(state,
    5474            0 :                                                  format("DetermineShadowingCombinations: Surface=\"{}\" is a receiving surface and is non-convex.",
    5475            0 :                                                         s_surf->Surface(HTSnum).Name));
    5476            0 :                                 ShowContinueError(state,
    5477              :                                                   "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
    5478              :                             } else {
    5479            2 :                                 ++state.dataErrTracking->TotalReceivingNonConvexSurfaces;
    5480              :                             }
    5481              :                         }
    5482              :                     }
    5483              :                 } else {
    5484          690 :                     *state.dataSolarShading->shd_stream << "Surface=" << s_surf->Surface(HTSnum).Name
    5485          690 :                                                         << " is not used as Receiving Surface in calculations.\n";
    5486              :                 }
    5487          829 :                 *state.dataSolarShading->shd_stream << "Number of general casting surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf
    5488          829 :                                                     << '\n';
    5489          906 :                 for (NGSS = 1; NGSS <= state.dataShadowComb->ShadowComb(HTSnum).NumGenSurf; ++NGSS) {
    5490           77 :                     if (NGSS <= 10)
    5491           77 :                         *state.dataSolarShading->shd_stream
    5492           77 :                             << "..Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).GenSurf(NGSS)).Name << '\n';
    5493           77 :                     CastingSurface(state.dataShadowComb->ShadowComb(HTSnum).GenSurf(NGSS)) = true;
    5494              :                 }
    5495          829 :                 *state.dataSolarShading->shd_stream << "Number of back surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumBackSurf << '\n';
    5496          863 :                 for (NGSS = 1; NGSS <= min(10, state.dataShadowComb->ShadowComb(HTSnum).NumBackSurf); ++NGSS) {
    5497           34 :                     *state.dataSolarShading->shd_stream
    5498           34 :                         << "...Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).BackSurf(NGSS)).Name << '\n';
    5499              :                 }
    5500          829 :                 *state.dataSolarShading->shd_stream << "Number of receiving sub surfaces=" << state.dataShadowComb->ShadowComb(HTSnum).NumSubSurf
    5501          829 :                                                     << '\n';
    5502          886 :                 for (NGSS = 1; NGSS <= min(10, state.dataShadowComb->ShadowComb(HTSnum).NumSubSurf); ++NGSS) {
    5503           57 :                     *state.dataSolarShading->shd_stream
    5504           57 :                         << "....Surface=" << s_surf->Surface(state.dataShadowComb->ShadowComb(HTSnum).SubSurf(NGSS)).Name << '\n';
    5505              :                 }
    5506              :             }
    5507              :         }
    5508              : 
    5509         1110 :         for (HTS = 1; HTS <= s_surf->TotSurfaces; ++HTS) {
    5510          977 :             if (CastingSurface(HTS) && !s_surf->Surface(HTS).IsConvex) {
    5511            2 :                 if (state.dataGlobal->DisplayExtraWarnings) {
    5512            0 :                     ShowSevereError(
    5513              :                         state,
    5514            0 :                         format("DetermineShadowingCombinations: Surface=\"{}\" is a casting surface and is non-convex.", s_surf->Surface(HTS).Name));
    5515            0 :                     ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
    5516              :                 } else {
    5517            2 :                     ++state.dataErrTracking->TotalCastingNonConvexSurfaces;
    5518              :                 }
    5519              :             }
    5520              :         }
    5521              : 
    5522          133 :         if (state.dataErrTracking->TotalReceivingNonConvexSurfaces > 0) {
    5523            6 :             ShowWarningMessage(state,
    5524            6 :                                format("DetermineShadowingCombinations: There are {} surfaces which are receiving surfaces and are non-convex.",
    5525            3 :                                       state.dataErrTracking->TotalReceivingNonConvexSurfaces));
    5526            6 :             ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
    5527            6 :             ShowContinueError(state, "...Add Output:Diagnostics,DisplayExtraWarnings; to see individual warnings for each surface.");
    5528            3 :             state.dataErrTracking->TotalWarningErrors += state.dataErrTracking->TotalReceivingNonConvexSurfaces;
    5529              :         }
    5530              : 
    5531          133 :         if (state.dataErrTracking->TotalCastingNonConvexSurfaces > 0) {
    5532            6 :             ShowSevereMessage(state,
    5533            6 :                               format("DetermineShadowingCombinations: There are {} surfaces which are casting surfaces and are non-convex.",
    5534            3 :                                      state.dataErrTracking->TotalCastingNonConvexSurfaces));
    5535            6 :             ShowContinueError(state, "...Shadowing values may be inaccurate. Check .shd report file for more surface shading details");
    5536            6 :             ShowContinueError(state, "...Add Output:Diagnostics,DisplayExtraWarnings; to see individual severes for each surface.");
    5537            3 :             state.dataErrTracking->TotalSevereErrors += state.dataErrTracking->TotalCastingNonConvexSurfaces;
    5538              :         }
    5539              :     }
    5540              : 
    5541          133 :     CastingSurface.deallocate();
    5542              : 
    5543              : #ifndef EP_NO_OPENGL
    5544          133 :     if (state.dataSolarShading->penumbra && state.dataSolarShading->penumbra->get_number_of_surfaces() > 0) {
    5545            0 :         state.dataSolarShading->penumbra->set_model();
    5546              :     }
    5547              : #endif
    5548          133 : }
    5549              : 
    5550        33798 : void SHADOW(EnergyPlusData &state,
    5551              :             int const iHour, // Hour index
    5552              :             int const TS     // Time Step
    5553              : )
    5554              : {
    5555              : 
    5556              :     // SUBROUTINE INFORMATION:
    5557              :     //       AUTHOR         Legacy Code
    5558              :     //       DATE WRITTEN
    5559              :     //       MODIFIED       Nov 2003, FCW: modify to do shadowing on shadowing surfaces
    5560              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    5561              : 
    5562              :     // PURPOSE OF THIS SUBROUTINE:
    5563              :     // This subroutine is a driving routine for calculations of shadows
    5564              :     // and sunlit areas used in computing the solar beam flux multipliers.
    5565              : 
    5566              :     // REFERENCES:
    5567              :     // BLAST/IBLAST code, original author George Walton
    5568              : 
    5569              :     Real64 XS; // Intermediate result
    5570              :     Real64 YS; // Intermediate result
    5571              :     Real64 ZS; // Intermediate result
    5572              :     int N;     // Vertex number
    5573              :     int NGRS;  // Coordinate transformation index
    5574              :     int NVT;
    5575              :     int HTS;         // Heat transfer surface number of the general receiving surface
    5576              :     int GRSNR;       // Surface number of general receiving surface
    5577              :     int NBKS;        // Number of back surfaces
    5578              :     int NGSS;        // Number of general shadowing surfaces
    5579              :     int NSBS;        // Number of subsurfaces (windows and doors)
    5580              :     Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
    5581              :     // For windows, includes divider area
    5582              : 
    5583        33798 :     auto &s_surf = state.dataSurface;
    5584              : 
    5585        33798 :     if (state.dataSolarShading->ShadowOneTimeFlag) {
    5586          112 :         state.dataSolarShading->XVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
    5587          112 :         state.dataSolarShading->YVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
    5588          112 :         state.dataSolarShading->ZVrt.allocate(s_surf->MaxVerticesPerSurface + 1);
    5589          112 :         state.dataSolarShading->XVrt = 0.0;
    5590          112 :         state.dataSolarShading->YVrt = 0.0;
    5591          112 :         state.dataSolarShading->ZVrt = 0.0;
    5592          112 :         state.dataSolarShading->ShadowOneTimeFlag = false;
    5593              :     }
    5594              : 
    5595              : #ifdef EP_Count_Calls
    5596              :     if (iHour == 0) {
    5597              :         ++state.dataTimingsData->NumShadow_Calls;
    5598              :     } else {
    5599              :         ++state.dataTimingsData->NumShadowAtTS_Calls;
    5600              :     }
    5601              : #endif
    5602              : 
    5603        33798 :     state.dataSolarShading->SurfSunlitArea = 0.0;
    5604              : 
    5605              : #ifndef EP_NO_OPENGL
    5606        33798 :     if (state.dataSolarShading->penumbra) {
    5607            0 :         Real64 ElevSun = Constant::PiOvr2 - std::acos(state.dataSolarShading->SUNCOS(3));
    5608            0 :         Real64 AzimSun = std::atan2(state.dataSolarShading->SUNCOS(1), state.dataSolarShading->SUNCOS(2));
    5609            0 :         state.dataSolarShading->penumbra->set_sun_position(AzimSun, ElevSun);
    5610            0 :         state.dataSolarShading->penumbra->submit_pssa();
    5611              :     }
    5612              : #endif
    5613              : 
    5614       301738 :     for (GRSNR = 1; GRSNR <= s_surf->TotSurfaces; ++GRSNR) {
    5615              : 
    5616       267940 :         if (!state.dataShadowComb->ShadowComb(GRSNR).UseThisSurf) continue;
    5617              : 
    5618       157882 :         state.dataSolarShading->SurfSunlitArea(GRSNR) = 0.0;
    5619              : 
    5620       157882 :         NGSS = state.dataShadowComb->ShadowComb(GRSNR).NumGenSurf;
    5621       157882 :         state.dataSolarShading->NGSSHC = 0;
    5622       157882 :         NBKS = state.dataShadowComb->ShadowComb(GRSNR).NumBackSurf;
    5623       157882 :         state.dataSolarShading->NBKSHC = 0;
    5624       157882 :         NSBS = state.dataShadowComb->ShadowComb(GRSNR).NumSubSurf;
    5625       157882 :         state.dataSolarShading->NRVLHC = 0;
    5626       157882 :         state.dataSolarShading->NSBSHC = 0;
    5627       157882 :         state.dataSolarShading->LOCHCA = 1;
    5628              :         // Temporarily determine the old heat transfer surface number (HTS)
    5629       157882 :         HTS = GRSNR;
    5630              : 
    5631       157882 :         if (state.dataSolarShading->SurfSunCosTheta(GRSNR) < DataEnvironment::SunIsUpValue) { //.001) THEN ! Receiving surface is not in the sun
    5632              : 
    5633        74481 :             state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
    5634        74481 :             SHDSBS(state, iHour, GRSNR, NBKS, NSBS, HTS, TS);
    5635              : 
    5636        83401 :         } else if ((NGSS <= 0) && (NSBS <= 0)) { // Simple surface--no shaders or subsurfaces
    5637              : 
    5638        67614 :             state.dataSolarShading->SurfSunlitArea(HTS) = s_surf->Surface(GRSNR).NetAreaShadowCalc;
    5639              :         } else { // Surface in sun and either shading surfaces or subsurfaces present (or both)
    5640              : 
    5641              : #ifndef EP_NO_OPENGL
    5642        15787 :             int id = s_surf->SurfPenumbraID(HTS);
    5643        15787 :             if (state.dataSolarShading->penumbra && id >= 0) {
    5644              :                 // SurfSunlitArea(HTS) = buildingPSSF.at(id) / SurfSunCosTheta(HTS);
    5645            0 :                 state.dataSolarShading->SurfSunlitArea(HTS) =
    5646            0 :                     state.dataSolarShading->penumbra->retrieve_pssa(id) / state.dataSolarShading->SurfSunCosTheta(HTS);
    5647              :                 // SurfSunlitArea(HTS) = penumbra->fetchPSSA(Surface(HTS).PenumbraID)/SurfSunCosTheta(HTS);
    5648            0 :                 for (int SS = 1; SS <= NSBS; ++SS) {
    5649            0 :                     int HTSS = state.dataShadowComb->ShadowComb(HTS).SubSurf(SS);
    5650            0 :                     id = s_surf->SurfPenumbraID(HTSS);
    5651            0 :                     if (id >= 0) {
    5652              :                         // SurfSunlitArea(HTSS) = buildingPSSF.at(id) / SurfSunCosTheta(HTSS);
    5653            0 :                         state.dataSolarShading->SurfSunlitArea(HTSS) =
    5654            0 :                             state.dataSolarShading->penumbra->retrieve_pssa(id) / state.dataSolarShading->SurfSunCosTheta(HTSS);
    5655              :                         // SurfSunlitArea(HTSS) = penumbra->fetchPSSA(Surface(HTSS).PenumbraID)/SurfSunCosTheta(HTSS);
    5656            0 :                         if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
    5657            0 :                             if (iHour > 0 && TS > 0)
    5658            0 :                                 state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
    5659            0 :                                     state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).Area;
    5660              :                         }
    5661              :                     }
    5662              :                 }
    5663        15787 :             } else if (!state.dataSolarShading->penumbra) {
    5664              : #else
    5665              :             {
    5666              : #endif
    5667        15787 :                 NGRS = s_surf->Surface(GRSNR).BaseSurf;
    5668        15787 :                 if (s_surf->Surface(GRSNR).IsShadowing) NGRS = GRSNR;
    5669              : 
    5670              :                 // Compute the X and Y displacements of a shadow.
    5671        15787 :                 XS = s_surf->Surface(NGRS).lcsx.x * state.dataSolarShading->SUNCOS(1) +
    5672        15787 :                      s_surf->Surface(NGRS).lcsx.y * state.dataSolarShading->SUNCOS(2) +
    5673        15787 :                      s_surf->Surface(NGRS).lcsx.z * state.dataSolarShading->SUNCOS(3);
    5674        15787 :                 YS = s_surf->Surface(NGRS).lcsy.x * state.dataSolarShading->SUNCOS(1) +
    5675        15787 :                      s_surf->Surface(NGRS).lcsy.y * state.dataSolarShading->SUNCOS(2) +
    5676        15787 :                      s_surf->Surface(NGRS).lcsy.z * state.dataSolarShading->SUNCOS(3);
    5677        15787 :                 ZS = s_surf->Surface(NGRS).lcsz.x * state.dataSolarShading->SUNCOS(1) +
    5678        15787 :                      s_surf->Surface(NGRS).lcsz.y * state.dataSolarShading->SUNCOS(2) +
    5679        15787 :                      s_surf->Surface(NGRS).lcsz.z * state.dataSolarShading->SUNCOS(3);
    5680              : 
    5681        15787 :                 if (std::abs(ZS) > Constant::SmallDistance) {
    5682        15787 :                     state.dataSolarShading->XShadowProjection = XS / ZS;
    5683        15787 :                     state.dataSolarShading->YShadowProjection = YS / ZS;
    5684        15787 :                     if (std::abs(state.dataSolarShading->XShadowProjection) < 1.e-8) state.dataSolarShading->XShadowProjection = 0.0;
    5685        15787 :                     if (std::abs(state.dataSolarShading->YShadowProjection) < 1.e-8) state.dataSolarShading->YShadowProjection = 0.0;
    5686              :                 } else {
    5687            0 :                     state.dataSolarShading->XShadowProjection = 0.0;
    5688            0 :                     state.dataSolarShading->YShadowProjection = 0.0;
    5689              :                 }
    5690              : 
    5691        15787 :                 CTRANS(state,
    5692              :                        GRSNR,
    5693              :                        NGRS,
    5694              :                        NVT,
    5695        15787 :                        state.dataSolarShading->XVrt,
    5696        15787 :                        state.dataSolarShading->YVrt,
    5697        15787 :                        state.dataSolarShading->ZVrt); // Transform coordinates of the receiving surface to 2-D form
    5698              : 
    5699              :                 // Re-order its vertices to clockwise sequential.
    5700        78935 :                 for (N = 1; N <= NVT; ++N) {
    5701        63148 :                     state.dataSolarShading->XVS(N) = state.dataSolarShading->XVrt(NVT + 1 - N);
    5702        63148 :                     state.dataSolarShading->YVS(N) = state.dataSolarShading->YVrt(NVT + 1 - N);
    5703              :                 }
    5704              : 
    5705        15787 :                 HTRANS1(state, 1, NVT); // Transform to homogeneous coordinates.
    5706              : 
    5707        15787 :                 state.dataSolarShading->HCAREA(1) = -state.dataSolarShading->HCAREA(1); // Compute (+) gross surface area.
    5708        15787 :                 state.dataSolarShading->HCT(1) = 1.0;
    5709              : 
    5710        15787 :                 SHDGSS(state, NGRS, iHour, TS, GRSNR, NGSS, HTS); // Determine shadowing on surface.
    5711              : 
    5712        15787 :                 if (!state.dataSolarShading->CalcSkyDifShading) {
    5713         9865 :                     SHDBKS(state, s_surf->Surface(GRSNR).BaseSurf, GRSNR, NBKS, HTS); // Determine possible back surfaces.
    5714              :                 }
    5715              :             }
    5716              : 
    5717        15787 :             SHDSBS(state, iHour, GRSNR, NBKS, NSBS, HTS, TS); // Subtract subsurf areas from total
    5718              : 
    5719              :             // Error checking:  require that 0 <= SurfSunlitArea <= AREA.  + or - .01*AREA added for round-off errors
    5720        15787 :             SurfArea = s_surf->Surface(GRSNR).NetAreaShadowCalc;
    5721        15787 :             state.dataSolarShading->SurfSunlitArea(HTS) = max(0.0, state.dataSolarShading->SurfSunlitArea(HTS));
    5722              : 
    5723        15787 :             state.dataSolarShading->SurfSunlitArea(HTS) = min(state.dataSolarShading->SurfSunlitArea(HTS), SurfArea);
    5724              :         } // ...end of surface in sun/surface with shaders and/or subsurfaces IF-THEN block
    5725              : 
    5726              :         // NOTE:
    5727              :         // There used to be a call to legacy subroutine SHDCVR here when the
    5728              :         // zone type was not a standard zone.
    5729              :     }
    5730        33798 : }
    5731              : 
    5732         9865 : void SHDBKS(EnergyPlusData &state,
    5733              :             int const NGRS, // Number of the general receiving surface
    5734              :             int const CurSurf,
    5735              :             int const NBKS, // Number of back surfaces
    5736              :             int const HTS   // Heat transfer surface number of the general receiving surf
    5737              : )
    5738              : {
    5739              : 
    5740              :     // SUBROUTINE INFORMATION:
    5741              :     //       AUTHOR         Legacy Code
    5742              :     //       DATE WRITTEN
    5743              :     //       MODIFIED       na
    5744              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    5745              : 
    5746              :     // PURPOSE OF THIS SUBROUTINE:
    5747              :     // This is the driving subroutine for computing
    5748              :     // the sunlit areas for back surfaces.
    5749              : 
    5750              :     // REFERENCES:
    5751              :     // BLAST/IBLAST code, original author George Walton
    5752              : 
    5753              :     typedef Array2D<Int64>::size_type size_type;
    5754              :     int I;
    5755              :     int M;
    5756              :     int N;
    5757              :     int NVR;
    5758              :     int NVT; // Number of vertices of back surface
    5759              :     int BackSurfaceNumber;
    5760              :     int NS1; // Number of the figure being overlapped
    5761              :     int NS2; // Number of the figure doing overlapping
    5762              :     int NS3; // Location to place results of overlap
    5763              : 
    5764         9865 :     auto &s_surf = state.dataSurface;
    5765              : 
    5766              :     // Tuned Linear indexing
    5767              : 
    5768         9865 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    5769         9865 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    5770              : 
    5771         9865 :     if (state.dataSolarShading->SHDBKSOneTimeFlag) {
    5772           27 :         state.dataSolarShading->XVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
    5773           27 :         state.dataSolarShading->YVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
    5774           27 :         state.dataSolarShading->ZVrtx.allocate(s_surf->MaxVerticesPerSurface + 1);
    5775           27 :         state.dataSolarShading->XVrtx = 0.0;
    5776           27 :         state.dataSolarShading->YVrtx = 0.0;
    5777           27 :         state.dataSolarShading->ZVrtx = 0.0;
    5778           27 :         state.dataSolarShading->SHDBKSOneTimeFlag = false;
    5779              :     }
    5780              : 
    5781        10570 :     if ((NBKS <= 0) || (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0) || (state.dataSolarShading->OverlapStatus == TooManyVertices) ||
    5782          705 :         (state.dataSolarShading->OverlapStatus == TooManyFigures))
    5783         9160 :         return;
    5784              : 
    5785          705 :     state.dataSolarShading->FBKSHC = state.dataSolarShading->LOCHCA + 1;
    5786              : 
    5787         4230 :     for (I = 1; I <= NBKS; ++I) { // Loop through all back surfaces associated with the receiving surface
    5788              : 
    5789         3525 :         BackSurfaceNumber = state.dataShadowComb->ShadowComb(CurSurf).BackSurf(I);
    5790              : 
    5791         3525 :         if (state.dataSolarShading->SurfSunCosTheta(BackSurfaceNumber) > -DataEnvironment::SunIsUpValue)
    5792         1410 :             continue; //-0.001) CYCLE ! go to next back surface since inside of this surface
    5793              :         // cannot be in sun if the outside can be
    5794              : 
    5795              :         // Transform coordinates of back surface from general system to the
    5796              :         // plane of the receiving surface
    5797              : 
    5798         2115 :         CTRANS(state, BackSurfaceNumber, NGRS, NVT, state.dataSolarShading->XVrtx, state.dataSolarShading->YVrtx, state.dataSolarShading->ZVrtx);
    5799              : 
    5800              :         // Project "shadow" from back surface along sun's rays to receiving surface.  Back surface vertices
    5801              :         // become clockwise sequential.
    5802              : 
    5803        10575 :         for (N = 1; N <= NVT; ++N) {
    5804         8460 :             state.dataSolarShading->XVS(N) =
    5805         8460 :                 state.dataSolarShading->XVrtx(N) - state.dataSolarShading->XShadowProjection * state.dataSolarShading->ZVrtx(N);
    5806         8460 :             state.dataSolarShading->YVS(N) =
    5807         8460 :                 state.dataSolarShading->YVrtx(N) - state.dataSolarShading->YShadowProjection * state.dataSolarShading->ZVrtx(N);
    5808              :         }
    5809              : 
    5810              :         // Transform to the homogeneous coordinate system.
    5811              : 
    5812         2115 :         NS3 = state.dataSolarShading->LOCHCA + 1;
    5813         2115 :         state.dataSolarShading->HCT(NS3) = 0.0;
    5814         2115 :         HTRANS1(state, NS3, NVT);
    5815              : 
    5816              :         // Adjust near-duplicate points.
    5817              : 
    5818         2115 :         NVR = state.dataSolarShading->HCNV(1);
    5819         2115 :         int l3 = state.dataSolarShading->HCX.index(NS3, 1);
    5820        10575 :         for (N = 1; N <= NVT; ++N, ++l3) {
    5821         8460 :             Real64 const x3 = state.dataSolarShading->HCX[l3]; // [ l3 ] == ( NS3, N )
    5822         8460 :             Real64 const y3 = state.dataSolarShading->HCY[l3];
    5823         8460 :             size_type l1 = 0;
    5824        35240 :             for (M = 1; M <= NVR; ++M, ++l1) {
    5825        29600 :                 if (std::abs(state.dataSolarShading->HCX[l1] - x3) > 6) continue; // [ l1 ] == ( 1, M )
    5826         4230 :                 if (std::abs(state.dataSolarShading->HCY[l1] - y3) > 6) continue;
    5827         2820 :                 state.dataSolarShading->HCX[l3] = state.dataSolarShading->HCX[l1];
    5828         2820 :                 state.dataSolarShading->HCY[l3] = state.dataSolarShading->HCY[l1];
    5829         2820 :                 break;
    5830              :             }
    5831              :         }
    5832              : 
    5833         2115 :         HTRANS0(state, NS3, NVT);
    5834              : 
    5835              :         // Determine area of overlap of projected back surface and receiving surface.
    5836              : 
    5837         2115 :         NS1 = 1;
    5838         2115 :         NS2 = NS3;
    5839         2115 :         state.dataSolarShading->HCT(NS3) = 1.0;
    5840         2115 :         DeterminePolygonOverlap(state, NS1, NS2, NS3);
    5841              : 
    5842         2115 :         if (state.dataSolarShading->OverlapStatus == NoOverlap) continue; // to next back surface
    5843         1446 :         if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
    5844            0 :             break; // back surfaces DO loop
    5845              : 
    5846              :         // Increment back surface count.
    5847              : 
    5848         1446 :         state.dataSolarShading->LOCHCA = NS3;
    5849         1446 :         state.dataSolarShading->HCNS(state.dataSolarShading->LOCHCA) = BackSurfaceNumber;
    5850         1446 :         state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
    5851         1446 :         state.dataSolarShading->NBKSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FBKSHC + 1;
    5852              :     }
    5853              : }
    5854              : 
    5855        15787 : void SHDGSS(EnergyPlusData &state,
    5856              :             int const NGRS,
    5857              :             int const iHour,   // Hour Counter
    5858              :             int const TS,      // TimeStep
    5859              :             int const CurSurf, // Current Surface
    5860              :             int const NGSS,    // Number of general shadowing surfaces
    5861              :             int const HTS      // Heat transfer surface number of the general receiving surf
    5862              : )
    5863              : {
    5864              : 
    5865              :     // SUBROUTINE INFORMATION:
    5866              :     //       AUTHOR         Legacy Code
    5867              :     //       DATE WRITTEN
    5868              :     //       MODIFIED       na
    5869              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    5870              : 
    5871              :     // PURPOSE OF THIS SUBROUTINE:
    5872              :     // This subroutine determines the shadows on a general receiving surface.
    5873              : 
    5874              :     // REFERENCES:
    5875              :     // BLAST/IBLAST code, original author George Walton
    5876              : 
    5877              :     typedef Array2D<Int64>::size_type size_type;
    5878              :     int GSSNR;             // General shadowing surface number
    5879              :     int MainOverlapStatus; // Overlap status of the main overlap calculation not the check for
    5880              :     // multiple overlaps (unless there was an error)
    5881              :     int NS1;         // Number of the figure being overlapped
    5882              :     int NS2;         // Number of the figure doing overlapping
    5883              :     int NS3;         // Location to place results of overlap
    5884              :     Real64 SchValue; // Value for Schedule of shading transmittance
    5885              : 
    5886        15787 :     auto &s_surf = state.dataSurface;
    5887              : 
    5888        15787 :     if (state.dataSolarShading->SHDGSSOneTimeFlag) {
    5889           29 :         state.dataSolarShading->XVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
    5890           29 :         state.dataSolarShading->YVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
    5891           29 :         state.dataSolarShading->ZVert.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
    5892           29 :         state.dataSolarShading->SHDGSSOneTimeFlag = false;
    5893              :     }
    5894              : 
    5895        15787 :     state.dataSolarShading->FGSSHC = state.dataSolarShading->LOCHCA + 1;
    5896        15787 :     MainOverlapStatus = NoOverlap; // Set to ensure that the value from the last surface is not saved
    5897        15787 :     state.dataSolarShading->OverlapStatus = NoOverlap;
    5898              : 
    5899        15787 :     if (NGSS <= 0) { // IF NO S.S., receiving surface FULLY SUNLIT.
    5900              : 
    5901         4958 :         state.dataSolarShading->SurfSunlitArea(HTS) = state.dataSolarShading->HCAREA(1); // Surface fully sunlit
    5902              : 
    5903              :     } else {
    5904              : 
    5905        10829 :         int ExitLoopStatus = -1;
    5906        10829 :         auto const &GenSurf = state.dataShadowComb->ShadowComb(CurSurf).GenSurf;
    5907        10829 :         int const sunIsUp = DataEnvironment::SunIsUpValue;
    5908        27796 :         for (int I = 1; I <= NGSS; ++I) { // Loop through all shadowing surfaces...
    5909              : 
    5910        17924 :             GSSNR = GenSurf(I);
    5911              : 
    5912        17924 :             if (state.dataSolarShading->SurfSunCosTheta(GSSNR) > sunIsUp) continue; //.001) CYCLE ! NO SHADOW IF GSS IN SUNLIGHT.
    5913              : 
    5914        12923 :             auto const &surface = s_surf->Surface(GSSNR);
    5915        12923 :             bool const notHeatTransSurf = !surface.HeatTransSurf;
    5916              : 
    5917              :             //     This used to check to see if the shadowing surface was not opaque (within the scheduled dates of
    5918              :             //            transmittance value.  Perhaps it ignored it if it were outside the range.  (if so, was an error)
    5919              :             //     The proper action seems to be delete this statement all together, but there would also be no shading if
    5920              :             //            the shading surface were transparent...
    5921              :             //---former stmt      IF ((.NOT.Surface(GSSNR)%HeatTransSurf) .AND. &
    5922              :             //---former stmt            GetCurrentScheduleValue(state, Surface(GSSNR)%SchedShadowSurfIndex,IHOUR) == 0.0) CYCLE
    5923              : 
    5924        12923 :             if (notHeatTransSurf) {
    5925         8315 :                 if (surface.IsTransparent) continue; // No shadow if shading surface is transparent
    5926         8315 :                 if (surface.shadowSurfSched != nullptr) {
    5927         6819 :                     if (surface.shadowSurfSched->getHrTsVal(state, iHour) == 1.0) continue;
    5928         5722 :                     if (!state.dataSolarShading->CalcSkyDifShading) {
    5929         3619 :                         if (surface.shadowSurfSched->getHrTsVal(state, iHour, TS) == 1.0) continue;
    5930              :                     }
    5931              :                 }
    5932              :             }
    5933              :             // Eliminate shadowing surfaces that is supposed to be disabled.
    5934        11826 :             if (state.dataSysVars->DisableAllSelfShading) {
    5935            0 :                 if (surface.Zone != 0) {
    5936            0 :                     continue; // Disable all shadowing surfaces in all zones. Attached shading surfaces are not part of a zone, zone value is 0.
    5937              :                 }
    5938        11826 :             } else if (state.dataSysVars->DisableGroupSelfShading) {
    5939            0 :                 std::vector<int> DisabledZones = s_surf->SurfShadowDisabledZoneList(CurSurf);
    5940            0 :                 bool isDisabledShadowSurf = false;
    5941            0 :                 for (int i : DisabledZones) {
    5942            0 :                     if (surface.Zone == i) {
    5943            0 :                         isDisabledShadowSurf = true;
    5944            0 :                         break;
    5945              :                     }
    5946              :                 }
    5947            0 :                 if (isDisabledShadowSurf) continue; // Disable all shadowing surfaces in all disabled zones.
    5948            0 :             }
    5949              : 
    5950              :             //      IF ((.NOT.Surface(GSSNR)%HeatTransSurf) .AND. &
    5951              :             //            GetCurrentScheduleValue(state, Surface(GSSNR)%SchedShadowSurfIndex) == 1.0) CYCLE
    5952              : 
    5953              :             // Transform shadow casting surface from cartesian to homogeneous coordinates according to surface type.
    5954              : 
    5955        11826 :             if ((notHeatTransSurf) && (surface.BaseSurf != 0)) {
    5956              : 
    5957              :                 // For shadowing subsurface coordinates of shadow casting surface are relative to the receiving surface
    5958              :                 // project shadow to the receiving surface
    5959              : 
    5960            0 :                 state.dataSolarShading->NVS = surface.Sides;
    5961            0 :                 auto const &XV = s_surf->ShadeV(GSSNR).XV;
    5962            0 :                 auto const &YV = s_surf->ShadeV(GSSNR).YV;
    5963            0 :                 auto const &ZV = s_surf->ShadeV(GSSNR).ZV;
    5964            0 :                 for (int N = 1; N <= state.dataSolarShading->NVS; ++N) {
    5965            0 :                     state.dataSolarShading->XVS(N) = XV(N) - state.dataSolarShading->XShadowProjection * ZV(N);
    5966            0 :                     state.dataSolarShading->YVS(N) = YV(N) - state.dataSolarShading->YShadowProjection * ZV(N);
    5967              :                 }
    5968              : 
    5969            0 :             } else {
    5970              :                 // Transform coordinates of shadow casting surface from general system to the system relative to the receiving surface
    5971              :                 int NVT;
    5972        11826 :                 CTRANS(state, GSSNR, NGRS, NVT, state.dataSolarShading->XVert, state.dataSolarShading->YVert, state.dataSolarShading->ZVert);
    5973        11826 :                 CLIP(state,
    5974              :                      NVT,
    5975        11826 :                      state.dataSolarShading->XVert,
    5976        11826 :                      state.dataSolarShading->YVert,
    5977        11826 :                      state.dataSolarShading->ZVert); // Clip portions of the shadow casting surface which are behind the receiving surface
    5978              : 
    5979        11826 :                 if (state.dataSolarShading->NumVertInShadowOrClippedSurface <= 2) continue;
    5980              : 
    5981              :                 // Project shadow from shadow casting surface along sun's rays to receiving surface Shadow vertices
    5982              :                 // become clockwise sequential
    5983              : 
    5984        59098 :                 for (int N = 1; N <= state.dataSolarShading->NumVertInShadowOrClippedSurface; ++N) {
    5985        47272 :                     state.dataSolarShading->XVS(N) =
    5986        47272 :                         state.dataSolarShading->XVC(N) - state.dataSolarShading->XShadowProjection * state.dataSolarShading->ZVC(N);
    5987        47272 :                     state.dataSolarShading->YVS(N) =
    5988        47272 :                         state.dataSolarShading->YVC(N) - state.dataSolarShading->YShadowProjection * state.dataSolarShading->ZVC(N);
    5989              :                 }
    5990              :             }
    5991              : 
    5992              :             // Transform to the homogeneous coordinate system.
    5993              : 
    5994        11826 :             NS3 = state.dataSolarShading->LOCHCA + 1;
    5995        11826 :             HTRANS1(state, NS3, state.dataSolarShading->NVS);
    5996              : 
    5997              :             // Adjust near-duplicate points.
    5998              : 
    5999        11826 :             assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    6000        11826 :             assert(state.dataSolarShading->HCX.index(1, 1) == 0u);
    6001        11826 :             size_type j(state.dataSolarShading->HCX.index(NS3, 1));
    6002        11826 :             size_type NVR(state.dataSolarShading->HCNV(1));
    6003        59098 :             for (int N = 1; N <= state.dataSolarShading->NumVertInShadowOrClippedSurface;
    6004        47272 :                  ++N, ++j) {                                       // Tuned Logic change: break after 1st "close" point found
    6005        47272 :                 Int64 const HCX_N(state.dataSolarShading->HCX[j]); // [ j ] == ( NS3, N )
    6006        47272 :                 Int64 const HCY_N(state.dataSolarShading->HCY[j]);
    6007       234767 :                 for (size_type l = 0; l < NVR; ++l) { // [ l ] == ( 1, l+1 )
    6008       188150 :                     Real64 const delX = std::abs(state.dataSolarShading->HCX[l] - HCX_N);
    6009       188150 :                     if (delX > 6) continue;
    6010         3436 :                     Real64 const delY = std::abs(state.dataSolarShading->HCY[l] - HCY_N);
    6011         3436 :                     if (delY > 6) continue;
    6012          655 :                     if (delX > 0) state.dataSolarShading->HCX[j] = state.dataSolarShading->HCX[l]; // [ j ] == ( NS3, N )
    6013          655 :                     if (delY > 0) state.dataSolarShading->HCY[j] = state.dataSolarShading->HCY[l];
    6014          655 :                     break;
    6015              :                 }
    6016              :             }
    6017        11826 :             HTRANS0(state, NS3, state.dataSolarShading->NumVertInShadowOrClippedSurface);
    6018        11826 :             if (!state.dataSolarShading->CalcSkyDifShading && surface.shadowSurfSched != nullptr) {
    6019         3619 :                 if (iHour != 0) {
    6020         3619 :                     SchValue = surface.shadowSurfSched->getHrTsVal(state, iHour, TS);
    6021              :                 } else {
    6022            0 :                     SchValue = surface.SchedMinValue;
    6023              :                 }
    6024              :             } else {
    6025         8207 :                 SchValue = surface.SchedMinValue;
    6026              :             }
    6027              : 
    6028        11826 :             state.dataSolarShading->HCT(NS3) = SchValue;
    6029              : 
    6030              :             // Determine overlap of shadow with receiving surface
    6031              : 
    6032        11826 :             state.dataSolarShading->CurrentShadowingSurface = I;
    6033        11826 :             state.dataSolarShading->CurrentSurfaceBeingShadowed = GSSNR;
    6034        11826 :             NS1 = 1;
    6035        11826 :             NS2 = NS3;
    6036        11826 :             DeterminePolygonOverlap(state, NS1, NS2, NS3);
    6037              :             //  Next statement is special to deal with transmitting shading devices
    6038        11826 :             if (state.dataSolarShading->OverlapStatus == FirstSurfWithinSecond && SchValue > 0.0)
    6039           67 :                 state.dataSolarShading->OverlapStatus = PartialOverlap;
    6040        11826 :             MainOverlapStatus = state.dataSolarShading->OverlapStatus;
    6041        11826 :             ExitLoopStatus = MainOverlapStatus;
    6042              : 
    6043        11826 :             if (MainOverlapStatus == NoOverlap) { // No overlap of general surface shadow and receiving surface
    6044              :                                                   // Continue
    6045         7693 :             } else if ((MainOverlapStatus == FirstSurfWithinSecond) || (MainOverlapStatus == TooManyVertices) ||
    6046              :                        (MainOverlapStatus == TooManyFigures)) {
    6047          957 :                 goto ShadowingSurfaces_exit;
    6048         6736 :             } else if ((MainOverlapStatus == SecondSurfWithinFirst) || (MainOverlapStatus == PartialOverlap)) {
    6049              :                 // Determine overlaps with previous shadows.
    6050         6736 :                 state.dataSolarShading->LOCHCA = NS3;
    6051         6736 :                 state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
    6052         7863 :                 if (state.dataSolarShading->NGSSHC > 1)
    6053         1127 :                     MULTOL(state,
    6054         1127 :                            state.dataSolarShading->LOCHCA,
    6055         1127 :                            state.dataSolarShading->FGSSHC - 1,
    6056         1127 :                            state.dataSolarShading->NGSSHC - 1); // HOYT - Remove this call
    6057              :             } else {
    6058            0 :                 goto ShadowingSurfaces_exit;
    6059              :             }
    6060              : 
    6061        10869 :             ExitLoopStatus = -1;
    6062              :         }
    6063         9872 :     ShadowingSurfaces_exit:;
    6064              : 
    6065              :         // Compute sunlit area of surface (excluding effects of subsurfs).
    6066              : 
    6067        10829 :         if (ExitLoopStatus == FirstSurfWithinSecond) { // Surface fully shaded
    6068          957 :             state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
    6069          957 :             state.dataSolarShading->LOCHCA = state.dataSolarShading->FGSSHC;
    6070              : 
    6071         9872 :         } else if ((ExitLoopStatus == TooManyVertices) || (ExitLoopStatus == TooManyFigures)) { // Array limits exceeded, estimate
    6072            0 :             state.dataSolarShading->SurfSunlitArea(HTS) = 0.25 * state.dataSolarShading->HCAREA(1);
    6073              : 
    6074              :         } else {
    6075              : 
    6076              :             // Compute the sunlit area here.
    6077              :             // Call UnionShadow(FGSSHC,LOCHCA)
    6078              : 
    6079         9872 :             state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
    6080         9872 :             if (state.dataSolarShading->NGSSHC <= 0) {
    6081         4263 :                 state.dataSolarShading->SurfSunlitArea(HTS) = state.dataSolarShading->HCAREA(1); // Surface fully sunlit
    6082              :             } else {
    6083         5609 :                 Real64 A(state.dataSolarShading->HCAREA(1)); // Area
    6084        12935 :                 for (int i = state.dataSolarShading->FGSSHC, e = state.dataSolarShading->FGSSHC + state.dataSolarShading->NGSSHC - 1; i <= e; ++i) {
    6085         7326 :                     A += state.dataSolarShading->HCAREA(i) * (1.0 - state.dataSolarShading->HCT(i));
    6086              :                 }
    6087         5609 :                 state.dataSolarShading->SurfSunlitArea(HTS) = A;
    6088         5609 :                 if (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0) { // Surface fully shaded
    6089           25 :                     state.dataSolarShading->SurfSunlitArea(HTS) = 0.0;
    6090           25 :                     state.dataSolarShading->LOCHCA = state.dataSolarShading->FGSSHC;
    6091              :                 }
    6092              :             }
    6093              :         }
    6094              :     }
    6095        15787 :     state.dataSolarShading->NGSSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FGSSHC + 1;
    6096        15787 : }
    6097              : 
    6098         6982 : void CalcInteriorSolarOverlaps(EnergyPlusData &state,
    6099              :                                int const iHour, // Hour Index
    6100              :                                int const NBKS,  // Number of back surfaces associated with this GRSNR (in general, only
    6101              :                                int const HTSS,  // Surface number of the subsurface (exterior window)
    6102              :                                int const GRSNR, // General receiving surface number (base surface of the exterior window)
    6103              :                                int const TS     // Time step Index
    6104              : )
    6105              : {
    6106              : 
    6107              :     // SUBROUTINE INFORMATION:
    6108              :     //       AUTHOR         Fred Winkelmann
    6109              :     //       DATE WRITTEN   January 1999
    6110              :     //       MODIFIED       Nov 2001, FW: include beam radiation overlaps with
    6111              :     //                       back windows and doors; previously these subsurfaces ignored.
    6112              :     //                      May 2002, FW: fix problem where reveal was not being considered
    6113              :     //                       in calculating overlap areas if window is shaded only by reveal.
    6114              :     //                      June 2002, FW: fix problem that gave incorrect calculation when
    6115              :     //                       window is not shaded only by reveal
    6116              :     //                      June 2002, FW: remove incorrect multiplication of overlap areas
    6117              :     //                       by sunlit fraction when window is shaded only by reveal
    6118              : 
    6119              :     // PURPOSE OF THIS SUBROUTINE:
    6120              :     // For an exterior window with surface number HTSS, determines (1) the surface numbers of back
    6121              :     // surfaces receiving beam radiation from the window and (2) for each such back surface, the area
    6122              :     // of the portion of the window sending beam radiation to the back surface; this is called the
    6123              :     // "overlap area."
    6124              : 
    6125              :     // REFERENCES:
    6126              :     // BLAST/IBLAST code, original author George Walton
    6127              : 
    6128              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    6129              :     //  some of these will receive beam radiation from HTSS this hour)
    6130              : 
    6131              :     // SUBROUTINE PARAMETER DEFINITIONS:
    6132         6982 :     int constexpr WindowShadedOnlyByReveal(2); // for use with RevealStatus
    6133              : 
    6134              :     typedef Array2D<Int64>::size_type size_type;
    6135              :     int JBKS;        // Counter of back surfaces with non-zero overlap with HTSS
    6136              :     int BackSurfNum; // Back surface number
    6137              : 
    6138              :     bool UseSimpleDistribution; // TRUE means simple interior solar distribution
    6139              :     // (all incoming beam assumed to strike floor),
    6140              :     // FALSE means exact interior solar distribution
    6141              :     // (track which back surfaces beam illuminates)
    6142              : 
    6143         6982 :     auto &s_surf = state.dataSurface;
    6144              : 
    6145              :     // Tuned Linear indexing
    6146              : 
    6147         6982 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCY));
    6148         6982 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCA));
    6149         6982 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCB));
    6150         6982 :     assert(equal_dimensions(state.dataSolarShading->HCX, state.dataSolarShading->HCC));
    6151              : 
    6152         6982 :     if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
    6153              : 
    6154         3822 :         UseSimpleDistribution = false;
    6155              : 
    6156         3822 :         if ((NBKS <= 0) || (s_surf->Surface(GRSNR).ExtBoundCond > 0)) {
    6157              : 
    6158         3117 :             UseSimpleDistribution = true;
    6159              : 
    6160              :         } else {
    6161              :             // Using 'exact' distribution, replace subsurface HC entries with reveal HC entries
    6162              :             // so that the reveal HC is used in calculating interior solar overlap areas
    6163              : 
    6164              :             // Adding the following line fixes a problem where, if the window was shaded only
    6165              :             // by reveal, then the reveal was not considered in calculating interior solar
    6166              :             // overlap areas (FCW 5/3/02).
    6167              :             // IF(Surface(HTSS)%Reveal > 0.0) NRVLHC = 1
    6168              :             // Changing the line to the following avoids incorrect calculation when window is not shaded
    6169              :             // only by reveal (FCW 6/28/02).
    6170          705 :             if (state.dataSolarShading->SurfWinRevealStatus(iHour, TS, HTSS) == WindowShadedOnlyByReveal) state.dataSolarShading->NRVLHC = 1;
    6171          705 :             if (state.dataSolarShading->NRVLHC > 0) {
    6172            0 :                 for (int I = 1; I <= state.dataSolarShading->NRVLHC; ++I) {
    6173            0 :                     int const iS(state.dataSolarShading->FSBSHC - 1 + I);
    6174            0 :                     int const iR(state.dataSolarShading->FRVLHC - 1 + I);
    6175            0 :                     state.dataSolarShading->HCT(iS) = state.dataSolarShading->HCT(iR);
    6176            0 :                     state.dataSolarShading->HCNV(iS) = state.dataSolarShading->HCNV(iR);
    6177            0 :                     state.dataSolarShading->HCAREA(iS) = state.dataSolarShading->HCAREA(iR);
    6178            0 :                     size_type lS(state.dataSolarShading->HCX.index(iS, 1));
    6179            0 :                     size_type lR(state.dataSolarShading->HCX.index(iR, 1));
    6180            0 :                     for (int J = 1; J <= state.dataSolarShading->MaxHCV; ++J, ++lS, ++lR) { // [ lS ] == ( iS, J ), [ lR ] == ( iR, J )
    6181            0 :                         state.dataSolarShading->HCX[lS] = state.dataSolarShading->HCX[lR];
    6182            0 :                         state.dataSolarShading->HCY[lS] = state.dataSolarShading->HCY[lR];
    6183            0 :                         state.dataSolarShading->HCA[lS] = state.dataSolarShading->HCA[lR];
    6184            0 :                         state.dataSolarShading->HCB[lS] = state.dataSolarShading->HCB[lR];
    6185            0 :                         state.dataSolarShading->HCC[lS] = state.dataSolarShading->HCC[lR];
    6186              :                     }
    6187              :                 }
    6188            0 :                 state.dataSolarShading->NSBSHC = state.dataSolarShading->NRVLHC;
    6189              :             }
    6190              :         }
    6191              : 
    6192              :         // Check for array space.
    6193         3822 :         if (state.dataSolarShading->FSBSHC + state.dataSolarShading->NBKSHC > state.dataSolarShading->MaxHCS) UseSimpleDistribution = true;
    6194              : 
    6195         3822 :         if (!UseSimpleDistribution) { // Compute overlaps
    6196              : 
    6197          705 :             std::unordered_map<unsigned, float> pssas;
    6198              : 
    6199              : #ifndef EP_NO_OPENGL
    6200          705 :             if (state.dataSolarShading->penumbra) {
    6201              :                 // Add back surfaces to array
    6202            0 :                 std::vector<unsigned> pbBackSurfaces;
    6203            0 :                 for (int bkSurfNum : state.dataShadowComb->ShadowComb(GRSNR).BackSurf) {
    6204            0 :                     if (bkSurfNum == 0) continue;
    6205            0 :                     if (state.dataSolarShading->SurfSunCosTheta(bkSurfNum) < DataEnvironment::SunIsUpValue) {
    6206            0 :                         pbBackSurfaces.push_back(s_surf->SurfPenumbraID(bkSurfNum));
    6207              :                     }
    6208              :                 }
    6209            0 :                 pssas = state.dataSolarShading->penumbra->calculate_interior_pssas({(unsigned)s_surf->SurfPenumbraID(HTSS)}, pbBackSurfaces);
    6210              :                 // penumbra->render_interior_scene({(unsigned)Surface(HTSS).PenumbraID}, pbBackSurfaces);
    6211              : 
    6212            0 :                 JBKS = 0;
    6213            0 :                 for (int bkSurfNum : state.dataShadowComb->ShadowComb(GRSNR).BackSurf) {
    6214            0 :                     if (bkSurfNum == 0) continue;
    6215            0 :                     if (pssas[s_surf->SurfPenumbraID(bkSurfNum)] > 0) {
    6216            0 :                         ++JBKS;
    6217            0 :                         state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, JBKS, HTSS) = bkSurfNum;
    6218            0 :                         Real64 OverlapArea = pssas[s_surf->SurfPenumbraID(bkSurfNum)] / state.dataSolarShading->SurfSunCosTheta(HTSS);
    6219            0 :                         state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS) = OverlapArea * s_surf->SurfaceWindow(HTSS).glazedFrac;
    6220              :                     }
    6221              :                 }
    6222            0 :             }
    6223              : #endif
    6224              : 
    6225          705 :             if (!state.dataSolarShading->penumbra) {
    6226              : 
    6227          705 :                 state.dataSolarShading->FINSHC = state.dataSolarShading->FSBSHC + state.dataSolarShading->NSBSHC;
    6228              : 
    6229          705 :                 JBKS = 0;
    6230              : 
    6231         2151 :                 for (int IBKS = 1; IBKS <= state.dataSolarShading->NBKSHC;
    6232              :                      ++IBKS) { // Loop over back surfaces to GRSNR this hour. NBKSHC is the number of
    6233              :                     // back surfaces that would receive beam radiation from the base surface, GRSNR,
    6234              :                     // if the base surface was transparent. In general, some (at least one) or all of these
    6235              :                     // will receive beam radiation from the exterior window subsurface, HTSS, of GRSNR,
    6236              :                     // depending on the size of HTSS and its location on GRSNR
    6237              : 
    6238         1446 :                     BackSurfNum = state.dataSolarShading->HCNS(state.dataSolarShading->FBKSHC - 1 + IBKS);
    6239              : 
    6240              :                     // Determine if this back surface number can receive beam radiation from the
    6241              :                     // exterior window, HTSS, this hour, i.e., overlap area is positive
    6242              : 
    6243         1446 :                     state.dataSolarShading->LOCHCA = state.dataSolarShading->FINSHC - 1;
    6244              : 
    6245         1446 :                     MULTOL(state, state.dataSolarShading->FBKSHC - 1 + IBKS, state.dataSolarShading->FSBSHC - 1, state.dataSolarShading->NSBSHC);
    6246              : 
    6247              :                     // Compute overlap area for this back surface
    6248              : 
    6249         1446 :                     state.dataSolarShading->NINSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FINSHC + 1;
    6250         1446 :                     if (state.dataSolarShading->NINSHC <= 0) continue;
    6251         1222 :                     Real64 OverlapArea = state.dataSolarShading->HCAREA(state.dataSolarShading->FINSHC);
    6252         1222 :                     for (int J = 2; J <= state.dataSolarShading->NINSHC; ++J) {
    6253            0 :                         OverlapArea += state.dataSolarShading->HCAREA(state.dataSolarShading->FINSHC - 1 + J) *
    6254            0 :                                        (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FINSHC - 1 + J));
    6255              :                     }
    6256              : 
    6257         1222 :                     if (OverlapArea > 0.001) {
    6258         1222 :                         ++JBKS;
    6259         1222 :                         if (JBKS <= state.dataBSDFWindow->MaxBkSurf) {
    6260         1222 :                             state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, JBKS, HTSS) = BackSurfNum;
    6261         1222 :                             int baseSurfaceNum = s_surf->Surface(BackSurfNum).BaseSurf;
    6262         1222 :                             state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS) = OverlapArea * s_surf->SurfaceWindow(HTSS).glazedFrac;
    6263              :                             // If this is a subsurface, subtract its overlap area from its base surface
    6264         1222 :                             if (baseSurfaceNum != BackSurfNum) {
    6265            0 :                                 for (int iBaseBKS = 1; iBaseBKS <= JBKS; ++iBaseBKS) {
    6266            0 :                                     if (baseSurfaceNum == state.dataHeatBal->SurfWinBackSurfaces(iHour, TS, iBaseBKS, HTSS)) {
    6267            0 :                                         state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, iBaseBKS, HTSS) =
    6268            0 :                                             max(0.0,
    6269            0 :                                                 state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, iBaseBKS, HTSS) -
    6270            0 :                                                     state.dataHeatBal->SurfWinOverlapAreas(iHour, TS, JBKS, HTSS));
    6271            0 :                                         break;
    6272              :                                     }
    6273              :                                 }
    6274              :                             }
    6275              :                         }
    6276              :                     }
    6277              :                 } // End of loop over back surfaces
    6278              :             }
    6279          705 :         }
    6280              :     } // End of check that sunlit area > 0.
    6281         6982 : }
    6282              : 
    6283        71220 : void CalcInteriorSolarDistribution(EnergyPlusData &state)
    6284              : {
    6285              : 
    6286              :     // SUBROUTINE INFORMATION:
    6287              :     //       AUTHOR         Fred Winkelmann
    6288              :     //       DATE WRITTEN   January 1999
    6289              :     //       MODIFIED       Nov 1999, FW, for Window5 calculation method
    6290              :     //                      Oct 2000, FW: add transmitted solar variables for reporting
    6291              :     //                      Mar 2001, FW: add new calc of solar absorbed by window shades
    6292              :     //                      May 2001, FW: add calc of solar transmitted and absorbed by window blinds
    6293              :     //                      Oct 2001, LL: remove interpolation, solar now at time step
    6294              :     //                      Oct 2001, FW: add solar transmitted through interior windows
    6295              :     //                      Mar 24, 2001, FW: remove incorrect multiplication of Boverlap by sunlit fraction
    6296              :     //                                        since effect of shadowing is already included in Aoverlap
    6297              :     //                      Apr 2001, FW: add effects of beam solar reflection from outside and inside reveals
    6298              :     //                      Jan 2003, FW: add between-glass shades and blinds
    6299              :     //                      Dec 2003, FW: report beam incident on inside of surface
    6300              :     //                      Jan 2004, FW: for blinds with horizontal slats, allow different diffuse/diffuse
    6301              :     //                                    transmittance for ground and sky solar
    6302              :     //                      Apr 2004, FW: allow diffusing glazing
    6303              :     //                      May 2006, RR: allow external window screen
    6304              :     //                      Jan 2010, TH: add calculating and reporting of WinBmBmSolar, WinBmDifSolar,
    6305              :     //                                    WinBmBmSolarEnergy, and WinBmDifSolarEnergy
    6306              :     //                      Jun 2013, SV: scheduled surface gains for walls and windows
    6307              : 
    6308              :     // PURPOSE OF THIS SUBROUTINE:
    6309              :     // For a time step, calculates solar radiation absorbed by exterior
    6310              :     // surfaces and interior solar radiation distribution
    6311              : 
    6312              :     using Dayltg::TransTDD;
    6313              :     using namespace DataWindowEquivalentLayer;
    6314              : 
    6315        71220 :     Array1D<Real64> CFBoverlap;    // Sum of boverlap for each back surface
    6316        71220 :     Array2D<Real64> CFDirBoverlap; // Directional boverlap (Direction, IBack)
    6317              : 
    6318        71220 :     auto &s_mat = state.dataMaterial;
    6319        71220 :     auto &s_surf = state.dataSurface;
    6320              : 
    6321              : #ifdef EP_Count_Calls
    6322              :     ++state.dataTimingsData->NumIntSolarDist_Calls;
    6323              : #endif
    6324              : 
    6325       170529 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    6326       212066 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    6327       112757 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
    6328       112757 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
    6329       112757 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
    6330       143871 :             for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
    6331       248912 :                 for (int lay = 1; lay <= CFSMAXNL + 1; ++lay) {
    6332       217798 :                     s_surf->SurfWinA(SurfNum, lay) = 0.0;
    6333              :                 }
    6334        31114 :                 state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfNum) = 0.0;
    6335        31114 :                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = 0.0;
    6336              :             }
    6337       112757 :             int const firstSurfOpaque = thisSpace.OpaqOrIntMassSurfaceFirst;
    6338       112757 :             int const lastSurfOpaque = thisSpace.OpaqOrIntMassSurfaceLast;
    6339       694821 :             for (int SurfNum = firstSurfOpaque; SurfNum <= lastSurfOpaque; ++SurfNum) {
    6340       582064 :                 s_surf->SurfOpaqAI(SurfNum) = 0.0;
    6341       582064 :                 s_surf->SurfOpaqAO(SurfNum) = 0.0;
    6342              :             }
    6343              :         }
    6344              :     }
    6345              : 
    6346        71220 :     if ((int)state.dataDaylightingDevicesData->TDDPipe.size() > 0) {
    6347            0 :         for (auto &e : state.dataDaylightingDevicesData->TDDPipe) {
    6348            0 :             int SurfDome = e.Dome;
    6349            0 :             for (int lay = 1; lay <= CFSMAXNL + 1; ++lay) {
    6350            0 :                 s_surf->SurfWinA(SurfDome, lay) = 0.0;
    6351              :             }
    6352            0 :             state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfDome) = 0.0;
    6353            0 :             state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfDome) = 0.0;
    6354              :         }
    6355              :     }
    6356              : 
    6357       177272 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    6358              :         // Solar entering a zone as beam or diffuse radiation, originating as beam solar incident on exterior windows)/(Beam normal solar) [W/(W/m2)]
    6359       106052 :         Real64 BTOTZone = 0.0;
    6360              :         // Beam radiation from exterior windows absorbed in a zone or transmitted through
    6361       106052 :         Real64 BABSZone = 0.0;
    6362       106052 :         state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
    6363       106052 :         state.dataHeatBal->EnclSolDBSSG(enclosureNum) = 0.0;
    6364       106052 :         state.dataHeatBal->EnclSolDBIntWin(enclosureNum) = 0.0;
    6365              :         // Loop over exterior surfaces in this zone
    6366       106052 :         auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
    6367              :         // delete values from previous timestep
    6368       106052 :         if (state.dataHeatBal->AnyBSDF) s_surf->SurfWinACFOverlap = 0.0;
    6369              : 
    6370              :         //-------------------------------------------------------------------------
    6371              :         // EXTERIOR BEAM SOLAR RADIATION ABSORBED ON THE OUTSIDE OF OPAQUE SURFACES
    6372              :         //-------------------------------------------------------------------------
    6373              :         // TODO: use opaq and window loop after airboundary is sorted
    6374              :         // TODO: It may be useful to sort SurfacePtr to group windows and domes together to reduce if conditions
    6375       719225 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    6376       613173 :             if (s_surf->Surface(SurfNum).Class != SurfaceClass::Window && s_surf->Surface(SurfNum).Class != SurfaceClass::TDD_Dome) {
    6377       582057 :                 if (!s_surf->Surface(SurfNum).HeatTransSurf) continue;
    6378       582057 :                 if (!s_surf->Surface(SurfNum).ExtSolar) continue;
    6379       348126 :                 int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
    6380       348126 :                 Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
    6381       348126 :                 Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
    6382       348126 :                 s_surf->SurfOpaqAO(SurfNum) = state.dataConstruction->Construct(ConstrNum).OutsideAbsorpSolar * CosInc * SunLitFract;
    6383              :             }
    6384              :         }
    6385              : 
    6386              :         //--------------------------------------------------------------------------------------------------------
    6387              :         // EXTERIOR WINDOWS OR TDD DOMES
    6388              :         //--------------------------------------------------------------------------------------------------------
    6389       719225 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    6390       613173 :             auto &surf = s_surf->Surface(SurfNum);
    6391       613173 :             if (surf.Class != SurfaceClass::Window && surf.Class != SurfaceClass::TDD_Dome) continue;
    6392        31116 :             if (!surf.ExtSolar && surf.OriginalClass != SurfaceClass::TDD_Diffuser) continue;
    6393              : 
    6394        31116 :             auto &surfWin = s_surf->SurfaceWindow(SurfNum);
    6395        31116 :             int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
    6396        31116 :             int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(SurfNum);
    6397        31116 :             auto &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    6398        31116 :             int ScNum = surfWin.screenNum;
    6399        31116 :             WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum); // Set in subr. WindowShadingManager
    6400              : 
    6401        31116 :             auto &surfShade = s_surf->surfShades(SurfNum);
    6402              : 
    6403        31116 :             Real64 ProfAng = 0.0; // Window solar profile angle (radians)
    6404              : 
    6405        31116 :             Real64 SlatAng = surfShade.blind.slatAng;
    6406        31116 :             int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
    6407        31116 :             int SurfNum2 = SurfNum;
    6408        31116 :             if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    6409            0 :                 SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
    6410              :             }
    6411        31116 :             Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    6412        31116 :             Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    6413              : 
    6414              :             //-----------------------------------------
    6415              :             // BLOCK 1
    6416              :             // EXTERIOR BEAM AND DIFFUSE SOLAR RADIATION ABSORBED IN THE GLASS LAYERS OF (SurfWinA)
    6417              :             // EXTERIOR BEAM ABSORBED BY SHADING DEVICE (SurfWinExtBeamAbsByShadFac)
    6418              :             //-----------------------------------------
    6419              :             // Somewhat of a kludge
    6420        31116 :             if (surf.Class == SurfaceClass::TDD_Dome || surf.OriginalClass == SurfaceClass::TDD_Diffuser)
    6421            0 :                 state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) =
    6422              :                     SunLitFract; // Frames/dividers not allow
    6423        31116 :             int FenSolAbsPtr = 0;
    6424        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    6425            0 :                 FenSolAbsPtr = WindowScheduledSolarAbs(state, SurfNum, ConstrNum);
    6426              :             }
    6427              :             bool SunlitFracWithoutReveal =
    6428        31116 :                 state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) > 0;
    6429              : 
    6430              :             // Calculate interpolated blind properties
    6431              :             Real64 FrontDiffDiffTrans; // Bare-blind front diffuse-diffuse solar transmittance
    6432              :             Real64 FrontDiffDiffRefl;
    6433              :             Real64 FrontDiffAbs;      // Bare-blind front diffuse solar reflectance
    6434              :             Real64 BackDiffDiffTrans; // Bare-blind back diffuse-diffuse solar transmittance
    6435              :             Real64 BackDiffDiffRefl;
    6436              :             Real64 BackDiffAbs; // Bare-blind back diffuse solar reflectance
    6437              : 
    6438              :             Real64 FrontBeamDiffTrans; // Blind ProfileAnglesolar front beam-diffuse transmittance
    6439              :             Real64 BackBeamDiffTrans;  // Blind solar back beam-diffuse transmittance
    6440              :             Real64 FrontBeamDiffRefl;  // Blind solar front beam-diffuse reflectance
    6441              :             Real64 BackBeamDiffRefl;   // Blind solar back beam-diffuse reflectance
    6442              :             Real64 FrontBeamAbs;       // Blind solar front beam absorptance
    6443              :             Real64 BackBeamAbs;        // Blind solar back beam absorptance
    6444              : 
    6445        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL && ANY_BLIND(ShadeFlag)) {
    6446            0 :                 auto const &surfShade = s_surf->surfShades(SurfNum);
    6447            0 :                 auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
    6448            0 :                 assert(matBlind != nullptr);
    6449              : 
    6450            0 :                 int profIdxLo = surfShade.blind.profAngIdxLo;
    6451            0 :                 int profIdxHi = surfShade.blind.profAngIdxHi;
    6452            0 :                 Real64 profInterpFac = surfShade.blind.profAngInterpFac;
    6453              : 
    6454            0 :                 FrontDiffDiffTrans = surfShade.blind.TAR.Sol.Ft.Df.Tra;
    6455              : 
    6456            0 :                 if (SunLitFract > 0.0 || SunlitFracWithoutReveal) {
    6457            0 :                     auto const &btar1 = surfShade.blind.TAR;
    6458            0 :                     auto const &btarFront1Lo = btar1.Sol.Ft.Bm[profIdxLo];
    6459            0 :                     auto const &btarFront1Hi = btar1.Sol.Ft.Bm[profIdxHi];
    6460              : 
    6461            0 :                     FrontBeamAbs = Interp(btarFront1Lo.Abs, btarFront1Hi.Abs, profInterpFac);
    6462            0 :                     FrontBeamDiffTrans = Interp(btarFront1Lo.DfTra, btarFront1Hi.DfTra, profInterpFac);
    6463            0 :                     if (ShadeFlag != WinShadingType::ExtBlind) { // FRONT: interior or bg blinds
    6464            0 :                         FrontDiffDiffRefl = btar1.Sol.Ft.Df.Ref;
    6465            0 :                         FrontDiffAbs = btar1.Sol.Ft.Df.Abs;
    6466            0 :                         FrontBeamDiffRefl = Interp(btarFront1Lo.DfRef, btarFront1Hi.DfRef, profInterpFac);
    6467              :                     }
    6468              : 
    6469            0 :                     if (ShadeFlag != WinShadingType::IntBlind) { // BACK: exterior or bg blinds{
    6470            0 :                         BackDiffDiffTrans = btar1.Sol.Bk.Df.Tra;
    6471            0 :                         BackDiffDiffRefl = btar1.Sol.Bk.Df.Ref;
    6472            0 :                         BackDiffAbs = btar1.Sol.Bk.Df.Abs;
    6473              : 
    6474            0 :                         auto const &btarBack1Lo = btar1.Sol.Bk.Bm[profIdxLo];
    6475            0 :                         auto const &btarBack1Hi = btar1.Sol.Bk.Bm[profIdxHi];
    6476              : 
    6477            0 :                         BackBeamDiffTrans = Interp(btarBack1Lo.DfTra, btarBack1Hi.DfTra, profInterpFac);
    6478            0 :                         BackBeamDiffRefl = Interp(btarBack1Lo.DfRef, btarBack1Hi.DfRef, profInterpFac);
    6479            0 :                         BackBeamAbs = Interp(btarBack1Lo.Abs, btarBack1Hi.Abs, profInterpFac);
    6480              :                     }
    6481              :                 } // if (SunLitFrac > 0.0)
    6482              :             }     // if (ANY_BLIND)
    6483              : 
    6484        31116 :             if (SunlitFracWithoutReveal) {
    6485              : 
    6486        16090 :                 if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
    6487              : 
    6488              :                     // For bare glazing or switchable glazing, the following includes the effects of
    6489              :                     // (1) diffuse solar produced by beam solar incident on the outside and inside reveal
    6490              :                     // surfaces, and (2) absorption of beam solar by outside and inside reveal surfaces.
    6491              :                     // If there is an exterior shade/blind both of these effects are ignored. If there
    6492              :                     // is an interior or between-glass shade/blind the effects of beam incident on
    6493              :                     // inside reveal surfaces is ignored.
    6494        15305 :                     int NGlass = thisConstruct.TotGlassLayers;
    6495        15305 :                     Array1D<Real64> AbWin(NGlass); // Factor for front beam radiation absorbed in window glass layer
    6496        33750 :                     for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6497        36890 :                         AbWin(Lay) = Window::POLYF(CosInc, thisConstruct.AbsBeamCoef(Lay)) * CosInc * SunLitFract *
    6498        18445 :                                      s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
    6499              :                     }
    6500        15305 :                     if (!IS_SHADED_NO_GLARE_CTRL(ShadeFlag)) {
    6501              :                         // (ShadeFlag <= 0 || ShadeFlag >= 10) - Bare window (ShadeFlag = -1 or 0 or shading device of off)
    6502        33750 :                         for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6503              :                             // Add contribution of beam reflected from outside and inside reveal
    6504        36890 :                             s_surf->SurfWinA(SurfNum, Lay) = AbWin(Lay) +
    6505        18445 :                                                              s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstruct.AbsDiff(Lay) +
    6506        18445 :                                                              s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) * thisConstruct.AbsDiffBack(Lay);
    6507              :                         }
    6508              :                     } else {
    6509              :                         // Shade, screen, blind or switchable glazing on (ShadeFlag > 0)
    6510              :                         Real64 FracSunLit =
    6511            0 :                             SunLitFract * s_surf->SurfaceWindow(SurfNum)
    6512            0 :                                               .OutProjSLFracMult[state.dataGlobal->HourOfDay]; // Effective fraction of window that is sunlit;
    6513            0 :                         Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    6514            0 :                         Array1D<Real64> AbWinSh(NGlass);    // Like AbWin, but for shaded window
    6515            0 :                         Array1D<Real64> ADiffWinSh(NGlass); // Diffuse solar absorptance of glass layer, window with shading device
    6516            0 :                         if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) FracSunLit = SunLitFract;
    6517              : 
    6518            0 :                         if (ANY_SHADE(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
    6519            0 :                             auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
    6520              :                             // Shade or switchable glazing on
    6521            0 :                             for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6522            0 :                                 AbWinSh(Lay) = Window::POLYF(CosInc, thisConstructSh.AbsBeamCoef(Lay)) * CosInc * FracSunLit;
    6523            0 :                                 ADiffWinSh(Lay) = thisConstructSh.AbsDiff(Lay);
    6524              :                             }
    6525            0 :                             if (ShadeFlag == WinShadingType::IntShade) { // Exterior beam absorbed by INTERIOR SHADE
    6526              :                                 // Note that AbsBeamShadeCoef includes effect of shade/glazing inter-reflection
    6527            0 :                                 Real64 AbsShade = Window::POLYF(CosInc,
    6528            0 :                                                                 thisConstructSh.AbsBeamShadeCoef); // Interior shade or blind beam solar absorptance
    6529            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
    6530            0 :                                     (AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
    6531            0 :                                      s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstructSh.AbsDiffShade) *
    6532            0 :                                     surfWin.glazedFrac;
    6533              :                                 // In the above, GlazedFrac corrects for shadowing of divider onto interior shade
    6534            0 :                             } else if (ShadeFlag == WinShadingType::ExtShade) { // Exterior beam absorbed by EXTERIOR SHADE
    6535            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = thisConstructSh.AbsDiffShade * CosInc * SunLitFract;
    6536            0 :                             } else if (ShadeFlag == WinShadingType::BGShade) { // Exterior beam absorbed by BETWEEN-GLASS SHADE
    6537            0 :                                 Real64 AbsShade = Window::POLYF(CosInc, thisConstructSh.AbsBeamShadeCoef);
    6538            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
    6539            0 :                                     AbsShade * CosInc * SunLitFract +
    6540            0 :                                     s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * thisConstructSh.AbsDiffShade;
    6541              :                             }
    6542              : 
    6543              :                         } else {
    6544              :                             // Blind or screen on
    6545            0 :                             ProfAng = surfShade.blind.profAng;
    6546            0 :                             if (ShadeFlag == WinShadingType::IntBlind) {
    6547              :                                 // Interior blind on
    6548            0 :                                 Real64 TBmBm = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef);
    6549            0 :                                 Real64 RGlDiffBack = thisConstruct.ReflectSolDiffBack; // Glazing system back diffuse solar reflectance
    6550            0 :                                 Real64 RhoBlFront = FrontBeamDiffRefl;                 // Blind solar front beam reflectance
    6551            0 :                                 Real64 RhoBlDiffFront = FrontDiffDiffRefl;             // Blind solar front diffuse reflectance
    6552            0 :                                 for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6553            0 :                                     Real64 ADiffWin = thisConstruct.AbsDiff(Lay);        // Diffuse solar absorptance of glass layer, bare window
    6554            0 :                                     Real64 AGlDiffBack = thisConstruct.AbsDiffBack(Lay); // Glass layer back diffuse solar absorptance
    6555            0 :                                     AbWinSh(Lay) =
    6556            0 :                                         AbWin(Lay) + (TBmBm * AGlDiffBack * RhoBlFront / (1.0 - RhoBlFront * RGlDiffBack)) * CosInc * FracSunLit;
    6557            0 :                                     ADiffWinSh(Lay) =
    6558            0 :                                         ADiffWin + thisConstruct.TransDiff * AGlDiffBack * RhoBlDiffFront / (1.0 - RhoBlDiffFront * RGlDiffBack);
    6559              :                                 }
    6560              :                                 // Exterior beam absorbed by INTERIOR BLIND
    6561              : 
    6562            0 :                                 Real64 AbsBlFront = FrontBeamAbs;     // Blind solar front beam absorptance
    6563            0 :                                 Real64 AbsBlDiffFront = FrontDiffAbs; // Blind solar front diffuse absorptance
    6564            0 :                                 Real64 AbsShade =
    6565            0 :                                     TBmBm * (AbsBlFront + RhoBlFront * RGlDiffBack * AbsBlDiffFront / (1.0 - RhoBlDiffFront * RGlDiffBack));
    6566            0 :                                 Real64 AbsShadeDiff =
    6567            0 :                                     thisConstruct.TransDiff *
    6568            0 :                                     (AbsBlDiffFront + RhoBlDiffFront * RGlDiffBack * AbsBlDiffFront /
    6569            0 :                                                           (1.0 - RhoBlDiffFront * RGlDiffBack)); // Interior shade or blind diffuse solar absorptance
    6570              : 
    6571            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
    6572            0 :                                     (AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
    6573            0 :                                      s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * AbsShadeDiff) *
    6574            0 :                                     surfWin.glazedFrac;
    6575              : 
    6576              :                                 // In the above, GlazedFrac corrects for shadowing of divider onto interior blind
    6577            0 :                             } else if (ShadeFlag == WinShadingType::ExtBlind) {
    6578              :                                 // Exterior blind on
    6579            0 :                                 Real64 TBlBmBm = surfShade.blind.bmBmTrans; // Blind solar front beam-beam transmittance
    6580            0 :                                 Real64 TBlDifDif = FrontDiffDiffTrans;      // Diffuse-diffuse solar transmittance of blind
    6581            0 :                                 Real64 TBlBmDiff = FrontBeamDiffTrans;      // Blind solar front beam-diffuse transmittance
    6582            0 :                                 Real64 RhoBlBack = BackBeamDiffRefl;        // Blind solar back beam-diffuse reflectance
    6583            0 :                                 Real64 RhoBlDiffBack = BackDiffDiffRefl;    // Blind solar back diffuse reflectance
    6584              :                                 Real64 RGlFront =
    6585            0 :                                     Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
    6586            0 :                                 Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront;       // Glazing system front diffuse solar reflectance
    6587            0 :                                 for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6588            0 :                                     Real64 ADiffWin = thisConstruct.AbsDiff(Lay);     // Diffuse solar absorptance of glass layer, bare window
    6589            0 :                                     Real64 AGlDiffFront = thisConstruct.AbsDiff(Lay); // Glass layer front diffuse solar absorptance
    6590            0 :                                     AbWinSh(Lay) = TBlBmBm * AbWin(Lay) + ((TBlBmBm * RGlFront * RhoBlBack + TBlBmDiff) * AGlDiffFront /
    6591            0 :                                                                            (1 - RGlDiffFront * RhoBlDiffBack)) *
    6592            0 :                                                                               CosInc * FracSunLit;
    6593              :                                     // ADiffWinSh = 0.0  ! Assumes no contribution from reveal reflection when exterior blind in place
    6594              :                                     // Replaced above line with (FCW, 2/10/03):
    6595            0 :                                     ADiffWinSh(Lay) = ADiffWin * TBlDifDif / (1.0 - RGlDiffFront * RhoBlDiffBack);
    6596              :                                 }
    6597              :                                 // Exterior beam absorbed by EXTERIOR BLIND
    6598            0 :                                 Real64 AbsBlFront = FrontBeamAbs;
    6599            0 :                                 Real64 AbsBlBack = BackBeamAbs;     // Blind solar back beam absorptance
    6600            0 :                                 Real64 AbsBlDiffBack = BackDiffAbs; // Blind solar back diffuse absorptance
    6601            0 :                                 Real64 AbsShade = AbsBlFront + AbsBlBack * RGlFront * TBlBmBm +
    6602            0 :                                                   (AbsBlDiffBack * RGlDiffFront / (1.0 - RhoBlDiffBack * RGlDiffFront)) *
    6603            0 :                                                       (RGlFront * TBlBmBm * RhoBlBack + TBlBmDiff);
    6604            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsShade * CosInc * SunLitFract * InOutProjSLFracMult;
    6605            0 :                             } else if (ShadeFlag == WinShadingType::ExtScreen) {
    6606              :                                 // Exterior screen on
    6607            0 :                                 auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
    6608            0 :                                 assert(screen != nullptr);
    6609              : 
    6610            0 :                                 auto &surf = s_surf->Surface(SurfNum);
    6611              : 
    6612            0 :                                 Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
    6613            0 :                                 Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
    6614            0 :                                 Real64 winPhi = surf.Tilt * Constant::DegToRad;
    6615            0 :                                 Real64 winTheta = surf.Azimuth * Constant::DegToRad;
    6616            0 :                                 Real64 phi = std::abs(solPhi - winPhi);
    6617            0 :                                 Real64 theta = std::abs(solTheta - winTheta);
    6618            0 :                                 Material::NormalizePhiTheta(phi, theta);
    6619              : #ifdef PRECALC_INTERP_SCREEN
    6620              :                                 int ip1, ip2, it1, it2;
    6621              :                                 BilinearInterpCoeffs coeffs;
    6622            0 :                                 Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
    6623            0 :                                 GetBilinearInterpCoeffs(
    6624            0 :                                     phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
    6625            0 :                                 auto const &b11 = screen->btars[ip1][it1];
    6626            0 :                                 auto const &b12 = screen->btars[ip1][it2];
    6627            0 :                                 auto const &b21 = screen->btars[ip2][it1];
    6628            0 :                                 auto const &b22 = screen->btars[ip2][it2];
    6629              : 
    6630            0 :                                 Real64 TScDifDif = screen->DfTrans;
    6631            0 :                                 Real64 TScBmDif = BilinearInterp(b11.DfTrans, b12.DfTrans, b21.DfTrans, b22.DfTrans, coeffs);
    6632            0 :                                 Real64 TScBmBm = BilinearInterp(b11.BmTrans, b12.BmTrans, b21.BmTrans, b22.BmTrans, coeffs);
    6633            0 :                                 Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
    6634            0 :                                 Real64 RScDifBack = screen->DfRef;
    6635              : 
    6636              :                                 Real64 RGlFront =
    6637            0 :                                     Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
    6638            0 :                                 Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront;       // Glazing system front diffuse solar reflectance
    6639            0 :                                 Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;           // Diffuse front reflectance of glass
    6640              :                                 // Reduce the bare window absorbed beam by the screen beam transmittance and then account for
    6641              :                                 // interreflections
    6642            0 :                                 for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6643            0 :                                     Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
    6644            0 :                                     AbWinSh(Lay) = TScBmBm * AbWin(Lay) + (TScBmBm * RGlFront * RScBack + TScBmDif) * thisConstruct.AbsDiff(Lay) /
    6645            0 :                                                                               (1.0 - RGlDiffFront * RScDifBack) * CosInc * FracSunLit;
    6646            0 :                                     ADiffWinSh(Lay) = ADiffWin * TScDifDif / (1.0 - RGlDifFr * RScDifBack);
    6647              :                                 }
    6648              :                                 // Exterior beam absorbed by EXTERIOR SCREEN
    6649            0 :                                 Real64 AbsScBeam = BilinearInterp(b11.AbsSolFront, b12.AbsSolFront, b21.AbsSolFront, b22.AbsSolFront, coeffs);
    6650            0 :                                 Real64 AbsScDiffBack = screen->DfAbs;
    6651            0 :                                 Real64 AbsScreen = AbsScBeam * (1.0 + TScBmBm * RGlFront) +
    6652            0 :                                                    (AbsScDiffBack * TScBmBm * RGlFront * RGlDiffFront * RScBack /
    6653            0 :                                                     (1.0 - RScDifBack * RGlDiffFront)); // Exterior screen beam solar absorptance
    6654            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsScreen * CosInc * SunLitFract * InOutProjSLFracMult;
    6655              : #else  // !PRECALC_INTERP_SCREEN
    6656              :                                 Material::ScreenBmTransAbsRef btar;
    6657              :                                 CalcScreenTransmittance(state, screen, phi, theta, btar);
    6658              : 
    6659              :                                 Real64 TScDifDif = screen->DfTrans;
    6660              :                                 Real64 TScBmDif = btar.DfTrans;
    6661              :                                 Real64 TScBmBm = btar.BmTrans;
    6662              :                                 Real64 RScBack = btar.RefSolFront;
    6663              :                                 Real64 RScDifBack = screen->DfRef;
    6664              : 
    6665              :                                 Real64 RGlFront =
    6666              :                                     Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Glazing system solar front beam-beam reflectance
    6667              :                                 Real64 RGlDiffFront = thisConstruct.ReflectSolDiffFront;       // Glazing system front diffuse solar reflectance
    6668              :                                 Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;           // Diffuse front reflectance of glass
    6669              :                                 // Reduce the bare window absorbed beam by the screen beam transmittance and then account for
    6670              :                                 // interreflections
    6671              :                                 for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6672              :                                     Real64 ADiffWin = thisConstruct.AbsDiff(Lay); // Diffuse solar absorptance of glass layer, bare window
    6673              :                                     AbWinSh(Lay) = TScBmBm * AbWin(Lay) + (TScBmBm * RGlFront * RScBack + TScBmDif) * thisConstruct.AbsDiff(Lay) /
    6674              :                                                                               (1.0 - RGlDiffFront * RScDifBack) * CosInc * FracSunLit;
    6675              :                                     ADiffWinSh(Lay) = ADiffWin * TScDifDif / (1.0 - RGlDifFr * RScDifBack);
    6676              :                                 }
    6677              :                                 // Exterior beam absorbed by EXTERIOR SCREEN
    6678              :                                 Real64 AbsScBeam = btar.AbsSolFront;
    6679              :                                 Real64 AbsScDiffBack = screen->DfAbs;
    6680              :                                 Real64 AbsScreen = AbsScBeam * (1.0 + TScBmBm * RGlFront) +
    6681              :                                                    (AbsScDiffBack * TScBmBm * RGlFront * RGlDiffFront * RScBack /
    6682              :                                                     (1.0 - RScDifBack * RGlDiffFront)); // Exterior screen beam solar absorptance
    6683              :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) = AbsScreen * CosInc * SunLitFract * InOutProjSLFracMult;
    6684              : #endif // PRECALC_INTERP_SCREEN
    6685            0 :                             } else if (ShadeFlag == WinShadingType::BGBlind) {
    6686              :                                 // Between-glass blind o
    6687              :                                 // Isolated glass and blind properties at current incidence angle, profile angle and slat angle
    6688            0 :                                 Real64 t1 = Window::POLYF(CosInc,
    6689            0 :                                                           thisConstruct.tBareSolCoef(1)); // Bare-glass beam solar trans for glass layers 1,2 and 3
    6690            0 :                                 Real64 t2 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(2));
    6691              :                                 Real64 af1 =
    6692            0 :                                     Window::POLYF(CosInc,
    6693            0 :                                                   thisConstruct.afBareSolCoef(1)); // Bare-glass beam solar front abs for glass layers 1,2 and 3
    6694            0 :                                 Real64 af2 = Window::POLYF(CosInc, thisConstruct.afBareSolCoef(2));
    6695            0 :                                 Real64 ab1 = Window::POLYF(
    6696              :                                     CosInc,
    6697            0 :                                     thisConstruct.abBareSolCoef(1)); // Bare-glass beam solar back absorptance for glass layers 1,2 and 3
    6698            0 :                                 Real64 ab2 = Window::POLYF(CosInc, thisConstruct.abBareSolCoef(2));
    6699            0 :                                 Real64 rf2 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(2));
    6700            0 :                                 Real64 td1 = thisConstruct.tBareSolDiff(1); // Bare-glass diffuse solar transmittance for glass layers 1,2 and 3
    6701            0 :                                 Real64 td2 = thisConstruct.tBareSolDiff(2);
    6702            0 :                                 Real64 afd1 = thisConstruct.afBareSolDiff(1); // Bare-glass diffuse solar front absorptance for glass layers 1,2 and 3
    6703            0 :                                 Real64 afd2 = thisConstruct.afBareSolDiff(2);
    6704            0 :                                 Real64 abd1 = thisConstruct.abBareSolDiff(1); // Bare-glass diffuse solar back absorptance for glass layers 1,2 and 3
    6705            0 :                                 Real64 abd2 = thisConstruct.abBareSolDiff(2);
    6706            0 :                                 Real64 rfd2 = thisConstruct.rfBareSolDiff(2);
    6707            0 :                                 Real64 rbd1 = thisConstruct.rbBareSolDiff(1); // Bare-glass diffuse solar back reflectance for glass layers 1,2 and 3
    6708            0 :                                 Real64 rbd2 = thisConstruct.rbBareSolDiff(2);
    6709            0 :                                 Real64 tfshBB = surfShade.blind.bmBmTrans; // Bare-blind front and back beam-beam solar transmittance
    6710              : 
    6711            0 :                                 auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
    6712            0 :                                 assert(matBlind != nullptr);
    6713            0 :                                 Real64 tbshBB = matBlind->BeamBeamTrans(ProfAng, Constant::Pi - SlatAng);
    6714            0 :                                 Real64 tfshBd = FrontBeamDiffTrans; // Bare-blind front and back beam-diffuse solar transmittance
    6715            0 :                                 Real64 tbshBd = BackBeamDiffTrans;
    6716            0 :                                 Real64 rfshB = FrontBeamDiffRefl; // Bare-blind front and back beam solar reflectance
    6717            0 :                                 Real64 rbshB = BackBeamDiffRefl;
    6718            0 :                                 Real64 afshB = FrontBeamAbs;
    6719            0 :                                 Real64 abshB = BackBeamAbs;
    6720              : 
    6721            0 :                                 Real64 tfshd = FrontDiffDiffTrans; // Bare-blind front and back diffuse-diffuse solar transmittance
    6722            0 :                                 Real64 tbshd = BackDiffDiffTrans;
    6723            0 :                                 Real64 rfshd = FrontDiffDiffRefl; // Bare-blind front and back diffuse solar reflectance
    6724            0 :                                 Real64 rbshd = BackDiffDiffRefl;
    6725            0 :                                 Real64 afshd = FrontDiffAbs;
    6726            0 :                                 Real64 abshd = BackDiffAbs;
    6727              : 
    6728            0 :                                 Real64 AbsShade = 0.0;
    6729            0 :                                 Real64 AbsShadeDiff = 0.0;
    6730            0 :                                 if (NGlass == 2) {
    6731            0 :                                     AbWinSh(1) = CosInc * FracSunLit *
    6732            0 :                                                  (af1 + t1 * tfshBB * rf2 * tbshBB * ab1 +
    6733            0 :                                                   t1 * (rfshB + rfshB * rbd1 * rfshd + tfshBB * rf2 * tbshBd + tfshBd * rfd2 * tbshd) * abd1);
    6734            0 :                                     ADiffWinSh(1) = afd1 + td1 * (rfshd + rfshd * rbd1 * rfshd + tfshd * rfd2 * tbshd) * abd1;
    6735            0 :                                     AbWinSh(2) =
    6736            0 :                                         CosInc * FracSunLit *
    6737            0 :                                         (t1 * rfshB * af2 + t1 * (rfshB * rf2 * rbshd + tfshBd * (1 + rfd2 * rbshd) + rfshB * rbd1 * tfshd) * afd2);
    6738            0 :                                     ADiffWinSh(2) = td1 * (tfshd * (1 + rfd2 * rbshd) + rfshd * rbd1 * tfshd) * afd2;
    6739            0 :                                     AbsShade = t1 * (afshB + tfshBB * rf2 * abshB + tfshBd * rfd2 * abshd + rfshB * rbd1 * afshd);
    6740            0 :                                     AbsShadeDiff = td1 * (afshd * (1 + rfshd * rbd1) + tfshd * rfd2 * abshd);
    6741            0 :                                 } else if (NGlass == 3) {
    6742            0 :                                     Real64 t1t2 = t1 * t2; // t1*t2
    6743            0 :                                     Real64 td1td2 = td1 * td2;
    6744            0 :                                     Real64 af3 = Window::POLYF(CosInc, thisConstruct.afBareSolCoef(3));
    6745            0 :                                     Real64 rf3 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(3));
    6746            0 :                                     Real64 afd3 = thisConstruct.afBareSolDiff(3);
    6747            0 :                                     Real64 rfd3 = thisConstruct.rfBareSolDiff(3);
    6748            0 :                                     Real64 td2 = thisConstruct.tBareSolDiff(2);
    6749            0 :                                     AbWinSh(1) = CosInc * FracSunLit *
    6750            0 :                                                  (af1 + t1 * rf2 * ab1 + t1t2 * tfshBB * rf3 * tbshBB * t2 * ab1 +
    6751            0 :                                                   t1t2 * (rfshB * td2 + rfshB * rbd2 * rfshd * td2 + tfshBd * rfd3 * tbshd * td2) * abd1);
    6752            0 :                                     ADiffWinSh(1) = afd1 + td1 * rbd2 * abd1 +
    6753            0 :                                                     td1td2 *
    6754            0 :                                                         (rfshd * (1 + rbd2 * rfshd + td2 * rbd1 * td2 * rfshd) +
    6755            0 :                                                          tfshd * (rfd3 * tbshd + rfd3 * rbshd * rfd3 * tbshd)) *
    6756            0 :                                                         td2 * abd1;
    6757            0 :                                     AbWinSh(2) = CosInc * FracSunLit *
    6758            0 :                                                  (t1 * af2 + t1t2 * (tfshBB * rf3 * tbshBB * ab2 + rfshB * td2 * rbd1 * afd2) +
    6759            0 :                                                   t1t2 * (rfshB * (1 + rbd2 * rfshd) + tfshBB * rf3 * tbshBd + tfshBd * rfd3 * tbshd) * abd2);
    6760            0 :                                     ADiffWinSh(2) = td1 * afd2 + td1td2 * rfshd * td2 * rbd1 * afd2 +
    6761            0 :                                                     td1td2 * (rfshd * (1 + rbd2 * rfshd) + tfshd * rfd3 * tbshd) * abd2;
    6762            0 :                                     AbWinSh(3) = CosInc * FracSunLit *
    6763            0 :                                                  (t1t2 * tfshBB * af3 + t1t2 *
    6764            0 :                                                                             (tfshBB * rf3 * rbshB + tfshBd * (1 + rfd3 * rbshd) +
    6765            0 :                                                                              rfshB * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) *
    6766              :                                                                             afd3);
    6767            0 :                                     ADiffWinSh(3) = td1td2 * (tfshd * (1 + rfd3 * rbshd) + rfshd * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) * afd3;
    6768            0 :                                     AbsShade = t1t2 * (afshB * (1 + tfshBB * rf3) + afshd * (tfshBd * rfd3 + rfshB * (rbd2 + td2 * rbd1 * td2)));
    6769            0 :                                     AbsShadeDiff = td1td2 * (afshd + tfshd * rfd3 * abshd + rfshd * (rfd2 + td2 * rbd2 * td2) * afshd);
    6770              :                                 } // End of check if NGlass
    6771            0 :                                 state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum) =
    6772            0 :                                     AbsShade * CosInc * SunLitFract * InOutProjSLFracMult +
    6773            0 :                                     s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * AbsShadeDiff;
    6774              :                             } // End of check if blind is interior, exterior or between-glass
    6775              :                         }     // End of check if a blind is on
    6776              : 
    6777            0 :                         if (ShadeFlag != WinShadingType::SwitchableGlazing) {
    6778              :                             // Interior or between glass shade or blind on
    6779            0 :                             for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6780            0 :                                 s_surf->SurfWinA(SurfNum, Lay) = AbWinSh(Lay);
    6781              :                                 // Add contribution of diffuse from beam on outside reveal
    6782            0 :                                 if (ANY_INTERIOR_SHADE_BLIND(ShadeFlag) || ANY_BETWEENGLASS_SHADE_BLIND(ShadeFlag))
    6783            0 :                                     s_surf->SurfWinA(SurfNum, Lay) += ADiffWinSh(Lay) * s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum);
    6784              :                             }
    6785              :                         } else {
    6786            0 :                             auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
    6787              :                             // Switchable glazing
    6788            0 :                             for (int Lay = 1; Lay <= NGlass; ++Lay) {
    6789            0 :                                 Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum);
    6790            0 :                                 Real64 ADiffWin = thisConstruct.AbsDiff(Lay);
    6791            0 :                                 s_surf->SurfWinA(SurfNum, Lay) = Window::InterpSw(SwitchFac, AbWin(Lay), AbWinSh(Lay));
    6792              :                                 // Add contribution of diffuse from beam on outside and inside reveal
    6793            0 :                                 s_surf->SurfWinA(SurfNum, Lay) +=
    6794            0 :                                     Window::InterpSw(SwitchFac, ADiffWin, ADiffWinSh(Lay)) * s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) +
    6795            0 :                                     Window::InterpSw(SwitchFac, thisConstruct.AbsDiffBack(Lay), thisConstructSh.AbsDiffBack(Lay)) *
    6796            0 :                                         s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum);
    6797              :                             }
    6798              :                         }
    6799            0 :                     }
    6800              : 
    6801        16090 :                 } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    6802              :                     // Do not read from schedule file here since this will be called only if direct beam is hitting the window and schedule
    6803              :                     // will not be loaded in that case even if diffuse part of solar radiation is entering through the window
    6804            0 :                     if (FenSolAbsPtr == 0) {
    6805              :                         // Put in the equivalent layer absorptions
    6806              :                         // Simon: This should not be multiplied with CosInc since Abs coefficient already includes angular
    6807              :                         // factor
    6808            0 :                         for (int Lay = 1;
    6809            0 :                              Lay <= s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).NLayers;
    6810              :                              ++Lay) {
    6811            0 :                             Real64 absBeamWin = s_surf->SurfaceWindow(SurfNum)
    6812            0 :                                                     .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    6813            0 :                                                     .WinBmFtAbs(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, Lay);
    6814              :                             Real64 AbWin =
    6815            0 :                                 absBeamWin * CosInc * SunLitFract * s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
    6816              : 
    6817              :                             // Add contribution of beam reflected from outside and inside reveal
    6818            0 :                             s_surf->SurfWinA(SurfNum, Lay) = AbWin +
    6819            0 :                                                              s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) *
    6820            0 :                                                                  s_surf->SurfaceWindow(SurfNum)
    6821            0 :                                                                      .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    6822            0 :                                                                      .WinFtHemAbs(Lay) +
    6823            0 :                                                              s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) *
    6824            0 :                                                                  s_surf->SurfaceWindow(SurfNum)
    6825            0 :                                                                      .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    6826            0 :                                                                      .WinBkHemAbs(Lay);
    6827              :                         }
    6828              :                     }
    6829              : 
    6830          785 :                 } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
    6831              :                     // call the ASHWAT fenestration model for optical properties
    6832              :                     // determine the beam radiation absorptance and transmittance of the
    6833              :                     // the equivalent layer window model
    6834          785 :                     WindowEquivalentLayer::CalcEQLOpticalProperty(state, SurfNum, SolarArrays::BEAM, state.dataSolarShading->SurfWinAbsSolBeamEQL);
    6835          785 :                     auto &CFS = state.dataWindowEquivLayer->CFS;
    6836              :                     // recalculate the diffuse absorptance and transmittance of the
    6837              :                     // the equivalent layer window model if there is shade control
    6838          785 :                     int EQLNum = state.dataConstruction->Construct(surf.Construction).EQLConsPtr; // equivalent layer fenestration index
    6839          785 :                     if (CFS(EQLNum).ISControlled) {
    6840          320 :                         WindowEquivalentLayer::CalcEQLOpticalProperty(
    6841          320 :                             state, SurfNum, SolarArrays::DIFF, state.dataSolarShading->SurfWinAbsSolDiffEQL);
    6842              :                     } else {
    6843          930 :                         state.dataSolarShading->SurfWinAbsSolDiffEQL(_, {1, CFS(EQLNum).NL + 1}) =
    6844         1395 :                             state.dataWindowEquivalentLayer->CFSDiffAbsTrans(_, {1, CFS(EQLNum).NL + 1}, EQLNum);
    6845              :                     }
    6846          785 :                     thisConstruct.TransDiff = state.dataSolarShading->SurfWinAbsSolDiffEQL(1, CFS(EQLNum).NL + 1);
    6847              : 
    6848         3628 :                     for (int Lay = 1; Lay <= CFS(EQLNum).NL + 1; ++Lay) {
    6849              :                         // Factor for front beam radiation absorbed for equivalent layer window model
    6850         2843 :                         Real64 AbWinEQL = state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay) * CosInc * SunLitFract *
    6851         2843 :                                           s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    6852              :                         ;
    6853         2843 :                         if (CFS(EQLNum).L(1).LTYPE != LayerType::GLAZE) {
    6854              :                             // if the first layer is not glazing (or it is a shade) do not
    6855            0 :                             s_surf->SurfWinA(SurfNum, Lay) = AbWinEQL;
    6856              :                         } else {
    6857              :                             // the first layer is a glazing, include the outside reveal reflection
    6858              :                             // and the inside reveal reflection until indoor shade layer is encountered.
    6859         2843 :                             if (CFS(EQLNum).L(Lay).LTYPE == LayerType::GLAZE) {
    6860         1570 :                                 s_surf->SurfWinA(SurfNum, Lay) =
    6861         1570 :                                     AbWinEQL +
    6862         1570 :                                     s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay) +
    6863         1570 :                                     s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) * state.dataSolarShading->SurfWinAbsSolDiffEQL(2, Lay);
    6864              :                             } else {
    6865         2546 :                                 s_surf->SurfWinA(SurfNum, Lay) = AbWinEQL + s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) *
    6866         1273 :                                                                                 state.dataSolarShading->SurfWinAbsSolBeamEQL(1, Lay);
    6867              :                             }
    6868              :                         }
    6869              :                     }
    6870              :                 }
    6871              :             } // End of SunlitFrac check
    6872              : 
    6873              :             //-----------------------------------------------------------------
    6874              :             // BLOCK 2
    6875              :             // SKY AND GROUND DIFFUSE SOLAR GAIN INTO ZONE FROM EXTERIOR WINDOW
    6876              :             //-----------------------------------------------------------------
    6877              : 
    6878              :             Real64 SkySolarInc =
    6879        31116 :                 s_surf->SurfSkySolarInc(SurfNum); // Incident solar radiation on a window: sky diffuse plus beam reflected from obstruction (W/m2)
    6880        31116 :             Real64 DiffTrans = 0.0;               // Glazing diffuse solar transmittance (including shade/blind/switching, if present)
    6881              :             Real64 DiffTransGnd;                  // Ground diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
    6882              :             Real64 DiffTransBmGnd;                // Complex fen: diffuse solar transmittance for ground-reflected beam radiation
    6883              :             Real64 DiffTransSky;                  // Sky diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
    6884        31116 :             Real64 NomDiffTrans = 0.0;
    6885              : 
    6886        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // complex fenestration
    6887            0 :                 if (FenSolAbsPtr == 0) {
    6888              :                     // Sky diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
    6889            0 :                     DiffTransSky =
    6890            0 :                         s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinSkyTrans;
    6891              :                     // Ground diffuse solar transmittance for glazing with blind with horiz. slats or complex fen
    6892            0 :                     DiffTransGnd =
    6893            0 :                         s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinSkyGndTrans;
    6894              :                     // Complex fen: diffuse solar transmittance for ground-reflected beam radiation
    6895            0 :                     DiffTransBmGnd = s_surf->SurfaceWindow(SurfNum)
    6896            0 :                                          .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    6897            0 :                                          .WinBmGndTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    6898              :                     // Define the effective transmittance for total sky and ground radiation
    6899            0 :                     if ((SkySolarInc + s_surf->SurfWinBmGndSolarInc(SurfNum) + s_surf->SurfWinSkyGndSolarInc(SurfNum)) != 0.0) {
    6900            0 :                         DiffTrans = (SkySolarInc * DiffTransSky + s_surf->SurfWinBmGndSolarInc(SurfNum) * DiffTransBmGnd +
    6901            0 :                                      s_surf->SurfWinSkyGndSolarInc(SurfNum) * DiffTransGnd) /
    6902            0 :                                     (SkySolarInc + s_surf->SurfWinBmGndSolarInc(SurfNum) + s_surf->SurfWinSkyGndSolarInc(SurfNum));
    6903              :                     }
    6904              :                     // Also update the nominal diffuse transmittance
    6905            0 :                     NomDiffTrans =
    6906            0 :                         s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinDiffTrans;
    6907              :                     // Do not store in TransDiff because it is not used by BSDF and rest of the code uses it as flag for opaque
    6908              :                     // surface incorrectly assuming wall heat transfer routines for windows.
    6909              :                     // Construct( Surface( SurfNum ).Construction ).TransDiff = NomDiffTrans;
    6910              :                 }
    6911        31116 :             } else if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    6912            0 :                 DiffTrans = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso);
    6913              :             } else {
    6914        31116 :                 DiffTrans = thisConstruct.TransDiff;
    6915              :             }
    6916              : 
    6917        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
    6918        29742 :                 if (IS_SHADED_NO_GLARE_CTRL(s_surf->SurfWinShadingFlag(SurfNum))) {
    6919            0 :                     auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
    6920            0 :                     if (ShadeFlag != WinShadingType::SwitchableGlazing) {
    6921              :                         // Shade or blind
    6922            0 :                         if (ANY_SHADE_SCREEN(ShadeFlag)) {
    6923              :                             // Shade or screen
    6924            0 :                             DiffTrans = constrSh.TransDiff;
    6925              :                         } else {
    6926              :                             // Blind
    6927            0 :                             int slatIdxLo = surfShade.blind.slatAngIdxLo;
    6928            0 :                             int slatIdxHi = surfShade.blind.slatAngIdxHi;
    6929            0 :                             Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
    6930              : 
    6931            0 :                             auto const &btarLo = constrSh.blindTARs[slatIdxLo];
    6932            0 :                             auto const &btarHi = constrSh.blindTARs[slatIdxHi];
    6933              : 
    6934            0 :                             DiffTrans = Interp(btarLo.Sol.Ft.Df.Tra, btarHi.Sol.Ft.Df.Tra, slatInterpFac);
    6935              : 
    6936              :                             // For blinds with horizontal slats, allow different diffuse/diffuse transmittance for
    6937              :                             // ground and sky solar
    6938            0 :                             auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
    6939            0 :                             assert(matBlind != nullptr);
    6940            0 :                             if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
    6941            0 :                                 DiffTransGnd = Interp(btarLo.Sol.Ft.Df.TraGnd, btarHi.Sol.Ft.Df.TraGnd, slatInterpFac);
    6942            0 :                                 DiffTransSky = Interp(btarLo.Sol.Ft.Df.TraSky, btarHi.Sol.Ft.Df.TraSky, slatInterpFac);
    6943              :                             }
    6944              :                         }
    6945              : 
    6946              :                     } else { // Switchable glazing
    6947              : 
    6948            0 :                         Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum); // Switching factor for a window
    6949            0 :                         DiffTrans = Window::InterpSw(SwitchFac, thisConstruct.TransDiff, constrSh.TransDiff);
    6950              :                     }
    6951              :                 }
    6952              :             }
    6953              : 
    6954              :             // Reporting variables
    6955        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
    6956        29742 :                 s_surf->SurfWinBlGlSysTsolDifDif(SurfNum) = DiffTrans;
    6957        29742 :                 s_surf->SurfWinScGlSysTsolDifDif(SurfNum) = DiffTrans;
    6958        29742 :                 if (ANY_BLIND(ShadeFlag) || ShadeFlag == WinShadingType::ExtScreen) {
    6959            0 :                     s_surf->SurfWinBlGlSysTsolDifDif(SurfNum) = DiffTrans;
    6960            0 :                     s_surf->SurfWinScGlSysTsolDifDif(SurfNum) = DiffTrans;
    6961            0 :                     if (ShadeFlag == WinShadingType::ExtScreen) {
    6962            0 :                         auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
    6963            0 :                         assert(screen != nullptr);
    6964            0 :                         s_surf->SurfWinScTsolDifDif(SurfNum) = screen->DfTrans;
    6965              :                     } else {
    6966            0 :                         s_surf->SurfWinBlTsolDifDif(SurfNum) = FrontDiffDiffTrans;
    6967              :                     }
    6968              :                 }
    6969              :             }
    6970              : 
    6971              :             //-----------------------------------------------------------------
    6972              :             // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
    6973              :             //-----------------------------------------------------------------
    6974        31116 :             Real64 TBmBm = 0.0;        // Beam-beam solar transmittance for bare window or window with switchable glazing
    6975        31116 :             Real64 TBmDif = 0.0;       // Beam-diffuse solar transmittance for bare window with diffusing glass
    6976        31116 :             Real64 TBmAllShBlSc = 0.0; // Beam-beam + beam-diffuse transmittance for window with shade, blind, screen, or switchable glazing
    6977        31116 :             Real64 TBmBmShBlSc = 0.0;  // Beam-beam transmittance for window with shade, blind, screen, or switchable glazing
    6978        31116 :             Real64 TBmDifShBlSc = 0.0; // Beam-diffuse transmittance for window with shade, blind, screen, or switchable glazing
    6979              :             Real64 TBmBmBl;            // Beam-beam transmittance for window with blind
    6980              :             Real64 TBmBmSc;            // Beam-beam transmittance for window with screen
    6981              :             Real64 TDifBare;           // Bare diffuse transmittance of exterior window
    6982              :             // Beam-beam transmittance for bare exterior window
    6983        31116 :             if (SunLitFract > 0.0) {
    6984        16092 :                 if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    6985            0 :                     TBmDif = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarBeam);
    6986            0 :                     state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolBeam = TBmDif;  // Report variable
    6987        16092 :                 } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) { // Regular window
    6988        15307 :                     if (!s_surf->SurfWinSolarDiffusing(SurfNum)) {                             // Clear glazing
    6989        15307 :                         TBmBm = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef);         //[-]
    6990              :                     } else {                                                                   // Diffusing glazing
    6991            0 :                         TBmDif = Window::POLYF(CosInc, thisConstruct.TransSolBeamCoef);        //[-]
    6992              :                     }
    6993          785 :                 } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    6994              :                     // Need to check what effect, if any, defining these here has
    6995            0 :                     TBmBm = s_surf->SurfaceWindow(SurfNum)
    6996            0 :                                 .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    6997            0 :                                 .WinDirSpecTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    6998            0 :                     TBmDif = s_surf->SurfaceWindow(SurfNum)
    6999            0 :                                  .ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState)
    7000            0 :                                  .WinDirHemiTrans(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep) -
    7001              :                              TBmBm;
    7002          785 :                 } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
    7003              :                     // get ASHWAT fenestration model beam-beam and beam-diffuse properties
    7004          785 :                     int EQLNum = state.dataConstruction->Construct(surf.Construction).EQLConsPtr; // equivalent layer fenestration index
    7005          785 :                     Real64 TBmBmEQL = state.dataSolarShading->SurfWinAbsSolBeamEQL(1, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1);
    7006              :                     // Beam-diffuse transmittance
    7007          785 :                     Real64 TBmDiffEQL = max(0.0, state.dataSolarShading->SurfWinAbsSolBeamEQL(2, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1));
    7008              :                     // Beam-beam transmittance: difference between beam-total and beam-diffuse transmittance
    7009          785 :                     TBmBmEQL = max(0.0, (TBmBmEQL - TBmDiffEQL));
    7010          785 :                     TBmBm = TBmBmEQL;
    7011          785 :                     TBmDif = TBmDiffEQL;
    7012              :                 }
    7013              :             }
    7014              :             // Diffuse-diffuse transmittance for bare exterior window
    7015        31116 :             if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    7016            0 :                 TDifBare = TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso);
    7017              :             } else {
    7018        31116 :                 if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    7019              :                     // Complex Fenestration: use hemispherical ave of directional-hemispherical transmittance
    7020              :                     // Note: this is not quite the same as the effective transmittance for total of sky and ground radiation
    7021            0 :                     TDifBare = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState).WinDiffTrans;
    7022              :                 } else { // Regular window
    7023        31116 :                     TDifBare = thisConstruct.TransDiff;
    7024              :                 }
    7025              :             }
    7026              : 
    7027              :             //-----------------------------------------------------------------
    7028              :             // BLOCK 3 - SCREEN, BLINDS AND GLAZING SYSTEM BEAM SOLAR TRANSMITTANCE
    7029              :             //-----------------------------------------------------------------
    7030        31116 :             if (ConstrNumSh != 0 && SunLitFract > 0.0) {
    7031         6440 :                 auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
    7032         6440 :                 if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
    7033         6440 :                     if (IS_SHADED_NO_GLARE_CTRL(ShadeFlag)) {
    7034              :                         // Shade or screen or blind on, or switchable glazing
    7035              :                         // (note in the following that diffusing glass is not oallowed in a window with shade, blind or switchable glazing)
    7036            0 :                         if (ANY_SHADE(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
    7037              :                             // Shade on or switchable glazing
    7038            0 :                             TBmAllShBlSc = Window::POLYF(CosInc, thisConstructSh.TransSolBeamCoef);
    7039              :                         } else {
    7040              :                             // Blind or Screen on
    7041              :                             Real64 TScBmDif;  // Beam-diffuse solar transmittance of screen
    7042              :                             Real64 TBlBmDif;  // Beam-diffuse solar transmittance of blind
    7043              :                             Real64 TBlDifDif; // Diffuse-diffuse solar transmittance of blind
    7044              :                             Real64 TScBmBm;
    7045              :                             Real64 TBlBmBm;
    7046            0 :                             if (ShadeFlag == WinShadingType::ExtScreen) { // Exterior screen
    7047            0 :                                 auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
    7048            0 :                                 assert(screen != nullptr);
    7049              : 
    7050            0 :                                 auto &surf = s_surf->Surface(SurfNum);
    7051            0 :                                 Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
    7052            0 :                                 Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
    7053            0 :                                 Real64 winPhi = surf.Tilt * Constant::DegToRad;
    7054            0 :                                 Real64 winTheta = surf.Azimuth * Constant::DegToRad;
    7055            0 :                                 Real64 phi = std::abs(solPhi - winPhi);
    7056            0 :                                 Real64 theta = std::abs(solTheta - winTheta);
    7057            0 :                                 Material::NormalizePhiTheta(phi, theta);
    7058              : #ifdef PRECALC_INTERP_SCREEN
    7059              :                                 int ip1, ip2, it1, it2;
    7060              :                                 BilinearInterpCoeffs coeffs;
    7061            0 :                                 Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
    7062            0 :                                 GetBilinearInterpCoeffs(
    7063            0 :                                     phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
    7064            0 :                                 auto const &b11 = screen->btars[ip1][it1];
    7065            0 :                                 auto const &b12 = screen->btars[ip1][it2];
    7066            0 :                                 auto const &b21 = screen->btars[ip2][it1];
    7067            0 :                                 auto const &b22 = screen->btars[ip2][it2];
    7068              : 
    7069            0 :                                 Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
    7070            0 :                                 Real64 RScDifBack = screen->DfRef;
    7071              : 
    7072            0 :                                 Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Beam front reflectance of glass
    7073            0 :                                 Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;                        // Diffuse front reflectance of glass
    7074              :                                 // beam transmittance (written in subroutine CalcScreenTransmittance each time step)
    7075            0 :                                 TScBmBm = BilinearInterp(b11.BmTrans, b12.BmTrans, b21.BmTrans, b22.BmTrans, coeffs);
    7076            0 :                                 TBmBmSc = TBmBm * TScBmBm;
    7077            0 :                                 TScBmDif = BilinearInterp(b11.DfTrans, b12.DfTrans, b21.DfTrans, b22.DfTrans, coeffs);
    7078              :                                 // beam-beam and diffuse transmittance of exterior beam
    7079            0 :                                 TBmAllShBlSc = TScBmBm * (TBmBm + RGlBmFr * RScBack * TDifBare / (1 - RGlDifFr * RScDifBack)) +
    7080            0 :                                                TScBmDif * TDifBare / (1 - RGlDifFr * RScDifBack);
    7081            0 :                                 TBmBmShBlSc = TBmBmSc;
    7082            0 :                                 TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
    7083              :                                 // Report variable for Beam-to-Diffuse transmittance (scattered transmittance)
    7084            0 :                                 s_surf->SurfWinScGlSysTsolBmBm(SurfNum) = TBmBmSc;
    7085            0 :                                 s_surf->SurfWinScTsolBmBm(SurfNum) = TScBmBm;
    7086            0 :                                 s_surf->SurfWinScTsolBmDif(SurfNum) = TScBmDif;
    7087              : #else  // !PRECALC_INTERP_SCREEN
    7088              :                                 Material::ScreenBmTransAbsRef btar;
    7089              :                                 CalcScreenTransmittance(state, screen, phi, theta, btar);
    7090              : 
    7091              :                                 Real64 RScBack = btar.RefSolFront;
    7092              :                                 Real64 RScDifBack = screen->DfRef;
    7093              : 
    7094              :                                 Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef); // Beam front reflectance of glass
    7095              :                                 Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;                        // Diffuse front reflectance of glass
    7096              :                                 // beam transmittance (written in subroutine CalcScreenTransmittance each time step)
    7097              :                                 TScBmBm = btar.BmTrans;
    7098              :                                 TBmBmSc = TBmBm * TScBmBm;
    7099              :                                 TScBmDif = btar.DfTrans;
    7100              :                                 // beam-beam and diffuse transmittance of exterior beam
    7101              :                                 TBmAllShBlSc = TScBmBm * (TBmBm + RGlBmFr * RScBack * TDifBare / (1 - RGlDifFr * RScDifBack)) +
    7102              :                                                TScBmDif * TDifBare / (1 - RGlDifFr * RScDifBack);
    7103              :                                 TBmBmShBlSc = TBmBmSc;
    7104              :                                 TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
    7105              :                                 // Report variable for Beam-to-Diffuse transmittance (scattered transmittance)
    7106              :                                 s_surf->SurfWinScGlSysTsolBmBm(SurfNum) = TBmBmSc;
    7107              :                                 s_surf->SurfWinScTsolBmBm(SurfNum) = TScBmBm;
    7108              :                                 s_surf->SurfWinScTsolBmDif(SurfNum) = TScBmDif;
    7109              : #endif // PRECALC_INTERP_SCREEN
    7110              :                             } else {
    7111            0 :                                 TBlBmBm = surfShade.blind.bmBmTrans;
    7112            0 :                                 TBlBmDif = FrontBeamDiffTrans;
    7113            0 :                                 if (ShadeFlag == WinShadingType::IntBlind) {
    7114            0 :                                     Real64 RhoBlBmDifFr = FrontBeamDiffRefl;            // Beam-diffuse front reflectance of blind
    7115            0 :                                     Real64 RGlDifBk = thisConstruct.ReflectSolDiffBack; // Diffuse front reflectance of glass
    7116            0 :                                     Real64 RhoBlDifDifFr = FrontDiffDiffRefl;           // Diffuse-diffuse front reflectance of blind
    7117              :                                     // beam-beam and diffuse transmittance of exterior beam
    7118            0 :                                     TBmBmBl = TBmBm * TBlBmBm;
    7119            0 :                                     TBlDifDif = FrontDiffDiffTrans;
    7120            0 :                                     TBmAllShBlSc =
    7121            0 :                                         TBmBm * (TBlBmBm + TBlBmDif + TBlDifDif * RhoBlBmDifFr * RGlDifBk / (1 - RhoBlDifDifFr * RGlDifBk));
    7122            0 :                                     TBmBmShBlSc = TBmBmBl; // TBmBm * TBlBmBm
    7123            0 :                                     TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
    7124            0 :                                     if (TBmDifShBlSc < 0.0) TBmDifShBlSc = 0.0;
    7125            0 :                                 } else if (ShadeFlag == WinShadingType::ExtBlind) {
    7126            0 :                                     Real64 RhoBlBmDifBk = BackBeamDiffRefl;  // Beam-diffuse back reflectance of blind
    7127            0 :                                     Real64 RhoBlDifDifBk = BackDiffDiffRefl; // Diffuse-diffuse back reflectance of blind
    7128            0 :                                     Real64 RGlBmFr = Window::POLYF(CosInc, thisConstruct.ReflSolBeamFrontCoef);
    7129            0 :                                     Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
    7130              :                                     // beam-beam and diffuse transmittance of exterior beam
    7131            0 :                                     TBmBmBl = TBmBm * TBlBmBm;
    7132            0 :                                     TBmAllShBlSc = TBlBmBm * (TBmBm + TDifBare * RGlBmFr * RhoBlBmDifBk / (1 - RGlDifFr * RhoBlDifDifBk)) +
    7133            0 :                                                    TBlBmDif * TDifBare / (1 - RGlDifFr * RhoBlDifDifBk);
    7134            0 :                                     TBmBmShBlSc = TBmBmBl; // TBmBm * TBlBmBm
    7135            0 :                                     TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
    7136              :                                 } else {
    7137              :                                     // Between-glass blind on
    7138            0 :                                     int NGlass = thisConstruct.TotGlassLayers;
    7139            0 :                                     Real64 td2 = thisConstruct.tBareSolDiff(2);
    7140            0 :                                     Real64 rbd1 = thisConstruct.rbBareSolDiff(1);
    7141            0 :                                     Real64 rbshB = BackBeamDiffRefl;
    7142            0 :                                     Real64 rfshd = FrontDiffDiffRefl;
    7143            0 :                                     Real64 rbshd = BackDiffDiffRefl;
    7144            0 :                                     Real64 tfshBd = FrontBeamDiffTrans;
    7145            0 :                                     Real64 t1 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(1));
    7146            0 :                                     Real64 t2 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(2));
    7147            0 :                                     Real64 tfshBB = surfShade.blind.bmBmTrans;
    7148            0 :                                     if (NGlass == 2) {
    7149            0 :                                         Real64 rf2 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(2));
    7150            0 :                                         Real64 rfshB = FrontBeamDiffRefl;
    7151            0 :                                         Real64 rfd2 = thisConstruct.rfBareSolDiff(2);
    7152            0 :                                         TBmBmBl = t1 * tfshBB * t2;
    7153            0 :                                         TBmAllShBlSc = t1 * tfshBB * t2 +
    7154            0 :                                                        t1 * (tfshBB * rf2 * rbshB + tfshBd * (1.0 + rfd2 * rbshd) + rfshB * rbd1 * rfshd) * td2;
    7155              :                                     } else { // NGlass = 3
    7156            0 :                                         Real64 t1t2 = t1 * t2;
    7157            0 :                                         Real64 t3 = Window::POLYF(CosInc, thisConstruct.tBareSolCoef(3));
    7158            0 :                                         Real64 td3 = thisConstruct.tBareSolDiff(3);
    7159            0 :                                         Real64 rf3 = Window::POLYF(CosInc, thisConstruct.rfBareSolCoef(3));
    7160            0 :                                         Real64 rbd2 = thisConstruct.rbBareSolDiff(2);
    7161            0 :                                         Real64 rfd3 = thisConstruct.rfBareSolDiff(3);
    7162            0 :                                         Real64 tfshd = FrontDiffDiffTrans;
    7163            0 :                                         TBmBmBl = t1 * t2 * tfshBB * t3;
    7164            0 :                                         TBmAllShBlSc = t1t2 * tfshBB * t3 + t1t2 *
    7165            0 :                                                                                 (tfshBB * rf3 * rbshB + tfshBd * (1.0 + rfd3 * rbshd) +
    7166            0 :                                                                                  rbshB * (rbd2 * tfshd + td2 * rbd1 * td2 * tfshd)) *
    7167              :                                                                                 td3;
    7168              :                                     }
    7169              :                                     // added TH 12/9/2009
    7170            0 :                                     TBmBmShBlSc = TBmBmBl;
    7171            0 :                                     TBmDifShBlSc = TBmAllShBlSc - TBmBmShBlSc;
    7172              :                                 }
    7173            0 :                                 s_surf->SurfWinBlTsolBmBm(SurfNum) = TBlBmBm;
    7174            0 :                                 s_surf->SurfWinBlTsolBmDif(SurfNum) = TBlBmDif;
    7175            0 :                                 s_surf->SurfWinBlGlSysTsolBmBm(SurfNum) = TBmBmBl;
    7176              :                             }
    7177              :                         }
    7178              :                     } // End of check if ShadeFlag > 0 and ShadeFlag < 10
    7179              :                 }     // end of checking if not eql window model
    7180              :             }         // end of checking if sunlitfract > 0
    7181              : 
    7182        31116 :             if (ShadeFlag == WinShadingType::SwitchableGlazing) {
    7183              :                 // Switchable glazing
    7184            0 :                 Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum);
    7185            0 :                 if (!s_surf->SurfWinSolarDiffusing(SurfNum)) {
    7186            0 :                     TBmBm = Window::InterpSw(SwitchFac, TBmBm, TBmAllShBlSc);
    7187              :                 } else {
    7188            0 :                     TBmDif = Window::InterpSw(SwitchFac, TBmDif, TBmAllShBlSc);
    7189              :                 }
    7190              :             }
    7191              :             // Report variables
    7192        31116 :             s_surf->SurfWinGlTsolBmBm(SurfNum) = TBmBm;
    7193        31116 :             s_surf->SurfWinGlTsolBmDif(SurfNum) = TBmDif;
    7194        31116 :             s_surf->SurfWinGlTsolDifDif(SurfNum) = TDifBare;
    7195              : 
    7196              :             //-----------------------------------------------------------------
    7197              :             // BLOCK 4 - REPORT WINDOW TRANSMITTANCE
    7198              :             //-----------------------------------------------------------------
    7199              : 
    7200              :             // The following SurfWinTransBmSolar and SurfWinTransDifSolar will be combined later to give
    7201              :             // WinTransSolar for reporting
    7202        31116 :             state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = 0.0;
    7203        31116 :             state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = 0.0;
    7204        31116 :             state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = 0.0;
    7205        31116 :             state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = 0.0;
    7206        31116 :             state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) =
    7207              :                 0.0; // Factor for exterior beam to beam solar transmitted through window, or window plus shade, into zone at current time (m2)
    7208        31116 :             state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) =
    7209              :                 0.0; // Factor for exterior beam to diffuse solar transmitted through window, or window plus shade, into zone at current time (m2)
    7210              : 
    7211        31116 :             Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    7212        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::EQL) {
    7213        29742 :                 state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = DiffTrans * surf.Area;
    7214        29742 :                 if (ANY_BLIND(ShadeFlag)) {
    7215            0 :                     auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
    7216            0 :                     assert(matBlind != nullptr);
    7217            0 :                     if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
    7218            0 :                         state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = DiffTransGnd * surf.Area;
    7219            0 :                         state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = DiffTransSky * surf.Area;
    7220              :                     }
    7221              :                 }
    7222              :             } else {
    7223              :                 // In equivalent layer window model system diffuse transmittance is based on unit
    7224              :                 // diffuse radiation flux, and hence doesn't distinguish between sky and
    7225              :                 // ground reflected diffuse radiations
    7226         1374 :                 state.dataSolarShading->SurfWinTransDifSolar(SurfNum) = DiffTrans * surf.Area;
    7227         1374 :                 state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum) = DiffTrans * surf.Area;
    7228         1374 :                 state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) = DiffTrans * surf.Area;
    7229              :             }
    7230              : 
    7231        31116 :             if (!IS_SHADED_NO_GLARE_CTRL(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
    7232              :                 // Unshaded or switchable glazing
    7233              :                 // Note: with previous defs of TBmBm & TBmDif, these come out right for Complex Fenestration
    7234              :                 // SurfWinTransBmSolar uses the directional-hemispherical transmittance
    7235        31116 :                 state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = (TBmBm + TBmDif) * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
    7236        31116 :                 state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBm * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;   // m2
    7237        31116 :                 state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDif * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
    7238              : 
    7239              :             } else {
    7240            0 :                 state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = TBmAllShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
    7241            0 :                 state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBmShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
    7242            0 :                 state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDifShBlSc * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
    7243              :             }
    7244              : 
    7245              :             // Add diffuse transmitted by window from beam reflected from outside reveal
    7246        31116 :             if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // Complex Fenestration
    7247            0 :                 if (FenSolAbsPtr == 0) {
    7248            0 :                     state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = (TBmBm + TBmDif) * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;
    7249            0 :                     state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum) = TBmBm * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult;   // m2
    7250            0 :                     state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = TBmDif * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // m2
    7251            0 :                     state.dataSolarShading->SurfWinTransBmSolar(SurfNum) +=
    7252            0 :                         s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
    7253            0 :                     state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) +=
    7254            0 :                         s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
    7255              :                 } else {
    7256            0 :                     state.dataSolarShading->SurfWinTransBmSolar(SurfNum) = 0.0;
    7257            0 :                     state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) = 0.0;
    7258              :                 }
    7259              :             } else { // Regular window
    7260              :                 // this is also valid for equivalent layer window
    7261        31116 :                 state.dataSolarShading->SurfWinTransBmSolar(SurfNum) += s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
    7262        31116 :                 state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum) += s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
    7263              :             }
    7264              : 
    7265              :             //-----------------------------------------------------------------
    7266              :             // BLOCK 5 - UPDATE SOLAR ENTERING A ZONE AS BEAM OR DIFFUSE RADIATION
    7267              :             //-----------------------------------------------------------------
    7268              :             // Increment factor for total exterior beam solar entering zone through window as beam or diffuse
    7269        31116 :             if (SunLitFract > 0.0 && surf.Class != SurfaceClass::TDD_Dome) {
    7270              :                 // Window is schedule surface gained. Do not make addition to what enters into zone since that information is not available
    7271        16092 :                 if (FenSolAbsPtr == 0) {
    7272              :                     Real64 TBmAll; // Window beam-to-(beam+diffuse) transmittance
    7273        16092 :                     if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::BSDF && (ANY_BLIND(ShadeFlag) || ANY_SHADE_SCREEN(ShadeFlag))) {
    7274            0 :                         TBmAll = TBmAllShBlSc;
    7275              :                     } else {
    7276        16092 :                         TBmAll = TBmBm + TBmDif;
    7277              :                     }
    7278        16092 :                     BTOTZone += surf.IncSolMultiplier * TBmAll * SunLitFract * CosInc * surf.Area * InOutProjSLFracMult; // [m2]
    7279              :                 }
    7280              :             }
    7281              : 
    7282              :             // Correct for effect of (1) beam absorbed by inside reveal, (2) diffuse entering zone from beam
    7283              :             // reflected by inside reveal and (3) diffuse transmitted by window from beam reflected from outside reveal.
    7284        31116 :             if (CosInc > 0.0) {
    7285              :                 // The BTOTZone is the solar into zone assuming no inside or outside reveals
    7286              :                 // The inside reveals receive solar (reflected part + absorbed part) from the window, this amount should be deducted from the
    7287              :                 // BTOTZone, then adds the InsRevealDiffIntoZone
    7288        16820 :                 if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) { // Complex Fenestration
    7289              :                     // Do not add total into zone from scheduled surface gains.  That will be added later
    7290            0 :                     if (SurfaceScheduledSolarInc(state, SurfNum, ConstrNum) == 0) {
    7291            0 :                         BTOTZone = BTOTZone - s_surf->SurfWinBmSolRefldInsReveal(SurfNum) - s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +
    7292            0 :                                    s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) +
    7293            0 :                                    s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * NomDiffTrans * surf.Area;
    7294              :                     }
    7295              :                 } else { // Regular window
    7296        16820 :                     BTOTZone = BTOTZone - s_surf->SurfWinBmSolRefldInsReveal(SurfNum) - s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +
    7297        16820 :                                s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) +
    7298        16820 :                                s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) * DiffTrans * surf.Area;
    7299              :                 }
    7300              :                 // Add beam solar absorbed by outside reveal to outside of window's base surface. Add beam solar absorbed by inside reveal to inside
    7301              :                 // of window's base surface. This ignores 2-D heat transfer effects.
    7302        16820 :                 int BaseSurfNum = surf.BaseSurf;
    7303        16820 :                 s_surf->SurfOpaqAI(BaseSurfNum) += s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / s_surf->Surface(BaseSurfNum).Area;
    7304        16820 :                 s_surf->SurfOpaqAO(BaseSurfNum) += s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) / s_surf->Surface(BaseSurfNum).Area;
    7305              :             }
    7306              : 
    7307              :             //-----------------------------------------------------------------
    7308              :             // BLOCK 6 - INTERIOR BEAM FROM EXTERIOR WINDOW THAT IS ABSORBED/TRANSMITTED BY BACK SURFACES
    7309              :             //-----------------------------------------------------------------
    7310              : 
    7311              :             // If shade is in place or there is a diffusing glass layer there is no interior beam
    7312              :             // from this exterior window since the beam-beam transmittance of shades and diffusing glass
    7313              :             // is assumed to be zero. The beam-beam transmittance of tubular daylighting devices is also
    7314              :             // assumed to be zero.
    7315        31116 :             if (SunLitFract > 0.0) {
    7316        16092 :                 if (s_surf->SurfWinWindowModelType(SurfNum) != WindowModel::BSDF)
    7317        32184 :                     if (ANY_SHADE(ShadeFlag) || s_surf->SurfWinSolarDiffusing(SurfNum) || surf.OriginalClass == SurfaceClass::TDD_Diffuser ||
    7318        16092 :                         surf.Class == SurfaceClass::TDD_Dome)
    7319            0 :                         continue;
    7320              : 
    7321              :                 // Find interior beam radiation that is:
    7322              :                 // (1) absorbed by opaque back surfaces;
    7323              :                 // (2) absorbed by glass layers of back surfaces that are interior or exterior windows;
    7324              :                 // (3) absorbed by interior, exterior or between-glass shades or blinds of back surfaces
    7325              :                 //       that are exterior windows; and
    7326              :                 // (4) transmitted through back surfaces that are interior or exterior windows.
    7327              :                 // Beam-beam transmittance of exterior window
    7328              :                 Real64 TBm;      // Window beam-beam transmittance
    7329              :                 Real64 TBmDenom; // TBmDenominator
    7330        16092 :                 Real64 TBmBmSc = s_surf->SurfWinScGlSysTsolBmBm(SurfNum);
    7331        16092 :                 Real64 TBmBmBl = s_surf->SurfWinBlGlSysTsolBmBm(SurfNum);
    7332        16092 :                 Real64 TBmBm = s_surf->SurfWinGlTsolBmBm(SurfNum);
    7333              : 
    7334        16092 :                 Real64 InOutProjSLFracMult = s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    7335        16092 :                 int InShelfSurf = 0; // Inside daylighting shelf surface number
    7336        16092 :                 int ShelfNum = s_surf->SurfDaylightingShelfInd(SurfNum);
    7337        16092 :                 if (ShelfNum > 0) { // Daylighting shelf
    7338            0 :                     InShelfSurf = state.dataDaylightingDevicesData->Shelf(ShelfNum).InSurf;
    7339              :                 }
    7340        16092 :                 if (ANY_BLIND(ShadeFlag)) {
    7341            0 :                     TBm = TBmBmBl; // Interior, exterior or between-glass blind on
    7342        16092 :                 } else if (ShadeFlag == WinShadingType::ExtScreen) {
    7343            0 :                     TBm = TBmBmSc; // Exterior screen on
    7344              :                 } else {
    7345        16092 :                     TBm = TBmBm; // Bare glass or switchable glazing
    7346              :                     // Correction for beam absorbed by inside reveal
    7347        16092 :                     TBmDenom = (SunLitFract * CosInc * surf.Area * InOutProjSLFracMult);
    7348        16092 :                     if (TBmDenom != 0.0) { // when =0.0, no correction
    7349        16081 :                         TBm -= s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / TBmDenom;
    7350              :                     }
    7351        16092 :                     TBm = max(0.0, TBm);
    7352              :                     // this multiplier doesn't work with other shading, so no need to apply in other branches
    7353        16092 :                     TBm *= surf.IncSolMultiplier;
    7354              :                 }
    7355              : 
    7356        16092 :                 if (TBm == 0.0) continue;
    7357        15783 :                 if (InShelfSurf > 0) { // Inside daylighting shelf
    7358              :                     // Inside daylighting shelves assume that no beam will pass the end of the shelf.
    7359              :                     // Since all beam is absorbed on the shelf, this might cause them to get unrealistically hot at times.
    7360              :                     // BTOTWinZone - Transmitted beam solar factor for a window [m2]
    7361            0 :                     Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * InOutProjSLFracMult;
    7362              :                     // Shelf surface area is divided by 2 because only one side sees beam (Area was multiplied by 2 during init)
    7363            0 :                     s_surf->SurfOpaqAI(InShelfSurf) += BTOTWinZone / (0.5 * s_surf->Surface(InShelfSurf).Area); //[-]
    7364            0 :                     BABSZone += BTOTWinZone;                                                                    //[m2]
    7365            0 :                     continue;
    7366            0 :                 }
    7367              : 
    7368        15783 :                 if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) { // Full interior solar distribution
    7369         2997 :                     if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::Detailed) {
    7370              :                         // Loop over back surfaces irradiated by beam from this exterior window
    7371         8220 :                         for (int IBack = 1; IBack <= state.dataBSDFWindow->MaxBkSurf; ++IBack) {
    7372              :                             int BackSurfNum =
    7373         8220 :                                 state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    7374         8220 :                             if (BackSurfNum == 0) break; // No more irradiated back surfaces for this exterior window
    7375              : 
    7376         5223 :                             auto &surfShadeBack = s_surf->surfShades(BackSurfNum);
    7377         5223 :                             int ConstrNumBack = s_surf->SurfActiveConstruction(BackSurfNum);
    7378         5223 :                             auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
    7379              : 
    7380         5223 :                             int NBackGlass = constrBack.TotGlassLayers;
    7381              :                             // Irradiated (overlap) area for this back surface, projected onto window plane
    7382              :                             // (includes effect of shadowing on exterior window)
    7383              :                             Real64 AOverlap =
    7384         5223 :                                 state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    7385              :                             // Back surface area irradiated by beam solar from an exterior window, projected onto window plane
    7386         5223 :                             Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
    7387              :                             // AOverlap multiplied by exterior window beam transmittance and cosine of incidence angle
    7388         5223 :                             if (constrBack.TransDiff <= 0.0) {
    7389              : 
    7390              :                                 // Back surface is opaque interior or exterior wall
    7391              :                                 // Interior solar absorptance of opaque surface
    7392         5222 :                                 Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
    7393         5222 :                                 s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
    7394         5222 :                                 BABSZone += BOverlap * AbsIntSurf;                                                            //[m2]
    7395              : 
    7396              :                             } else {
    7397              : 
    7398              :                                 // Back surface is an interior or exterior window
    7399              :                                 // Note that exterior back windows can have a shading device but interior back windows
    7400              :                                 // are assumed to be bare, i.e., they have no shading device and are non-switchable.
    7401              :                                 // The layer order for interior windows is "outside" to "inside," where "outside" refers to
    7402              :                                 // the adjacent zone and "inside" refers to the current zone.
    7403            1 :                                 WinShadingType ShadeFlagBack = s_surf->SurfWinShadingFlag(BackSurfNum);
    7404            1 :                                 Real64 slatAngBack = surfShadeBack.blind.slatAng;
    7405              :                                 Real64 CosIncBack =
    7406            1 :                                     std::abs(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, BackSurfNum));
    7407            1 :                                 if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    7408              :                                     // Transmitting window is complex fen, change the incident angle to one for ray joining
    7409              :                                     // transmitting and back window centers
    7410            0 :                                     CosIncBack = std::abs(state.dataBSDFWindow->ComplexWind(SurfNum).sdotN(IBack));
    7411              :                                 }
    7412            1 :                                 int ConstrNumBackShRaw = s_surf->SurfWinActiveShadedConstruction(BackSurfNum);
    7413            1 :                                 int const ConstrNumBackSh = ConstrNumBackShRaw == 0 ? ConstrNumBack : ConstrNumBackShRaw;
    7414            1 :                                 state.dataSolarShading->SurfWinAbsBeam.dimension(state.dataHeatBal->MaxSolidWinLayers, 0.0);
    7415            1 :                                 Real64 TransBeamWin = 0.0;           // Beam solar transmittance of a window
    7416            1 :                                 Real64 AbsBeamTotWin = 0.0;          // Sum of window glass layer beam solar absorptances
    7417            1 :                                 Real64 backSurfBeamSolInTrans = 0.0; // Fraction of BeamSolarRad transmitted out through window inside face [W]
    7418              : 
    7419              :                                 // Interior beam absorptance of glass layers and beam transmittance of back exterior  &
    7420              :                                 // or interior window WITHOUT SHADING this timestep
    7421            1 :                                 if (NOT_SHADED(ShadeFlagBack)) {
    7422            3 :                                     for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7423            2 :                                         state.dataSolarShading->SurfWinAbsBeam(Lay) = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
    7424              :                                     }
    7425            1 :                                     TransBeamWin = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
    7426              :                                 }
    7427              : 
    7428              :                                 // Interior beam absorptance of glass layers and beam transmittance
    7429              :                                 // of back exterior window with SHADE
    7430            1 :                                 if (ANY_SHADE(ShadeFlagBack)) {
    7431            0 :                                     for (int Lay = 1; Lay <= state.dataConstruction->Construct(ConstrNumBackSh).TotGlassLayers; ++Lay) {
    7432            0 :                                         state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7433            0 :                                             Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).AbsBeamBackCoef(Lay));
    7434              :                                     }
    7435            0 :                                     TransBeamWin = Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).TransSolBeamCoef);
    7436              :                                 }
    7437              : 
    7438              :                                 // Interior beam absorbed by INTERIOR SHADE of back exterior window
    7439            1 :                                 if (ShadeFlagBack == WinShadingType::IntShade) {
    7440            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7441            0 :                                         BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade /
    7442            0 :                                         (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7443            0 :                                     BABSZone += BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade;
    7444            0 :                                     backSurfBeamSolInTrans += BOverlap * state.dataConstruction->Construct(ConstrNumBackSh).AbsDiffBackShade;
    7445              : 
    7446              :                                     // Interior beam absorbed by EXTERIOR SHADE of back exterior window
    7447            1 :                                 } else if (ShadeFlagBack == WinShadingType::ExtShade) {
    7448            0 :                                     Real64 RGlFront = constrBack.ReflectSolDiffFront;
    7449            0 :                                     auto const *matSh = s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(1));
    7450            0 :                                     auto const *matFenSh = dynamic_cast<Material::MaterialFen const *>(matSh);
    7451            0 :                                     assert(matFenSh != nullptr);
    7452              : 
    7453            0 :                                     Real64 AbsSh = matFenSh->AbsorpSolar;
    7454            0 :                                     Real64 RhoSh = 1.0 - AbsSh - matFenSh->Trans;
    7455            0 :                                     Real64 AShBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef) * AbsSh / (1.0 - RGlFront * RhoSh);
    7456            0 :                                     BABSZone += BOverlap * AShBack;
    7457            0 :                                     backSurfBeamSolInTrans += BOverlap * AShBack;
    7458            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7459            0 :                                         BOverlap * AShBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7460              : 
    7461              :                                     // Interior beam absorbed by BETWEEN-GLASS SHADE of back exterior window
    7462            1 :                                 } else if (ShadeFlagBack == WinShadingType::BGShade) {
    7463            0 :                                     Real64 rbd1k = constrBack.rbBareSolDiff(1);
    7464            0 :                                     Real64 rfd2k = constrBack.rfBareSolDiff(2);
    7465              :                                     Real64 AShBack; // System shade absorptance for interior beam solar
    7466            0 :                                     if (NBackGlass == 2) {
    7467            0 :                                         Real64 t2k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(2));
    7468            0 :                                         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(
    7469            0 :                                             s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(3)));
    7470            0 :                                         assert(matShade != nullptr);
    7471            0 :                                         Real64 TrSh = matShade->Trans;                       // Shade material solar transmittance
    7472            0 :                                         Real64 RhoSh = matShade->ReflectShade;               // Shade material solar absorptance
    7473            0 :                                         Real64 AbsSh = min(1.0, max(0.0, 1 - TrSh - RhoSh)); // Shade material solar absorptance
    7474            0 :                                         AShBack = t2k * (1 + RhoSh * rfd2k + TrSh * rbd1k) * AbsSh;
    7475              :                                     } else { // NBackGlass = 3
    7476            0 :                                         Real64 t3k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(3));
    7477            0 :                                         Real64 td2k = constrBack.tBareSolDiff(2);
    7478            0 :                                         Real64 rbd2k = constrBack.rbBareSolDiff(2);
    7479            0 :                                         Real64 rfd3k = constrBack.rfBareSolDiff(3);
    7480            0 :                                         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(
    7481            0 :                                             s_mat->materials(state.dataConstruction->Construct(ConstrNumBackSh).LayerPoint(5)));
    7482            0 :                                         assert(matShade != nullptr);
    7483            0 :                                         Real64 TrSh = matShade->Trans;
    7484            0 :                                         Real64 RhoSh = matShade->ReflectShade;
    7485            0 :                                         Real64 AbsSh = min(1.0, max(0.0, 1 - TrSh - RhoSh));
    7486            0 :                                         AShBack = t3k * (1 + RhoSh * rfd3k + TrSh * (rbd2k + td2k * rbd1k * td2k)) * AbsSh;
    7487              :                                     }
    7488            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7489            0 :                                         BOverlap * AShBack / s_surf->Surface(BackSurfNum).Area;
    7490            0 :                                     BABSZone += BOverlap * AShBack;
    7491            0 :                                     backSurfBeamSolInTrans += BOverlap * AShBack;
    7492              :                                 }
    7493              : 
    7494              :                                 // Interior beam absorptance of glass layers and beam absorbed in blind
    7495              :                                 // of back exterior window with BLIND
    7496            1 :                                 if (ANY_BLIND(ShadeFlagBack)) {
    7497            0 :                                     auto const &btarBack = surfShadeBack.blind.TAR;
    7498              :                                     auto const *matBlindBack =
    7499            0 :                                         dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShadeBack.blind.matNum));
    7500            0 :                                     assert(matBlindBack != nullptr);
    7501              : 
    7502            0 :                                     auto const &btar = surfShade.blind.TAR;
    7503            0 :                                     Real64 profAngBack = surfShadeBack.blind.profAng;
    7504              : 
    7505            0 :                                     int profIdxLoBack = surfShadeBack.blind.profAngIdxLo;
    7506            0 :                                     int profIdxHiBack = surfShadeBack.blind.profAngIdxHi;
    7507            0 :                                     Real64 profInterpFacBack = surfShadeBack.blind.profAngInterpFac;
    7508              : 
    7509            0 :                                     Real64 TGlBmBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
    7510            0 :                                     Real64 TBlBmBmBack = matBlindBack->BeamBeamTrans(profAngBack, Constant::Pi - slatAngBack);
    7511              : 
    7512              :                                     // Blind solar back beam-diffuse transmittance
    7513              :                                     // Is this supposed to be blindBack?
    7514              :                                     Real64 TBlBmDiffBack =
    7515            0 :                                         Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfTra, btar.Sol.Bk.Bm[profIdxLoBack].DfTra, profInterpFacBack);
    7516              : 
    7517            0 :                                     if (ShadeFlagBack == WinShadingType::IntBlind) {
    7518              :                                         // Interior beam absorptance of GLASS LAYERS of exterior back window with INTERIOR BLIND
    7519            0 :                                         FrontDiffDiffRefl = btarBack.Sol.Ft.Df.Ref; // Blind solar front beam reflectance
    7520            0 :                                         FrontDiffAbs = btarBack.Sol.Ft.Df.Abs;
    7521              :                                         Real64 RhoBlFront =
    7522            0 :                                             Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfRef, btar.Sol.Ft.Bm[profIdxHiBack].DfRef, profInterpFacBack);
    7523              :                                         Real64 AbsBlFront =
    7524            0 :                                             Interp(btar.Sol.Ft.Bm[profIdxLoBack].Abs, btar.Sol.Ft.Bm[profIdxHiBack].Abs, profInterpFacBack);
    7525              :                                         Real64 AbsBlBack =
    7526            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
    7527              : 
    7528            0 :                                         Real64 RhoBlDiffFront = FrontDiffDiffRefl; // Glazing system solar back beam-beam reflectance
    7529            0 :                                         Real64 RGlBack = Window::POLYF(
    7530            0 :                                             CosIncBack, constrBack.ReflSolBeamBackCoef); // Glazing system back diffuse solar reflectance
    7531            0 :                                         Real64 RGlDiffBack = constrBack.ReflectSolDiffBack;
    7532            0 :                                         for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7533            0 :                                             Real64 AbWinBack = Window::POLYF(
    7534              :                                                 CosIncBack,
    7535              :                                                 constrBack.AbsBeamBackCoef(Lay)); // Factor for back beam radiation absorbed in window glass layer
    7536            0 :                                             Real64 AGlDiffBack = constrBack.AbsDiffBack(Lay); // Glass layer back diffuse solar absorptance
    7537            0 :                                             state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7538            0 :                                                 TBlBmBmBack * AbWinBack + ((TBlBmBmBack * RGlBack * RhoBlFront + TBlBmDiffBack) * AGlDiffBack /
    7539            0 :                                                                            (1.0 - RGlDiffBack * RhoBlDiffFront));
    7540              :                                         }
    7541              : 
    7542              :                                         // Interior beam transmitted by exterior back window with INTERIOR BLIND
    7543            0 :                                         Real64 TGlDif = constrBack.TransDiff; // Bare diffuse transmittance of back window
    7544            0 :                                         TransBeamWin =
    7545            0 :                                             TBlBmBmBack * (TGlBmBack + TGlDif * RGlBack * RhoBlFront / (1.0 - RGlDiffBack * RhoBlDiffFront)) +
    7546            0 :                                             TBlBmDiffBack * TGlDif / (1.0 - RGlDiffBack * RhoBlDiffFront);
    7547              : 
    7548              :                                         // Interior beam absorbed by BLIND on exterior back window with INTERIOR BLIND
    7549              : 
    7550            0 :                                         Real64 AbsBlDiffFront = FrontDiffAbs; // Blind solar front diffuse absorptance
    7551            0 :                                         Real64 ABlBack = AbsBlBack + TBlBmBmBack * RGlBack * AbsBlFront +
    7552            0 :                                                          (AbsBlDiffFront * RGlDiffBack / (1 - RhoBlDiffFront * RGlDiffBack)) *
    7553            0 :                                                              (RGlBack * TBlBmBmBack * RhoBlFront +
    7554              :                                                               TBlBmDiffBack); // Blind solar back absorptance for interior solar
    7555            0 :                                         state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7556            0 :                                             BOverlap * ABlBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7557            0 :                                         BABSZone += BOverlap * ABlBack;
    7558            0 :                                         backSurfBeamSolInTrans += BOverlap * ABlBack;
    7559              : 
    7560            0 :                                     } else if (ShadeFlagBack == WinShadingType::ExtBlind) {
    7561              : 
    7562              :                                         // Interior beam absorptance of GLASS LAYERS of exterior back window with EXTERIOR BLIND
    7563              : 
    7564            0 :                                         Real64 RGlDiffFront = state.dataConstruction->Construct(ConstrNumBack)
    7565            0 :                                                                   .ReflectSolDiffFront; // Glazing system front diffuse solar reflectance
    7566              : 
    7567              :                                         // Is this supposed to be beam-beam reflection?
    7568              :                                         Real64 RhoBlBack =
    7569            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
    7570              :                                         Real64 RhoBlBmDifBk =
    7571            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
    7572              :                                         Real64 AbsBlBack =
    7573            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
    7574              : 
    7575            0 :                                         for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7576            0 :                                             Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
    7577            0 :                                             Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
    7578            0 :                                             state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7579            0 :                                                 AbWinBack + (TGlBmBack * AGlDiffFront * RhoBlBack / (1.0 - RhoBlBack * RGlDiffFront));
    7580              :                                         }
    7581              : 
    7582              :                                         // Interior beam transmitted by exterior back window with EXTERIOR BLIND
    7583            0 :                                         Real64 TBlDifDif = BackDiffDiffTrans;
    7584            0 :                                         Real64 RhoBlDifDifBk = BackDiffDiffRefl;
    7585            0 :                                         Real64 AbsBlDiffBack = BackDiffAbs;
    7586            0 :                                         Real64 ABlBack =
    7587            0 :                                             TGlBmBack * (AbsBlBack + RhoBlBack * RGlDiffFront * AbsBlDiffBack / (1 - RhoBlDifDifBk * RGlDiffFront));
    7588            0 :                                         Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
    7589            0 :                                         TransBeamWin = TGlBmBack * (TBlBmBmBack + TBlBmDiffBack +
    7590            0 :                                                                     TBlDifDif * RhoBlBmDifBk * RGlDifFr / (1.0 - RhoBlDifDifBk * RGlDifFr));
    7591              :                                         // Interior beam absorbed by EXTERIOR BLIND on exterior back window
    7592            0 :                                         BABSZone += BOverlap * ABlBack;
    7593            0 :                                         backSurfBeamSolInTrans += BOverlap * ABlBack;
    7594            0 :                                         state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7595            0 :                                             BOverlap * ABlBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7596              : 
    7597              :                                     } else {
    7598              :                                         // ShadeFlagBack == BGBlindOn
    7599            0 :                                         Real64 t1k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(1));
    7600            0 :                                         Real64 t2k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(2));
    7601            0 :                                         Real64 af2k = Window::POLYF(CosIncBack, constrBack.afBareSolCoef(2));
    7602            0 :                                         Real64 ab1k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(1));
    7603            0 :                                         Real64 ab2k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(2));
    7604            0 :                                         Real64 rb1k = Window::POLYF(CosIncBack, constrBack.rbBareSolCoef(1));
    7605            0 :                                         Real64 rb2k = Window::POLYF(CosIncBack, constrBack.rbBareSolCoef(2));
    7606            0 :                                         Real64 td1k = constrBack.tBareSolDiff(1);
    7607            0 :                                         Real64 td2k = constrBack.tBareSolDiff(2);
    7608            0 :                                         Real64 afd2k = constrBack.afBareSolDiff(2);
    7609            0 :                                         Real64 abd1k = constrBack.abBareSolDiff(1);
    7610            0 :                                         Real64 abd2k = constrBack.abBareSolDiff(2);
    7611            0 :                                         Real64 rfd2k = constrBack.rfBareSolDiff(2);
    7612            0 :                                         Real64 rbd1k = constrBack.rbBareSolDiff(1);
    7613            0 :                                         Real64 rbd2k = constrBack.rbBareSolDiff(2);
    7614            0 :                                         Real64 tfshBBk = matBlindBack->BeamBeamTrans(profAngBack, slatAngBack);
    7615            0 :                                         Real64 tbshBBk = matBlindBack->BeamBeamTrans(profAngBack, Constant::Pi - slatAngBack);
    7616              : 
    7617              :                                         Real64 tfshBdk =
    7618            0 :                                             Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfTra, btar.Sol.Ft.Bm[profIdxHiBack].DfTra, profInterpFacBack);
    7619              :                                         Real64 tbshBdk =
    7620            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfTra, btar.Sol.Bk.Bm[profIdxHiBack].DfTra, profInterpFacBack);
    7621              :                                         Real64 rfshBk =
    7622            0 :                                             Interp(btar.Sol.Ft.Bm[profIdxLoBack].DfRef, btar.Sol.Ft.Bm[profIdxHiBack].DfRef, profInterpFacBack);
    7623              :                                         Real64 rbshBk =
    7624            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].DfRef, btar.Sol.Bk.Bm[profIdxHiBack].DfRef, profInterpFacBack);
    7625              :                                         Real64 afshBk =
    7626            0 :                                             Interp(btar.Sol.Ft.Bm[profIdxLoBack].Abs, btar.Sol.Ft.Bm[profIdxHiBack].Abs, profInterpFacBack);
    7627              :                                         Real64 abshBk =
    7628            0 :                                             Interp(btar.Sol.Bk.Bm[profIdxLoBack].Abs, btar.Sol.Bk.Bm[profIdxHiBack].Abs, profInterpFacBack);
    7629            0 :                                         Real64 tfshdk = btarBack.Sol.Ft.Df.Tra;
    7630            0 :                                         Real64 rfshdk = btarBack.Sol.Ft.Df.Ref;
    7631            0 :                                         Real64 afshdk = btarBack.Sol.Ft.Df.Abs;
    7632            0 :                                         Real64 tbshdk = btarBack.Sol.Bk.Df.Tra;
    7633            0 :                                         Real64 rbshdk = btarBack.Sol.Bk.Df.Ref;
    7634            0 :                                         Real64 abshdk = btarBack.Sol.Bk.Df.Abs;
    7635              :                                         Real64 ABlBack;
    7636              : 
    7637            0 :                                         if (NBackGlass == 2) {
    7638              :                                             // Interior beam absorptance of GLASS LAYERS of exterior back window with BETWEEN-GLASS BLIND
    7639            0 :                                             state.dataSolarShading->SurfWinAbsBeam(2) =
    7640            0 :                                                 ab2k + t2k * tbshBBk * rb1k * tfshBBk * af2k +
    7641            0 :                                                 t2k * (tbshBBk * rb1k * tfshBdk + tbshBdk * rbd1k * tfshdk + rbshBk * (1.0 + rfd2k * rbshdk)) * afd2k;
    7642            0 :                                             state.dataSolarShading->SurfWinAbsBeam(1) =
    7643            0 :                                                 t2k * tbshBBk * ab1k + t2k * (rbshBk * rfd2k * tbshdk + tbshBdk * (1.0 + rbd1k * rfshdk)) * abd1k;
    7644              :                                             // Interior beam transmitted by exterior back window with BETWEEN-GLASS BLIND
    7645            0 :                                             TransBeamWin =
    7646            0 :                                                 t2k * tbshBBk * t1k +
    7647            0 :                                                 t2k * (tbshBBk * rb1k * rfshBk + rbshBk * rfd2k * tbshdk + tbshBdk * (1.0 + rbd1k * rfshdk)) * td1k;
    7648              :                                             // Interior beam absorbed by BLIND on exterior back window with BETWEEN-GLASS BLIND
    7649            0 :                                             ABlBack = t2k * (abshBk + tbshBBk * rb1k * afshBk + rbshBk * rfd2k * abshdk + tbshBdk * rbd1k * afshdk);
    7650              :                                         } else { // NBackGlass = 3
    7651            0 :                                             Real64 t3k = Window::POLYF(CosIncBack, constrBack.tBareSolCoef(3));
    7652            0 :                                             Real64 af3k = Window::POLYF(CosIncBack, constrBack.afBareSolCoef(3));
    7653            0 :                                             Real64 ab3k = Window::POLYF(CosIncBack, constrBack.abBareSolCoef(3));
    7654            0 :                                             Real64 afd3k = constrBack.afBareSolDiff(3);
    7655            0 :                                             Real64 rfd3k = constrBack.rfBareSolDiff(3);
    7656            0 :                                             state.dataSolarShading->SurfWinAbsBeam(3) =
    7657            0 :                                                 ab3k + t3k * tbshBBk * (rb2k + t2k * rb1k * t2k) * tfshBBk * af3k +
    7658            0 :                                                 t3k *
    7659            0 :                                                     (tbshBdk * rbd2k * tfshdk + tbshBdk * td2k * rbd1k * td2k * tfshdk +
    7660            0 :                                                      rbshBk * (1.0 + rfd3k * rbshdk)) *
    7661              :                                                     afd3k;
    7662            0 :                                             state.dataSolarShading->SurfWinAbsBeam(2) =
    7663            0 :                                                 t3k * tbshBBk * (ab2k + t2k * rb1k * (af2k + t2k * rfshBk * abd2k)) +
    7664            0 :                                                 t3k * (tbshBdk + tbshBdk * (rbd2k + td2k * rbd1k * td2k) * rfshdk + rbshBk * rfd3k * tbshdk) * abd2k +
    7665            0 :                                                 t3k * tbshBdk * td2k * rbd1k * afd2k;
    7666            0 :                                             state.dataSolarShading->SurfWinAbsBeam(1) =
    7667            0 :                                                 t3k * tbshBBk * (t2k * ab1k + (rb2k + t2k * rb1k * t2k) * rfshBk * td2k * abd1k) +
    7668            0 :                                                 t3k * (rbshBk * rfd3k * tbshdk + tbshBdk * (1.0 + rbd2k * rfshdk + td2k * rbd2k * td2k * rfshdk)) *
    7669            0 :                                                     td2k * abd1k;
    7670            0 :                                             TransBeamWin = t3k * tbshBBk * t2k * t1k +
    7671            0 :                                                            t3k *
    7672            0 :                                                                (tbshBBk * (rb2k * rfshBk + t2k * rb1k * t2k * rfshBk) + rbshBk * rfd3k * tbshdk +
    7673            0 :                                                                 tbshBdk * (1.0 + rbd2k * rfshdk + td2k * rbd1k * td2k * rfshdk)) *
    7674            0 :                                                                td2k * td1k;
    7675            0 :                                             ABlBack = t3k * abshBk + t3k * tbshBBk * (rb2k + t2k * rb1k * t2k) * afshBk +
    7676            0 :                                                       t3k * rbshBk * rfd3k * abshdk + t3k * tbshBdk * (rbd2k + td2k * rbd1k * td2k) * afshdk;
    7677              :                                         }
    7678              : 
    7679            0 :                                         BABSZone += BOverlap * ABlBack;
    7680            0 :                                         backSurfBeamSolInTrans += BOverlap * ABlBack;
    7681            0 :                                         state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7682            0 :                                             BOverlap * ABlBack / s_surf->Surface(BackSurfNum).Area;
    7683              : 
    7684              :                                     } // End of check if between-glass blind is on back window
    7685            1 :                                 } else if (ShadeFlagBack == WinShadingType::ExtScreen) {
    7686              : 
    7687              :                                     // Interior beam absorptance of GLASS LAYERS of exterior back window with EXTERIOR SCREEN
    7688            0 :                                     Real64 TGlBmBack = Window::POLYF(CosIncBack, constrBack.TransSolBeamCoef);
    7689            0 :                                     Real64 RGlDiffFront = constrBack.ReflectSolDiffFront;
    7690              : 
    7691            0 :                                     auto const *screen = dynamic_cast<Material::MaterialScreen const *>(s_mat->materials(ScNum));
    7692            0 :                                     assert(screen != nullptr);
    7693              : 
    7694            0 :                                     auto &surf = s_surf->Surface(SurfNum);
    7695            0 :                                     Real64 solPhi = std::acos(state.dataEnvrn->SOLCOS.z);
    7696            0 :                                     Real64 solTheta = std::atan2(state.dataEnvrn->SOLCOS.x, state.dataEnvrn->SOLCOS.y);
    7697            0 :                                     Real64 winPhi = surf.Tilt * Constant::DegToRad;
    7698            0 :                                     Real64 winTheta = surf.Azimuth * Constant::DegToRad;
    7699            0 :                                     Real64 phi = std::abs(solPhi - winPhi);
    7700            0 :                                     Real64 theta = std::abs(solTheta - winTheta);
    7701            0 :                                     Material::NormalizePhiTheta(phi, theta);
    7702              : #ifdef PRECALC_INTERP_SCREEN
    7703              :                                     int ip1, ip2, it1, it2;
    7704              :                                     BilinearInterpCoeffs coeffs;
    7705            0 :                                     Material::GetPhiThetaIndices(phi, theta, screen->dPhi, screen->dTheta, ip1, ip2, it1, it2);
    7706            0 :                                     GetBilinearInterpCoeffs(
    7707            0 :                                         phi, theta, ip1 * screen->dPhi, ip2 * screen->dPhi, it1 * screen->dTheta, it2 * screen->dTheta, coeffs);
    7708            0 :                                     auto const &b11 = screen->btars[ip1][it1];
    7709            0 :                                     auto const &b12 = screen->btars[ip1][it2];
    7710            0 :                                     auto const &b21 = screen->btars[ip2][it1];
    7711            0 :                                     auto const &b22 = screen->btars[ip2][it2];
    7712              : 
    7713            0 :                                     Real64 TScBmBmBack = BilinearInterp(b11.BmTransBack, b12.BmTransBack, b21.BmTransBack, b22.BmTransBack, coeffs);
    7714            0 :                                     Real64 TScBmDiffBack = BilinearInterp(b11.DfTransBack, b12.DfTransBack, b21.DfTransBack, b22.DfTransBack, coeffs);
    7715            0 :                                     Real64 RScBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
    7716            0 :                                     Real64 RScDifBack = screen->DfRef;
    7717            0 :                                     for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7718            0 :                                         Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
    7719            0 :                                         Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
    7720            0 :                                         state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7721            0 :                                             AbWinBack + (TGlBmBack * AGlDiffFront * RScBack / (1.0 - RScDifBack * RGlDiffFront));
    7722              :                                     }
    7723              : 
    7724              :                                     // Interior beam transmitted by exterior back window with EXTERIOR SCREEN
    7725            0 :                                     Real64 TScDifDif = screen->DfTrans;
    7726            0 :                                     Real64 RScBmDifBk = BilinearInterp(b11.RefSolBack, b12.RefSolBack, b21.RefSolBack, b22.RefSolBack, coeffs);
    7727            0 :                                     Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
    7728            0 :                                     Real64 RScDifDifBk = screen->DfRef;
    7729            0 :                                     TransBeamWin = TGlBmBack *
    7730            0 :                                                    (TScBmBmBack + TScBmDiffBack + TScDifDif * RScBmDifBk * RGlDifFr / (1.0 - RScDifDifBk * RGlDifFr));
    7731              : 
    7732              :                                     // Interior beam absorbed by EXTERIOR SCREEN on exterior back window
    7733            0 :                                     Real64 AbsScBack = BilinearInterp(b11.AbsSolBack, b12.AbsSolBack, b21.AbsSolBack, b22.AbsSolBack, coeffs);
    7734            0 :                                     Real64 AbsScDiffBack = screen->DfAbs;
    7735            0 :                                     Real64 RScDiffBack = BilinearInterp(b11.RefSolFront, b12.RefSolFront, b21.RefSolFront, b22.RefSolFront, coeffs);
    7736              :                                     // Screen solar back absorptance for interior solar
    7737            0 :                                     Real64 AScBack =
    7738            0 :                                         TGlBmBack * (AbsScBack + RScBack * RGlDiffFront * AbsScDiffBack / (1.0 - RScDiffBack * RGlDiffFront));
    7739              : 
    7740            0 :                                     BABSZone += BOverlap * AScBack;
    7741            0 :                                     backSurfBeamSolInTrans += BOverlap * AScBack;
    7742            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7743            0 :                                         BOverlap * AScBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7744              : #else  // !PRECALC_INTERP_SCREEN
    7745              :                                     Material::ScreenBmTransAbsRef btar;
    7746              :                                     Material::CalcScreenTransmittance(state, screen, phi, theta, btar);
    7747              : 
    7748              :                                     Real64 TScBmBmBack = btar.BmTransBack;
    7749              :                                     Real64 TScBmDiffBack = btar.DfTransBack;
    7750              :                                     Real64 RScBack = btar.RefSolFront;
    7751              :                                     Real64 RScDifBack = screen->DfRef;
    7752              :                                     for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7753              :                                         Real64 AbWinBack = Window::POLYF(CosIncBack, constrBack.AbsBeamBackCoef(Lay));
    7754              :                                         Real64 AGlDiffFront = constrBack.AbsDiff(Lay);
    7755              :                                         state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7756              :                                             AbWinBack + (TGlBmBack * AGlDiffFront * RScBack / (1.0 - RScDifBack * RGlDiffFront));
    7757              :                                     }
    7758              : 
    7759              :                                     // Interior beam transmitted by exterior back window with EXTERIOR SCREEN
    7760              :                                     Real64 TScDifDif = screen->DfTrans;
    7761              :                                     Real64 RScBmDifBk = btar.RefSolBack;
    7762              :                                     Real64 RGlDifFr = thisConstruct.ReflectSolDiffFront;
    7763              :                                     Real64 RScDifDifBk = screen->DfRef;
    7764              :                                     TransBeamWin = TGlBmBack *
    7765              :                                                    (TScBmBmBack + TScBmDiffBack + TScDifDif * RScBmDifBk * RGlDifFr / (1.0 - RScDifDifBk * RGlDifFr));
    7766              : 
    7767              :                                     // Interior beam absorbed by EXTERIOR SCREEN on exterior back window
    7768              :                                     Real64 AbsScBack = btar.AbsSolBack;
    7769              :                                     Real64 AbsScDiffBack = screen->DfAbs;
    7770              :                                     Real64 RScDiffBack = btar.RefSolFront;
    7771              :                                     // Screen solar back absorptance for interior solar
    7772              :                                     Real64 AScBack =
    7773              :                                         TGlBmBack * (AbsScBack + RScBack * RGlDiffFront * AbsScDiffBack / (1.0 - RScDiffBack * RGlDiffFront));
    7774              : 
    7775              :                                     BABSZone += BOverlap * AScBack;
    7776              :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    7777              :                                         BOverlap * AScBack / (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    7778              : #endif // PRECALC_INTERP_SCREEN
    7779              : 
    7780              :                                 } // End of check if exterior screen on back window
    7781              : 
    7782              :                                 // Interior beam absorptance of glass layers of back exterior window with SWITCHABLE GLAZING
    7783            1 :                                 if (ShadeFlagBack == WinShadingType::SwitchableGlazing && s_surf->Surface(BackSurfNum).ExtBoundCond == 0) {
    7784            0 :                                     Real64 SwitchFac = s_surf->SurfWinSwitchingFactor(SurfNum); // Switching factor for a window
    7785              :                                     Real64 AbsBeamWinSh; // Glass layer beam solar absorptance of a shaded window
    7786            0 :                                     for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7787              :                                         AbsBeamWinSh =
    7788            0 :                                             Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).AbsBeamBackCoef(Lay));
    7789            0 :                                         state.dataSolarShading->SurfWinAbsBeam(Lay) =
    7790            0 :                                             Window::InterpSw(SwitchFac, state.dataSolarShading->SurfWinAbsBeam(Lay), AbsBeamWinSh);
    7791              :                                     }
    7792              :                                     // Beam solar transmittance of a shaded window
    7793              :                                     Real64 TransBeamWinSh =
    7794            0 :                                         Window::POLYF(CosIncBack, state.dataConstruction->Construct(ConstrNumBackSh).TransSolBeamCoef);
    7795            0 :                                     TransBeamWin = Window::InterpSw(SwitchFac, TransBeamWin, TransBeamWinSh);
    7796              :                                 }
    7797              : 
    7798              :                                 // Sum of interior beam absorbed by all glass layers of back window
    7799            1 :                                 AbsBeamTotWin = 0.0;
    7800            3 :                                 for (int Lay = 1; Lay <= NBackGlass; ++Lay) {
    7801            2 :                                     AbsBeamTotWin += state.dataSolarShading->SurfWinAbsBeam(Lay);
    7802            2 :                                     s_surf->SurfWinA(BackSurfNum, Lay) +=
    7803            2 :                                         BOverlap * state.dataSolarShading->SurfWinAbsBeam(Lay) /
    7804            2 :                                         (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum)); //[-]
    7805              :                                 }
    7806              : 
    7807              :                                 // To BABSZon, add interior beam glass absorption and overall beam transmission for this back window
    7808            1 :                                 BABSZone += BOverlap * (AbsBeamTotWin + TransBeamWin);
    7809            1 :                                 backSurfBeamSolInTrans += BOverlap * (AbsBeamTotWin + TransBeamWin);
    7810            1 :                                 state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfNum) +=
    7811            1 :                                     backSurfBeamSolInTrans * state.dataEnvrn->BeamSolarRad; //[W]
    7812              :                                 // Interior beam transmitted to adjacent zone through an interior back window (assumed unshaded);
    7813              :                                 // this beam radiation is categorized as diffuse radiation in the adjacent zone.
    7814            1 :                                 int AdjSurfNum = s_surf->Surface(BackSurfNum).ExtBoundCond;
    7815            1 :                                 if (AdjSurfNum > 0) {
    7816            0 :                                     int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
    7817            0 :                                     state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BOverlap * TransBeamWin; //[m2]
    7818            0 :                                     s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) +=
    7819            0 :                                         BOverlap * TransBeamWin * state.dataEnvrn->BeamSolarRad; //[W]
    7820            0 :                                     s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfNum) =
    7821            0 :                                         s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
    7822              :                                 }
    7823              :                             } // End of check if back surface is opaque or window
    7824         5223 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) += BOverlap;
    7825         5223 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(BackSurfNum) =
    7826         5223 :                                 state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
    7827              :                         } // End of loop over back surfaces
    7828            0 :                     } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    7829              :                         // For complex window calculation goes over outgoing basis directions for current state
    7830            0 :                         int CurCplxFenState = s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState; // Current state for complex fenestration
    7831              :                         // Get construction number which keeps transmittance properties
    7832            0 :                         int IConst = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(CurCplxFenState).Konst; // Current surface construction number
    7833              :                                                                                                              // (it depends of state too)
    7834              :                         // Solar radiation from this window will be calculated only in case when this window is not scheduled surface gained
    7835            0 :                         if (WindowScheduledSolarAbs(state, SurfNum, IConst) == 0) {
    7836              :                             // Current incoming direction number (Sun direction)
    7837            0 :                             int IBm = state.dataBSDFWindow->ComplexWind(SurfNum)
    7838            0 :                                           .Geom(CurCplxFenState)
    7839            0 :                                           .SolBmIndex(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    7840              :                             // Report variables for complex fenestration here
    7841            0 :                             state.dataHeatBal->SurfWinBSDFBeamDirectionRep(SurfNum) = IBm;
    7842            0 :                             state.dataHeatBal->SurfWinBSDFBeamThetaRep(SurfNum) =
    7843            0 :                                 state.dataBSDFWindow->ComplexWind(SurfNum)
    7844            0 :                                     .Geom(CurCplxFenState)
    7845            0 :                                     .ThetaBm(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    7846            0 :                             state.dataHeatBal->SurfWinBSDFBeamPhiRep(SurfNum) = state.dataBSDFWindow->ComplexWind(SurfNum)
    7847            0 :                                                                                     .Geom(CurCplxFenState)
    7848            0 :                                                                                     .PhiBm(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep);
    7849              : 
    7850            0 :                             int BaseSurf = surf.BaseSurf; // Base surface number for current complex window
    7851              :                             // Get total number of back surfaces for current window (surface)
    7852              :                             // Note that it is organized by base surface
    7853            0 :                             int NBkSurf = state.dataShadowComb->ShadowComb(BaseSurf).NumBackSurf;
    7854            0 :                             if (!allocated(CFBoverlap)) {
    7855            0 :                                 CFBoverlap.allocate(NBkSurf);
    7856              :                             }
    7857            0 :                             if (!allocated(CFDirBoverlap)) {
    7858            0 :                                 CFDirBoverlap.allocate(NBkSurf, state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis);
    7859              :                             }
    7860              : 
    7861            0 :                             CFBoverlap = 0.0;
    7862              :                             // Calculate effects on all back surfaces for each of basis directions.  Each of basis directions from the back of the
    7863              :                             // window has to be considered as beam and therefore calculate CFBoverlap for each of them
    7864            0 :                             for (int CurTrnDir = 1; CurTrnDir <= state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis;
    7865              :                                  ++CurTrnDir) {
    7866            0 :                                 Real64 CurLambda = state.dataBSDFWindow->ComplexWind(SurfNum)
    7867            0 :                                                        .Geom(CurCplxFenState)
    7868            0 :                                                        .Trn.Lamda(CurTrnDir); // Current lambda value in BSDF outgoing directions
    7869            0 :                                 Real64 DirTrans = state.dataConstruction->Construct(IConst).BSDFInput.SolFrtTrans(
    7870            0 :                                     IBm, CurTrnDir); // Current BSDF directional transmittance
    7871              :                                 // Now calculate effect of this direction on all back surfaces
    7872            0 :                                 for (int IBack = 1; IBack <= NBkSurf; ++IBack) {
    7873            0 :                                     CFDirBoverlap(IBack, CurTrnDir) =
    7874            0 :                                         state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).AOverlap(IBack, CurTrnDir) * DirTrans *
    7875            0 :                                         CurLambda * CosInc;
    7876            0 :                                     CFBoverlap(IBack) += CFDirBoverlap(IBack, CurTrnDir);
    7877              :                                 } // DO IBack = 1,MaxBkSurf
    7878              :                             }
    7879              : 
    7880              :                             // Summarizing results
    7881            0 :                             for (int IBack = 1; IBack <= NBkSurf; ++IBack) {
    7882            0 :                                 int BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(IBack);
    7883            0 :                                 int ConstrNumBack = s_surf->Surface(BackSurfaceNumber).Construction;
    7884            0 :                                 auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
    7885              :                                 // Do not perform any calculation if surface is scheduled for incoming solar radiation
    7886            0 :                                 int SurfSolIncPtr = SurfaceScheduledSolarInc(state, BackSurfaceNumber, ConstrNumBack);
    7887              : 
    7888            0 :                                 if (SurfSolIncPtr == 0) {
    7889              :                                     // Surface hit is another complex fenestration
    7890            0 :                                     if (s_surf->SurfWinWindowModelType(BackSurfaceNumber) == WindowModel::BSDF) {
    7891              :                                         int CurBackState =
    7892            0 :                                             s_surf->SurfaceWindow(BackSurfaceNumber)
    7893            0 :                                                 .ComplexFen.CurrentState; // Current state for back surface if that surface is complex fenestration
    7894              :                                         // Do not take into account this window if it is scheduled for surface gains
    7895            0 :                                         if (WindowScheduledSolarAbs(state, BackSurfaceNumber, ConstrNumBack) == 0) {
    7896              :                                             // Calculate energy loss per each outgoing orientation
    7897            0 :                                             for (int CurTrnDir = 1;
    7898            0 :                                                  CurTrnDir <= state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).Trn.NBasis;
    7899              :                                                  ++CurTrnDir) {
    7900              :                                                 Real64 bestDot; // complex fenestration hits other complex fenestration, it is important to find
    7901              :                                                 // matching beam directions.  Beam leaving one window will have certain number for it's basis
    7902              :                                                 // while same beam reaching back surface will have different beam number.  This value is used
    7903              :                                                 // to keep best matching dot product for those directions
    7904              :                                                 Real64 curDot;   // temporary variable for current dot product
    7905              :                                                 int bestBackTrn; // Direction corresponding best dot product for back surface window
    7906            0 :                                                 for (int CurBackDir = 1;
    7907            0 :                                                      CurBackDir <= state.dataBSDFWindow->ComplexWind(BackSurfaceNumber).Geom(CurBackState).Trn.NBasis;
    7908              :                                                      ++CurBackDir) {
    7909              :                                                     // Purpose of this part is to find best match for outgoing beam number of window back surface
    7910              :                                                     // and incoming beam number of complex fenestration which this beam will hit on (back surface
    7911              :                                                     // again)
    7912              :                                                     curDot =
    7913            0 :                                                         dot(state.dataBSDFWindow->ComplexWind(SurfNum).Geom(CurCplxFenState).sTrn(CurTrnDir),
    7914            0 :                                                             state.dataBSDFWindow->ComplexWind(BackSurfaceNumber).Geom(CurBackState).sTrn(CurBackDir));
    7915            0 :                                                     if (CurBackDir == 1) {
    7916            0 :                                                         bestDot = curDot;
    7917            0 :                                                         bestBackTrn = CurBackDir;
    7918              :                                                     } else {
    7919            0 :                                                         if (curDot < bestDot) {
    7920            0 :                                                             bestDot = curDot;
    7921            0 :                                                             bestBackTrn = CurBackDir;
    7922              :                                                         }
    7923              :                                                     }
    7924              :                                                 }
    7925              :                                                 // CurLambda = ComplexWind(BackSurfaceNumber)%Geom(CurBackState)%Trn%Lamda(CurTrnDir)
    7926              :                                                 // Add influence of this exact direction to what stays in the zone.  It is important to note that
    7927              :                                                 // this needs to be done for each outgoing direction
    7928            0 :                                                 Real64 babs = CFDirBoverlap(IBack, CurTrnDir) * (1 - s_surf->SurfaceWindow(BackSurfaceNumber)
    7929            0 :                                                                                                          .ComplexFen.State(CurBackState)
    7930            0 :                                                                                                          .IntegratedBkRefl(bestBackTrn));
    7931            0 :                                                 BABSZone += babs;
    7932            0 :                                                 state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfaceNumber) +=
    7933            0 :                                                     babs * state.dataEnvrn->BeamSolarRad; //[W]
    7934              : 
    7935              :                                                 // Absorptance from current back direction
    7936            0 :                                                 int TotSolidLay = constrBack.TotSolidLayers;
    7937            0 :                                                 for (int Lay = 1; Lay <= TotSolidLay; ++Lay) {
    7938              :                                                     // IF (ALLOCATED(Construct(ConstrNumBack)%BSDFInput)) THEN
    7939              :                                                     // CFDirBoverlap is energy transmitted for current basis beam.  It is important to note that
    7940              :                                                     // AWinOverlap array needs to contain flux and not absorbed energy because later in the code
    7941              :                                                     // this will be multiplied with window area
    7942            0 :                                                     s_surf->SurfWinACFOverlap(BackSurfaceNumber, Lay) +=
    7943            0 :                                                         constrBack.BSDFInput.Layer(Lay).BkAbs(bestBackTrn, 1) * CFDirBoverlap(IBack, CurTrnDir) /
    7944            0 :                                                         s_surf->Surface(BackSurfaceNumber).Area;
    7945              :                                                     // END IF
    7946              :                                                 }
    7947              : 
    7948              :                                                 // Interior beam transmitted to adjacent zone through an interior back window;
    7949              :                                                 // This beam radiation is categorized as diffuse radiation in the adjacent zone.
    7950              :                                                 // Note that this is done for each outgoing direction of exterior window
    7951            0 :                                                 int AdjSurfNum = s_surf->Surface(BackSurfaceNumber).ExtBoundCond;
    7952            0 :                                                 if (AdjSurfNum > 0) {
    7953            0 :                                                     int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
    7954            0 :                                                     state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) +=
    7955            0 :                                                         CFDirBoverlap(IBack, CurTrnDir) * s_surf->SurfaceWindow(BackSurfaceNumber)
    7956            0 :                                                                                               .ComplexFen.State(CurBackState)
    7957            0 :                                                                                               .IntegratedBkTrans(bestBackTrn);
    7958            0 :                                                     s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfaceNumber) +=
    7959            0 :                                                         CFDirBoverlap(IBack, CurTrnDir) *
    7960            0 :                                                         s_surf->SurfaceWindow(BackSurfaceNumber)
    7961            0 :                                                             .ComplexFen.State(CurBackState)
    7962            0 :                                                             .IntegratedBkTrans(bestBackTrn) *
    7963            0 :                                                         state.dataEnvrn->BeamSolarRad; //[W]
    7964            0 :                                                     s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfaceNumber) =
    7965            0 :                                                         s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfaceNumber) * state.dataGlobal->TimeStepZoneSec;
    7966              :                                                 }
    7967              :                                             }
    7968              :                                         }
    7969              :                                     } else {
    7970            0 :                                         if (constrBack.TransDiff <= 0.0) {
    7971              :                                             // Do not take into account this window if it is scheduled for surface gains
    7972            0 :                                             Real64 AbsIntSurf = constrBack.InsideAbsorpSolar;
    7973            0 :                                             s_surf->SurfOpaqAI(BackSurfaceNumber) +=
    7974            0 :                                                 CFBoverlap(IBack) * AbsIntSurf / s_surf->Surface(BackSurfaceNumber).Area;
    7975            0 :                                             BABSZone += CFBoverlap(IBack) * AbsIntSurf;
    7976              :                                         } else {
    7977              :                                             // Code for mixed windows goes here.  It is same as above code for "ordinary" windows.
    7978              :                                             // Try to do something which will not produce duplicate code.
    7979              :                                         }
    7980              :                                     }
    7981              :                                 }
    7982              :                             }
    7983              : 
    7984            0 :                             if (allocated(CFBoverlap)) CFBoverlap.deallocate();
    7985            0 :                             if (allocated(CFDirBoverlap)) CFDirBoverlap.deallocate();
    7986              :                         }
    7987              : 
    7988            0 :                     } else if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::EQL) {
    7989              : 
    7990            0 :                         for (int IBack = 1; IBack <= state.dataBSDFWindow->MaxBkSurf; ++IBack) {
    7991              :                             int BackSurfNum =
    7992            0 :                                 state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    7993            0 :                             if (BackSurfNum == 0) break; // No more irradiated back surfaces for this exterior window
    7994            0 :                             if (s_surf->SurfWinWindowModelType(IBack) != WindowModel::EQL) continue; // only EQL back window is allowed
    7995              : 
    7996            0 :                             int ConstrNumBack = s_surf->Surface(BackSurfNum).Construction;
    7997            0 :                             auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
    7998            0 :                             int NBackGlass = constrBack.TotGlassLayers;
    7999              :                             // Irradiated (overlap) area for this back surface, projected onto window plane
    8000              :                             // (includes effect of shadowing on exterior window)
    8001              : 
    8002              :                             Real64 AOverlap =
    8003            0 :                                 state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    8004            0 :                             Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
    8005              : 
    8006            0 :                             if (constrBack.TransDiff <= 0.0) {
    8007              : 
    8008              :                                 // Back surface is opaque interior or exterior wall
    8009            0 :                                 Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
    8010            0 :                                 s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
    8011            0 :                                 BABSZone += BOverlap * AbsIntSurf;                                                            //[m2]
    8012              : 
    8013              :                             } else {
    8014              : 
    8015              :                                 // Back surface is an interior or exterior window
    8016              :                                 // Note that exterior back windows with and without shades are treated as defined.
    8017              :                                 // Equivalent Layer window model has no distinction when treating windows with and
    8018              :                                 // without shades (interior, inbetween and exterior shades)
    8019              :                                 //  Note in equivalent layer window model if storm window exists it is defined as part of
    8020              :                                 //  window construction, hence it does not require a separate treatment
    8021            0 :                                 state.dataSolarShading->SurfWinAbsBeamEQL = 0.0;
    8022            0 :                                 Real64 TransBeamWin = 0.0;           // Beam solar transmittance of a window
    8023            0 :                                 Real64 backSurfBeamSolInTrans = 0.0; // Fraction of BeamSolarRad transmitted out through window inside face [W]
    8024              : 
    8025              :                                 // Interior beam absorptance of glass layers and beam transmittance of back exterior  &
    8026              :                                 // or interior window (treats windows with/without shades as defined) for this timestep
    8027              : 
    8028              :                                 // call the ASHWAT fenestration model for beam radiation here
    8029            0 :                                 WindowEquivalentLayer::CalcEQLOpticalProperty(
    8030            0 :                                     state, BackSurfNum, SolarArrays::BEAM, state.dataSolarShading->SurfWinAbsSolBeamBackEQL);
    8031            0 :                                 auto &CFS = state.dataWindowEquivLayer->CFS;
    8032            0 :                                 int EQLNum = constrBack.EQLConsPtr;
    8033            0 :                                 state.dataSolarShading->SurfWinAbsBeamEQL({1, CFS(EQLNum).NL}) =
    8034            0 :                                     state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, {1, CFS(EQLNum).NL});
    8035              :                                 // get the interior beam transmitted through back exterior or interior EQL window
    8036            0 :                                 TransBeamWin = state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL + 1);
    8037              :                                 //   Absorbed by the interior shade layer of back exterior window
    8038            0 :                                 if (CFS(EQLNum).L(CFS(EQLNum).NL).LTYPE != LayerType::GLAZE) {
    8039            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    8040            0 :                                         BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL) /
    8041            0 :                                         (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    8042            0 :                                     BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL);
    8043            0 :                                     backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, CFS(EQLNum).NL);
    8044              :                                 }
    8045              :                                 //   Absorbed by the exterior shade layer of back exterior window
    8046            0 :                                 if (CFS(EQLNum).L(1).LTYPE != LayerType::GLAZE) {
    8047            0 :                                     state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) =
    8048            0 :                                         BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1) /
    8049            0 :                                         (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum));
    8050            0 :                                     BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1);
    8051            0 :                                     backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, 1);
    8052              :                                 }
    8053              : 
    8054              :                                 // determine the number of glass layers
    8055            0 :                                 NBackGlass = 0;
    8056            0 :                                 for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
    8057            0 :                                     if (CFS(EQLNum).L(Lay).LTYPE != LayerType::GLAZE) continue;
    8058            0 :                                     ++NBackGlass;
    8059              :                                 }
    8060            0 :                                 if (NBackGlass >= 2) {
    8061              :                                     // If the number of glass is greater than 2, in between glass shade can be present
    8062            0 :                                     for (int Lay = 2; Lay <= CFS(EQLNum).NL - 1; ++Lay) {
    8063            0 :                                         if (CFS(EQLNum).L(CFS(EQLNum).NL).LTYPE != LayerType::GLAZE) {
    8064              :                                             // if there is in between shade glass determine the shade absorptance
    8065            0 :                                             state.dataSolarShading->SurfWinIntBeamAbsByShadFac(BackSurfNum) +=
    8066            0 :                                                 BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay) /
    8067            0 :                                                 s_surf->Surface(BackSurfNum).Area;
    8068            0 :                                             BABSZone += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay);
    8069            0 :                                             backSurfBeamSolInTrans += BOverlap * state.dataSolarShading->SurfWinAbsSolBeamBackEQL(1, Lay);
    8070              :                                         }
    8071              :                                     }
    8072              :                                 }
    8073              :                                 // Sum of interior beam absorbed by all glass layers of back window
    8074            0 :                                 Real64 AbsBeamTotWin = 0.0; // Glass layer beam solar absorptance of a shaded window
    8075            0 :                                 for (int Lay = 1; Lay <= CFS(EQLNum).NL; ++Lay) {
    8076            0 :                                     AbsBeamTotWin += state.dataSolarShading->SurfWinAbsBeamEQL(Lay);
    8077            0 :                                     s_surf->SurfWinA(BackSurfNum, Lay) +=
    8078            0 :                                         BOverlap * state.dataSolarShading->SurfWinAbsBeamEQL(Lay) /
    8079            0 :                                         (s_surf->Surface(BackSurfNum).Area + s_surf->SurfWinDividerArea(BackSurfNum)); //[-]
    8080              :                                 }
    8081              : 
    8082              :                                 // To BABSZon, add interior beam glass absorption and overall beam transmission for this back window
    8083              : 
    8084            0 :                                 BABSZone += BOverlap * (AbsBeamTotWin + TransBeamWin);
    8085            0 :                                 backSurfBeamSolInTrans += BOverlap * (AbsBeamTotWin + TransBeamWin);
    8086            0 :                                 state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(BackSurfNum) +=
    8087            0 :                                     backSurfBeamSolInTrans * state.dataEnvrn->BeamSolarRad; //[W]
    8088              : 
    8089              :                                 // Interior beam transmitted to adjacent zone through an interior back window (assumed unshaded);
    8090              :                                 // this beam radiation is categorized as diffuse radiation in the adjacent zone.
    8091              : 
    8092            0 :                                 int AdjSurfNum = s_surf->Surface(BackSurfNum).ExtBoundCond;
    8093            0 :                                 if (AdjSurfNum > 0) {
    8094            0 :                                     int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
    8095            0 :                                     state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BOverlap * TransBeamWin; //[m2]
    8096            0 :                                     s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) +=
    8097            0 :                                         BOverlap * TransBeamWin * state.dataEnvrn->BeamSolarRad; //[W]
    8098            0 :                                     s_surf->SurfWinBmSolTransThruIntWinRepEnergy(BackSurfNum) =
    8099            0 :                                         s_surf->SurfWinBmSolTransThruIntWinRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
    8100              :                                 }
    8101              :                             } // End of check if back surface is opaque or window
    8102            0 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) += BOverlap;
    8103            0 :                             state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(BackSurfNum) =
    8104            0 :                                 state.dataHeatBal->SurfBmIncInsSurfAmountRep(BackSurfNum) * state.dataGlobal->TimeStepZoneSec;
    8105              :                         } // End of loop over back surfaces
    8106              : 
    8107              :                         //  *****************************
    8108              : 
    8109              :                     }    // IF (SurfaceWindow(SurfNum)%WindowModelType /= WindowModel:: BSDF) THEN
    8110              :                 } else { // Simple interior solar distribution. All beam from exterior windows falls on floor;
    8111              :                     // some of this is absorbed/transmitted, rest is reflected to other surfaces.
    8112              : 
    8113       187294 :                     for (int const FloorNum : thisEnclosure.SurfacePtr) {
    8114              :                         // In following, ISABSF is zero except for nominal floor surfaces
    8115       174508 :                         if (state.dataSolarShading->SurfIntAbsFac(FloorNum) <= 0.0 || FloorNum == SurfNum) continue; // Keep only floor surfaces
    8116        19225 :                         int const FlConstrNum = s_surf->SurfActiveConstruction(FloorNum);
    8117              : 
    8118        19225 :                         Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * InOutProjSLFracMult; //[m2]
    8119        19225 :                         Real64 AbsBeamTotWin = 0.0;
    8120              : 
    8121        19225 :                         if (state.dataConstruction->Construct(FlConstrNum).TransDiff <= 0.0) {
    8122              :                             // Opaque surface
    8123        19224 :                             s_surf->SurfOpaqAI(FloorNum) +=
    8124        19224 :                                 BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) / s_surf->Surface(FloorNum).Area; //[-]
    8125              :                         } else {
    8126              :                             // Window
    8127              : 
    8128              :                             // Note that diffuse solar absorptance is used here for floor windows even though we're
    8129              :                             // dealing with incident beam radiation. This is because, for this simple interior distribution,
    8130              :                             // the beam radiation from exterior windows is assumed to be uniformly distributed over the
    8131              :                             // floor and so it makes no sense to use directional absorptances. Note also that floor windows
    8132              :                             // are assumed to not have blinds or shades in this calculation.
    8133              :                             // For the case of the floor window a complex fenestration (strange situation) the correct back
    8134              :                             // diffuse layer absorptions have already been put into the construction
    8135              : 
    8136            3 :                             for (int Lay = 1; Lay <= state.dataConstruction->Construct(FlConstrNum).TotGlassLayers; ++Lay) {
    8137            2 :                                 AbsBeamTotWin += state.dataConstruction->Construct(FlConstrNum).AbsDiffBack(Lay);
    8138              :                             }
    8139              :                             // In the following we have to multiply by the AbsDiffBack(Lay)/AbsBeamTotWin ratio to get the
    8140              :                             // layer by layer absorbed beam since ISABSF(FloorNum) is proportional to AbsBeamTotWin
    8141              :                             // (see ComputeIntSolarAbsorpFactors).
    8142              : 
    8143            3 :                             for (int Lay = 1; Lay <= state.dataConstruction->Construct(FlConstrNum).TotGlassLayers; ++Lay) {
    8144            4 :                                 s_surf->SurfWinA(FloorNum, Lay) += state.dataConstruction->Construct(FlConstrNum).AbsDiffBack(Lay) / AbsBeamTotWin *
    8145            2 :                                                                    BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) /
    8146            2 :                                                                    s_surf->Surface(FloorNum).Area; //[-]
    8147              :                             }
    8148              :                         }
    8149              : 
    8150        19225 :                         BABSZone += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum); //[m2]
    8151              : 
    8152        19225 :                         int AdjSurfNum = s_surf->Surface(FloorNum).ExtBoundCond;
    8153        19225 :                         if (state.dataConstruction->Construct(FlConstrNum).TransDiff > 0.0 && AdjSurfNum > 0) {
    8154              : 
    8155              :                             // Window in an interior floor
    8156              : 
    8157            0 :                             int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
    8158              : 
    8159              :                             // Contribution (assumed diffuse) to adjacent zone of beam radiation passing
    8160              :                             // through this window
    8161            0 :                             state.dataHeatBal->EnclSolDBIntWin(adjEnclosureNum) += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) *
    8162            0 :                                                                                    state.dataConstruction->Construct(FlConstrNum).TransDiff /
    8163              :                                                                                    AbsBeamTotWin;
    8164              : 
    8165            0 :                             BABSZone += BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) *
    8166            0 :                                         state.dataConstruction->Construct(FlConstrNum).TransDiff / AbsBeamTotWin;
    8167              :                         }
    8168              : 
    8169              :                     } // End of loop over floor sections
    8170              :                 }     // End of check on complex vs. simple interior solar distribution
    8171              : 
    8172              :             } // End of sunlit fraction > 0 test
    8173              :         }     // End of first loop over surfaces in zone
    8174              : 
    8175       106052 :         Real64 BABSZoneSSG = 0.0; // Beam radiation from exterior windows absorbed in a zone (only for scheduled surface gains)
    8176       106052 :         Real64 BTOTZoneSSG = 0.0; // Solar entering a zone in case of scheduled surface gains
    8177       106052 :         for (int iSSG = 1; iSSG <= s_surf->TotSurfIncSolSSG; ++iSSG) {
    8178            0 :             int SurfNum = s_surf->SurfIncSolSSG(iSSG).SurfPtr;
    8179            0 :             auto &surf = s_surf->Surface(SurfNum);
    8180              :             // do calculation only if construction number match.
    8181            0 :             if (s_surf->SurfIncSolSSG(iSSG).ConstrPtr == surf.Construction) {
    8182            0 :                 if (surf.SolarEnclIndex == enclosureNum) {
    8183            0 :                     Real64 AbsIntSurf = state.dataConstruction->Construct(surf.Construction).InsideAbsorpSolar;
    8184              :                     // SolarIntoZone = GetCurrentScheduleValue(SurfIncSolSSG(iSSG)%SchedPtr) * Surface(SurfNum)%Area
    8185            0 :                     Real64 SolarIntoZone = s_surf->SurfIncSolSSG(iSSG).sched->getCurrentVal(); // Solar radiation into zone to current surface
    8186            0 :                     s_surf->SurfOpaqAI(SurfNum) = SolarIntoZone * AbsIntSurf;
    8187            0 :                     BABSZoneSSG += s_surf->SurfOpaqAI(SurfNum) * surf.Area;
    8188            0 :                     BTOTZoneSSG += SolarIntoZone * surf.Area;
    8189              :                 }
    8190              :             }
    8191              :         }
    8192       106052 :         state.dataHeatBal->EnclSolDBSSG(enclosureNum) = BTOTZoneSSG - BABSZoneSSG;
    8193       106052 :         state.dataHeatBal->EnclSolDB(enclosureNum) = BTOTZone - BABSZone;
    8194              : 
    8195       106052 :         if (state.dataHeatBal->EnclSolDB(enclosureNum) < 0.0) {
    8196            0 :             state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
    8197              :         }
    8198              : 
    8199              :         // Variables for reporting
    8200       719225 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    8201       613173 :             auto &surf = s_surf->Surface(SurfNum);
    8202              : 
    8203       613173 :             Real64 SurfIncSolarMultiplier = surf.IncSolMultiplier;
    8204       613173 :             Real64 currBeamSolarRad = state.dataEnvrn->BeamSolarRad * SurfIncSolarMultiplier;
    8205       613173 :             Real64 currDifSolarRad = state.dataEnvrn->DifSolarRad * SurfIncSolarMultiplier;
    8206       613173 :             Real64 currGndSolarRad = state.dataEnvrn->GndSolarRad * SurfIncSolarMultiplier;
    8207       613173 :             if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
    8208        78961 :                 state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) *= currBeamSolarRad;
    8209        78961 :                 state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) =
    8210        78961 :                     state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8211        78961 :                 state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) =
    8212        78961 :                     state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) / (surf.Area + s_surf->SurfWinDividerArea(SurfNum));
    8213              :             } else { // Simple interior solar distribution. All beam falls on floor.
    8214       534212 :                 if (state.dataSolarShading->SurfIntAbsFac(SurfNum) > 0.0 && surf.HeatTransSurf) {
    8215       105174 :                     if (thisEnclosure.FloorArea > 0.0) {
    8216              :                         // spread onto all floor surfaces, these may or may not be called "floor"
    8217       105174 :                         state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = currBeamSolarRad * BTOTZone / thisEnclosure.FloorArea;
    8218            0 :                     } else if (thisEnclosure.TotalSurfArea > 0.0) {
    8219              :                         // spread onto all interior surfaces
    8220            0 :                         state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = currBeamSolarRad * BTOTZone / thisEnclosure.TotalSurfArea;
    8221              :                     } else { // divide be zero otherwise
    8222            0 :                         state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum) = 0.0;
    8223              :                     }
    8224              :                 }
    8225       534212 :                 state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) = surf.Area * state.dataHeatBal->SurfBmIncInsSurfIntensRep(SurfNum);
    8226       534212 :                 state.dataHeatBal->SurfBmIncInsSurfAmountRepEnergy(SurfNum) =
    8227       534212 :                     state.dataHeatBal->SurfBmIncInsSurfAmountRep(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8228              :             }
    8229       613173 :             if (surf.Class == SurfaceClass::Window || surf.Class == SurfaceClass::TDD_Dome) {
    8230              : 
    8231        31116 :                 s_surf->SurfWinIntBeamAbsByShade(SurfNum) = state.dataSolarShading->SurfWinIntBeamAbsByShadFac(SurfNum);
    8232        31116 :                 s_surf->SurfWinExtBeamAbsByShade(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinExtBeamAbsByShadFac(SurfNum);
    8233              : 
    8234        31116 :                 if ((surf.ExtBoundCond == ExternalEnvironment) || (surf.ExtBoundCond == OtherSideCondModeledExt)) {
    8235              : 
    8236        31116 :                     WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum);
    8237        31116 :                     int ShelfNum = s_surf->SurfDaylightingShelfInd(SurfNum);
    8238        31116 :                     int OutShelfSurf = 0;
    8239        31116 :                     if (ShelfNum > 0) { // Outside daylighting shelf
    8240            0 :                         OutShelfSurf = state.dataDaylightingDevicesData->Shelf(ShelfNum).OutSurf;
    8241              :                     }
    8242              : 
    8243              :                     // This lookup may be avoid if this 2nd surf loop can be combined with the 1st
    8244        31116 :                     if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    8245            0 :                         int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
    8246            0 :                         int SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
    8247            0 :                         Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    8248              :                         // Exterior diffuse solar incident on window (W/m2)
    8249            0 :                         Real64 DifSolarInc = currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(SurfNum2) +
    8250            0 :                                              currGndSolarRad * s_surf->Surface(SurfNum2).ViewFactorGround;
    8251              :                         // Exterior diffuse sky solar transmitted by TDD (W/m2)
    8252            0 :                         Real64 SkySolarTrans = currDifSolarRad * TransTDD(state, PipeNum, CosInc, Dayltg::RadType::SolarAniso) *
    8253            0 :                                                state.dataSolarShading->SurfAnisoSkyMult(SurfNum2);
    8254              :                         // Exterior diffuse ground solar transmitted by TDD (W/m2)
    8255            0 :                         Real64 GndSolarTrans = currGndSolarRad * state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolIso *
    8256            0 :                                                s_surf->Surface(SurfNum2).ViewFactorGround;
    8257              : 
    8258            0 :                         s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
    8259            0 :                         s_surf->SurfWinDifSolar(SurfNum) = SkySolarTrans * surf.Area + GndSolarTrans * surf.Area;
    8260            0 :                         s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8261            0 :                         s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8262              : 
    8263            0 :                         s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
    8264            0 :                         s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8265              : 
    8266            0 :                         state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransmittedSolar = s_surf->SurfWinTransSolar(SurfNum);
    8267              :                         // TDDPipe(PipeNum)%TransSolBeam = TBmBm ! Reported above
    8268            0 :                         if (DifSolarInc > 0) {
    8269            0 :                             state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolDiff = (SkySolarTrans + GndSolarTrans) / DifSolarInc;
    8270              :                         } else {
    8271            0 :                             state.dataDaylightingDevicesData->TDDPipe(PipeNum).TransSolDiff = 0.0;
    8272              :                         }
    8273              : 
    8274        31116 :                     } else if (OutShelfSurf > 0) { // Outside daylighting shelf
    8275              :                         Real64 ShelfSolarRad =
    8276            0 :                             (currBeamSolarRad *
    8277            0 :                                  state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, OutShelfSurf) *
    8278            0 :                                  state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, OutShelfSurf) +
    8279            0 :                              currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(OutShelfSurf)) *
    8280            0 :                             state.dataDaylightingDevicesData->Shelf(ShelfNum).OutReflectSol;
    8281              : 
    8282            0 :                         Real64 DifSolarInc = currDifSolarRad * state.dataSolarShading->SurfAnisoSkyMult(SurfNum) +
    8283            0 :                                              currGndSolarRad * surf.ViewFactorGround +
    8284            0 :                                              ShelfSolarRad * state.dataDaylightingDevicesData->Shelf(ShelfNum).ViewFactor;
    8285              : 
    8286            0 :                         s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
    8287            0 :                         s_surf->SurfWinDifSolar(SurfNum) = DifSolarInc * state.dataSolarShading->SurfWinTransDifSolar(SurfNum);
    8288            0 :                         s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8289            0 :                         s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8290              : 
    8291            0 :                         s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
    8292            0 :                         s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8293              : 
    8294              :                     } else { // Regular window
    8295        31116 :                         Real64 SkySolarInc = s_surf->SurfSkySolarInc(SurfNum);
    8296        31116 :                         Real64 GndSolarInc = s_surf->SurfGndSolarInc(SurfNum);
    8297        31116 :                         Real64 DifSolarInc = SkySolarInc + GndSolarInc;
    8298        31116 :                         s_surf->SurfWinBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmSolar(SurfNum);
    8299              :                         // Note: for complex fenestration, SurfWinTransDifSolar has previously been defined using the effective
    8300              :                         // transmittance for sky and ground diffuse radiation (including beam radiation reflected from the ground)
    8301              :                         // so these calculations should be correct
    8302        31116 :                         s_surf->SurfWinDifSolar(SurfNum) = DifSolarInc * state.dataSolarShading->SurfWinTransDifSolar(SurfNum);
    8303        31116 :                         s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8304        31116 :                         s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8305        31116 :                         if (ANY_BLIND(ShadeFlag)) {
    8306            0 :                             auto const &surfShade = s_surf->surfShades(SurfNum);
    8307            0 :                             auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
    8308            0 :                             assert(matBlind != nullptr);
    8309            0 :                             if (matBlind->SlatOrientation == DataWindowEquivalentLayer::Orientation::Horizontal) {
    8310            0 :                                 s_surf->SurfWinDifSolar(SurfNum) = SkySolarInc * state.dataSolarShading->SurfWinTransDifSolarSky(SurfNum) +
    8311            0 :                                                                    GndSolarInc * state.dataSolarShading->SurfWinTransDifSolarGnd(SurfNum);
    8312            0 :                                 s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8313              :                             }
    8314              :                         }
    8315              : 
    8316        31116 :                         s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum); //[W]
    8317        31116 :                         s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8318              :                     }
    8319              : 
    8320              :                     // added TH 12/9/2009, CR 7907 & 7809
    8321        31116 :                     s_surf->SurfWinBmBmSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmBmSolar(SurfNum);
    8322              : 
    8323        31116 :                     s_surf->SurfWinBmDifSolar(SurfNum) = currBeamSolarRad * state.dataSolarShading->SurfWinTransBmDifSolar(SurfNum);
    8324        31116 :                     s_surf->SurfWinBmBmSolarEnergy(SurfNum) = s_surf->SurfWinBmBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8325        31116 :                     s_surf->SurfWinBmDifSolarEnergy(SurfNum) = s_surf->SurfWinBmDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8326              : 
    8327              :                     // Solar not added by TDD:DOME; added to zone via TDD:DIFFUSER
    8328        31116 :                     if (surf.Class != SurfaceClass::TDD_Dome) {
    8329        31116 :                         state.dataHeatBal->ZoneTransSolar(enclosureNum) += s_surf->SurfWinTransSolar(SurfNum); //[W]
    8330        31116 :                         state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) =
    8331        31116 :                             state.dataHeatBal->ZoneTransSolar(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8332        31116 :                         state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinBmSolar(SurfNum);
    8333        31116 :                         state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinDifSolar(SurfNum);
    8334        31116 :                         state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) =
    8335        31116 :                             state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8336        31116 :                         state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) =
    8337        31116 :                             state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8338              :                     }
    8339              :                 }
    8340              :             }
    8341              :         } // End of second loop over surfaces in zone
    8342              : 
    8343              :     } // End of first zone loop
    8344              : 
    8345              :     // Add interior window contribution to EnclSolDB
    8346              : 
    8347       177272 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    8348       106052 :         state.dataHeatBal->EnclSolDB(enclosureNum) += state.dataHeatBal->EnclSolDBIntWin(enclosureNum);
    8349       106052 :         state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum) = state.dataHeatBal->EnclSolDBIntWin(enclosureNum) * state.dataEnvrn->BeamSolarRad;
    8350       106052 :         state.dataHeatBal->ZoneBmSolFrIntWinsRepEnergy(enclosureNum) =
    8351       106052 :             state.dataHeatBal->ZoneBmSolFrIntWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8352              :     }
    8353              : 
    8354              :     // RJH - Calculate initial distribution of diffuse solar transmitted by exterior windows into each zone
    8355              :     //       to all interior surfaces in the zone
    8356              :     //       Includes subsequent transmittance of diffuse solar to adjacent zones through interior windows
    8357        71220 :     CalcWinTransDifSolInitialDistribution(state);
    8358        71220 : }
    8359            0 : void CalcAbsorbedOnExteriorOpaqueSurfaces(EnergyPlusData &state)
    8360              : {
    8361              :     // SUBROUTINE INFORMATION:
    8362              :     //       AUTHOR         Simon Vidanovic
    8363              :     //       DATE WRITTEN   May 2017
    8364              :     //       MODIFIED       na
    8365              :     //       RE-ENGINEERED  na
    8366              : 
    8367              :     // PURPOSE OF THIS SUBROUTINE:
    8368              :     // Calculates solar energy absorbed on exterior opaque surfaces
    8369              : 
    8370            0 :     auto &s_surf = state.dataSurface;
    8371              : 
    8372            0 :     for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    8373            0 :         for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    8374            0 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
    8375            0 :             for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
    8376            0 :                 auto &surf = s_surf->Surface(SurfNum);
    8377              :                 // TH added 3/24/2010 while debugging CR 7872
    8378            0 :                 if (!surf.ExtSolar && surf.OriginalClass != SurfaceClass::TDD_Diffuser) continue;
    8379            0 :                 int const ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
    8380            0 :                 int SurfNum2 = SurfNum;
    8381            0 :                 if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    8382            0 :                     int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
    8383            0 :                     SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
    8384              :                 }
    8385            0 :                 Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    8386            0 :                 Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    8387              : 
    8388              :                 //-------------------------------------------------------------------------
    8389              :                 // EXTERIOR BEAM SOLAR RADIATION ABSORBED ON THE OUTSIDE OF OPAQUE SURFACES
    8390              :                 //-------------------------------------------------------------------------
    8391              : 
    8392            0 :                 if (SunLitFract > 0.0 && state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) {
    8393            0 :                     s_surf->SurfOpaqAO(SurfNum) = state.dataConstruction->Construct(ConstrNum).OutsideAbsorpSolar * CosInc * SunLitFract;
    8394              : 
    8395              :                     // Note: movable insulation, if present, is accounted for in subr. InitIntSolarDistribution,
    8396              :                     // where SurfQRadSWOutMvIns is calculated from SurfOpaqQRadSWOutAbs and insulation solar absorptance
    8397              :                 }
    8398              :             }
    8399              :         }
    8400              :     }
    8401            0 : }
    8402              : 
    8403            0 : void CalcInteriorSolarDistributionWCESimple(EnergyPlusData &state)
    8404              : {
    8405              : 
    8406              :     // SUBROUTINE INFORMATION:
    8407              :     //       AUTHOR         Simon Vidanovic
    8408              :     //       DATE WRITTEN   May 2017
    8409              : 
    8410              :     // PURPOSE OF THIS SUBROUTINE:
    8411              :     // For a time step, calculates solar radiation absorbed by window layers, sky and diffuse solar
    8412              :     // gain into zone from exterior window, beam solar on exterior window transmitted as beam and/or diffuse
    8413              :     // and interior beam from exterior window that is absorbed/transmitted by back surfaces
    8414              : 
    8415              :     using namespace MultiLayerOptics;
    8416              : 
    8417            0 :     auto &s_surf = state.dataSurface;
    8418              : 
    8419            0 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    8420            0 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    8421            0 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
    8422            0 :             int const firstSurf = thisSpace.HTSurfaceFirst;
    8423            0 :             int const lastSurf = thisSpace.HTSurfaceLast;
    8424            0 :             for (int surfNum = firstSurf; surfNum <= lastSurf; ++surfNum) {
    8425            0 :                 s_surf->SurfOpaqAI(surfNum) = 0.0;
    8426            0 :                 s_surf->SurfOpaqAO(surfNum) = 0.0;
    8427              :             }
    8428              :         }
    8429              :     }
    8430              : 
    8431            0 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    8432              : 
    8433            0 :         Real64 BABSZone = 0;
    8434            0 :         Real64 BTOTZone = 0;
    8435            0 :         state.dataHeatBal->EnclSolDB(enclosureNum) = 0.0;
    8436            0 :         state.dataHeatBal->EnclSolDBIntWin(enclosureNum) = 0.0;
    8437            0 :         state.dataHeatBal->ZoneTransSolar(enclosureNum) = 0;
    8438            0 :         state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) = 0;
    8439            0 :         state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) = 0;
    8440            0 :         state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) = 0;
    8441            0 :         state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) = 0;
    8442            0 :         state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) = 0;
    8443            0 :         auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
    8444              : 
    8445            0 :         for (int const SurfNum : thisEnclosure.SurfacePtr) {
    8446            0 :             auto &surf = s_surf->Surface(SurfNum);
    8447            0 :             if (surf.Class != SurfaceClass::Window) continue;
    8448            0 :             int SurfNum2 = 0;
    8449            0 :             if (surf.OriginalClass == SurfaceClass::TDD_Diffuser) {
    8450            0 :                 int PipeNum = s_surf->SurfWinTDDPipeNum(SurfNum);
    8451            0 :                 SurfNum2 = state.dataDaylightingDevicesData->TDDPipe(PipeNum).Dome;
    8452              :             } else {
    8453            0 :                 SurfNum2 = SurfNum;
    8454              :             }
    8455            0 :             auto &window = s_surf->SurfaceWindow(SurfNum2);
    8456            0 :             Real64 CosInc = state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2); // Note: surfnum 2
    8457            0 :             Real64 SunLitFract = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2);
    8458              : 
    8459            0 :             std::pair<Real64, Real64> incomingAngle = getSunWCEAngles(state, SurfNum2, BSDFDirection::Incoming);
    8460            0 :             Real64 Theta = incomingAngle.first;
    8461            0 :             Real64 Phi = incomingAngle.second;
    8462              : 
    8463            0 :             int ConstrNum = s_surf->Surface(SurfNum2).Construction;
    8464            0 :             if (s_surf->Surface(SurfNum2).activeShadedConstruction > 0) ConstrNum = s_surf->Surface(SurfNum2).activeShadedConstruction;
    8465              :             auto aLayer = // (AUTO_OK_OBJ)
    8466            0 :                 CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, WavelengthRange::Solar, ConstrNum);
    8467              : 
    8468              :             ///////////////////////////////////////////////
    8469              :             // Solar absorbed in window layers
    8470              :             ///////////////////////////////////////////////
    8471            0 :             if (state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum2) > 0.0) {
    8472            0 :                 size_t numOfLayers = aLayer->getNumOfLayers();
    8473            0 :                 if (s_surf->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
    8474            0 :                     int CurrentState = s_surf->SurfaceWindow(SurfNum).ComplexFen.CurrentState;
    8475            0 :                     auto &cplxState = s_surf->SurfaceWindow(SurfNum).ComplexFen.State(CurrentState);
    8476            0 :                     for (size_t Lay = 1; Lay <= numOfLayers; ++Lay) {
    8477              :                         // Simon: Important note about this equation is to use BeamSolarRad and not SurfQRadSWOutIncident
    8478              :                         // is because BeamSolarRad is direct normal radiation (looking at the Sun) while SurfRadSWOutIncident
    8479              :                         // is normal to window incidence. Since BSDF coefficients are taking into account angle of incidence,
    8480              :                         // BeamSolarRad should be used in this case
    8481            0 :                         state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) =
    8482            0 :                             cplxState.WinSkyFtAbs(Lay) * s_surf->SurfSkySolarInc(SurfNum2) +
    8483            0 :                             cplxState.WinSkyGndAbs(Lay) * s_surf->SurfGndSolarInc(SurfNum2) +
    8484            0 :                             s_surf->SurfWinA(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad +
    8485            0 :                             s_surf->SurfWinACFOverlap(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad;
    8486            0 :                         state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfNum, Lay) = state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) * surf.Area;
    8487            0 :                         s_surf->SurfWinADiffFront(SurfNum, Lay) = cplxState.WinSkyGndAbs(Lay);
    8488              :                     }
    8489              :                 } else {
    8490            0 :                     for (size_t Lay = 1; Lay <= numOfLayers; ++Lay) {
    8491            0 :                         Real64 AbWinBeam = aLayer->getAbsorptanceLayer(Lay, Side::Front, ScatteringSimple::Direct, Theta, Phi) *
    8492            0 :                                            window.OutProjSLFracMult[state.dataGlobal->HourOfDay];
    8493            0 :                         Real64 AbWinDiffFront = aLayer->getAbsorptanceLayer(Lay, Side::Front, ScatteringSimple::Diffuse, Theta, Phi);
    8494              :                         //                        Real64 AbWinDiffBack = aLayer->getAbsorptanceLayer(Lay, Side::Back, ScatteringSimple::Diffuse,
    8495              :                         //                        Theta, Phi);
    8496              : 
    8497              :                         // Simon: This should not be multiplied with cosine of incident angle. This however gives same
    8498              :                         // results as BSDF and Winkelmann models.
    8499            0 :                         s_surf->SurfWinA(SurfNum, Lay) =
    8500            0 :                             AbWinBeam * CosInc * SunLitFract * s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[state.dataGlobal->HourOfDay];
    8501            0 :                         s_surf->SurfWinADiffFront(SurfNum, Lay) = AbWinDiffFront;
    8502              : 
    8503              :                         // Simon: Same not as for BSDF. Normal solar radiation should be taken here because angle of
    8504              :                         // incidence is already taken into account
    8505            0 :                         Real64 absBeam = s_surf->SurfWinA(SurfNum, Lay) * state.dataEnvrn->BeamSolarRad;
    8506              :                         Real64 absDiff =
    8507            0 :                             s_surf->SurfWinADiffFront(SurfNum, Lay) * (s_surf->SurfSkySolarInc(SurfNum2) + s_surf->SurfGndSolarInc(SurfNum2));
    8508            0 :                         state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) = (absBeam + absDiff);
    8509            0 :                         state.dataHeatBal->SurfWinQRadSWwinAbsLayer(SurfNum, Lay) = state.dataHeatBal->SurfWinQRadSWwinAbs(SurfNum, Lay) * surf.Area;
    8510              :                     }
    8511              :                 }
    8512              :             }
    8513              : 
    8514              :             ////////////////////////////////////////////////////////////////////
    8515              :             // SKY AND GROUND DIFFUSE SOLAR GAIN INTO ZONE FROM EXTERIOR WINDOW
    8516              :             ////////////////////////////////////////////////////////////////////
    8517            0 :             constexpr Real64 minLambda{0.3};
    8518            0 :             constexpr Real64 maxLambda{2.5};
    8519              :             const Real64 Tdiff =
    8520            0 :                 aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DiffuseDiffuse, Theta, Phi);
    8521            0 :             state.dataConstruction->Construct(ConstrNum).TransDiff = Tdiff;
    8522            0 :             Real64 EnclSolDSWin = s_surf->SurfSkySolarInc(SurfNum2) * Tdiff * s_surf->Surface(SurfNum2).Area;
    8523            0 :             if ((state.dataEnvrn->DifSolarRad != 0)) {
    8524            0 :                 EnclSolDSWin /= state.dataEnvrn->DifSolarRad;
    8525              :             } else {
    8526            0 :                 EnclSolDSWin /= 1e-8;
    8527              :             }
    8528              : 
    8529            0 :             Real64 EnclSolDGWin = s_surf->SurfGndSolarInc(SurfNum2) * Tdiff * s_surf->Surface(SurfNum2).Area;
    8530            0 :             (state.dataEnvrn->GndSolarRad != 0) ? EnclSolDGWin /= state.dataEnvrn->GndSolarRad : EnclSolDGWin /= 1e-8;
    8531              : 
    8532              :             ////////////////////////////////////////////////////////////////////
    8533              :             // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
    8534              :             ////////////////////////////////////////////////////////////////////
    8535            0 :             Real64 TBmBm = aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DirectDirect, Theta, Phi);
    8536            0 :             Real64 TBmDif = aLayer->getPropertySimple(minLambda, maxLambda, PropertySimple::T, Side::Front, Scattering::DirectDiffuse, Theta, Phi);
    8537            0 :             Real64 SurfWinTransBmBmSolar = TBmBm * SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    8538            0 :             Real64 SurfWinTransBmDifSolar = TBmDif * SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    8539            0 :             BTOTZone += SurfWinTransBmBmSolar + SurfWinTransBmDifSolar;
    8540              : 
    8541            0 :             Real64 DifSolarRadiation = s_surf->SurfSkySolarInc(SurfNum2) + s_surf->SurfGndSolarInc(SurfNum2);
    8542            0 :             s_surf->SurfWinBmSolar(SurfNum) = state.dataEnvrn->BeamSolarRad * (TBmBm + TBmDif) * surf.Area * CosInc;
    8543            0 :             s_surf->SurfWinDifSolar(SurfNum) = DifSolarRadiation * Tdiff * surf.Area;
    8544            0 :             s_surf->SurfWinBmSolarEnergy(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8545            0 :             s_surf->SurfWinDifSolarEnergy(SurfNum) = s_surf->SurfWinDifSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8546            0 :             s_surf->SurfWinTransSolar(SurfNum) = s_surf->SurfWinBmSolar(SurfNum) + s_surf->SurfWinDifSolar(SurfNum);
    8547            0 :             s_surf->SurfWinTransSolarEnergy(SurfNum) = s_surf->SurfWinTransSolar(SurfNum) * state.dataGlobal->TimeStepZoneSec;
    8548              : 
    8549              :             // Add beam solar absorbed by outside reveal to outside of window's base surface.
    8550              :             // Add beam solar absorbed by inside reveal to inside of window's base surface.
    8551              :             // This ignores 2-D heat transfer effects.
    8552            0 :             int BaseSurfNum = surf.BaseSurf;
    8553            0 :             s_surf->SurfOpaqAI(BaseSurfNum) = s_surf->SurfWinBmSolAbsdInsReveal(SurfNum2) / s_surf->Surface(BaseSurfNum).Area;
    8554            0 :             s_surf->SurfOpaqAO(BaseSurfNum) = s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum2) / s_surf->Surface(BaseSurfNum).Area;
    8555              : 
    8556              :             ////////////////////////////////////////////////////////////////////
    8557              :             // BEAM SOLAR ON EXTERIOR WINDOW TRANSMITTED AS BEAM AND/OR DIFFUSE
    8558              :             ////////////////////////////////////////////////////////////////////
    8559            0 :             Real64 TBm = TBmBm;
    8560              :             // Correction for beam absorbed by inside reveal
    8561            0 :             Real64 TBmDenom = SunLitFract * CosInc * surf.Area * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay];
    8562            0 :             if (TBmDenom != 0.0) { // when =0.0, no correction
    8563            0 :                 TBm -= s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) / TBmDenom;
    8564              :             }
    8565              : 
    8566            0 :             TBm = max(0.0, TBm);
    8567            0 :             TBm *= surf.IncSolMultiplier;
    8568              : 
    8569            0 :             int NumOfBackSurf = state.dataShadowComb->ShadowComb(BaseSurfNum).NumBackSurf;
    8570              : 
    8571            0 :             if (state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::FullInteriorExterior) {
    8572            0 :                 for (int IBack = 1; IBack <= NumOfBackSurf; ++IBack) {
    8573              : 
    8574              :                     int const BackSurfNum =
    8575            0 :                         state.dataHeatBal->SurfWinBackSurfaces(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    8576              : 
    8577            0 :                     if (BackSurfNum == 0) break; // No more irradiated back surfaces for this exterior window
    8578            0 :                     int ConstrNumBack = s_surf->Surface(BackSurfNum).Construction;
    8579            0 :                     auto const &constrBack = state.dataConstruction->Construct(ConstrNumBack);
    8580              :                     // NBackGlass = Construct( ConstrNumBack ).TotGlassLayers;
    8581              :                     // Irradiated (overlap) area for this back surface, projected onto window plane
    8582              :                     // (includes effect of shadowing on exterior window)
    8583            0 :                     Real64 AOverlap = state.dataHeatBal->SurfWinOverlapAreas(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, IBack, SurfNum);
    8584            0 :                     Real64 BOverlap = TBm * AOverlap * CosInc; //[m2]
    8585              : 
    8586            0 :                     if (constrBack.TransDiff <= 0.0) {
    8587              :                         // Back surface is opaque interior or exterior wall
    8588              : 
    8589            0 :                         Real64 AbsIntSurf = state.dataHeatBalSurf->SurfAbsSolarInt(BackSurfNum);
    8590            0 :                         s_surf->SurfOpaqAI(BackSurfNum) += BOverlap * AbsIntSurf / s_surf->Surface(BackSurfNum).Area; //[-]
    8591            0 :                         BABSZone += BOverlap * AbsIntSurf;                                                            //[m2]
    8592              :                     }
    8593              :                 }
    8594              :             } else {
    8595            0 :                 for (int const FloorNum : thisEnclosure.SurfacePtr) {
    8596              :                     // In following, ISABSF is zero except for nominal floor surfaces
    8597            0 :                     if (!s_surf->Surface(FloorNum).HeatTransSurf) continue;
    8598            0 :                     if (state.dataSolarShading->SurfIntAbsFac(FloorNum) <= 0.0 || FloorNum == SurfNum) continue; // Keep only floor surfaces
    8599              : 
    8600            0 :                     Real64 BTOTWinZone = TBm * SunLitFract * surf.Area * CosInc * window.InOutProjSLFracMult[state.dataGlobal->HourOfDay]; //[m2]
    8601              : 
    8602            0 :                     if (state.dataConstruction->Construct(s_surf->Surface(FloorNum).Construction).TransDiff <= 0.0) {
    8603              :                         // Opaque surface
    8604            0 :                         s_surf->SurfOpaqAI(FloorNum) +=
    8605            0 :                             BTOTWinZone * state.dataSolarShading->SurfIntAbsFac(FloorNum) / s_surf->Surface(FloorNum).Area; //[-]
    8606              :                     }
    8607              :                 }
    8608              :             }
    8609            0 :             state.dataHeatBal->ZoneTransSolar(enclosureNum) += s_surf->SurfWinTransSolar(SurfNum); //[W]
    8610            0 :             state.dataHeatBal->ZoneTransSolarEnergy(enclosureNum) =
    8611            0 :                 state.dataHeatBal->ZoneTransSolar(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8612            0 :             state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinBmSolar(SurfNum);
    8613            0 :             state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) += s_surf->SurfWinDifSolar(SurfNum);
    8614            0 :             state.dataHeatBal->ZoneBmSolFrExtWinsRepEnergy(enclosureNum) =
    8615            0 :                 state.dataHeatBal->ZoneBmSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8616            0 :             state.dataHeatBal->ZoneDifSolFrExtWinsRepEnergy(enclosureNum) =
    8617            0 :                 state.dataHeatBal->ZoneDifSolFrExtWinsRep(enclosureNum) * state.dataGlobal->TimeStepZoneSec; //[J]
    8618            0 :         }
    8619            0 :         state.dataHeatBal->EnclSolDB(enclosureNum) = BTOTZone - BABSZone;
    8620              :     }
    8621            0 : }
    8622              : 
    8623            0 : int WindowScheduledSolarAbs(EnergyPlusData &state,
    8624              :                             int const SurfNum, // Surface number
    8625              :                             int const ConstNum // Construction number
    8626              : )
    8627              : {
    8628              :     // SUBROUTINE INFORMATION:
    8629              :     //       AUTHOR         Simon Vidanovic
    8630              :     //       DATE WRITTEN   June 2013
    8631              : 
    8632              :     // PURPOSE OF THIS SUBROUTINE:
    8633              :     // Returns scheduled surface gain object for given surface-construction combination
    8634            0 :     auto &s_surf = state.dataSurface;
    8635              : 
    8636            0 :     for (int i = 1; i <= s_surf->TotFenLayAbsSSG; ++i) {
    8637            0 :         if ((s_surf->FenLayAbsSSG(i).SurfPtr == SurfNum) && (s_surf->FenLayAbsSSG(i).ConstrPtr == ConstNum)) {
    8638            0 :             return i;
    8639              :         }
    8640              :     }
    8641              : 
    8642            0 :     return 0;
    8643              : }
    8644              : 
    8645       582049 : int SurfaceScheduledSolarInc(EnergyPlusData &state,
    8646              :                              int const SurfNum, // Surface number
    8647              :                              int const ConstNum // Construction number
    8648              : )
    8649              : {
    8650              :     // SUBROUTINE INFORMATION:
    8651              :     //       AUTHOR         Simon Vidanovic
    8652              :     //       DATE WRITTEN   June 2013
    8653              : 
    8654              :     // PURPOSE OF THIS SUBROUTINE:
    8655              :     // Returns scheduled surface gain pointer for given surface-construction combination
    8656              : 
    8657       582049 :     auto &s_surf = state.dataSurface;
    8658              : 
    8659       582061 :     for (int i = 1; i <= s_surf->TotSurfIncSolSSG; ++i) {
    8660           15 :         if ((s_surf->SurfIncSolSSG(i).SurfPtr == SurfNum) && (s_surf->SurfIncSolSSG(i).ConstrPtr == ConstNum)) {
    8661            3 :             return i;
    8662              :         }
    8663              :     }
    8664              : 
    8665       582046 :     return 0;
    8666              : }
    8667              : 
    8668         3643 : void PerformSolarCalculations(EnergyPlusData &state)
    8669              : {
    8670              : 
    8671              :     // SUBROUTINE INFORMATION:
    8672              :     //       AUTHOR         Linda K. Lawrie
    8673              :     //       DATE WRITTEN   July 1999
    8674              :     //       MODIFIED       Sept 2003, FCW: add calls to CalcBeamSolDiffuseReflFactors and
    8675              :     //                       CalcBeamSolSpecularReflFactors
    8676              :     //                      Jan 2004, FCW: call CalcDayltgCoefficients if storm window status on
    8677              :     //                       any window has changed
    8678              :     //       RE-ENGINEERED  na
    8679              : 
    8680              :     // PURPOSE OF THIS SUBROUTINE:
    8681              :     // This subroutine determines if new solar/shading calculations need
    8682              :     // to be performed and calls the proper routines to do the job.
    8683              : 
    8684              :     // METHODOLOGY EMPLOYED:
    8685              :     // Users are allowed to enter a value for number of days in each period that
    8686              :     // will be used for calculating solar.  (Later, this could be more complicated as
    8687              :     // in allowing a number of days in a month or something).  Using this value or the
    8688              :     // default (20 days) if nothing is entered by the user, the routine will use the
    8689              :     // number of days left to determine if a new set of calculations should be done.
    8690              :     // The calculations use the average of "equation of time" and "solar declination"
    8691              :     // to perform the calculations.
    8692              : 
    8693              :     // REFERENCES:
    8694              :     // na
    8695              : 
    8696              :     // Using/Aliasing
    8697              :     using Dayltg::CalcDayltgCoefficients;
    8698              :     // Locals
    8699              :     // SUBROUTINE ARGUMENT DEFINITIONS:
    8700              :     // na
    8701              : 
    8702              :     // SUBROUTINE PARAMETER DEFINITIONS:
    8703              :     // na
    8704              : 
    8705              :     // INTERFACE BLOCK SPECIFICATIONS
    8706              :     // na
    8707              : 
    8708              :     // DERIVED TYPE DEFINITIONS
    8709              :     // na
    8710              : 
    8711              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    8712              :     Real64 SumDec;
    8713              :     Real64 SumET;
    8714              :     Real64 AvgEqOfTime;
    8715              :     Real64 AvgSinSolarDeclin;
    8716              :     Real64 AvgCosSolarDeclin;
    8717              :     int PerDayOfYear;
    8718              :     int Count;
    8719              :     Real64 SinDec;
    8720              :     Real64 EqTime;
    8721              :     // not used INTEGER SurfNum
    8722              : 
    8723         3643 :     auto &s_surf = state.dataSurface;
    8724              :     // Calculate sky diffuse shading
    8725              : 
    8726         3643 :     if (state.dataGlobal->BeginSimFlag) {
    8727          104 :         state.dataSolarShading->CalcSkyDifShading = true;
    8728          104 :         SkyDifSolarShading(state); // Calculate factors for shading of sky diffuse solar
    8729          104 :         state.dataSolarShading->CalcSkyDifShading = false;
    8730              :     }
    8731              : 
    8732         3643 :     if (state.dataGlobal->BeginEnvrnFlag) {
    8733          481 :         state.dataSolarShading->ShadowingDaysLeft = 0;
    8734              :     }
    8735              : 
    8736         3643 :     if (state.dataSolarShading->ShadowingDaysLeft <= 0 || state.dataSysVars->DetailedSolarTimestepIntegration) {
    8737              : 
    8738         1836 :         if (!state.dataSysVars->DetailedSolarTimestepIntegration) {
    8739              :             //  Perform calculations.
    8740          478 :             state.dataSolarShading->ShadowingDaysLeft = state.dataSolarShading->ShadowingCalcFrequency;
    8741          478 :             if (state.dataGlobal->DayOfSim + state.dataSolarShading->ShadowingDaysLeft > state.dataGlobal->NumOfDayInEnvrn) {
    8742          458 :                 state.dataSolarShading->ShadowingDaysLeft = state.dataGlobal->NumOfDayInEnvrn - state.dataGlobal->DayOfSim + 1;
    8743              :             }
    8744              : 
    8745              :             //  Calculate average Equation of Time, Declination Angle for this period
    8746              : 
    8747          478 :             if (!state.dataGlobal->WarmupFlag) {
    8748            1 :                 if (state.dataGlobal->KindOfSim == Constant::KindOfSim::RunPeriodWeather) {
    8749            1 :                     DisplayString(state, "Updating Shadowing Calculations, Start Date=" + state.dataEnvrn->CurMnDyYr);
    8750              :                 } else {
    8751            0 :                     DisplayString(state, "Updating Shadowing Calculations, Start Date=" + state.dataEnvrn->CurMnDy);
    8752              :                 }
    8753            1 :                 state.dataReportFlag->DisplayPerfSimulationFlag = true;
    8754              :             }
    8755              : 
    8756          478 :             PerDayOfYear = state.dataEnvrn->DayOfYear;
    8757          478 :             SumDec = 0.0;
    8758          478 :             SumET = 0.0;
    8759         1336 :             for (Count = 1; Count <= state.dataSolarShading->ShadowingDaysLeft; ++Count) {
    8760          858 :                 SUN3(PerDayOfYear, SinDec, EqTime);
    8761          858 :                 SumDec += SinDec;
    8762          858 :                 SumET += EqTime;
    8763          858 :                 ++PerDayOfYear;
    8764              :             }
    8765              : 
    8766              :             //  Compute Period Values
    8767          478 :             AvgSinSolarDeclin = SumDec / double(state.dataSolarShading->ShadowingDaysLeft);
    8768          478 :             AvgCosSolarDeclin = std::sqrt(1.0 - pow_2(AvgSinSolarDeclin));
    8769          478 :             AvgEqOfTime = SumET / double(state.dataSolarShading->ShadowingDaysLeft);
    8770              :         } else {
    8771         1358 :             SUN3(state.dataEnvrn->DayOfYear, AvgSinSolarDeclin, AvgEqOfTime);
    8772         1358 :             AvgCosSolarDeclin = std::sqrt(1.0 - pow_2(AvgSinSolarDeclin));
    8773              :             // trigger display of progress in the simulation every two weeks
    8774         1358 :             if (!state.dataGlobal->WarmupFlag && state.dataGlobal->BeginDayFlag && (state.dataGlobal->DayOfSim % 14 == 0)) {
    8775            0 :                 state.dataReportFlag->DisplayPerfSimulationFlag = true;
    8776              :             }
    8777              :         }
    8778              : 
    8779         1836 :         CalcPerSolarBeam(state, AvgEqOfTime, AvgSinSolarDeclin, AvgCosSolarDeclin);
    8780              : 
    8781              :         // Calculate factors for solar reflection
    8782         1836 :         if (s_surf->CalcSolRefl) {
    8783            0 :             CalcBeamSolDiffuseReflFactors(state);
    8784            0 :             CalcBeamSolSpecularReflFactors(state);
    8785            0 :             if (state.dataGlobal->BeginSimFlag) CalcSkySolDiffuseReflFactors(state);
    8786              :         }
    8787              :         //  Calculate daylighting coefficients
    8788         1836 :         CalcDayltgCoefficients(state);
    8789              :     }
    8790              : 
    8791         3643 :     if (!state.dataGlobal->WarmupFlag) {
    8792          417 :         --state.dataSolarShading->ShadowingDaysLeft;
    8793              :     }
    8794              : 
    8795              :     // Recalculate daylighting coefficients if storm window has been added
    8796              :     // or removed from one or more windows at beginning of day
    8797         5005 :     if (state.dataDayltg->TotWindowsWithDayl > 0 && !state.dataGlobal->BeginSimFlag && !state.dataGlobal->BeginEnvrnFlag &&
    8798         5005 :         !state.dataGlobal->WarmupFlag && s_surf->TotStormWin > 0 && state.dataHeatBal->StormWinChangeThisDay) {
    8799            0 :         CalcDayltgCoefficients(state);
    8800              :     }
    8801         3643 : }
    8802              : 
    8803         8010 : void SHDRVL(EnergyPlusData &state,
    8804              :             int const HTSS,  // Heat transfer surface number of the subsurface
    8805              :             int const SBSNR, // Subsurface number
    8806              :             int const Hour,
    8807              :             int const TS)
    8808              : {
    8809              : 
    8810              :     // SUBROUTINE INFORMATION:
    8811              :     //       AUTHOR         Legacy Code
    8812              :     //       DATE WRITTEN
    8813              :     //       MODIFIED       May 2002 (FCW): allow triangular windows to have reveal.
    8814              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    8815              : 
    8816              :     // PURPOSE OF THIS SUBROUTINE:
    8817              :     // This subroutine computes the shadowing from a reveal onto a subsurface.
    8818              : 
    8819              :     // REFERENCES:
    8820              :     // BLAST/IBLAST code, original author George Walton
    8821              : 
    8822              :     int NVS; // Number of vertices
    8823              : 
    8824         8010 :     int constexpr None(0);                       // for use with RevealStatus
    8825         8010 :     int constexpr EntireWindowShadedByReveal(1); // for use with RevealStatus
    8826         8010 :     int constexpr WindowShadedOnlyByReveal(2);   // for use with RevealStatus
    8827              : 
    8828              :     Real64 A; // Area
    8829              :     Real64 R; // Depth of the reveal (m)
    8830              :     int I;    // Loop control
    8831              :     int N;    // Vertex number
    8832              :     int NS1;  // Locations in homogeneous coordinate array
    8833              :     int NS2;
    8834              :     // note, below dimensions not changed because subsurface still max 4
    8835         8010 :     Array1D<Real64> XVT(5); // Projected X coordinates of vertices
    8836         8010 :     Array1D<Real64> YVT(5); // Projected Y coordinates of vertices
    8837              :     bool RevealStatusSet;   // Used to control flow through this subroutine.
    8838              :     // Certain operations performed only if reveal status not yet set.
    8839              :     int RevealStatus; // Status of the reveal, takes the parameter values above
    8840              : 
    8841         8010 :     auto &s_surf = state.dataSurface;
    8842              : 
    8843         8010 :     RevealStatus = None;
    8844         8010 :     RevealStatusSet = false;
    8845              : 
    8846         8010 :     if (!state.dataSolarShading->CalcSkyDifShading) {
    8847         4994 :         state.dataSolarShading->SurfWinRevealStatus(Hour, TS, SBSNR) = None;
    8848              :     }
    8849              : 
    8850         8010 :     R = s_surf->Surface(SBSNR).Reveal;
    8851         8010 :     if (R <= 0.0) {
    8852         8010 :         RevealStatus = None;
    8853         8010 :         RevealStatusSet = true;
    8854              :     }
    8855              : 
    8856         8010 :     if (!RevealStatusSet) {
    8857              : 
    8858            0 :         state.dataSolarShading->FRVLHC = state.dataSolarShading->LOCHCA + 1;
    8859            0 :         ++state.dataSolarShading->LOCHCA;
    8860            0 :         NVS = s_surf->Surface(SBSNR).Sides;
    8861              : 
    8862              :         // Currently (06May02) windows are either rectangles (NVS=4) or triangles (NVS=3)
    8863              : 
    8864            0 :         if (NVS == 4) { // Rectangular subsurface
    8865              : 
    8866              :             // Determine vertices of reveal.
    8867              :             // Project the subsurface up to the plane of the wall.
    8868              : 
    8869            0 :             XVT(1) = s_surf->ShadeV(SBSNR).XV(1) + R * max(state.dataSolarShading->XShadowProjection, 0.0);
    8870            0 :             XVT(2) = s_surf->ShadeV(SBSNR).XV(2) + R * max(state.dataSolarShading->XShadowProjection, 0.0);
    8871            0 :             XVT(3) = s_surf->ShadeV(SBSNR).XV(3) + R * min(state.dataSolarShading->XShadowProjection, 0.0);
    8872            0 :             XVT(4) = s_surf->ShadeV(SBSNR).XV(4) + R * min(state.dataSolarShading->XShadowProjection, 0.0);
    8873            0 :             YVT(1) = s_surf->ShadeV(SBSNR).YV(1) + R * min(state.dataSolarShading->YShadowProjection, 0.0);
    8874            0 :             YVT(2) = s_surf->ShadeV(SBSNR).YV(2) + R * max(state.dataSolarShading->YShadowProjection, 0.0);
    8875            0 :             YVT(3) = s_surf->ShadeV(SBSNR).YV(3) + R * max(state.dataSolarShading->YShadowProjection, 0.0);
    8876            0 :             YVT(4) = s_surf->ShadeV(SBSNR).YV(4) + R * min(state.dataSolarShading->YShadowProjection, 0.0);
    8877              : 
    8878              :             // Check for complete shadowing.
    8879              : 
    8880            0 :             if ((XVT(2) >= XVT(3)) || (YVT(2) >= YVT(1))) {
    8881              : 
    8882            0 :                 RevealStatus = EntireWindowShadedByReveal;
    8883            0 :                 RevealStatusSet = true;
    8884              : 
    8885              :             } else {
    8886              :                 // Re-order vertices to clockwise.
    8887              : 
    8888            0 :                 for (N = 1; N <= NVS; ++N) {
    8889            0 :                     state.dataSolarShading->XVS(N) = XVT(NVS + 1 - N);
    8890            0 :                     state.dataSolarShading->YVS(N) = YVT(NVS + 1 - N);
    8891              :                 }
    8892              : 
    8893              :                 // Transform to homogeneous coordinates
    8894              : 
    8895            0 :                 HTRANS1(state, state.dataSolarShading->FRVLHC, NVS);
    8896            0 :                 state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC) = -state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC);
    8897            0 :                 state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC) = 1.0;
    8898              : 
    8899            0 :                 if (state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC) <= 0.0) {
    8900            0 :                     RevealStatus = EntireWindowShadedByReveal;
    8901            0 :                     RevealStatusSet = true;
    8902              :                 }
    8903              :             }
    8904              : 
    8905            0 :         } else if (NVS == 3) { // Triangular window
    8906              : 
    8907              :             // Project window to outside plane of parent surface
    8908              : 
    8909            0 :             for (N = 1; N <= 3; ++N) {
    8910            0 :                 XVT(N) = s_surf->ShadeV(SBSNR).XV(N) + R * state.dataSolarShading->XShadowProjection;
    8911            0 :                 YVT(N) = s_surf->ShadeV(SBSNR).YV(N) + R * state.dataSolarShading->YShadowProjection;
    8912              :             }
    8913              : 
    8914              :             // Find the overlap between the original window and the projected window
    8915              :             // Put XVT,YVT in clockwise order
    8916              : 
    8917            0 :             for (N = 1; N <= NVS; ++N) {
    8918            0 :                 state.dataSolarShading->XVS(N) = XVT(NVS + 1 - N);
    8919            0 :                 state.dataSolarShading->YVS(N) = YVT(NVS + 1 - N);
    8920              :             }
    8921              : 
    8922              :             // Transform to homogeneous coordinates
    8923              : 
    8924            0 :             NS1 = state.dataSolarShading->LOCHCA + 1;
    8925            0 :             state.dataSolarShading->LOCHCA = NS1;
    8926            0 :             HTRANS1(state, NS1, NVS);
    8927              : 
    8928              :             // Put XV,YV in clockwise order
    8929              : 
    8930            0 :             for (N = 1; N <= NVS; ++N) {
    8931            0 :                 state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(NVS + 1 - N);
    8932            0 :                 state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(NVS + 1 - N);
    8933              :             }
    8934              : 
    8935              :             // Transform to homogeneous coordinates
    8936              : 
    8937            0 :             NS2 = state.dataSolarShading->LOCHCA + 1;
    8938            0 :             state.dataSolarShading->LOCHCA = NS2;
    8939            0 :             HTRANS1(state, NS2, NVS);
    8940            0 :             state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC) = 1.0;
    8941              : 
    8942              :             // Find overlap
    8943              : 
    8944            0 :             DeterminePolygonOverlap(state, NS1, NS2, state.dataSolarShading->FRVLHC);
    8945            0 :             if (state.dataSolarShading->OverlapStatus == NoOverlap) {
    8946            0 :                 RevealStatus = EntireWindowShadedByReveal;
    8947            0 :                 RevealStatusSet = true;
    8948              :             }
    8949              :         }
    8950              :     }
    8951              : 
    8952         8010 :     if (!RevealStatusSet) {
    8953              : 
    8954              :         // Check for no shadows on window.
    8955              : 
    8956            0 :         if (state.dataSolarShading->NSBSHC <= 1) {
    8957            0 :             RevealStatus = WindowShadedOnlyByReveal;
    8958            0 :             RevealStatusSet = true;
    8959              :         } else {
    8960              :             // Reduce all previous shadows to size of reveal opening.
    8961            0 :             state.dataSolarShading->LOCHCA = state.dataSolarShading->FRVLHC;
    8962            0 :             MULTOL(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->FSBSHC, state.dataSolarShading->NSBSHC - 1);
    8963            0 :             if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures)) {
    8964            0 :                 RevealStatus = None;
    8965            0 :                 RevealStatusSet = true;
    8966              :             } else {
    8967            0 :                 state.dataSolarShading->NRVLHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FRVLHC + 1;
    8968            0 :                 if (state.dataSolarShading->NRVLHC <= 1) {
    8969            0 :                     RevealStatus = WindowShadedOnlyByReveal;
    8970            0 :                     RevealStatusSet = true;
    8971              :                 }
    8972              :             }
    8973              :         }
    8974              :     }
    8975              : 
    8976         8010 :     if (!RevealStatusSet) {
    8977              :         // Compute sunlit area.
    8978            0 :         A = state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC);
    8979            0 :         for (I = 2; I <= state.dataSolarShading->NRVLHC; ++I) {
    8980            0 :             A += state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC - 1 + I) *
    8981            0 :                  (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FRVLHC - 1 + I));
    8982              :         }
    8983            0 :         state.dataSolarShading->SurfSunlitArea(HTSS) = A;
    8984              :     }
    8985              : 
    8986         8010 :     if ((RevealStatus == EntireWindowShadedByReveal) || (state.dataSolarShading->SurfSunlitArea(HTSS) < 0.0)) {
    8987            0 :         state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0; // Window entirely shaded by reveal.
    8988         8010 :     } else if (RevealStatus == WindowShadedOnlyByReveal) {
    8989            0 :         state.dataSolarShading->SurfSunlitArea(HTSS) =
    8990            0 :             state.dataSolarShading->HCAREA(state.dataSolarShading->FRVLHC); // Window shaded only by reveal.
    8991              :     }
    8992              : 
    8993         8010 :     if (!state.dataSolarShading->CalcSkyDifShading) {
    8994         4994 :         state.dataSolarShading->SurfWinRevealStatus(Hour, TS, SBSNR) = RevealStatus;
    8995              :     }
    8996         8010 : }
    8997              : 
    8998        90268 : void SHDSBS(EnergyPlusData &state,
    8999              :             int const iHour, // Hour Index
    9000              :             int const CurSurf,
    9001              :             int const NBKS, // Number of back surfaces
    9002              :             int const NSBS, // Number of subsurfaces
    9003              :             int const HTS,  // Heat transfer surface number of the general receiving surf
    9004              :             int const TS    // Time step Index
    9005              : )
    9006              : {
    9007              : 
    9008              :     // SUBROUTINE INFORMATION:
    9009              :     //       AUTHOR         Legacy Code
    9010              :     //       DATE WRITTEN
    9011              :     //       MODIFIED       FCW, Oct 2002: Surface%Area --> Surface%Area + SurfaceWindow%DividerArea
    9012              :     //                       in calculation of SunlitFracWithoutReveal (i.e., use full window area, not
    9013              :     //                       just glass area.
    9014              :     //                      TH, May 2009: Bug fixed to address part of CR 7596 - inside reveals
    9015              :     //                       causing high cooling loads
    9016              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    9017              : 
    9018              :     // PURPOSE OF THIS SUBROUTINE:
    9019              :     // This subroutine determines the shadowing on subsurfaces and
    9020              :     // revises the base surface area accordingly.  It also computes
    9021              :     // the effect of transparent subsurfaces.
    9022              : 
    9023              :     // REFERENCES:
    9024              :     // BLAST/IBLAST code, original author George Walton
    9025              : 
    9026              :     Real64 A;        // Area
    9027              :     int I;           // Loop control
    9028              :     int J;           // Loop control
    9029              :     int K;           // Window construction number
    9030              :     int N;           // Vertex number
    9031              :     Real64 SurfArea; // Surface area. For walls, includes all window frame areas.
    9032              :     // For windows, includes divider area
    9033              :     //  REAL(r64) FrameAreaAdd    ! Additional frame area sunlit
    9034              :     //  REAL(r64) DividerAreaAdd  ! Additional frame area sunlit
    9035              :     int HTSS;  // Heat transfer surface number of the subsurface
    9036              :     int SBSNR; // Subsurface number
    9037              : 
    9038        90268 :     auto &s_surf = state.dataSurface;
    9039              : 
    9040        90268 :     if (NSBS > 0) { // Action taken only if subsurfaces present
    9041              : 
    9042        15470 :         state.dataSolarShading->FSBSHC = state.dataSolarShading->LOCHCA + 1;
    9043              : 
    9044        32628 :         for (I = 1; I <= NSBS; ++I) { // Do for all subsurfaces (sbs).
    9045              : 
    9046        17158 :             SBSNR = state.dataShadowComb->ShadowComb(CurSurf).SubSurf(I);
    9047              : 
    9048        17158 :             HTSS = SBSNR;
    9049              : 
    9050        17158 :             K = s_surf->Surface(SBSNR).Construction;
    9051              : 
    9052        17158 :             if (!state.dataSolarShading->penumbra) {
    9053        34316 :                 if ((state.dataSolarShading->OverlapStatus != TooManyVertices) && (state.dataSolarShading->OverlapStatus != TooManyFigures) &&
    9054        17158 :                     (state.dataSolarShading->SurfSunlitArea(HTS) > 0.0)) {
    9055              : 
    9056              :                     // Re-order vertices to clockwise sequential; compute homogeneous coordinates.
    9057         8329 :                     state.dataSolarShading->NVS = s_surf->Surface(SBSNR).Sides;
    9058        41645 :                     for (N = 1; N <= state.dataSolarShading->NVS; ++N) {
    9059        33316 :                         state.dataSolarShading->XVS(N) = s_surf->ShadeV(SBSNR).XV(state.dataSolarShading->NVS + 1 - N);
    9060        33316 :                         state.dataSolarShading->YVS(N) = s_surf->ShadeV(SBSNR).YV(state.dataSolarShading->NVS + 1 - N);
    9061              :                     }
    9062         8329 :                     state.dataSolarShading->LOCHCA = state.dataSolarShading->FSBSHC;
    9063         8329 :                     HTRANS1(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->NVS);
    9064         8329 :                     state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
    9065         8329 :                     state.dataSolarShading->HCT(state.dataSolarShading->LOCHCA) = 1.0;
    9066         8329 :                     state.dataSolarShading->NSBSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FSBSHC + 1;
    9067              : 
    9068              :                     // Determine sunlit area of subsurface due to shadows on general receiving surface.
    9069         8329 :                     if (state.dataSolarShading->NGSSHC > 0) {
    9070         2773 :                         MULTOL(state, state.dataSolarShading->LOCHCA, state.dataSolarShading->FGSSHC - 1, state.dataSolarShading->NGSSHC);
    9071         2773 :                         if ((state.dataSolarShading->OverlapStatus != TooManyVertices) && (state.dataSolarShading->OverlapStatus != TooManyFigures))
    9072         2773 :                             state.dataSolarShading->NSBSHC = state.dataSolarShading->LOCHCA - state.dataSolarShading->FSBSHC + 1;
    9073              :                     }
    9074              :                 }
    9075              : 
    9076        34316 :                 if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures) ||
    9077        17158 :                     (state.dataSolarShading->SurfSunlitArea(HTS) <= 0.0)) { // General receiving surface totally shaded.
    9078              : 
    9079         8829 :                     state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
    9080              : 
    9081         8829 :                     if (iHour > 0 && TS > 0) state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) = 0.0;
    9082              : 
    9083         8329 :                 } else if ((state.dataSolarShading->NGSSHC <= 0) || (state.dataSolarShading->NSBSHC == 1)) { // No shadows.
    9084              : 
    9085         5608 :                     state.dataSolarShading->SurfSunlitArea(HTSS) = state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC);
    9086         5608 :                     state.dataSolarShading->SurfSunlitArea(HTS) -=
    9087         5608 :                         state.dataSolarShading->SurfSunlitArea(HTSS); // Revise sunlit area of general receiving surface.
    9088              : 
    9089              :                     // TH. This is a bug.  SunLitFracWithoutReveal should be a ratio of area
    9090              :                     // IF(IHour > 0 .AND. TS > 0) SunLitFracWithoutReveal(HTSS,IHour,TS) = &
    9091              :                     //      Surface(HTSS)%NetAreaShadowCalc
    9092              : 
    9093              :                     // new code fixed part of CR 7596. TH 5/29/2009
    9094         5608 :                     if (iHour > 0 && TS > 0)
    9095         3452 :                         state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
    9096         3452 :                             state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).NetAreaShadowCalc;
    9097              : 
    9098         5608 :                     SHDRVL(state, HTSS, SBSNR, iHour, TS); // Determine shadowing from reveal.
    9099              : 
    9100         5608 :                     if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
    9101            0 :                         state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
    9102              : 
    9103              :                 } else { // Compute area.
    9104              : 
    9105         2721 :                     A = state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC);
    9106         6211 :                     for (J = 2; J <= state.dataSolarShading->NSBSHC; ++J) {
    9107         3490 :                         A += state.dataSolarShading->HCAREA(state.dataSolarShading->FSBSHC - 1 + J) *
    9108         3490 :                              (1.0 - state.dataSolarShading->HCT(state.dataSolarShading->FSBSHC - 1 + J));
    9109              :                     }
    9110         2721 :                     state.dataSolarShading->SurfSunlitArea(HTSS) = A;
    9111         2721 :                     if (state.dataSolarShading->SurfSunlitArea(HTSS) > 0.0) {
    9112              : 
    9113         2402 :                         state.dataSolarShading->SurfSunlitArea(HTS) -=
    9114         2402 :                             state.dataSolarShading->SurfSunlitArea(HTSS); // Revise sunlit area of general receiving surface.
    9115              : 
    9116         2402 :                         if (iHour > 0 && TS > 0)
    9117         1542 :                             state.dataHeatBal->SurfSunlitFracWithoutReveal(iHour, TS, HTSS) =
    9118         1542 :                                 state.dataSolarShading->SurfSunlitArea(HTSS) / s_surf->Surface(HTSS).Area;
    9119              : 
    9120         2402 :                         SHDRVL(state, HTSS, SBSNR, iHour, TS); // Determine shadowing from reveal.
    9121              : 
    9122         2402 :                         if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
    9123            0 :                             state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
    9124              : 
    9125              :                     } else { // General receiving surface totally shaded.
    9126              : 
    9127          319 :                         state.dataSolarShading->SurfSunlitArea(HTSS) = 0.0;
    9128              :                     }
    9129              :                 }
    9130              :             }
    9131              : 
    9132              :             // Determine transmittance and absorptances of sunlit window.
    9133        17158 :             if (state.dataConstruction->Construct(K).TransDiff > 0.0) {
    9134              : 
    9135        11878 :                 if (!state.dataSolarShading->CalcSkyDifShading) { // Overlaps calculation is only done for beam solar
    9136              :                     // shading, not for sky diffuse solar shading
    9137              : 
    9138         6982 :                     CalcInteriorSolarOverlaps(state, iHour, NBKS, HTSS, CurSurf, TS);
    9139              :                 }
    9140              :             }
    9141              : 
    9142              :             // Error checking.
    9143        17158 :             SurfArea = s_surf->Surface(SBSNR).NetAreaShadowCalc;
    9144        17158 :             state.dataSolarShading->SurfSunlitArea(HTSS) = max(0.0, state.dataSolarShading->SurfSunlitArea(HTSS));
    9145              : 
    9146        17158 :             state.dataSolarShading->SurfSunlitArea(HTSS) = min(state.dataSolarShading->SurfSunlitArea(HTSS), SurfArea);
    9147              : 
    9148              :         } // End of subsurface loop
    9149              :     }
    9150        90268 : }
    9151              : 
    9152         2216 : void SUN3(int const JulianDayOfYear,      // Julian Day Of Year
    9153              :           Real64 &SineOfSolarDeclination, // Sine of Solar Declination
    9154              :           Real64 &EquationOfTime          // Equation of Time (Degrees)
    9155              : )
    9156              : {
    9157              : 
    9158              :     // SUBROUTINE INFORMATION:
    9159              :     //       AUTHOR         Legacy Code
    9160              :     //       DATE WRITTEN
    9161              :     //       MODIFIED       na
    9162              :     //       RE-ENGINEERED  Linda K. Lawrie
    9163              : 
    9164              :     // PURPOSE OF THIS SUBROUTINE:
    9165              :     // This subroutine computes the coefficients for determining
    9166              :     // the solar position.
    9167              : 
    9168              :     // METHODOLOGY EMPLOYED:
    9169              :     // The expressions are based on least-squares fits of data on p.316 of 'Thermal
    9170              :     // Environmental Engineering' by Threlkeld and on p.387 of the ASHRAE Handbook
    9171              :     // of Fundamentals (need date of ASHRAE HOF).
    9172              : 
    9173              :     // REFERENCES:
    9174              :     // BLAST/IBLAST code, original author George Walton
    9175              : 
    9176              :     // Fitted coefficients of Fourier series | Sine of declination coefficients
    9177              :     static constexpr std::array<Real64, 9> SineSolDeclCoef = {
    9178              :         0.00561800, 0.0657911, -0.392779, 0.00064440, -0.00618495, -0.00010101, -0.00007951, -0.00011691, 0.00002096};
    9179              :     // Fitted coefficients of Fourier Series | Equation of Time coefficients
    9180              :     static constexpr std::array<Real64, 9> EqOfTimeCoef = {
    9181              :         0.00021971, -0.122649, 0.00762856, -0.156308, -0.0530028, -0.00388702, -0.00123978, -0.00270502, -0.00167992};
    9182              : 
    9183              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    9184              :     Real64 X;     // Day of Year in Radians (Computed from Input JulianDayOfYear)
    9185              :     Real64 CosX;  // COS(X)
    9186              :     Real64 SineX; // SIN(X)
    9187              : 
    9188         2216 :     X = 0.017167 * JulianDayOfYear; // Convert julian date to angle X
    9189              : 
    9190              :     // Calculate sines and cosines of X
    9191         2216 :     SineX = std::sin(X);
    9192         2216 :     CosX = std::cos(X);
    9193              : 
    9194         2216 :     SineOfSolarDeclination = SineSolDeclCoef[0] + SineSolDeclCoef[1] * SineX + SineSolDeclCoef[2] * CosX + SineSolDeclCoef[3] * (SineX * CosX * 2.0) +
    9195         2216 :                              SineSolDeclCoef[4] * (pow_2(CosX) - pow_2(SineX)) +
    9196         2216 :                              SineSolDeclCoef[5] * (SineX * (pow_2(CosX) - pow_2(SineX)) + CosX * (SineX * CosX * 2.0)) +
    9197         2216 :                              SineSolDeclCoef[6] * (CosX * (pow_2(CosX) - pow_2(SineX)) - SineX * (SineX * CosX * 2.0)) +
    9198         2216 :                              SineSolDeclCoef[7] * (2.0 * (SineX * CosX * 2.0) * (pow_2(CosX) - pow_2(SineX))) +
    9199         2216 :                              SineSolDeclCoef[8] * (pow_2(pow_2(CosX) - pow_2(SineX)) - pow_2(SineX * CosX * 2.0));
    9200              : 
    9201         2216 :     EquationOfTime = EqOfTimeCoef[0] + EqOfTimeCoef[1] * SineX + EqOfTimeCoef[2] * CosX + EqOfTimeCoef[3] * (SineX * CosX * 2.0) +
    9202         2216 :                      EqOfTimeCoef[4] * (pow_2(CosX) - pow_2(SineX)) +
    9203         2216 :                      EqOfTimeCoef[5] * (SineX * (pow_2(CosX) - pow_2(SineX)) + CosX * (SineX * CosX * 2.0)) +
    9204         2216 :                      EqOfTimeCoef[6] * (CosX * (pow_2(CosX) - pow_2(SineX)) - SineX * (SineX * CosX * 2.0)) +
    9205         2216 :                      EqOfTimeCoef[7] * (2.0 * (SineX * CosX * 2.0) * (pow_2(CosX) - pow_2(SineX))) +
    9206         2216 :                      EqOfTimeCoef[8] * (pow_2(pow_2(CosX) - pow_2(SineX)) - pow_2(SineX * CosX * 2.0));
    9207         2216 : }
    9208              : 
    9209        30561 : void SUN4(EnergyPlusData &state,
    9210              :           Real64 const CurrentTime,    // Time to use in shadowing calculations
    9211              :           Real64 const EqOfTime,       // Equation of time for current day
    9212              :           Real64 const SinSolarDeclin, // Sine of the Solar declination (current day)
    9213              :           Real64 const CosSolarDeclin  // Cosine of the Solar declination (current day)
    9214              : )
    9215              : {
    9216              : 
    9217              :     // SUBROUTINE INFORMATION:
    9218              :     //       AUTHOR         Legacy Code
    9219              :     //       DATE WRITTEN
    9220              :     //       MODIFIED       na
    9221              :     //       RE-ENGINEERED  Lawrie, Oct 2000
    9222              : 
    9223              :     // PURPOSE OF THIS SUBROUTINE:
    9224              :     // This subroutine computes solar direction cosines for a given hour.  These
    9225              :     // cosines are used in the shadowing calculations.
    9226              :     // REFERENCES:
    9227              :     // BLAST/IBLAST code, original author George Walton
    9228              : 
    9229              :     Real64 H;       // Hour angle (before noon = +) (in radians)
    9230              :     Real64 HrAngle; // Basic hour angle
    9231              : 
    9232              :     // Compute the hour angle
    9233        30561 :     HrAngle = (15.0 * (12.0 - (CurrentTime + EqOfTime)) + (state.dataEnvrn->TimeZoneMeridian - state.dataEnvrn->Longitude));
    9234        30561 :     H = HrAngle * Constant::DegToRad;
    9235              : 
    9236              :     // Compute the cosine of the solar zenith angle.
    9237        30561 :     state.dataSolarShading->SUNCOS(3) = SinSolarDeclin * state.dataEnvrn->SinLatitude + CosSolarDeclin * state.dataEnvrn->CosLatitude * std::cos(H);
    9238        30561 :     state.dataSolarShading->SUNCOS(2) = 0.0;
    9239        30561 :     state.dataSolarShading->SUNCOS(1) = 0.0;
    9240              : 
    9241        30561 :     if (state.dataSolarShading->SUNCOS(3) < DataEnvironment::SunIsUpValue) return; // Return if sun not above horizon.
    9242              : 
    9243              :     // Compute other direction cosines.
    9244        15058 :     state.dataSolarShading->SUNCOS(2) = SinSolarDeclin * state.dataEnvrn->CosLatitude - CosSolarDeclin * state.dataEnvrn->SinLatitude * std::cos(H);
    9245        15058 :     state.dataSolarShading->SUNCOS(1) = CosSolarDeclin * std::sin(H);
    9246              : }
    9247              : 
    9248       249958 : void WindowShadingManager(EnergyPlusData &state)
    9249              : {
    9250              : 
    9251              :     // SUBROUTINE INFORMATION:
    9252              :     //       AUTHOR         Fred Winkelmann
    9253              :     //       DATE WRITTEN   December 1998
    9254              :     //       MODIFIED       November 1999 (FW)
    9255              :     //                      Aug 2001 (FW): change shading control names, change approach
    9256              :     //                       to scheduling and glare control, add movable
    9257              :     //                       insulation controls (mainly for heating reduction)
    9258              :     //                      Dec 2001 (FW): add slat angle control for blinds
    9259              :     //                      Aug 2002 (FW): add four new control types:
    9260              :     //                        OnIfHighOutsideAirTempAndHighSolarOnWindow
    9261              :     //                        OnIfHighOutsideAirTempAndHighHorizontalSolar
    9262              :     //                        OnIfHighZoneAirTempAndHighSolarOnWindow
    9263              :     //                        OnIfHighZoneAirTempAndHighHorizontalSolar
    9264              :     //                      Dec 2002 (FW): add between-glass shade/blind
    9265              :     //                      Mar 2003 (FW): allow GlareControlIsActive = .TRUE. only for daylit zones
    9266              :     //                      Apr 2003 (FW): use SNLoadCoolRate or SNLoadHeatRate only if not first time step
    9267              :     //                                     (fixes problem when used first time thru and not allocated)
    9268              :     //                      May 2006 (RR): add exterior window screen
    9269              :     //                      May 2009 (BG): add EMS actuator override for shade flag and slat angle
    9270              :     //       RE-ENGINEERED  na
    9271              : 
    9272              :     // PURPOSE OF THIS SUBROUTINE:
    9273              :     // For windows with shading, selects the shaded construction
    9274              :     // that is used in the heat balance calculation, and sets
    9275              :     // the window shading flag, which is:
    9276              :     //  -1: if window has no shading device
    9277              :     //   0: if shading device is off
    9278              :     //   1: if interior shade is on
    9279              :     //   2: if glazing is switched to darker state
    9280              :     //   3: if exterior shade is on
    9281              :     //   6: if interior blind is on
    9282              :     //   7: if exterior blind is on
    9283              :     //   8: if between-glass shade is on
    9284              :     //   9: if between-glass blind is on
    9285              :     //  10: window has interior shade that is off but may be triggered on later
    9286              :     //       to control daylight glare
    9287              :     //  20: window has switchable glazing that is unswitched but may be switched later
    9288              :     //       to control daylight glare or daylight illuminance
    9289              :     //  30: window has exterior shade that is off but may be triggered on later
    9290              :     //       to control daylight glare or daylight illuminance
    9291              :     //  60: window has interior blind that is off but may be triggered on later
    9292              :     //       to control daylight glare or daylight illuminance
    9293              :     //  70: window has exterior blind that is off but may be triggered on later
    9294              :     //       to control daylight glare or daylight illuminance
    9295              :     //  80: window has between-glass shade that is off but may be triggered on later
    9296              :     //       to control daylight glare or daylight illuminance
    9297              :     //  90: window has between-glass blind that is off but may be triggered on later
    9298              :     //       to control daylight glare or daylight illuminance
    9299              :     // A "shading device" may be an exterior, interior or between-glass shade or blind,
    9300              :     // or the lower-transmitting (dark) state of switchable glazing (e.g., electrochromic).
    9301              :     // In all cases, the unshaded condition is represented
    9302              :     // by the construction given by window's Surface()%Construction and
    9303              :     // the shaded condition is represented by the construction given by
    9304              :     // the window's Surface()%ShadedConstruction
    9305              :     // REFERENCES:
    9306              :     // na
    9307              : 
    9308              :     int IConst; // Construction
    9309              : 
    9310       249958 :     auto &s_mat = state.dataMaterial;
    9311       249958 :     auto &s_surf = state.dataSurface;
    9312              : 
    9313       586610 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
    9314       709607 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
    9315       372955 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
    9316       372955 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
    9317       372955 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
    9318       461523 :             for (int ISurf = firstSurfWin; ISurf <= lastSurfWin; ++ISurf) {
    9319        88568 :                 auto &surfWin = s_surf->SurfaceWindow(ISurf);
    9320        88568 :                 s_surf->SurfWinExtIntShadePrevTS(ISurf) = s_surf->SurfWinShadingFlag(ISurf);
    9321              : 
    9322        88568 :                 s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::NoShade;
    9323        88568 :                 s_surf->SurfWinFracTimeShadingDeviceOn(ISurf) = 0.0;
    9324        88568 :                 if (s_surf->SurfWinWindowModelType(ISurf) == WindowModel::EQL) {
    9325         2369 :                     int EQLNum = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction).EQLConsPtr;
    9326         2369 :                     if (state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr > 0) {
    9327         1473 :                         auto &surfShade = s_surf->surfShades(ISurf);
    9328         1473 :                         if (state.dataWindowEquivLayer->CFS(EQLNum).L(state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr).CNTRL ==
    9329         1473 :                             state.dataWindowEquivalentLayer->lscNONE) {
    9330          507 :                             surfShade.blind.slatAngDeg =
    9331          507 :                                 state.dataWindowEquivLayer->CFS(EQLNum).L(state.dataWindowEquivLayer->CFS(EQLNum).VBLayerPtr).PHI_DEG;
    9332              :                         } else {
    9333          966 :                             surfShade.blind.slatAngDeg = 0.0;
    9334              :                         }
    9335              :                     }
    9336              :                 }
    9337              : 
    9338              :                 // Initialization of complex fenestration shading device
    9339        88568 :                 if (s_surf->SurfWinWindowModelType(ISurf) == WindowModel::BSDF) {
    9340            0 :                     auto &construction = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction);
    9341            0 :                     int TotLayers = construction.TotLayers;
    9342            0 :                     for (int Lay = 1; Lay <= TotLayers; ++Lay) {
    9343            0 :                         const int LayPtr = construction.LayerPoint(Lay);
    9344            0 :                         auto const *material = s_mat->materials(LayPtr);
    9345            0 :                         const bool isShading = material->group == Material::Group::ComplexShade;
    9346            0 :                         if (isShading && Lay == 1) {
    9347            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtShade;
    9348              :                         }
    9349            0 :                         if (isShading && Lay == TotLayers) {
    9350            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntShade;
    9351              :                         }
    9352              :                     }
    9353              : 
    9354            0 :                     if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::IntShade) {
    9355            0 :                         auto &surfShade = s_surf->surfShades(ISurf);
    9356            0 :                         auto &construction = state.dataConstruction->Construct(s_surf->Surface(ISurf).Construction);
    9357            0 :                         const int TotLay = construction.TotLayers;
    9358            0 :                         int ShadingLayerPtr = construction.LayerPoint(TotLay);
    9359              : 
    9360            0 :                         auto const *matComplexShade = dynamic_cast<Material::MaterialComplexShade *>(s_mat->materials(ShadingLayerPtr));
    9361            0 :                         Real64 TauShadeIR = matComplexShade->TransThermal;
    9362            0 :                         Real64 EpsShadeIR = matComplexShade->BackEmissivity;
    9363            0 :                         Real64 RhoShadeIR = max(0.0, 1.0 - TauShadeIR - EpsShadeIR);
    9364              :                         // Get properties of glass next to inside shading layer
    9365            0 :                         int GlassLayPtr = construction.LayerPoint(TotLay - 2);
    9366            0 :                         Real64 EpsGlassIR = s_mat->materials(GlassLayPtr)->AbsorpThermalBack;
    9367            0 :                         Real64 RhoGlassIR = 1 - EpsGlassIR;
    9368              : 
    9369            0 :                         surfShade.effShadeEmi = EpsShadeIR * (1.0 + RhoGlassIR * TauShadeIR / (1.0 - RhoGlassIR * RhoShadeIR));
    9370            0 :                         surfShade.effGlassEmi = EpsGlassIR * TauShadeIR / (1.0 - RhoGlassIR * RhoShadeIR);
    9371              :                     }
    9372              :                 }
    9373              : 
    9374        88568 :                 if (s_surf->Surface(ISurf).ExtBoundCond != ExternalEnvironment) continue;
    9375        88568 :                 if (!s_surf->Surface(ISurf).HasShadeControl) {
    9376        56212 :                     continue;
    9377              :                 } else {
    9378              :                     //
    9379              :                 }
    9380              : 
    9381              :                 // Initialize switching factor (applicable only to switchable glazing) to unswitched
    9382        32356 :                 s_surf->SurfWinSwitchingFactor(ISurf) = 0.0;
    9383              : 
    9384        32356 :                 IConst = s_surf->Surface(ISurf).Construction;
    9385              :                 // Vis trans at normal incidence of unswitched glass. Counting the GlazedFrac
    9386        32356 :                 if (IConst > 0)
    9387        32352 :                     s_surf->SurfWinVisTransSelected(ISurf) =
    9388        32352 :                         Window::POLYF(1.0, state.dataConstruction->Construct(IConst).TransVisBeamCoef) * surfWin.glazedFrac;
    9389              : 
    9390              :                 // Window has shading control
    9391              :                 // select the active window shading control and corresponding constructions
    9392        32356 :                 size_t indexWindowShadingControl = selectActiveWindowShadingControlIndex(state, ISurf);
    9393        64712 :                 if (!s_surf->Surface(ISurf).windowShadingControlList.empty() &&
    9394        32356 :                     indexWindowShadingControl <= s_surf->Surface(ISurf).windowShadingControlList.size() - 1) {
    9395        32356 :                     s_surf->Surface(ISurf).activeWindowShadingControl = s_surf->Surface(ISurf).windowShadingControlList[indexWindowShadingControl];
    9396              :                 }
    9397        32356 :                 s_surf->Surface(ISurf).activeShadedConstructionPrev = s_surf->Surface(ISurf).activeShadedConstruction;
    9398        64708 :                 if (!s_surf->Surface(ISurf).shadedConstructionList.empty() &&
    9399        32352 :                     indexWindowShadingControl <= s_surf->Surface(ISurf).shadedConstructionList.size() - 1) {
    9400        32352 :                     s_surf->Surface(ISurf).activeShadedConstruction = s_surf->Surface(ISurf).shadedConstructionList[indexWindowShadingControl];
    9401              :                 }
    9402        32356 :                 s_surf->SurfWinActiveShadedConstruction(ISurf) = s_surf->Surface(ISurf).activeShadedConstruction;
    9403        32356 :                 if (!s_surf->Surface(ISurf).shadedStormWinConstructionList.empty() &&
    9404            0 :                     indexWindowShadingControl <= s_surf->Surface(ISurf).shadedStormWinConstructionList.size() - 1) {
    9405            0 :                     if (s_surf->SurfWinStormWinFlag(ISurf) == 1) {
    9406            0 :                         s_surf->SurfWinActiveShadedConstruction(ISurf) =
    9407            0 :                             s_surf->Surface(ISurf).shadedStormWinConstructionList[indexWindowShadingControl];
    9408              :                     }
    9409              :                 }
    9410              : 
    9411        32356 :                 int IShadingCtrl = s_surf->Surface(ISurf).activeWindowShadingControl;
    9412        32356 :                 int IZone = s_surf->Surface(ISurf).Zone;
    9413              :                 // Setpoint for shading
    9414        32356 :                 Real64 SetPoint = s_surf->WindowShadingControl(IShadingCtrl).SetPoint;   // Control setpoint
    9415        32356 :                 Real64 SetPoint2 = s_surf->WindowShadingControl(IShadingCtrl).SetPoint2; // Second control setpoint
    9416              : 
    9417        32356 :                 bool SchedAllowsControl = true; // True if control schedule is not specified or is specified and schedule value = 1
    9418        32356 :                 auto const *sched = s_surf->WindowShadingControl(IShadingCtrl).sched;
    9419        32356 :                 if (sched != nullptr) {
    9420        32352 :                     if (s_surf->WindowShadingControl(IShadingCtrl).ShadingControlIsScheduled && sched->getCurrentVal() <= 0.0)
    9421        32352 :                         SchedAllowsControl = false;
    9422              :                 }
    9423              : 
    9424        32356 :                 Real64 GlareControlIsActive = (state.dataDayltg->ZoneDaylight(IZone).totRefPts > 0 && state.dataEnvrn->SunIsUp &&
    9425            0 :                                                s_surf->WindowShadingControl(IShadingCtrl).GlareControlIsActive); // True if glare control is active
    9426              : 
    9427        32356 :                 Real64 SolarOnWindow = 0.0;     // Direct plus diffuse solar intensity on window (W/m2)
    9428        32356 :                 Real64 BeamSolarOnWindow = 0.0; // Direct solar intensity on window (W/m2)
    9429        32356 :                 Real64 HorizSolar = 0.0;        // Horizontal direct plus diffuse solar intensity
    9430        32356 :                 if (state.dataEnvrn->SunIsUp) {
    9431        16354 :                     Real64 SkySolarOnWindow = state.dataSolarShading->SurfAnisoSkyMult(ISurf) *
    9432        16354 :                                               state.dataEnvrn->DifSolarRad; // Sky diffuse solar intensity on window (W/m2)
    9433        16354 :                     BeamSolarOnWindow = state.dataEnvrn->BeamSolarRad *
    9434        16354 :                                         state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, ISurf) *
    9435        16354 :                                         state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, ISurf);
    9436        16354 :                     SolarOnWindow = BeamSolarOnWindow + SkySolarOnWindow + state.dataEnvrn->GndSolarRad * s_surf->Surface(ISurf).ViewFactorGround;
    9437        16354 :                     HorizSolar = state.dataEnvrn->BeamSolarRad * state.dataEnvrn->SOLCOS(3) + state.dataEnvrn->DifSolarRad;
    9438              :                 }
    9439              : 
    9440              :                 // Determine whether to deploy shading depending on type of control
    9441        32356 :                 auto &thisIZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(IZone);
    9442              : 
    9443        32356 :                 bool shadingOn = false;
    9444        32356 :                 bool shadingOffButGlareControlOn = false;
    9445        32356 :                 switch (s_surf->WindowShadingControl(IShadingCtrl).shadingControlType) {
    9446            0 :                 case WindowShadingControlType::AlwaysOn: // 'ALWAYSON'
    9447            0 :                     shadingOn = true;
    9448            0 :                     break;
    9449            0 :                 case WindowShadingControlType::AlwaysOff: // 'ALWAYSOFF'
    9450            0 :                     break;
    9451        32352 :                 case WindowShadingControlType::OnIfScheduled: // 'ONIFSCHEDULEALLOWS'
    9452        32352 :                     if (SchedAllowsControl) shadingOn = true;
    9453        32352 :                     break;
    9454            0 :                 case WindowShadingControlType::HiSolar: // 'ONIFHIGHSOLARONWINDOW'
    9455              :                     // ! Direct plus diffuse solar intensity on window
    9456            0 :                     if (state.dataEnvrn->SunIsUp) {
    9457            0 :                         if (SolarOnWindow > SetPoint && SchedAllowsControl) {
    9458            0 :                             shadingOn = true;
    9459            0 :                         } else if (GlareControlIsActive) {
    9460            0 :                             shadingOffButGlareControlOn = true;
    9461              :                         }
    9462              :                     }
    9463            0 :                     break;
    9464              : 
    9465            0 :                 case WindowShadingControlType::HiHorzSolar: // 'ONIFHIGHHORIZONTALSOLAR'  ! Direct plus diffuse exterior horizontal solar intensity
    9466            0 :                     if (state.dataEnvrn->SunIsUp) {
    9467            0 :                         if (HorizSolar > SetPoint && SchedAllowsControl) {
    9468            0 :                             shadingOn = true;
    9469            0 :                         } else if (GlareControlIsActive) {
    9470            0 :                             shadingOffButGlareControlOn = true;
    9471              :                         }
    9472              :                     }
    9473            0 :                     break;
    9474              : 
    9475            0 :                 case WindowShadingControlType::HiOutAirTemp: // 'OnIfHighOutdoorAirTemperature'
    9476            0 :                     if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && SchedAllowsControl) {
    9477            0 :                         shadingOn = true;
    9478            0 :                     } else if (GlareControlIsActive) {
    9479            0 :                         shadingOffButGlareControlOn = true;
    9480              :                     }
    9481            0 :                     break;
    9482              : 
    9483            0 :                 case WindowShadingControlType::HiZoneAirTemp: // 'OnIfHighZoneAirTemperature'  ! Previous time step zone air temperature
    9484            0 :                     if (thisIZoneHB.MAT > SetPoint && SchedAllowsControl) {
    9485            0 :                         shadingOn = true;
    9486            0 :                     } else if (GlareControlIsActive) {
    9487            0 :                         shadingOffButGlareControlOn = true;
    9488              :                     }
    9489            0 :                     break;
    9490              : 
    9491            0 :                 case WindowShadingControlType::OnHiOutTemp_HiSolarWindow: // 'OnIfHighOutdoorAirTempAndHighSolarOnWindow'  ! Outside air temp and
    9492              :                                                                           // solar on window
    9493            0 :                     if (state.dataEnvrn->SunIsUp) {
    9494            0 :                         if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && SolarOnWindow > SetPoint2 && SchedAllowsControl) {
    9495            0 :                             shadingOn = true;
    9496            0 :                         } else if (GlareControlIsActive) {
    9497            0 :                             shadingOffButGlareControlOn = true;
    9498              :                         }
    9499              :                     }
    9500            0 :                     break;
    9501              : 
    9502            0 :                 case WindowShadingControlType::OnHiOutTemp_HiHorzSolar: // 'OnIfHighOutdoorAirTempAndHighHorizontalSolar'  ! Outside air temp and
    9503              :                                                                         // horizontal solar
    9504            0 :                     if (state.dataEnvrn->SunIsUp) {
    9505            0 :                         if (s_surf->SurfOutDryBulbTemp(ISurf) > SetPoint && HorizSolar > SetPoint2 && SchedAllowsControl) {
    9506            0 :                             shadingOn = true;
    9507            0 :                         } else if (GlareControlIsActive) {
    9508            0 :                             shadingOffButGlareControlOn = true;
    9509              :                         }
    9510              :                     }
    9511            0 :                     break;
    9512              : 
    9513            0 :                 case WindowShadingControlType::OnHiZoneTemp_HiSolarWindow: // 'ONIFHIGHZONEAIRTEMPANDHIGHSOLARONWINDOW'  ! Zone air temp and solar on
    9514              :                                                                            // window
    9515            0 :                     if (state.dataEnvrn->SunIsUp) {
    9516            0 :                         if (thisIZoneHB.MAT > SetPoint && SolarOnWindow > SetPoint2 && SchedAllowsControl) {
    9517            0 :                             shadingOn = true;
    9518            0 :                         } else if (GlareControlIsActive) {
    9519            0 :                             shadingOffButGlareControlOn = true;
    9520              :                         }
    9521              :                     }
    9522            0 :                     break;
    9523              : 
    9524            0 :                 case WindowShadingControlType::OnHiZoneTemp_HiHorzSolar: // 'ONIFHIGHZONEAIRTEMPANDHIGHHORIZONTALSOLAR'  ! Zone air temp and
    9525              :                                                                          // horizontal solar
    9526            0 :                     if (state.dataEnvrn->SunIsUp) {
    9527            0 :                         if (thisIZoneHB.MAT > SetPoint && HorizSolar > SetPoint2 && SchedAllowsControl) {
    9528            0 :                             shadingOn = true;
    9529            0 :                         } else if (GlareControlIsActive) {
    9530            0 :                             shadingOffButGlareControlOn = true;
    9531              :                         }
    9532              :                     }
    9533            0 :                     break;
    9534              : 
    9535            0 :                 case WindowShadingControlType::HiZoneCooling:
    9536              :                     // 'ONIFHIGHZONECOOLING'  ! Previous time step zone sensible cooling rate [W]
    9537              :                     // In the following, the check on BeginSimFlag is needed since SNLoadCoolRate (and SNLoadHeatRate,
    9538              :                     // used in other CASEs) are not allocated at this point for the first time step of the simulation.
    9539            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9540            0 :                         if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > SetPoint && SchedAllowsControl) {
    9541            0 :                             shadingOn = true;
    9542            0 :                         } else if (GlareControlIsActive) {
    9543            0 :                             shadingOffButGlareControlOn = true;
    9544              :                         }
    9545              :                     }
    9546            0 :                     break;
    9547              : 
    9548            0 :                 case WindowShadingControlType::HiGlare:
    9549              :                     // 'ONIFHIGHGLARE'  ! Daylight glare index at first reference point in the zone.
    9550              :                     // This type of shading control is done in DayltgInteriorIllum. Glare control is not affected
    9551              :                     // by control schedule.
    9552            0 :                     if (state.dataEnvrn->SunIsUp) {
    9553            0 :                         shadingOffButGlareControlOn = true;
    9554              :                     }
    9555            0 :                     break;
    9556              : 
    9557            0 :                 case WindowShadingControlType::MeetDaylIlumSetp:
    9558              :                     // 'MEETDAYLIGHTILLUMINANCESETPOINT')  !  Daylight illuminance test is done in DayltgInteriorIllum
    9559              :                     // Only switchable glazing does daylight illuminance control
    9560            0 :                     if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
    9561            0 :                         shadingOffButGlareControlOn = true;
    9562              :                     }
    9563            0 :                     break;
    9564              : 
    9565            1 :                 case WindowShadingControlType::HiSolar_HiLumin_OffMidNight:
    9566              :                     // 'OnIfHighSolarOrHighLuminanceTillMidnight'
    9567              :                     // if shade is already on, then keep it on until midnight, otherwise check thresholds
    9568            1 :                     if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
    9569            0 :                         shadingOn = true;
    9570            1 :                     } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
    9571            1 :                         if (SolarOnWindow > SetPoint) {
    9572            0 :                             shadingOn = true;
    9573              :                         } else {
    9574              :                             // pass to DayltgInteriorIllum to check for luminance
    9575            1 :                             shadingOn = false;
    9576            1 :                             shadingOffButGlareControlOn = true;
    9577              :                         }
    9578              :                     }
    9579              :                     // if it is the beginning of the day, then shades off
    9580            1 :                     if (state.dataGlobal->BeginDayFlag) {
    9581            0 :                         shadingOn = false;
    9582            0 :                         shadingOffButGlareControlOn = false;
    9583              :                     }
    9584            1 :                     break;
    9585              : 
    9586            0 :                 case WindowShadingControlType::HiSolar_HiLumin_OffSunset:
    9587              :                     // 'OnIfHighSolarOrHighLuminanceTillSunset'
    9588              :                     // if shade is already on, then keep it on until sunset, otherwise check thresholds
    9589            0 :                     if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
    9590            0 :                         shadingOn = true;
    9591            0 :                     } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
    9592            0 :                         if (SolarOnWindow > SetPoint) {
    9593            0 :                             shadingOn = true;
    9594              :                         } else {
    9595              :                             // pass to DayltgInteriorIllum to check for luminance
    9596            0 :                             shadingOn = false;
    9597            0 :                             shadingOffButGlareControlOn = true;
    9598              :                         }
    9599              :                     }
    9600              :                     // if sunset, then shades off
    9601            0 :                     if (!state.dataEnvrn->SunIsUp) {
    9602            0 :                         shadingOn = false;
    9603            0 :                         shadingOffButGlareControlOn = false;
    9604              :                     }
    9605            0 :                     break;
    9606              : 
    9607            1 :                 case WindowShadingControlType::HiSolar_HiLumin_OffNextMorning:
    9608              :                     // 'OnIfHighSolarOrHighLuminanceTillNextMorning'
    9609              :                     // if shade is already on, then keep it on until next day when sun is up, otherwise check thresholds
    9610            1 :                     if (SchedAllowsControl && IS_SHADED(s_surf->SurfWinExtIntShadePrevTS(ISurf))) {
    9611            0 :                         shadingOn = true;
    9612            1 :                     } else if (state.dataEnvrn->SunIsUp && SchedAllowsControl) {
    9613            1 :                         if (SolarOnWindow > SetPoint) {
    9614            1 :                             shadingOn = true;
    9615              :                         } else {
    9616              :                             // pass to DayltgInteriorIllum to check for luminance
    9617            0 :                             shadingOn = false;
    9618            0 :                             shadingOffButGlareControlOn = true;
    9619              :                         }
    9620              :                     }
    9621              :                     // if next morning (identified by sun is not up in previous time step and is up now), then shades off
    9622            1 :                     if (!state.dataEnvrn->SunIsUpPrevTS && state.dataEnvrn->SunIsUp) {
    9623            0 :                         shadingOn = false;
    9624            0 :                         shadingOffButGlareControlOn = false;
    9625              :                     }
    9626            1 :                     break;
    9627              : 
    9628            0 :                 case WindowShadingControlType::OnNightLoOutTemp_OffDay: // 'OnNightIfLowOutdoorTempAndOffDay'
    9629            0 :                     if (!state.dataEnvrn->SunIsUp && s_surf->SurfOutDryBulbTemp(ISurf) < SetPoint && SchedAllowsControl) {
    9630            0 :                         shadingOn = true;
    9631            0 :                     } else if (GlareControlIsActive) {
    9632            0 :                         shadingOffButGlareControlOn = true;
    9633              :                     }
    9634            0 :                     break;
    9635              : 
    9636            0 :                 case WindowShadingControlType::OnNightLoInTemp_OffDay: // 'OnNightIfLowInsideTempAndOffDay')
    9637            0 :                     if (!state.dataEnvrn->SunIsUp && thisIZoneHB.MAT < SetPoint && SchedAllowsControl) {
    9638            0 :                         shadingOn = true;
    9639            0 :                     } else if (GlareControlIsActive) {
    9640            0 :                         shadingOffButGlareControlOn = true;
    9641              :                     }
    9642            0 :                     break;
    9643              : 
    9644            0 :                 case WindowShadingControlType::OnNightIfHeating_OffDay: // 'OnNightIfHeatingAndOffDay'
    9645            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9646            0 :                         if (!state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysHeatRate > SetPoint &&
    9647              :                             SchedAllowsControl) {
    9648            0 :                             shadingOn = true;
    9649            0 :                         } else if (GlareControlIsActive) {
    9650            0 :                             shadingOffButGlareControlOn = true;
    9651              :                         }
    9652              :                     }
    9653            0 :                     break;
    9654              : 
    9655            0 :                 case WindowShadingControlType::OnNightLoOutTemp_OnDayCooling: // 'OnNightIfLowOutdoorTempAndOnDayIfCooling'
    9656            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9657            0 :                         if (!state.dataEnvrn->SunIsUp) { // Night
    9658            0 :                             if (s_surf->SurfOutDryBulbTemp(ISurf) < SetPoint && SchedAllowsControl) shadingOn = true;
    9659              :                         } else { // Day
    9660            0 :                             if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 && SchedAllowsControl) {
    9661            0 :                                 shadingOn = true;
    9662            0 :                             } else if (GlareControlIsActive) {
    9663            0 :                                 shadingOffButGlareControlOn = true;
    9664              :                             }
    9665              :                         }
    9666              :                     }
    9667            0 :                     break;
    9668              : 
    9669            0 :                 case WindowShadingControlType::OnNightIfHeating_OnDayCooling: // 'OnNightIfHeatingAndOnDayIfCooling'
    9670            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9671            0 :                         if (!state.dataEnvrn->SunIsUp) { // Night
    9672            0 :                             if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysHeatRate > SetPoint && SchedAllowsControl)
    9673            0 :                                 shadingOn = true;
    9674              :                         } else { // Day
    9675            0 :                             if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 && SchedAllowsControl) {
    9676            0 :                                 shadingOn = true;
    9677            0 :                             } else if (GlareControlIsActive) {
    9678            0 :                                 shadingOffButGlareControlOn = true;
    9679              :                             }
    9680              :                         }
    9681              :                     }
    9682            0 :                     break;
    9683              : 
    9684            0 :                 case WindowShadingControlType::OffNight_OnDay_HiSolarWindow: // 'OffNightAndOnDayIfCoolingAndHighSolarOnWindow'
    9685            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9686            0 :                         if (state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 &&
    9687              :                             SchedAllowsControl) {
    9688            0 :                             if (SolarOnWindow > SetPoint) shadingOn = true;
    9689            0 :                         } else if (GlareControlIsActive) {
    9690            0 :                             shadingOffButGlareControlOn = true;
    9691              :                         }
    9692              :                     }
    9693            0 :                     break;
    9694              : 
    9695            0 :                 case WindowShadingControlType::OnNight_OnDay_HiSolarWindow: // 'OnNightAndOnDayIfCoolingAndHighSolarOnWindow'
    9696            0 :                     if (!state.dataGlobal->BeginSimFlag) {
    9697            0 :                         if (state.dataEnvrn->SunIsUp && state.dataZoneEnergyDemand->ZoneSysEnergyDemand(IZone).airSysCoolRate > 0.0 &&
    9698              :                             SchedAllowsControl) {
    9699            0 :                             if (SolarOnWindow > SetPoint) shadingOn = true;
    9700            0 :                         } else if (!state.dataEnvrn->SunIsUp && SchedAllowsControl) {
    9701            0 :                             shadingOn = true;
    9702            0 :                         } else if (GlareControlIsActive) {
    9703            0 :                             shadingOffButGlareControlOn = true;
    9704              :                         }
    9705              :                     }
    9706            0 :                     break;
    9707            2 :                 default:
    9708            2 :                     ShowWarningError(state, format("Invalid Selection of Window Shading Control Type for Surface {}", s_surf->Surface(ISurf).Name));
    9709              :                 }
    9710              : 
    9711        32356 :                 WinShadingType ShType = s_surf->WindowShadingControl(IShadingCtrl).ShadingType;
    9712              : 
    9713        32356 :                 s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ShadeOff; // Initialize shading flag to off
    9714              : 
    9715        32356 :                 if (IS_SHADED(ShType)) {
    9716        32355 :                     if (shadingOn) {
    9717            1 :                         s_surf->SurfWinShadingFlag(ISurf) = ShType;
    9718        32354 :                     } else if (shadingOffButGlareControlOn) {
    9719            1 :                         if (ShType == WinShadingType::SwitchableGlazing)
    9720            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::GlassConditionallyLightened;
    9721            1 :                         else if (ShType == WinShadingType::IntShade)
    9722            1 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntShadeConditionallyOff;
    9723            0 :                         else if (ShType == WinShadingType::ExtShade)
    9724            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtShadeConditionallyOff;
    9725            0 :                         else if (ShType == WinShadingType::IntBlind)
    9726            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::IntBlindConditionallyOff;
    9727            0 :                         else if (ShType == WinShadingType::ExtBlind)
    9728            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::ExtBlindConditionallyOff;
    9729            0 :                         else if (ShType == WinShadingType::BGShade)
    9730            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::BGShadeConditionallyOff;
    9731            0 :                         else if (ShType == WinShadingType::BGBlind)
    9732            0 :                             s_surf->SurfWinShadingFlag(ISurf) = WinShadingType::BGBlindConditionallyOff;
    9733              :                     }
    9734              :                 }
    9735              : 
    9736              :                 // Set switching factor to fully switched if ShadingFlag = 2
    9737        32356 :                 if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::SwitchableGlazing) {
    9738            0 :                     s_surf->SurfWinSwitchingFactor(ISurf) = 1.0;
    9739              : 
    9740              :                     // Added TH 1/20/2010
    9741              :                     // Vis trans at normal incidence of fully switched glass
    9742            0 :                     IConst = s_surf->Surface(ISurf).activeShadedConstruction;
    9743            0 :                     s_surf->SurfWinVisTransSelected(ISurf) =
    9744            0 :                         Window::POLYF(1.0, state.dataConstruction->Construct(IConst).TransVisBeamCoef) * surfWin.glazedFrac;
    9745              :                 }
    9746              : 
    9747              :                 // Slat angle control for blinds
    9748        32356 :                 auto &surfShade = s_surf->surfShades(ISurf);
    9749        32356 :                 surfShade.blind.slatAng = 0.0;
    9750        32356 :                 surfShade.blind.slatAngDeg = 0.0;
    9751        32356 :                 surfShade.blind.slatBlockBeam = false;
    9752        64712 :                 if (ANY_BLIND(s_surf->SurfWinShadingFlag(ISurf)) || s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::IntBlindConditionallyOff ||
    9753        97068 :                     s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::ExtBlindConditionallyOff ||
    9754        32356 :                     s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::BGBlindConditionallyOff) {
    9755              :                     // Blind in place or may be in place due to glare control
    9756            0 :                     if (surfShade.blind.matNum > 0) {
    9757            0 :                         auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(s_mat->materials(surfShade.blind.matNum));
    9758            0 :                         assert(matBlind != nullptr);
    9759            0 :                         Real64 InputSlatAngle = matBlind->SlatAngle * Constant::DegToRad; // Slat angle of associated Material:WindowBlind (rad)
    9760              :                         Real64 ThetaBase;                                                 // Intermediate slat angle variable (rad)
    9761              :                         Real64 ThetaBlock1;                                               // Slat angles that just block beam solar (rad)
    9762              :                         Real64 ThetaBlock2;
    9763              : 
    9764            0 :                         Real64 ProfAng = surfShade.blind.profAng =
    9765            0 :                             Dayltg::ProfileAngle(state, ISurf, state.dataEnvrn->SOLCOS, matBlind->SlatOrientation);
    9766              : 
    9767            0 :                         if (ProfAng > Constant::PiOvr2 || ProfAng < -Constant::PiOvr2) {
    9768            0 :                             ProfAng = min(max(ProfAng, -Constant::PiOvr2), Constant::PiOvr2);
    9769              :                         }
    9770            0 :                         surfShade.blind.profAngIdxLo = int((ProfAng + Constant::PiOvr2) / Material::dProfAng) + 1;
    9771            0 :                         surfShade.blind.profAngIdxHi = std::min(Material::MaxProfAngs, surfShade.blind.profAngIdxLo + 1);
    9772              : 
    9773            0 :                         surfShade.blind.profAngInterpFac =
    9774            0 :                             (ProfAng + Constant::PiOvr2 - (surfShade.blind.profAngIdxLo - 1) * Material::dProfAng) / Material::dProfAng;
    9775              : 
    9776            0 :                         if (matBlind->SlatWidth > matBlind->SlatSeparation && BeamSolarOnWindow > 0.0) {
    9777            0 :                             ProfAng = surfShade.blind.profAng;
    9778            0 :                             Real64 ThetaBase = std::acos(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth);
    9779              :                             // There are two solutions for the slat angle that just blocks beam radiation
    9780            0 :                             ThetaBlock1 = ProfAng + ThetaBase;
    9781            0 :                             ThetaBlock2 = ProfAng + Constant::Pi - ThetaBase;
    9782            0 :                             state.dataSolarShading->ThetaSmall = min(ThetaBlock1, ThetaBlock2);
    9783            0 :                             state.dataSolarShading->ThetaBig = max(ThetaBlock1, ThetaBlock2);
    9784            0 :                             state.dataSolarShading->ThetaMin = matBlind->MinSlatAngle * Constant::DegToRad;
    9785            0 :                             state.dataSolarShading->ThetaMax = matBlind->MaxSlatAngle * Constant::DegToRad;
    9786              :                         }
    9787              : 
    9788              :                         // TH 5/20/2010, CR 8064: Slat Width <= Slat Separation
    9789            0 :                         if (matBlind->SlatWidth <= matBlind->SlatSeparation && BeamSolarOnWindow > 0.0) {
    9790            0 :                             if (s_surf->WindowShadingControl(IShadingCtrl).slatAngleControl == SlatAngleControl::BlockBeamSolar) {
    9791            0 :                                 ProfAng = surfShade.blind.profAng;
    9792            0 :                                 if (std::abs(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth) <= 1.0) {
    9793              :                                     // set to block 100% of beam solar, not necessarily to block maximum solar (beam + diffuse)
    9794            0 :                                     ThetaBase = std::acos(std::cos(ProfAng) * matBlind->SlatSeparation / matBlind->SlatWidth);
    9795            0 :                                     surfShade.blind.slatBlockBeam = true;
    9796              :                                 } else {
    9797              :                                     // cannot block 100% of beam solar, turn slats to be perpendicular to sun beam to block maximal beam solar
    9798            0 :                                     ThetaBase = 0.0;
    9799              :                                 }
    9800              : 
    9801              :                                 // There are two solutions for the slat angle that just blocks beam radiation
    9802            0 :                                 ThetaBlock1 = ProfAng + ThetaBase;
    9803            0 :                                 ThetaBlock2 = ProfAng - ThetaBase + Constant::Pi;
    9804              : 
    9805            0 :                                 state.dataSolarShading->ThetaSmall = min(ThetaBlock1, ThetaBlock2);
    9806            0 :                                 state.dataSolarShading->ThetaBig = max(ThetaBlock1, ThetaBlock2);
    9807            0 :                                 state.dataSolarShading->ThetaMin = matBlind->MinSlatAngle * Constant::DegToRad;
    9808            0 :                                 state.dataSolarShading->ThetaMax = matBlind->MaxSlatAngle * Constant::DegToRad;
    9809              :                             }
    9810              :                         }
    9811              : 
    9812              :                         //
    9813            0 :                         Real64 slatAng = 0.0;
    9814            0 :                         bool slatBlockBeam = false;
    9815            0 :                         switch (s_surf->WindowShadingControl(IShadingCtrl).slatAngleControl) {
    9816              : 
    9817            0 :                         case SlatAngleControl::Fixed: { // 'FIXEDSLATANGLE'
    9818            0 :                             slatAng = InputSlatAngle;
    9819              : 
    9820            0 :                             if ((slatAng <= state.dataSolarShading->ThetaSmall || slatAng >= state.dataSolarShading->ThetaBig) &&
    9821            0 :                                 (matBlind->SlatWidth > matBlind->SlatSeparation) && (BeamSolarOnWindow > 0.0))
    9822            0 :                                 slatBlockBeam = true;
    9823            0 :                         } break;
    9824              : 
    9825            0 :                         case SlatAngleControl::Scheduled: { // 'SCHEDULEDSLATANGLE'
    9826            0 :                             slatAng = s_surf->WindowShadingControl(IShadingCtrl).slatAngleSched->getCurrentVal();
    9827            0 :                             slatAng = max(matBlind->MinSlatAngle, min(slatAng, matBlind->MaxSlatAngle)) * Constant::DegToRad;
    9828              : 
    9829            0 :                             if ((slatAng <= state.dataSolarShading->ThetaSmall || slatAng >= state.dataSolarShading->ThetaBig) &&
    9830            0 :                                 (matBlind->SlatWidth > matBlind->SlatSeparation) && (BeamSolarOnWindow > 0.0))
    9831            0 :                                 slatBlockBeam = true;
    9832            0 :                         } break;
    9833              : 
    9834            0 :                         case SlatAngleControl::BlockBeamSolar: { // 'BLOCKBEAMSOLAR'
    9835            0 :                             if (BeamSolarOnWindow > 0.0) {
    9836            0 :                                 if (matBlind->SlatSeparation >= matBlind->SlatWidth) {
    9837              :                                     // TH 5/20/2010. CR 8064.
    9838              :                                     // The following line of code assumes slats are always vertical/closed to minimize solar penetration
    9839              :                                     // The slat angle can however change if the only goal is to block maximum amount of direct beam solar
    9840              :                                     // SurfaceWindow(ISurf)%SlatAngThisTS = 0.0  ! Allows beam penetration but minimizes it
    9841              : 
    9842            0 :                                     if (state.dataSolarShading->ThetaSmall >= state.dataSolarShading->ThetaMin &&
    9843            0 :                                         state.dataSolarShading->ThetaSmall <= state.dataSolarShading->ThetaMax) {
    9844            0 :                                         slatAng = state.dataSolarShading->ThetaSmall;
    9845            0 :                                     } else if (state.dataSolarShading->ThetaBig >= state.dataSolarShading->ThetaMin &&
    9846            0 :                                                state.dataSolarShading->ThetaBig <= state.dataSolarShading->ThetaMax) {
    9847            0 :                                         slatAng = state.dataSolarShading->ThetaBig;
    9848            0 :                                     } else if (state.dataSolarShading->ThetaSmall < state.dataSolarShading->ThetaMin &&
    9849            0 :                                                state.dataSolarShading->ThetaBig < state.dataSolarShading->ThetaMin) {
    9850            0 :                                         slatAng = state.dataSolarShading->ThetaMin;
    9851            0 :                                     } else if (state.dataSolarShading->ThetaSmall > state.dataSolarShading->ThetaMax &&
    9852            0 :                                                state.dataSolarShading->ThetaBig > state.dataSolarShading->ThetaMax) {
    9853            0 :                                         slatAng = state.dataSolarShading->ThetaMax;
    9854              :                                     } else { // ThetaBig > ThetaMax and ThetaSmall < ThetaMin (no-block condition)
    9855            0 :                                         slatAng = state.dataSolarShading->ThetaMin;
    9856              :                                     }
    9857              : 
    9858              :                                 } else { // Usual case -- slat width greater than slat separation
    9859            0 :                                     if (state.dataSolarShading->ThetaSmall >= state.dataSolarShading->ThetaMin &&
    9860            0 :                                         state.dataSolarShading->ThetaSmall <= state.dataSolarShading->ThetaMax) {
    9861            0 :                                         slatAng = state.dataSolarShading->ThetaSmall;
    9862            0 :                                         slatBlockBeam = true;
    9863            0 :                                     } else if (state.dataSolarShading->ThetaBig >= state.dataSolarShading->ThetaMin &&
    9864            0 :                                                state.dataSolarShading->ThetaBig <= state.dataSolarShading->ThetaMax) {
    9865            0 :                                         slatAng = state.dataSolarShading->ThetaBig;
    9866            0 :                                         slatBlockBeam = true;
    9867            0 :                                     } else if (state.dataSolarShading->ThetaSmall < state.dataSolarShading->ThetaMin &&
    9868            0 :                                                state.dataSolarShading->ThetaBig < state.dataSolarShading->ThetaMin) {
    9869            0 :                                         slatAng = state.dataSolarShading->ThetaMin;
    9870            0 :                                         slatBlockBeam = true;
    9871            0 :                                     } else if (state.dataSolarShading->ThetaSmall > state.dataSolarShading->ThetaMax &&
    9872            0 :                                                state.dataSolarShading->ThetaBig > state.dataSolarShading->ThetaMax) {
    9873            0 :                                         slatAng = state.dataSolarShading->ThetaMax;
    9874            0 :                                         slatBlockBeam = true;
    9875              :                                     } else { // ThetaBig > ThetaMax and ThetaSmall < ThetaMin (no-block condition)
    9876            0 :                                         slatAng = state.dataSolarShading->ThetaMin;
    9877              :                                     }
    9878              :                                 }
    9879              :                             } else {
    9880            0 :                                 slatAng = InputSlatAngle;
    9881              :                             }
    9882            0 :                         } break;
    9883            0 :                         default:
    9884            0 :                             break;
    9885              :                         } // switch (slatAngControl)
    9886              : 
    9887            0 :                         if (surfShade.blind.slatAngDegEMSon) {
    9888            0 :                             slatAng = Constant::DegToRad * surfShade.blind.slatAngDegEMSValue;
    9889              :                         }
    9890              : 
    9891              :                         // Slat angle is changing, need to recalculate stored values
    9892            0 :                         if (slatAng != surfShade.blind.slatAng) {
    9893            0 :                             surfShade.blind.slatAng = slatAng;
    9894            0 :                             surfShade.blind.slatAngDeg = surfShade.blind.slatAng * Constant::RadToDeg;
    9895              : 
    9896            0 :                             Material::GetSlatIndicesInterpFac(surfShade.blind.slatAng,
    9897            0 :                                                               surfShade.blind.slatAngIdxLo,
    9898            0 :                                                               surfShade.blind.slatAngIdxHi,
    9899            0 :                                                               surfShade.blind.slatAngInterpFac);
    9900            0 :                             surfShade.blind.TAR.interpSlatAng(matBlind->TARs[surfShade.blind.slatAngIdxLo],
    9901            0 :                                                               matBlind->TARs[surfShade.blind.slatAngIdxHi],
    9902              :                                                               surfShade.blind.slatAngInterpFac);
    9903              : 
    9904            0 :                             Real64 TauShIR = surfShade.blind.TAR.IR.Ft.Tra;
    9905            0 :                             Real64 EpsShIR = surfShade.blind.TAR.IR.Bk.Emi;
    9906            0 :                             Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
    9907              : 
    9908            0 :                             surfShade.effShadeEmi = EpsShIR * (1.0 + surfShade.glass.rhoIR * TauShIR / (1.0 - surfShade.glass.rhoIR * RhoShIR));
    9909            0 :                             surfShade.effGlassEmi = surfShade.glass.epsIR * TauShIR / (1.0 - surfShade.glass.rhoIR * RhoShIR);
    9910              :                         }
    9911              : 
    9912            0 :                         surfShade.blind.slatBlockBeam = slatBlockBeam;
    9913              : 
    9914              :                         // Air flow permeability for calculation of convective air flow between blind and glass
    9915            0 :                         Real64 PermeabilityA = std::sin(surfShade.blind.slatAng) - matBlind->SlatThickness / matBlind->SlatSeparation;
    9916            0 :                         Real64 PermeabilityB = 1.0 - (std::abs(matBlind->SlatWidth * std::cos(surfShade.blind.slatAng)) +
    9917            0 :                                                       matBlind->SlatThickness * std::sin(surfShade.blind.slatAng)) /
    9918            0 :                                                          matBlind->SlatSeparation;
    9919            0 :                         surfShade.blind.airFlowPermeability = min(1.0, max(0.0, PermeabilityA, PermeabilityB));
    9920            0 :                         surfShade.blind.bmBmTrans = matBlind->BeamBeamTrans(surfShade.blind.profAng, surfShade.blind.slatAng);
    9921              :                     }
    9922              :                 } // End of check if interior or exterior or between glass blind in place
    9923              : 
    9924              :                 // AR: don't need to do this anymore I don't think
    9925              :                 // CALL CalcScreenTransmittance to initialized all screens prior to HB calc's
    9926              :                 // if (s_surf->SurfWinShadingFlag(ISurf) == WinShadingType::ExtScreen && state.dataEnvrn->SunIsUp) {
    9927              :                 //    CalcScreenTransmittance(state, ISurf);
    9928              :                 // }
    9929              : 
    9930              :                 // EMS Actuator Point: override setting if ems flag on
    9931        32356 :                 if (s_surf->SurfWinShadingFlagEMSOn(ISurf)) {
    9932            1 :                     WinShadingType SurfWinShadingFlagEMS = findValueInEnumeration(s_surf->SurfWinShadingFlagEMSValue(ISurf));
    9933            1 :                     if (SurfWinShadingFlagEMS != WinShadingType::Invalid) {
    9934            1 :                         s_surf->SurfWinShadingFlag(ISurf) = SurfWinShadingFlagEMS;
    9935              :                     } else {
    9936            0 :                         ShowWarningError(state,
    9937            0 :                                          format("Invalid EMS value of Window Shading Control Type for Surface {}", s_surf->Surface(ISurf).Name));
    9938              :                     }
    9939              :                 }
    9940              :             } // End of surface loop
    9941              :         }
    9942              :     }
    9943       249958 : }
    9944              : 
    9945       249956 : void CheckGlazingShadingStatusChange(EnergyPlusData &state)
    9946              : {
    9947       249956 :     auto &s_surf = state.dataSurface;
    9948       249956 :     if (state.dataGlobal->BeginSimFlag) {
    9949          112 :         if (state.dataWindowManager->inExtWindowModel->isExternalLibraryModel() && state.dataWindowManager->winOpticalModel->isSimplifiedModel()) {
    9950            0 :             state.dataHeatBal->EnclRadAlwaysReCalc = true;
    9951              :         } else {
    9952          244 :             for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    9953          282 :                 for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
    9954          150 :                     auto &thisSpace = state.dataHeatBal->space(spaceNum);
    9955          937 :                     for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
    9956          793 :                         auto &surf = s_surf->Surface(SurfNum);
    9957         1586 :                         if (state.dataConstruction->Construct(surf.Construction).isTCWindow ||
    9958          793 :                             state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
    9959            6 :                             state.dataHeatBal->EnclRadAlwaysReCalc = true;
    9960            6 :                             break;
    9961              :                         }
    9962              :                     }
    9963              :                 }
    9964              :             }
    9965              :         }
    9966          112 :         if (state.dataHeatBal->EnclRadAlwaysReCalc) {
    9967           12 :             for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    9968            6 :                 state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
    9969              :             }
    9970           12 :             for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
    9971            6 :                 state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
    9972              :             }
    9973              :         }
    9974              :     }
    9975       249956 :     if (state.dataHeatBal->EnclRadAlwaysReCalc) return;
    9976              : 
    9977       247588 :     if (state.dataGlobal->BeginEnvrnFlag || state.dataGlobal->AnyConstrOverridesInModel || state.dataGlobal->AnySurfPropOverridesInModel) {
    9978        15405 :         for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    9979         7826 :             state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
    9980              :         }
    9981        15405 :         for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
    9982         7826 :             state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
    9983              :         }
    9984         7579 :         return;
    9985              :     }
    9986       585389 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    9987       345380 :         state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = false;
    9988              :     }
    9989       585389 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
    9990       345380 :         state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = false;
    9991              :     }
    9992       240009 :     if (!state.dataGlobal->AndShadingControlInModel) return;
    9993        16144 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfSolarEnclosures; ++enclosureNum) {
    9994       153368 :         for (int const SurfNum : state.dataViewFactor->EnclRadInfo(enclosureNum).SurfacePtr) {
    9995       141260 :             auto &surf = s_surf->Surface(SurfNum);
    9996       141260 :             auto &surfShade = s_surf->surfShades(SurfNum);
    9997       141260 :             bool surfShadingStatusChange = s_surf->SurfWinExtIntShadePrevTS(SurfNum) != s_surf->SurfWinShadingFlag(SurfNum) ||
    9998       141260 :                                            surf.activeShadedConstruction != surf.activeShadedConstructionPrev || surfShade.blind.movableSlats;
    9999       141260 :             if (surfShadingStatusChange) {
   10000            0 :                 state.dataViewFactor->EnclSolInfo(enclosureNum).radReCalc = true;
   10001            0 :                 state.dataViewFactor->EnclRadInfo(enclosureNum).radReCalc = true;
   10002            0 :                 break;
   10003              :             }
   10004              :         }
   10005              :     }
   10006              : }
   10007              : 
   10008            1 : DataSurfaces::WinShadingType findValueInEnumeration(Real64 controlValue)
   10009              : {
   10010              :     // This is a workaround to translate EMS Shading control numerical values
   10011              :     // EMS control of window shading devices involves setting the control values for shading control actuators with
   10012              :     // one of these values.  The variable names can be used or replaced, it is the whole number values that trigger
   10013              :     // changes in the modeling.
   10014              :     // Shades and Blinds are either fully on or fully off, partial positions require multiple windows.
   10015              :     // the window shading control flag values follow
   10016              :     // -1: if window has no shading device
   10017              :     // 0: if shading device is off
   10018              :     // 1: if interior shade is on
   10019              :     // 2: if glazing is switched to darker state
   10020              :     // 3: if exterior shade is on
   10021              :     // 4: if exterior screen is on
   10022              :     // 6: if interior blind is on
   10023              :     // 7: if exterior blind is on
   10024              :     // 8: if between-glass shade is on
   10025              :     // 9: if between-glass blind is on
   10026              :     // 10: window has interior shade that is off but may be triggered on later to control daylight glare
   10027              :     // 20: window has switchable glazing that is unswitched but may be switched later to control daylight glare or
   10028              :     // daylight illuminance 30: window has exterior shade that is off but may be triggered on later to control
   10029              :     // daylight glare or daylight illuminance 60: window has interior blind that is off but may be triggered on later
   10030              :     // to control daylight glare or daylight illuminance 70: window has exterior blind that is off but may be
   10031              :     // triggered on later to control daylight glare or daylight illuminance 80: window has between-glass shade that is
   10032              :     // off but may be triggered on later to control daylight glare or daylight illuminance 90: window has
   10033              :     // between-glass blind that is off but may be triggered on later to control daylight glare or daylight illuminance
   10034            1 :     if (controlValue == -1.0) return WinShadingType::NoShade;
   10035            1 :     if (controlValue == 0.0) return WinShadingType::ShadeOff;
   10036            1 :     if (controlValue == 1.0) return WinShadingType::IntShade;
   10037            0 :     if (controlValue == 2.0) return WinShadingType::SwitchableGlazing;
   10038            0 :     if (controlValue == 3.0) return WinShadingType::ExtShade;
   10039            0 :     if (controlValue == 4.0) return WinShadingType::ExtScreen;
   10040            0 :     if (controlValue == 6.0) return WinShadingType::IntBlind;
   10041            0 :     if (controlValue == 7.0) return WinShadingType::ExtBlind;
   10042            0 :     if (controlValue == 8.0) return WinShadingType::BGShade;
   10043            0 :     if (controlValue == 9.0) return WinShadingType::BGBlind;
   10044            0 :     if (controlValue == 10.0) return WinShadingType::IntShadeConditionallyOff;
   10045            0 :     if (controlValue == 20.0) return WinShadingType::GlassConditionallyLightened;
   10046            0 :     if (controlValue == 30.0) return WinShadingType::ExtShadeConditionallyOff;
   10047            0 :     if (controlValue == 60.0) return WinShadingType::IntBlindConditionallyOff;
   10048            0 :     if (controlValue == 70.0) return WinShadingType::ExtBlindConditionallyOff;
   10049            0 :     if (controlValue == 80.0) return WinShadingType::BGShadeConditionallyOff;
   10050            0 :     if (controlValue == 90.0) return WinShadingType::BGBlindConditionallyOff;
   10051            0 :     return WinShadingType::Invalid;
   10052              : }
   10053              : 
   10054        32364 : int selectActiveWindowShadingControlIndex(EnergyPlusData &state, int curSurface)
   10055              : {
   10056        32364 :     auto &s_surf = state.dataSurface;
   10057              :     // For a given surface, determine based on the schedules which index to the window shading control list vector
   10058              :     // should be active
   10059              :     // presume it is the first shading control - even if it is not active it needs to be some
   10060              :     // shading control which is then turned off in the WindowShadingManager
   10061        32364 :     if (s_surf->Surface(curSurface).windowShadingControlList.size() > 1) {
   10062            6 :         for (std::size_t listIndex = 0; listIndex < s_surf->Surface(curSurface).windowShadingControlList.size(); ++listIndex) {
   10063            6 :             int wsc = s_surf->Surface(curSurface).windowShadingControlList[listIndex];
   10064              :             // pick the first WindowShadingControl that has a non-zero schedule value
   10065            6 :             if (s_surf->WindowShadingControl(wsc).sched->getCurrentVal() > 0.0) {
   10066            3 :                 return listIndex;
   10067              :             }
   10068              :         }
   10069              :     }
   10070        32361 :     return 0;
   10071              : }
   10072              : 
   10073            0 : void WindowGapAirflowControl(EnergyPlusData &state)
   10074              : {
   10075              : 
   10076              :     // SUBROUTINE INFORMATION:
   10077              :     //       AUTHOR         Fred Winkelmann
   10078              :     //       DATE WRITTEN   February 2003
   10079              :     //       MODIFIED       June 2003, FCW: add fatal error for illegal schedule value
   10080              :     //       RE-ENGINEERED  na
   10081              : 
   10082              :     // PURPOSE OF THIS SUBROUTINE:
   10083              :     // For airflow windows, determines the airflow in the gap of
   10084              :     // double glazing and in the inner gap of triple glazing.
   10085              : 
   10086              :     // REFERENCES:
   10087              :     // na
   10088              : 
   10089            0 :     auto &s_surf = state.dataSurface;
   10090            0 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
   10091            0 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
   10092            0 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
   10093            0 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
   10094            0 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
   10095            0 :             for (int ISurf = firstSurfWin; ISurf <= lastSurfWin; ++ISurf) {
   10096              : 
   10097            0 :                 s_surf->SurfWinAirflowThisTS(ISurf) = 0.0;
   10098            0 :                 if (s_surf->SurfWinMaxAirflow(ISurf) == 0.0) continue;
   10099            0 :                 if (s_surf->Surface(ISurf).ExtBoundCond != ExternalEnvironment) continue;
   10100            0 :                 switch (s_surf->SurfWinAirflowControlType(ISurf)) {
   10101            0 :                 case WindowAirFlowControlType::MaxFlow: {
   10102            0 :                     s_surf->SurfWinAirflowThisTS(ISurf) = s_surf->SurfWinMaxAirflow(ISurf);
   10103            0 :                 } break;
   10104            0 :                 case WindowAirFlowControlType::AlwaysOff: {
   10105            0 :                     s_surf->SurfWinAirflowThisTS(ISurf) = 0.0;
   10106            0 :                 } break;
   10107            0 :                 case WindowAirFlowControlType::Schedule: {
   10108            0 :                     if (s_surf->SurfWinAirflowHasSchedule(ISurf)) {
   10109            0 :                         auto const *sched = s_surf->SurfWinAirflowScheds(ISurf);
   10110            0 :                         Real64 ScheduleMult = sched->getCurrentVal(); // Multiplier value from schedule
   10111            0 :                         if (ScheduleMult < 0.0 || ScheduleMult > 1.0) {
   10112            0 :                             ShowFatalError(
   10113              :                                 state,
   10114            0 :                                 format("Airflow schedule has a value outside the range 0.0 to 1.0 for window={}", s_surf->Surface(ISurf).Name));
   10115              :                         }
   10116            0 :                         s_surf->SurfWinAirflowThisTS(ISurf) = ScheduleMult * s_surf->SurfWinMaxAirflow(ISurf);
   10117              :                     }
   10118            0 :                 } break;
   10119            0 :                 default:
   10120            0 :                     break;
   10121              :                 }
   10122              :             } // End of surface loop
   10123              :         }     // End of space loop
   10124              :     }         // End of zone loop
   10125            0 : }
   10126              : 
   10127          113 : void SkyDifSolarShading(EnergyPlusData &state)
   10128              : {
   10129              : 
   10130              :     // SUBROUTINE INFORMATION:
   10131              :     //       AUTHOR         Fred Winkelmann
   10132              :     //       DATE WRITTEN   May 1999
   10133              :     //       MODIFIED       Sep 2000, FCW: add IR view factor calc
   10134              :     //                      Sep 2002, FCW: correct error in expression for ground IR view factor.
   10135              :     //                         Affects only non-vertical surfaces that are shadowed. For these surfaces
   10136              :     //                         error caused underestimate of IR from ground and shadowing surfaces.
   10137              :     //                      Dec 2002; LKL: Sky Radiance Distribution now only anisotropic
   10138              :     //                      Nov 2003: FCW: modify to do sky solar shading of shadowing surfaces
   10139              :     //       RE-ENGINEERED  na
   10140              : 
   10141              :     // PURPOSE OF THIS SUBROUTINE:
   10142              :     // Calculates factors that account for shading of sky diffuse
   10143              :     // solar radiation by shadowing surfaces such as overhangs and detached
   10144              :     // shades.
   10145              :     // Called by PerformSolarCalculations
   10146              :     // For each exterior heat transfer surface calculates the following
   10147              :     // ratio (called DifShdgRatioIsoSky in this subroutine):
   10148              :     //  R1 = (Diffuse solar from sky dome on surface, with shading)/
   10149              :     //       (Diffuse solar from sky dome on surface, without shading)
   10150              :     // To calculate the incident diffuse radiation on a surface the sky
   10151              :     // hemisphere is divided into source elements ("patches"). Each patch
   10152              :     // is assumed to have the same radiance, i.e. the sky radiance is isotropic.
   10153              :     // The irradiance from each patch on a surface is calculated. Then these
   10154              :     // irradiances are summed to get the net irradiance on a surface, which
   10155              :     // the denominator of R1.
   10156              :     // To get the numerator of R1 the same summation is done, but for each surface
   10157              :     // and each patch the Shadow subroutine is called to determine how much
   10158              :     // radiation from a patch is blocked by shading surfaces.
   10159              :     // Also calculated is the following ratio (called DifShdgRatioHoriz in this routine):
   10160              :     //  R2 = (Diffuse solar from sky horizon band on surface, with shading)/
   10161              :     //       (Diffuse solar from sky horizon band on surface, without shading)
   10162              :     // For this ratio only a band of sky just above the horizon is considered.
   10163              :     // R1 and R2 are used in SUBROUTINE AnisoSkyViewFactors, which determines the
   10164              :     // sky diffuse solar irradiance on each exterior heat transfer surface each
   10165              :     // time step. In that routine the sky radiance distribution is a superposition
   10166              :     // of an isotropic distribution,
   10167              :     // a horizon brightening distribution and a circumsolar brightening distribution,
   10168              :     // where the proportion of each distribution depends
   10169              :     // on cloud cover, sun position and other factors. R1 multiplies the irradiance
   10170              :     // due to the isotropic component and R2 multiplies the irradiance due to the
   10171              :     // horizon brightening component.
   10172              :     // Calculates sky and ground IR view factors assuming sky IR is isotropic and
   10173              :     // shadowing surfaces are opaque to IR.
   10174              : 
   10175              :     // Using/Aliasing
   10176              : 
   10177              :     Real64 Fac1WoShdg;      // Intermediate calculation factor, without shading
   10178              :     Real64 FracIlluminated; // Fraction of surface area illuminated by a sky patch
   10179              :     Real64 Fac1WithShdg;    // Intermediate calculation factor, with shading
   10180              :     Real64 SurfArea;        // Surface area (m2)
   10181              :     // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WithShdgIsoSky     ! Diffuse solar irradiance from isotropic
   10182              :     //                                                          ! sky on surface, with shading
   10183              :     // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WoShdgIsoSky       ! Diffuse solar from isotropic
   10184              :     //                                                           ! sky on surface, without shading
   10185              :     // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WithShdgHoriz      ! Diffuse solar irradiance from horizon portion
   10186              :     // of
   10187              :     //                                                           ! sky on surface, with shading
   10188              :     // REAL(r64), ALLOCATABLE, DIMENSION(:) :: WoShdgHoriz        ! Diffuse solar irradiance from horizon portion
   10189              :     // of
   10190              :     //                                                           ! sky on surface, without shading
   10191              :     // INTEGER iHour,iTS
   10192              : 
   10193              :     // Initialize Surfaces Arrays
   10194          113 :     auto &s_surf = state.dataSurface;
   10195              : 
   10196          122 :     bool detailedShading = state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
   10197            9 :                            state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal;
   10198          113 :     state.dataSolarShading->SurfSunlitArea = 0.0;
   10199          113 :     state.dataSolarShading->SurfWithShdgIsoSky.dimension(s_surf->TotSurfaces, 0.0);
   10200          113 :     state.dataSolarShading->SurfWoShdgIsoSky.dimension(s_surf->TotSurfaces, 0.0);
   10201          113 :     state.dataSolarShading->SurfWithShdgHoriz.dimension(s_surf->TotSurfaces, 0.0);
   10202          113 :     state.dataSolarShading->SurfWoShdgHoriz.dimension(s_surf->TotSurfaces, 0.0);
   10203          113 :     state.dataSolarShading->SurfDifShdgRatioIsoSky.allocate(s_surf->TotSurfaces);
   10204          113 :     state.dataSolarShading->SurfDifShdgRatioHoriz.allocate(s_surf->TotSurfaces);
   10205              :     // initialized as no shading
   10206          113 :     state.dataSolarShading->SurfDifShdgRatioIsoSky = 1.0;
   10207          113 :     state.dataSolarShading->SurfDifShdgRatioHoriz = 1.0;
   10208          113 :     if (detailedShading) {
   10209            9 :         state.dataSolarShading->SurfCurDifShdgRatioIsoSky.dimension(s_surf->TotSurfaces, 1.0);
   10210            9 :         state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS.allocate(state.dataGlobal->TimeStepsInHour, 24, s_surf->TotSurfaces);
   10211            9 :         state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS = 1.0;
   10212            9 :         state.dataSolarShading->SurfDifShdgRatioHorizHRTS.allocate(state.dataGlobal->TimeStepsInHour, 24, s_surf->TotSurfaces);
   10213            9 :         state.dataSolarShading->SurfDifShdgRatioHorizHRTS = 1.0;
   10214              :     }
   10215              : 
   10216          659 :     for (int SurfNum : s_surf->AllExtSolarSurfaceList) {
   10217          546 :         auto &surf = s_surf->Surface(SurfNum);
   10218              : 
   10219              :         // CurrentModuleObject='Surfaces'
   10220          546 :         if (detailedShading) {
   10221          162 :             SetupOutputVariable(state,
   10222              :                                 "Debug Surface Solar Shading Model DifShdgRatioIsoSky",
   10223              :                                 Constant::Units::None,
   10224           81 :                                 state.dataSolarShading->SurfCurDifShdgRatioIsoSky(SurfNum),
   10225              :                                 OutputProcessor::TimeStepType::Zone,
   10226              :                                 OutputProcessor::StoreType::Average,
   10227           81 :                                 surf.Name);
   10228              :         } else {
   10229          930 :             SetupOutputVariable(state,
   10230              :                                 "Debug Surface Solar Shading Model DifShdgRatioIsoSky",
   10231              :                                 Constant::Units::None,
   10232          465 :                                 state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum),
   10233              :                                 OutputProcessor::TimeStepType::Zone,
   10234              :                                 OutputProcessor::StoreType::Average,
   10235          465 :                                 surf.Name);
   10236              :         }
   10237         1092 :         SetupOutputVariable(state,
   10238              :                             "Debug Surface Solar Shading Model DifShdgRatioHoriz",
   10239              :                             Constant::Units::None,
   10240          546 :                             state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum),
   10241              :                             OutputProcessor::TimeStepType::Zone,
   10242              :                             OutputProcessor::StoreType::Average,
   10243          546 :                             surf.Name);
   10244         1092 :         SetupOutputVariable(state,
   10245              :                             "Debug Surface Solar Shading Model WithShdgIsoSky",
   10246              :                             Constant::Units::None,
   10247          546 :                             state.dataSolarShading->SurfWithShdgIsoSky(SurfNum),
   10248              :                             OutputProcessor::TimeStepType::Zone,
   10249              :                             OutputProcessor::StoreType::Average,
   10250          546 :                             surf.Name);
   10251         1092 :         SetupOutputVariable(state,
   10252              :                             "Debug Surface Solar Shading Model WoShdgIsoSky",
   10253              :                             Constant::Units::None,
   10254          546 :                             state.dataSolarShading->SurfWoShdgIsoSky(SurfNum),
   10255              :                             OutputProcessor::TimeStepType::Zone,
   10256              :                             OutputProcessor::StoreType::Average,
   10257          546 :                             surf.Name);
   10258              :     }
   10259              : 
   10260          791 :     for (int IPhi = 0; IPhi < NPhi; ++IPhi) { // Loop over patch altitude values
   10261          678 :         state.dataSolarShading->SUNCOS(3) = state.dataSolarShading->sin_Phi[IPhi];
   10262              : 
   10263        16950 :         for (int ITheta = 0; ITheta < NTheta; ++ITheta) { // Loop over patch azimuth values
   10264        16272 :             state.dataSolarShading->SUNCOS(1) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->cos_Theta[ITheta];
   10265        16272 :             state.dataSolarShading->SUNCOS(2) = state.dataSolarShading->cos_Phi[IPhi] * state.dataSolarShading->sin_Theta[ITheta];
   10266              : 
   10267        94896 :             for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
   10268        78624 :                 auto &surf = s_surf->Surface(SurfNum);
   10269              : 
   10270              :                 // Cosine of angle of incidence on surface of solar radiation from patch
   10271       157248 :                 state.dataSolarShading->SurfSunCosTheta(SurfNum) = state.dataSolarShading->SUNCOS.x * surf.OutNormVec.x +
   10272        78624 :                                                                    state.dataSolarShading->SUNCOS.y * surf.OutNormVec.y +
   10273        78624 :                                                                    state.dataSolarShading->SUNCOS.z * surf.OutNormVec.z;
   10274              :             }
   10275              : 
   10276        16272 :             SHADOW(state, 24, 0);
   10277              : 
   10278        94896 :             for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
   10279        78624 :                 auto &surf = s_surf->Surface(SurfNum);
   10280              : 
   10281        78624 :                 if (state.dataSolarShading->SurfSunCosTheta(SurfNum) < 0.0) continue;
   10282              : 
   10283        42372 :                 Fac1WoShdg = state.dataSolarShading->cos_Phi[IPhi] * DThetaDPhi * state.dataSolarShading->SurfSunCosTheta(SurfNum);
   10284        42372 :                 SurfArea = surf.NetAreaShadowCalc;
   10285        42372 :                 if (SurfArea > Eps) {
   10286        42372 :                     FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / SurfArea;
   10287              :                 } else {
   10288            0 :                     FracIlluminated = state.dataSolarShading->SurfSunlitArea(SurfNum) / (SurfArea + Eps);
   10289              :                 }
   10290        42372 :                 Fac1WithShdg = Fac1WoShdg * FracIlluminated;
   10291        42372 :                 state.dataSolarShading->SurfWithShdgIsoSky(SurfNum) += Fac1WithShdg;
   10292        42372 :                 state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) += Fac1WoShdg;
   10293              : 
   10294              :                 // Horizon region
   10295        42372 :                 if (IPhi == 0) {
   10296         7047 :                     state.dataSolarShading->SurfWithShdgHoriz(SurfNum) += Fac1WithShdg;
   10297         7047 :                     state.dataSolarShading->SurfWoShdgHoriz(SurfNum) += Fac1WoShdg;
   10298              :                 }
   10299              :             } // End of surface loop
   10300              :         }     // End of Theta loop
   10301              :     }         // End of Phi loop
   10302              : 
   10303          659 :     for (int SurfNum : s_surf->AllExtSolAndShadingSurfaceList) {
   10304              : 
   10305          546 :         if (std::abs(state.dataSolarShading->SurfWoShdgIsoSky(SurfNum)) > Eps) {
   10306          494 :             state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) =
   10307          494 :                 (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum));
   10308              :         } else {
   10309           52 :             state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum) =
   10310           52 :                 (state.dataSolarShading->SurfWithShdgIsoSky(SurfNum)) / (state.dataSolarShading->SurfWoShdgIsoSky(SurfNum) + Eps);
   10311              :         }
   10312          546 :         if (std::abs(state.dataSolarShading->SurfWoShdgHoriz(SurfNum)) > Eps) {
   10313          494 :             state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum) =
   10314          494 :                 (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum));
   10315              :         } else {
   10316           52 :             state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum) =
   10317           52 :                 (state.dataSolarShading->SurfWithShdgHoriz(SurfNum)) / (state.dataSolarShading->SurfWoShdgHoriz(SurfNum) + Eps);
   10318              :         }
   10319              :     }
   10320              : 
   10321              :     // Get IR view factors. An exterior surface can receive IR radiation from
   10322              :     // sky, ground or shadowing surfaces. Assume shadowing surfaces have same
   10323              :     // temperature as outside air (and therefore same temperature as ground),
   10324              :     // so that the view factor to these shadowing surfaces can be included in
   10325              :     // the ground view factor. Sky IR is assumed to be isotropic and shadowing
   10326              :     // surfaces are assumed to be opaque to IR so they totally "shade" IR from
   10327              :     // sky or ground.
   10328              : 
   10329          945 :     for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
   10330          832 :         auto &surface = s_surf->Surface(SurfNum);
   10331          913 :         if (!state.dataSysVars->DetailedSkyDiffuseAlgorithm || !s_surf->ShadingTransmittanceVaries ||
   10332           81 :             state.dataHeatBal->SolarDistribution == DataHeatBalance::Shadowing::Minimal) {
   10333          751 :             surface.ViewFactorSkyIR *= state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum);
   10334              :         } else {
   10335           81 :             surface.ViewFactorSkyIR *= state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS(1, 1, SurfNum);
   10336              :         }
   10337          832 :         surface.ViewFactorGroundIR = 1.0 - surface.ViewFactorSkyIR;
   10338              : 
   10339          832 :         if (surface.SurfHasSurroundingSurfProperty) {
   10340            1 :             surface.ViewFactorGroundIR = 1.0 - surface.ViewFactorSkyIR - surface.ViewFactorSrdSurfs;
   10341              :         }
   10342              :     }
   10343              : 
   10344              :     //  DEALLOCATE(WithShdgIsoSky)
   10345              :     //  DEALLOCATE(WoShdgIsoSky)
   10346              :     //  DEALLOCATE(WithShdgHoriz)
   10347              :     //  DEALLOCATE(WoShdgHoriz)
   10348              : 
   10349          122 :     if (state.dataSysVars->DetailedSkyDiffuseAlgorithm && s_surf->ShadingTransmittanceVaries &&
   10350            9 :         state.dataHeatBal->SolarDistribution != DataHeatBalance::Shadowing::Minimal) {
   10351           90 :         for (int SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
   10352          162 :             state.dataSolarShading->SurfDifShdgRatioIsoSkyHRTS({1, state.dataGlobal->TimeStepsInHour}, {1, 24}, SurfNum) =
   10353          162 :                 state.dataSolarShading->SurfDifShdgRatioIsoSky(SurfNum);
   10354          162 :             state.dataSolarShading->SurfDifShdgRatioHorizHRTS({1, state.dataGlobal->TimeStepsInHour}, {1, 24}, SurfNum) =
   10355          162 :                 state.dataSolarShading->SurfDifShdgRatioHoriz(SurfNum);
   10356              :         }
   10357              :     }
   10358          113 : }
   10359              : 
   10360        71216 : void CalcWindowProfileAngles(EnergyPlusData &state)
   10361              : {
   10362              : 
   10363              :     // SUBROUTINE INFORMATION:
   10364              :     //       AUTHOR         Fred Winkelmann
   10365              :     //       DATE WRITTEN   April 2002
   10366              :     //       MODIFIED       na
   10367              :     //       RE-ENGINEERED  na
   10368              :     // PURPOSE OF THIS SUBROUTINE:
   10369              :     // Called by CalcPerSolarBeam for wholly or partially sunlit exterior windows
   10370              :     // Calculates horizontal and vertical beam solar profile angles
   10371              : 
   10372              :     Real64 ElevSun;       // Sun elevation; angle between sun and horizontal
   10373              :     Real64 ElevWin;       // Window elevation: angle between window outward normal and horizontal
   10374              :     Real64 AzimWin;       // Window azimuth (radians)
   10375              :     Real64 AzimSun;       // Sun azimuth (radians)
   10376              :     Real64 ProfileAngHor; // Solar profile angle (radians) for horizontally oriented window elements
   10377              :     // such as the top and bottom of a frame.
   10378              :     // This is the incidence angle in a plane that is normal to the window
   10379              :     // and parallel to the Y-axis of the window (the axis along
   10380              :     // which the height of the window is measured).
   10381              :     Real64 ProfileAngVert; // Solar profile angle (radians) for vertically oriented elements
   10382              :     // such as the sides of a frame.
   10383              :     // This is the incidence angle in a plane that is normal to the window
   10384              :     // and parallel to the X-axis of the window (the axis along
   10385              :     // which the width of the window is measured).
   10386        71216 :     Vector3<Real64> WinNorm;                                  // Unit vector normal to window
   10387        71216 :     Vector3<Real64> WinNormCrossBase;                         // Cross product of WinNorm and vector along window baseline
   10388        71216 :     Vector3<Real64> SunPrime;                                 // Projection of sun vector onto plane (perpendicular to
   10389        71216 :     Vector3<Real64> const SolCosVec(state.dataEnvrn->SOLCOS); // Local Vector3 copy for speed (until SOLCOS mig to Vector3)
   10390              :     //  window plane) determined by WinNorm and vector along
   10391              :     //  baseline of window
   10392              :     Real64 ThWin; // Azimuth angle of WinNorm (radians)
   10393              :     Real64 dot1;
   10394              :     Real64 dot2;
   10395              :     Real64 dot3;
   10396              : 
   10397        71216 :     auto &s_surf = state.dataSurface;
   10398              : 
   10399        71216 :     ElevSun = Constant::PiOvr2 - std::acos(SolCosVec.z);
   10400        71216 :     AzimSun = std::atan2(SolCosVec.x, SolCosVec.y);
   10401              : 
   10402        71216 :     Real64 const cos_ElevSun = std::cos(ElevSun);
   10403        71216 :     Real64 const sin_ElevSun = std::sin(ElevSun);
   10404              : 
   10405       170521 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
   10406       212058 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
   10407       112753 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
   10408       112753 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
   10409       112753 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
   10410       143857 :             for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
   10411        31104 :                 auto &surf = s_surf->Surface(SurfNum);
   10412        31104 :                 if (surf.ExtBoundCond != ExternalEnvironment && surf.ExtBoundCond != OtherSideCondModeledExt) continue;
   10413              : 
   10414        31104 :                 s_surf->SurfWinProfileAngHor(SurfNum) = 0.0;
   10415        31104 :                 s_surf->SurfWinProfileAngVert(SurfNum) = 0.0;
   10416        31104 :                 if (state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) <= 0.0) continue;
   10417              : 
   10418        16810 :                 ElevWin = Constant::PiOvr2 - surf.Tilt * Constant::DegToRad;
   10419        16810 :                 AzimWin = surf.Azimuth * Constant::DegToRad;
   10420              : 
   10421        16810 :                 ProfileAngHor = std::atan(sin_ElevSun / std::abs(cos_ElevSun * std::cos(AzimWin - AzimSun))) - ElevWin;
   10422              : 
   10423              :                 // CR9280 - were having negative profile angles on west sides.  commenting out previous code
   10424              :                 // (original code) for vertical windows
   10425              :                 //  IF(ABS(ElevWin) < 0.1d0) THEN  ! Near-vertical window
   10426              :                 //    ProfileAngVert = ABS(AzimWin-AzimSun)
   10427              :                 //  ELSE
   10428        16810 :                 WinNorm = surf.OutNormVec;
   10429        16810 :                 ThWin = AzimWin - Constant::PiOvr2;
   10430        16810 :                 Real64 const sin_Elevwin(std::sin(ElevWin));
   10431        16810 :                 WinNormCrossBase.x = -(sin_Elevwin * std::cos(ThWin));
   10432        16810 :                 WinNormCrossBase.y = sin_Elevwin * std::sin(ThWin);
   10433        16810 :                 WinNormCrossBase.z = std::cos(ElevWin);
   10434        16810 :                 SunPrime = SolCosVec - WinNormCrossBase * dot(SolCosVec, WinNormCrossBase);
   10435        16810 :                 dot1 = dot(WinNorm, SunPrime);
   10436        16810 :                 dot2 = SunPrime.magnitude();
   10437        16810 :                 dot3 = dot1 / dot2;
   10438        16810 :                 if (dot3 > 1.0) {
   10439            0 :                     dot3 = 1.0;
   10440        16810 :                 } else if (dot3 < -1.0) {
   10441            0 :                     dot3 = -1.0;
   10442              :                 }
   10443              :                 //    ProfileAngVert =
   10444              :                 //    ABS(ACOS(DOT_PRODUCT(WinNorm,SunPrime)/SQRT(DOT_PRODUCT(SunPrime,SunPrime))))
   10445        16810 :                 ProfileAngVert = std::abs(std::acos(dot3));
   10446              :                 //  END IF
   10447              :                 // Constrain to 0 to pi
   10448        16810 :                 if (ProfileAngVert > Constant::Pi) ProfileAngVert = Constant::TwoPi - ProfileAngVert;
   10449              : 
   10450        16810 :                 s_surf->SurfWinProfileAngHor(SurfNum) = ProfileAngHor / Constant::DegToRad;
   10451        16810 :                 s_surf->SurfWinProfileAngVert(SurfNum) = ProfileAngVert / Constant::DegToRad;
   10452        16810 :                 s_surf->SurfWinTanProfileAngHor(SurfNum) = std::abs(std::tan(ProfileAngHor));
   10453        16810 :                 s_surf->SurfWinTanProfileAngVert(SurfNum) = std::abs(std::tan(ProfileAngVert));
   10454              :             }
   10455              :         }
   10456              :     }
   10457        71216 : }
   10458              : 
   10459           17 : void CalcFrameDividerShadow(EnergyPlusData &state,
   10460              :                             int const SurfNum,  // Surface number
   10461              :                             int const FrDivNum, // Frame/divider number
   10462              :                             int const HourNum   // Hour number
   10463              : )
   10464              : {
   10465              : 
   10466              :     // SUBROUTINE INFORMATION:
   10467              :     //       AUTHOR         Fred Winkelmann
   10468              :     //       DATE WRITTEN   June 2000
   10469              :     //       MODIFIED       Aug 2000, FW: add effective shadowing by inside
   10470              :     //                      projections
   10471              :     //       RE-ENGINEERED  na
   10472              : 
   10473              :     // PURPOSE OF THIS SUBROUTINE:
   10474              :     // Called by CalcPerSolarBeam for wholly or partially sunlit exterior windows
   10475              :     // with a frame and/or divider. Using beam solar profile angles,
   10476              :     // calculates fraction of glass shaded by exterior frame and divider projections,
   10477              :     // The frame and divider profiles are assumed to be rectangular.
   10478              :     // A similar shadowing approach is used to calculate the fraction of glass area
   10479              :     // that produces beam solar illumination on interior frame and divider projections.
   10480              :     // This fraction is used in CalcWinFrameAndDividerTemps to determine the
   10481              :     // beam solar absorbed by inside projections. Beam solar reflected by inside projections
   10482              :     // is assumed to stay in the zone (as beam solar) although in actuality roughly
   10483              :     // half of this is reflected back onto the glass and the half that is reflected
   10484              :     // into the zone is diffuse.
   10485              :     // For multipane glazing the effect of solar absorbed by the exposed portion of
   10486              :     // frame or divider between the panes is not calculated. Beam solar incident on
   10487              :     // these portions is assumed to be transmitted into the zone unchanged.
   10488              :     // The shadowing of diffuse solar radiation by projections is not considered.
   10489              : 
   10490              :     Real64 ElevSun;       // Sun elevation; angle between sun and horizontal
   10491              :     Real64 ElevWin;       // Window elevation: angle between window outward normal and horizontal
   10492              :     Real64 AzimWin;       // Window azimuth (radians)
   10493              :     Real64 AzimSun;       // Sun azimuth (radians)
   10494              :     Real64 ProfileAngHor; // Solar profile angle (radians) for horizontally oriented projections
   10495              :     // such as the top and bottom of a frame or horizontal dividers.
   10496              :     // This is the incidence angle in a plane that is normal to the window
   10497              :     // and parallel to the Y-axis of the window (the axis along
   10498              :     // which the height of the window is measured).
   10499              :     Real64 ProfileAngVert; // Solar profile angle (radians) for vertically oriented projections
   10500              :     // such as the top and bottom of a frame or horizontal dividers.
   10501              :     // This is the incidence angle in a plane that is normal to the window
   10502              :     // and parallel to the X-axis of the window (the axis along
   10503              :     // which the width of the window is measured).
   10504              :     Real64 TanProfileAngHor;  // Tangent of ProfileAngHor
   10505              :     Real64 TanProfileAngVert; // Tangent of ProfileAngVert
   10506              :     Real64 FrWidth;           // Frame width (m)
   10507              :     Real64 DivWidth;          // Divider width (m)
   10508              :     Real64 FrProjOut;         // Outside frame projection (m)
   10509              :     Real64 DivProjOut;        // Outside divider projection (m)
   10510              :     Real64 FrProjIn;          // Inside frame projection (m)
   10511              :     Real64 DivProjIn;         // Inside divider projection (m)
   10512              :     int NHorDiv;              // Number of horizontal dividers
   10513              :     int NVertDiv;             // Number of vertical dividers
   10514              :     Real64 GlArea;            // Glazed area (m2)
   10515              :     Real64 Arealite;          // Area of a single lite of glass (m2); glazed area, GlArea,
   10516              :     // if there is no divider (in which case there is only one lite).
   10517              :     Real64 ArealiteCol; // Area of a vertical column of lites (m2)
   10518              :     Real64 ArealiteRow; // Area of a horizontal row of lites (m2)
   10519              :     Real64 AshVDout;    // Shaded area from all vertical divider outside projections (m2)
   10520              :     Real64 AshVDin;     // Shaded area from all vertical divider inside projections (m2)
   10521              :     Real64 AshHDout;    // Shaded area from all horizontal divider outside projections (m2)
   10522              :     Real64 AshHDin;     // Shaded area from all horizontal divider inside projections (m2)
   10523              :     Real64 AshVFout;    // Shaded area from outside projection of vertical sides of frame (m2)
   10524              :     Real64 AshVFin;     // Shaded area from inside projection of vertical sides of frame (m2)
   10525              :     Real64 AshHFout;    // Shaded area from outside projection of horizontal sides
   10526              :     //   (top) of frame (m2)
   10527              :     Real64 AshHFin; // Shaded area from inside projection of horizontal sides
   10528              :     //   (top) of frame (m2)
   10529              :     Real64 AshDDover;   // Divider/divider shadow overlap area (m2)
   10530              :     Real64 AshFFover;   // Frame/frame shadow overlap area (m2)
   10531              :     Real64 AshFVDover;  // Frame/vertical divider overlap area (m2)
   10532              :     Real64 AshFHDover;  // Frame/horizontal divider overlap area (m2)
   10533              :     Real64 AshFDtotOut; // Total outside projection shadow area (m2)
   10534              :     Real64 AshFDtotIn;  // Total inside projection shadow area (m2)
   10535              :     Real64 FracShFDOut; // Fraction of glazing shadowed by frame and divider
   10536              :     //  outside projections
   10537              :     Real64 FracShFDin; // Fraction of glazing that illuminates frame and divider
   10538              :     //  inside projections with beam radiation
   10539              : 
   10540           17 :     Vector3<Real64> WinNorm(3);  // Window outward normal unit vector // Why the (3)?
   10541              :     Real64 ThWin;                // Azimuth angle of WinNorm
   10542           17 :     Vector3<Real64> SunPrime(3); // Projection of sun vector onto plane (perpendicular to // Why the (3)?
   10543              :     //  window plane) determined by WinNorm and vector along
   10544              :     //  baseline of window
   10545           17 :     Vector3<Real64> WinNormCrossBase(3); // Cross product of WinNorm and vector along window baseline // Why the (3)?
   10546              : 
   10547           17 :     auto &s_surf = state.dataSurface;
   10548              : 
   10549           17 :     if (s_surf->FrameDivider(FrDivNum).FrameProjectionOut == 0.0 && s_surf->FrameDivider(FrDivNum).FrameProjectionIn == 0.0 &&
   10550           17 :         s_surf->FrameDivider(FrDivNum).DividerProjectionOut == 0.0 && s_surf->FrameDivider(FrDivNum).DividerProjectionIn == 0.0)
   10551            0 :         return;
   10552              : 
   10553           17 :     FrProjOut = s_surf->FrameDivider(FrDivNum).FrameProjectionOut;
   10554           17 :     FrProjIn = s_surf->FrameDivider(FrDivNum).FrameProjectionIn;
   10555           17 :     DivProjOut = s_surf->FrameDivider(FrDivNum).DividerProjectionOut;
   10556           17 :     DivProjIn = s_surf->FrameDivider(FrDivNum).DividerProjectionIn;
   10557              : 
   10558           17 :     auto &surf = s_surf->Surface(SurfNum);
   10559           17 :     GlArea = surf.Area;
   10560           17 :     ElevWin = Constant::PiOvr2 - surf.Tilt * Constant::DegToRad;
   10561           17 :     ElevSun = Constant::PiOvr2 - std::acos(state.dataSolarShading->SUNCOS(3));
   10562           17 :     AzimWin = surf.Azimuth * Constant::DegToRad;
   10563           17 :     AzimSun = std::atan2(state.dataSolarShading->SUNCOS(1), state.dataSolarShading->SUNCOS(2));
   10564              : 
   10565           17 :     ProfileAngHor = std::atan(std::sin(ElevSun) / std::abs(std::cos(ElevSun) * std::cos(AzimWin - AzimSun))) - ElevWin;
   10566           17 :     if (std::abs(ElevWin) < 0.1) { // Near-vertical window
   10567           17 :         ProfileAngVert = std::abs(AzimWin - AzimSun);
   10568              :     } else {
   10569            0 :         WinNorm = surf.OutNormVec;
   10570            0 :         ThWin = AzimWin - Constant::PiOvr2;
   10571            0 :         WinNormCrossBase(1) = -std::sin(ElevWin) * std::cos(ThWin);
   10572            0 :         WinNormCrossBase(2) = std::sin(ElevWin) * std::sin(ThWin);
   10573            0 :         WinNormCrossBase(3) = std::cos(ElevWin);
   10574            0 :         SunPrime = state.dataSolarShading->SUNCOS - WinNormCrossBase * dot(state.dataSolarShading->SUNCOS, WinNormCrossBase);
   10575            0 :         ProfileAngVert = std::abs(std::acos(dot(WinNorm, SunPrime) / magnitude(SunPrime)));
   10576              :     }
   10577              :     // Constrain to 0 to pi
   10578           17 :     if (ProfileAngVert > Constant::Pi) ProfileAngVert = 2 * Constant::Pi - ProfileAngVert;
   10579           17 :     TanProfileAngHor = std::abs(std::tan(ProfileAngHor));
   10580           17 :     TanProfileAngVert = std::abs(std::tan(ProfileAngVert));
   10581              : 
   10582           17 :     NHorDiv = s_surf->FrameDivider(FrDivNum).HorDividers;
   10583           17 :     NVertDiv = s_surf->FrameDivider(FrDivNum).VertDividers;
   10584           17 :     FrWidth = s_surf->FrameDivider(FrDivNum).FrameWidth;
   10585           17 :     DivWidth = s_surf->FrameDivider(FrDivNum).DividerWidth;
   10586              : 
   10587           17 :     Arealite = (surf.Height / (NHorDiv + 1.0) - DivWidth / 2.0) * (surf.Width / (NVertDiv + 1.0) - DivWidth / 2.0);
   10588           17 :     if (DivProjOut > 0.0 || DivProjIn > 0.0) {
   10589           17 :         ArealiteCol = (NHorDiv + 1) * Arealite;
   10590           17 :         ArealiteRow = (NVertDiv + 1) * Arealite;
   10591              :     } else {
   10592            0 :         ArealiteCol = GlArea;
   10593            0 :         ArealiteRow = GlArea;
   10594              :     }
   10595           17 :     AshVDout = 0.0;
   10596           17 :     AshVDin = 0.0;
   10597           17 :     AshHDout = 0.0;
   10598           17 :     AshHDin = 0.0;
   10599           17 :     AshVFout = 0.0;
   10600           17 :     AshVFin = 0.0;
   10601           17 :     AshHFout = 0.0;
   10602           17 :     AshHFin = 0.0;
   10603           17 :     AshDDover = 0.0;
   10604           17 :     AshFFover = 0.0;
   10605           17 :     AshFVDover = 0.0;
   10606           17 :     AshFHDover = 0.0;
   10607              : 
   10608           17 :     if (DivProjOut > 0.0 || DivProjIn > 0.0) {
   10609              : 
   10610              :         // Shaded area from all vertical dividers
   10611           17 :         AshVDout = NVertDiv * min((surf.Height - NHorDiv * DivWidth) * DivProjOut * TanProfileAngVert, ArealiteCol);
   10612           17 :         AshVDin = NVertDiv * min((surf.Height - NHorDiv * DivWidth) * DivProjIn * TanProfileAngVert, ArealiteCol);
   10613              : 
   10614              :         // Shaded area from all horizontal dividers
   10615           17 :         AshHDout = NHorDiv * min((surf.Width - NVertDiv * DivWidth) * DivProjOut * TanProfileAngHor, ArealiteRow);
   10616           17 :         AshHDin = NHorDiv * min((surf.Width - NVertDiv * DivWidth) * DivProjIn * TanProfileAngHor, ArealiteRow);
   10617              : 
   10618              :         // Horizontal divider/vertical divider shadow overlap
   10619           17 :         AshDDover = min(DivProjOut * TanProfileAngHor * DivProjOut * TanProfileAngVert, Arealite) * NHorDiv * NVertDiv;
   10620              :     }
   10621              : 
   10622           17 :     if (FrProjOut > 0.0 || FrProjIn > 0.0) {
   10623              : 
   10624              :         // Shaded area from sides of frame; to avoid complications from possible overlaps between
   10625              :         // shadow from side of frame and shadow from vertical divider the shaded area from side of
   10626              :         // frame is restricted to the area of one column of lites.
   10627           17 :         AshVFout = min((surf.Height - NHorDiv * DivWidth) * FrProjOut * TanProfileAngVert, ArealiteCol);
   10628           17 :         AshVFin = min((surf.Height - NHorDiv * DivWidth) * FrProjIn * TanProfileAngVert, ArealiteCol);
   10629              : 
   10630              :         // Shaded area from top or bottom of frame; to avoid complications from possible overlaps
   10631              :         // between shadow from top or bottom of frame and shadow from horizontal divider, the shaded
   10632              :         // area from the top or bottom of frame is restricted to the area of one row of lites.
   10633           17 :         AshHFout = min((surf.Width - NVertDiv * DivWidth) * FrProjOut * TanProfileAngHor, ArealiteRow);
   10634           17 :         AshHFin = min((surf.Width - NVertDiv * DivWidth) * FrProjIn * TanProfileAngHor, ArealiteRow);
   10635              : 
   10636              :         // Top/bottom of frame/side of frame shadow overlap
   10637           17 :         AshFFover = min(FrProjOut * TanProfileAngHor * FrProjOut * TanProfileAngVert, Arealite);
   10638           17 :         if (DivProjOut > 0.0) {
   10639              :             // Frame/vertical divider shadow overlap
   10640           17 :             AshFVDover = min(FrProjOut * DivProjOut * TanProfileAngHor * TanProfileAngVert, Arealite) * NVertDiv;
   10641              :             // Frame/horizontal divider shadow overlap
   10642           17 :             AshFHDover = min(FrProjOut * DivProjOut * TanProfileAngHor * TanProfileAngVert, Arealite) * NHorDiv;
   10643              :         }
   10644              :     }
   10645              : 
   10646           17 :     AshFDtotOut = AshVDout + AshHDout + AshVFout + AshHFout - (AshDDover + AshFFover + AshFVDover + AshFHDover);
   10647           17 :     AshFDtotIn =
   10648           17 :         (AshVDin + AshHDin) * s_surf->FrameDivider(FrDivNum).DividerSolAbsorp + (AshVFin + AshHFin) * s_surf->FrameDivider(FrDivNum).FrameSolAbsorp;
   10649              : 
   10650              :     // Divide by the glazed area of the window
   10651           17 :     FracShFDOut = AshFDtotOut / GlArea;
   10652           17 :     FracShFDin = AshFDtotIn / GlArea;
   10653           17 :     s_surf->SurfaceWindow(SurfNum).OutProjSLFracMult[HourNum] = 1.0 - FracShFDOut;
   10654           17 :     s_surf->SurfaceWindow(SurfNum).InOutProjSLFracMult[HourNum] = 1.0 - (FracShFDin + FracShFDOut);
   10655           17 : }
   10656              : 
   10657            3 : void CalcBeamSolarOnWinRevealSurface(EnergyPlusData &state)
   10658              : {
   10659              : 
   10660              :     // SUBROUTINE INFORMATION:
   10661              :     //       AUTHOR         F. Winkelmann
   10662              :     //       DATE WRITTEN   April 2002
   10663              :     //       MODIFIED:na
   10664              :     //       RE-ENGINEERED:na
   10665              : 
   10666              :     // PURPOSE OF THIS SUBROUTINE
   10667              :     // Called by InitHeatGains when the sun is up.
   10668              :     // Calculates beam solar radiation absorbed and reflected by top, bottom,
   10669              :     // right and left sides of outside and inside window reveal surfaces.
   10670              :     // In doing this calculation, the shadowing on a reveal surface by other reveal surfaces
   10671              :     // is determined using the orientation of the reveal surfaces and the sun position.
   10672              :     // It is assumed that:
   10673              :     // (1) The window is an exterior window and is rectangular.
   10674              :     // (2) The reveal surfaces are perpendicular to the window plane.
   10675              :     // (3) If an exterior shade or blind is in place, there is no beam solar on
   10676              :     //     on exterior or interior reveal surfaces.
   10677              :     // (3) If an interior shade or blind is in place, there is no beam solar on
   10678              :     //     interior reveal surfaces.
   10679              :     // (4) The effect of window divider, if present, is ignored, including shadowing
   10680              :     //     of divider on inside reveal surfaces.
   10681              : 
   10682              :     // In the variable names, the "subscript" 1 = outside reveal, 2 = inside reveal
   10683              :     // The outside reveal surfaces (top, bottom, left, right) are assumed to have the same depth
   10684              :     // (given by Surface%Reveal and determined from vertices of window and vertices of parent
   10685              :     // wall) and the same solar absorptance. The inside reveal surfaces are divided into
   10686              :     // two categories: (1) the bottom reveal surface, called here the "inside sill;" and
   10687              :     // the other reveal surfaces (left, right and top). The left, right and top inside reveal
   10688              :     // surfaces are assumed to have the same depth and solar absorptance.
   10689              :     // The depth of the outside reveal is measured from the outside surface of the glazing;
   10690              :     // The depth of the inside sill and the other reveal surfaces is measured from the inside
   10691              :     // surface of the glazing. The inside sill is
   10692              :     // allowed to have depth and solar absorptance values that are different from the corresponding
   10693              :     // values for the other inside reveal surfaces. The inside sill depth is required to be
   10694              :     // greater than or equal to the depth of the other inside reveal surfaces. If the inside sill
   10695              :     // depth is greater than zero the depth of the other inside reveal surfaces is required to
   10696              :     // to be greater than zero.
   10697              :     // The reflection of beam solar radiation from all reveal surfaces is assumed to be isotropic
   10698              :     // diffuse; there is no specular component. Half of the beam solar reflected from outside
   10699              :     // reveal surfaces is assumed to go towards the window; the other half is assumed to go back
   10700              :     // to the exterior environment (i.e., reflection of this outward-going component from
   10701              :     // other outside reveal surfaces is not considered). The half that goes towards the window
   10702              :     // is added to the other radiation incident on the window.
   10703              :     // Correspondingly, half of the beam solar reflected from inside reveal surfaces is assumed
   10704              :     // to go towards the window, with the other half going into the zone (this half, and the portion
   10705              :     // going towards the window that is reflected) is added in CalcInteriorSolarDistribution
   10706              :     // to the variable BTOTzone, which is the total beam solar entering the zone as beam or diffuse.
   10707              :     // The portion going towards the window that is not reflected is absorbed in the glazing or
   10708              :     // transmitted back out into the exterior environment.
   10709              :     // The beam solar that is absorbed by outside reveal surfaces is added to the solar absorbed
   10710              :     // by the outside surface of the window's parent wall; similarly, the beam solar absorbed
   10711              :     // by the inside reveal surfaces is added to the solar absorbed by the inside surface of the
   10712              :     // parent wall (and is subtracted from BTOTzone).
   10713              :     // The net effect of beam solar reflected from outside reveal surfaces is to INCREASE the
   10714              :     // the heat gain to the zone, whereas the effect of beam solar reflected from interior reveal
   10715              :     // surfaces is to DECREASE the heat gain to the zone since part of this reflected solar is
   10716              :     // transmitted back out the window.
   10717              :     // If the window has a frame, the absorption of reflected beam solar by the inside and outside
   10718              :     // surfaces of the frame is considered. The shadowing of the frame onto interior reveal
   10719              :     // surfaces is also considered.
   10720              : 
   10721              :     // The total glazing thickness is taken to be the sum of the thickness of the glass layers
   10722              :     // and between-glass gas layers. If the window has an exterior, movable, storm window glass layer
   10723              :     // the presence of this layer and its adjacent air gap is considered in calculating the glazing
   10724              :     // properties (solar transmittance, etc.). But the storm window glass is assumed to be close
   10725              :     // enough to the rest of the glazing that its effect on total glazing thickness and outside
   10726              :     // reveal depth can be ignored.
   10727              : 
   10728              :     // METHODOLOGY EMPLOYED
   10729              :     // na
   10730              : 
   10731              :     // REFERENCES
   10732              :     // na
   10733              : 
   10734              :     // Locals
   10735              :     // SUBROUTINE ARGUMENT DEFINITIONS:na
   10736              : 
   10737              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS
   10738              : 
   10739              :     int ConstrNum;        // Construction number
   10740              :     int ConstrNumSh;      // Shaded construction number
   10741              :     Real64 CosBetaBottom; // Cosine of beam solar angle of incidence on bottom reveal
   10742              :     Real64 CosBetaLeft;   // Cosine of beam solar angle of incidence on left reveal
   10743              :     Real64 CosBeta;       // ABS of CosBetaBottom or CosBetaLeft
   10744              :     Real64 d1;            // Depth of outside reveal + half of glazing thickness (m)
   10745              :     Real64 d2;            // Depth of inside sill or of inside reveal plus half of glazing thickness (m)
   10746              :     Real64 d2prime;       // Depth of shadow cast on a reveal surface by opposite reveal (m)
   10747              :     Real64 d2prime2;      // Depth of shadow cast by frame onto inside reveal (m)
   10748              :     Real64 d12;           // d12 = d1 + d2 - d2prime (m)
   10749              :     Real64 TanAlpha;      // Tangent of horizontal or vertical profile angle
   10750              :     Real64 TanGamma;      // Tangent of vertical or horizontal profile angle
   10751              :     Real64 H;             // Window height, width (m)
   10752              :     Real64 W;
   10753              :     Real64 L;                    // Window height or width (m)
   10754              :     Real64 A1sh;                 // Shadowed area of outside horizontal or vertical reveal (m2)
   10755              :     Real64 A2sh;                 // Shadowed area of inside horizontal or vertical reveal (m2)
   10756              :     Real64 A1ill;                // Illuminated area of outside horizontal or vertical reveal (m2)
   10757              :     Real64 A2ill;                // Illuminated area of inside horizontal or vertical reveal (m2)
   10758              :     Real64 SolTransGlass;        // Beam solar transmittance of glazing
   10759              :     Real64 SolTransGlassSh;      // For switchable glazing, beam solar trans in switched state
   10760              :     Real64 DiffReflGlass;        // Diffuse back reflectance of glazing
   10761              :     Real64 DiffReflGlassSh;      // For switchable glazing, diffuse back refl in switched state
   10762              :     int HorVertReveal;           // Index: 1 = horizontal reveal, 2 = vertical reveal
   10763              :     Real64 OutsReveal;           // Depth of outside reveal (from outside glazing plane to outside wall plane) (m)
   10764              :     Real64 InsReveal;            // Depth of inside reveal (from inside glazing plane to inside wall plane (m)
   10765              :     Real64 InsSillDepth;         // Depth of inside sill, measured from innermost face of glazing (m)
   10766              :     Real64 GlazingThickness;     // Thickness of glazing, measured from innermost face to outermost face (m)
   10767              :     Real64 InsideRevealSolAbs;   // Solar absorptance of inside reveal or inside sill
   10768              :     Real64 BmSolRefldOutsReveal; // Multiplied by beam solar gives beam solar reflected by horiz or vertical
   10769              :     //  outside reveal surface (m2)
   10770              :     Real64 BmSolRefldInsReveal; // Multiplied by beam solar gives beam solar reflected by horiz or vertical
   10771              :     //  inside reveal surface (m2)
   10772              :     WinShadingType ShadeFlag; // Shading flag
   10773              :     int FrameDivNum;          // Frame/Divider number
   10774              :     Real64 FrameWidth;        // Frame width (m)
   10775              :     Real64 P1;                // Frame outside/inside projection plus half of glazing thickness (m)
   10776              :     Real64 P2;
   10777              :     Real64 f1; // f1=d1-P1, f2=d2-P2 (m)
   10778              :     Real64 f2;
   10779              :     Real64 L1; // Average distance of outside/inside illuminated area to frame;
   10780              :     Real64 L2;
   10781              :     // used in calculating view factor to frame (m)
   10782              :     Real64 FracToGlassOuts;   // View factor from outside horizontal or vertical reveal to glass
   10783              :     Real64 FracToGlassIns;    // View factor from inside horizontal or vertical reveal to glass
   10784              :     Real64 TanProfileAngVert; // Tangent of vertical profile angle (the profile angle appropriate for
   10785              :     // vertical reveal surfaces.
   10786              :     Real64 TanProfileAngHor; // Tangent of horizontal profile angle (the profile angle appropriate for
   10787              :     // horizontal reveal surfaces.
   10788              : 
   10789              :     Real64 tmp_SunlitFracWithoutReveal; // Temporary variable
   10790              : 
   10791            3 :     auto &s_surf = state.dataSurface;
   10792              : 
   10793            6 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
   10794            6 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
   10795            3 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
   10796            3 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
   10797            3 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
   10798            9 :             for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
   10799              :                 // Added TH for initialization. CR 7596 inside reveal causing high cooling loads
   10800              :                 // for outside reveals
   10801            6 :                 s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) = 0.0;
   10802            6 :                 s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) = 0.0;
   10803            6 :                 s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfNum) = 0.0;
   10804            6 :                 s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) = 0.0;
   10805            6 :                 s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) = 0.0;
   10806              :                 // for inside reveals
   10807            6 :                 s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) = 0.0;
   10808            6 :                 s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) = 0.0;
   10809            6 :                 s_surf->SurfWinBmSolRefldInsReveal(SurfNum) = 0.0;
   10810            6 :                 s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) = 0.0;
   10811            6 :                 s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfNum) = 0.0;
   10812            6 :                 s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) = 0.0;
   10813            6 :                 s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) = 0.0;
   10814            6 :                 s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) = 0.0;
   10815            6 :                 s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) = 0.0;
   10816            6 :                 s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) = 0.0;
   10817            6 :                 s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) = 0.0;
   10818              : 
   10819            6 :                 auto &surf = s_surf->Surface(SurfNum);
   10820            6 :                 if ((surf.ExtBoundCond != ExternalEnvironment && surf.ExtBoundCond != OtherSideCondModeledExt)) continue;
   10821            6 :                 if (surf.Reveal == 0.0 && s_surf->SurfWinInsideReveal(SurfNum) == 0.0 && s_surf->SurfWinInsideSillDepth(SurfNum) == 0.0) continue;
   10822            6 :                 if (surf.Sides != 4) continue;
   10823            6 :                 if (s_surf->SurfWinInsideSillDepth(SurfNum) < s_surf->SurfWinInsideReveal(SurfNum)) continue;
   10824              : 
   10825            6 :                 ShadeFlag = s_surf->SurfWinShadingFlag(SurfNum);
   10826            6 :                 if ((ShadeFlag == WinShadingType::ExtShade) || (ShadeFlag == WinShadingType::ExtBlind)) continue;
   10827              : 
   10828            6 :                 if (state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) <= 0.0) continue;
   10829              : 
   10830            6 :                 tmp_SunlitFracWithoutReveal =
   10831            6 :                     state.dataHeatBal->SurfSunlitFracWithoutReveal(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
   10832              : 
   10833              :                 // Calculate cosine of angle of incidence of beam solar on reveal surfaces,
   10834              :                 // assumed to be perpendicular to window plane
   10835              : 
   10836            6 :                 CosBetaBottom = -state.dataEnvrn->SOLCOS(1) * surf.SinAzim * surf.CosTilt - state.dataEnvrn->SOLCOS(2) * surf.CosAzim * surf.CosTilt +
   10837            6 :                                 state.dataEnvrn->SOLCOS(3) * surf.SinTilt;
   10838              : 
   10839            6 :                 CosBetaLeft = -state.dataEnvrn->SOLCOS(1) * surf.CosAzim - state.dataEnvrn->SOLCOS(2) * surf.SinAzim;
   10840              : 
   10841              :                 // Note: CosBetaTop = -CosBetaBottom, CosBetaRight = -CosBetaLeft
   10842              : 
   10843            6 :                 OutsReveal = surf.Reveal;
   10844            6 :                 InsReveal = s_surf->SurfWinInsideReveal(SurfNum);
   10845            6 :                 InsideRevealSolAbs = 0.0;
   10846            6 :                 GlazingThickness = s_surf->SurfWinTotGlazingThickness(SurfNum);
   10847            6 :                 H = surf.Height;
   10848            6 :                 W = surf.Width;
   10849            6 :                 d1 = OutsReveal + 0.5 * GlazingThickness;
   10850            6 :                 ConstrNum = s_surf->SurfActiveConstruction(SurfNum);
   10851            6 :                 ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(SurfNum);
   10852            6 :                 auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
   10853              : 
   10854            6 :                 SolTransGlass = Window::POLYF(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum),
   10855            6 :                                               thisConstruct.TransSolBeamCoef);
   10856            6 :                 TanProfileAngVert = s_surf->SurfWinTanProfileAngVert(SurfNum);
   10857            6 :                 TanProfileAngHor = s_surf->SurfWinTanProfileAngHor(SurfNum);
   10858            6 :                 FrameDivNum = surf.FrameDivider;
   10859            6 :                 FrameWidth = 0.0;
   10860            6 :                 if (FrameDivNum != 0) {
   10861            6 :                     FrameWidth = s_surf->FrameDivider(FrameDivNum).FrameWidth;
   10862            6 :                     if (FrameWidth > 0.0) {
   10863            6 :                         P1 = s_surf->FrameDivider(FrameDivNum).FrameProjectionOut + 0.5 * GlazingThickness;
   10864            6 :                         P2 = s_surf->FrameDivider(FrameDivNum).FrameProjectionIn + 0.5 * GlazingThickness;
   10865            6 :                         if (OutsReveal + 0.5 * GlazingThickness <= P1) d1 = P1 + 0.001;
   10866              :                     }
   10867              :                 }
   10868              :                 // Loop over vertical and horizontal reveal surfaces
   10869           18 :                 for (HorVertReveal = 1; HorVertReveal <= 2; ++HorVertReveal) {
   10870              : 
   10871           12 :                     FracToGlassOuts = 0.5;
   10872           12 :                     FracToGlassIns = 0.5;
   10873           12 :                     BmSolRefldOutsReveal = 0.0;
   10874           12 :                     BmSolRefldInsReveal = 0.0;
   10875           12 :                     A1ill = 0.0;
   10876           12 :                     A2ill = 0.0;
   10877              : 
   10878              :                     // Added TH. 5/27/2009
   10879           12 :                     A1sh = 0.0;
   10880           12 :                     A2sh = 0.0;
   10881              : 
   10882           12 :                     if (HorVertReveal == 1) { // Vertical reveal
   10883            6 :                         TanAlpha = TanProfileAngHor;
   10884            6 :                         TanGamma = TanProfileAngVert;
   10885            6 :                         CosBeta = std::abs(CosBetaLeft);
   10886            6 :                         L = surf.Height;
   10887            6 :                         d2 = InsReveal + 0.5 * GlazingThickness;
   10888            6 :                         d2prime = d1 + d2 - W / TanGamma;
   10889            6 :                         InsideRevealSolAbs = s_surf->SurfWinInsideRevealSolAbs(SurfNum);
   10890              :                     } else { // Horizontal reveal
   10891            6 :                         InsSillDepth = s_surf->SurfWinInsideSillDepth(SurfNum);
   10892            6 :                         TanAlpha = TanProfileAngVert;
   10893            6 :                         TanGamma = TanProfileAngHor;
   10894            6 :                         CosBeta = std::abs(CosBetaBottom);
   10895            6 :                         L = surf.Width;
   10896            6 :                         if (CosBetaBottom > 0.0) { // Bottom reveal surfaces may be illuminated
   10897            6 :                             d2 = InsSillDepth + 0.5 * GlazingThickness;
   10898            6 :                             InsideRevealSolAbs = s_surf->SurfWinInsideSillSolAbs(SurfNum);
   10899              :                         } else { // Top reveal surfaces may be illuminated
   10900            0 :                             d2 = InsReveal + 0.5 * GlazingThickness;
   10901            0 :                             InsideRevealSolAbs = s_surf->SurfWinInsideRevealSolAbs(SurfNum);
   10902              :                         }
   10903            6 :                         d2prime = d1 + d2 - H / TanGamma;
   10904              :                     }
   10905           12 :                     if (d2prime < 0.0) d2prime = 0.0; // No shadow from opposing reveal
   10906           12 :                     d12 = d1 + d2 - d2prime;
   10907              : 
   10908           12 :                     if (FrameWidth <= 0.001) {
   10909              :                         // Window without frame
   10910              : 
   10911              :                         // Find inside and outside shadowed area of vertical or horizontal reveal surfaces
   10912              :                         // that can be illuminated by beam solar; shadowing is by other reveal surfaces.
   10913              : 
   10914            0 :                         if (d2prime <= d2) {
   10915            0 :                             if (d12 * TanAlpha <= L) {
   10916            0 :                                 A1sh = 0.5 * TanAlpha * pow_2(d1);
   10917            0 :                                 A2sh = d2prime * L + 0.5 * TanAlpha * pow_2(d12) - A1sh;
   10918              :                             } else { // d12*TanAlpha > L
   10919            0 :                                 if (d1 * TanAlpha <= L) {
   10920            0 :                                     A1sh = 0.5 * TanAlpha * pow_2(d1);
   10921            0 :                                     A2sh = d2 * L - 0.5 * TanAlpha * pow_2(L / TanAlpha - d1);
   10922              :                                 } else { // d1*TanAlpha > L
   10923            0 :                                     A1sh = d1 * L - (0.5 / TanAlpha) * pow_2(L);
   10924            0 :                                     A2sh = d2 * L;
   10925              :                                 }
   10926              :                             }
   10927              :                         } else { // d2prime > d2
   10928            0 :                             A2sh = d2 * L;
   10929            0 :                             if (d2prime < d1 + d2) {
   10930            0 :                                 if (d12 * TanAlpha <= L) {
   10931            0 :                                     A1sh = L * (d2prime - d2) + 0.5 * TanAlpha * pow_2(d12);
   10932              :                                 } else { // d12*TanAlpha > L
   10933            0 :                                     A1sh = d1 * L - 0.5 * pow_2(L) / TanAlpha;
   10934              :                                 }
   10935              :                             } else { // d2prime >= d1+d2
   10936            0 :                                 A1sh = d1 * L;
   10937              :                             }
   10938              :                         }
   10939              : 
   10940              :                         // Added TH. 5/27/2009
   10941            0 :                         if (A1sh < 0.0) A1sh = 0.0;
   10942            0 :                         if (A2sh < 0.0) A2sh = 0.0;
   10943              : 
   10944            0 :                         if (OutsReveal >= 0.001) A1ill = d1 * L - A1sh; // A1ill = 0.0 if OutsReveal < 0.001
   10945            0 :                         if (InsReveal >= 0.001) A2ill = d2 * L - A2sh;  // A2ill = 0.0 if InsReveal < 0.001
   10946              : 
   10947              :                     } else { // Window with frame; take into account shadowing
   10948              :                         // of inside reveal surfaces by frame
   10949           12 :                         f1 = d1 - P1;
   10950           12 :                         f2 = d2 - P2;
   10951           12 :                         d2prime2 = FrameWidth / TanGamma;
   10952           12 :                         if (HorVertReveal == 1) { // Vertical reveal
   10953            6 :                             if (InsReveal + 0.5 * GlazingThickness <= P2) d2 = P2 + 0.001;
   10954              :                         } else {                       // Horizontal
   10955            6 :                             if (CosBetaBottom > 0.0) { // Bottom reveal surfaces may be illuminated
   10956            6 :                                 if (InsSillDepth + 0.5 * GlazingThickness <= P2) d2 = P2 + 0.001;
   10957              :                             } else { // Top reveal surfaces may be illuminated
   10958            0 :                                 if (InsReveal + 0.5 * GlazingThickness <= P2) d2 = P2 + 0.001;
   10959              :                             }
   10960              :                         }
   10961              : 
   10962           12 :                         if (d2prime <= f2) { // Shadow from opposing reveal does not go beyond inside surface of frame
   10963              : 
   10964           10 :                             if (d12 * TanAlpha <= L) {
   10965            5 :                                 A1sh = 0.5 * TanAlpha * pow_2(f1);
   10966            5 :                                 L1 = f1 * (f1 * TanAlpha / (6.0 * L) + 0.5);
   10967            5 :                                 if (d2 - (d2prime + d2prime2 + P2) >= 0.0) {
   10968            5 :                                     A2sh = (d2prime + d2prime2) * L + 0.5 * TanAlpha * (pow_2(d1 + d2 - d2prime) - pow_2(d1 + P2 + d2prime2));
   10969            5 :                                     L2 = d2prime2 + 0.5 * (d2 - (d2prime + d2prime2 + P2));
   10970              :                                 } else { // d2-(d2prime+d2prime2+P2) < 0.  ! Inside reveal is fully shadowed by
   10971              :                                          // frame and/or opposing reveal
   10972            0 :                                     A2sh = f2 * L;
   10973            0 :                                     L2 = f2;
   10974              :                                 }
   10975              :                             } else { // d12*TanAlpha >= L
   10976            5 :                                 if ((d1 + P2) * TanAlpha <= L) {
   10977            5 :                                     A1sh = 0.5 * TanAlpha * pow_2(f1);
   10978            5 :                                     L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
   10979            5 :                                     if ((d1 + P2 + d2prime2) * TanAlpha >= L) {
   10980            0 :                                         A2sh = f2 * L;
   10981            0 :                                         L2 = f2;
   10982              :                                     } else { // (d1+P2+d2prime2)*TanAlpha < L
   10983            5 :                                         A2sh = f2 * L - 0.5 * pow_2(L - (d1 + P2) * TanAlpha) / TanAlpha +
   10984            5 :                                                d2prime2 * (L - (d1 + P2 + d2prime2 / 2.0) * TanAlpha);
   10985            5 :                                         L2 = d2prime2 + (L / TanAlpha - (d1 + P2 + d2prime2)) / 3.0;
   10986              :                                     }
   10987              :                                 } else { // (d1+P2)*TanAlpha > L
   10988            0 :                                     L2 = f2;
   10989            0 :                                     A2sh = f2 * L;
   10990            0 :                                     if (f1 * TanAlpha <= L) {
   10991            0 :                                         A1sh = 0.5 * TanAlpha * pow_2(f1);
   10992            0 :                                         L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
   10993              :                                     } else { // f1*TanAlpha > L
   10994            0 :                                         A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
   10995            0 :                                         L1 = f1 - (L / TanAlpha) / 3.0;
   10996              :                                     }
   10997              :                                 }
   10998              :                             }
   10999              : 
   11000              :                         } else { // d2prime > f2   ! Shadow from opposing reveal goes beyond inside of frame
   11001              : 
   11002            2 :                             A2sh = f2 * L;
   11003            2 :                             L2 = f2;
   11004            2 :                             if (d2prime >= d1 + d2) {
   11005            0 :                                 A1sh = 0.0;
   11006            0 :                                 L1 = f1;
   11007              :                             } else { // d2prime < d1+d2
   11008            2 :                                 if (d2prime <= d2 + P1) {
   11009            2 :                                     if (f1 * TanAlpha <= L) {
   11010            2 :                                         A1sh = 0.5 * TanAlpha * pow_2(f1);
   11011            2 :                                         L1 = f1 * ((f1 * TanAlpha) / (6.0 * L) + 0.5);
   11012              :                                     } else { // f1*TanAlpha > L
   11013            0 :                                         A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
   11014            0 :                                         L1 = f1 - (L / TanAlpha) / 3.0;
   11015              :                                     }
   11016              :                                 } else { // d2prime > d2+P1
   11017            0 :                                     if (d12 * TanAlpha <= L) {
   11018            0 :                                         A1sh = L * (d2prime - (d2 + P1)) + 0.5 * TanAlpha * pow_2(d12);
   11019            0 :                                         L1 = (L * (f1 - d12 / 2.0) - d12 * TanAlpha * (f1 / 2 - d12 / 3.0)) / (L - d12 * TanAlpha / 2.0);
   11020              :                                     } else { // d12*TanAlpha > L
   11021            0 :                                         A1sh = f1 * L - 0.5 * pow_2(L) / TanAlpha;
   11022            0 :                                         L1 = f1 - (L / TanAlpha) / 3.0;
   11023              :                                     }
   11024              :                                 }
   11025              :                             }
   11026              :                         }
   11027              : 
   11028              :                         // Added TH. 5/27/2009
   11029           12 :                         if (A1sh < 0.0) A1sh = 0.0;
   11030           12 :                         if (A2sh < 0.0) A2sh = 0.0;
   11031              : 
   11032           12 :                         if (OutsReveal >= P1 + 0.5 * GlazingThickness + 0.001) A1ill = L * f1 - A1sh;
   11033           12 :                         if (InsReveal >= P2 + 0.5 * GlazingThickness + 0.001) A2ill = L * f2 - A2sh;
   11034           12 :                         if (L1 == 0.0) {
   11035            0 :                             FracToGlassOuts = 0.0;
   11036              :                         } else {
   11037           12 :                             FracToGlassOuts = 0.5 * (1.0 - std::atan(FrameWidth / L1) / Constant::PiOvr2);
   11038              :                         }
   11039           12 :                         if (L2 == 0.0) {
   11040            0 :                             FracToGlassIns = 0.0;
   11041              :                         } else {
   11042           12 :                             FracToGlassIns = 0.5 * (1.0 - std::atan(FrameWidth / L2) / Constant::PiOvr2);
   11043              :                         }
   11044              :                     } // End of check if window has frame
   11045              : 
   11046              :                     // Added TH. 5/27/2009
   11047           12 :                     if (A1ill < 0.0) A1ill = 0.0;
   11048           12 :                     if (A2ill < 0.0) A2ill = 0.0;
   11049              : 
   11050              :                     // Quantities related to outside reveal
   11051           12 :                     if (A1ill > Constant::OneMillionth) {
   11052              : 
   11053            0 :                         s_surf->SurfWinBmSolAbsdOutsReveal(SurfNum) +=
   11054            0 :                             A1ill * s_surf->SurfWinOutsideRevealSolAbs(SurfNum) * CosBeta * tmp_SunlitFracWithoutReveal;
   11055              : 
   11056            0 :                         BmSolRefldOutsReveal = A1ill * (1.0 - s_surf->SurfWinOutsideRevealSolAbs(SurfNum)) * CosBeta * tmp_SunlitFracWithoutReveal;
   11057              : 
   11058            0 :                         s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) += state.dataEnvrn->BeamSolarRad * BmSolRefldOutsReveal;
   11059            0 :                         s_surf->SurfWinBmSolRefldOutsRevealRepEnergy(SurfNum) =
   11060            0 :                             s_surf->SurfWinBmSolRefldOutsRevealReport(SurfNum) * state.dataGlobal->TimeStepZoneSec;
   11061              : 
   11062              :                         // Reflected solar from outside horizontal and vertical reveal incident on glazing
   11063            0 :                         s_surf->SurfWinOutsRevealDiffOntoGlazing(SurfNum) += FracToGlassOuts * BmSolRefldOutsReveal / surf.Area;
   11064              : 
   11065            0 :                         if (FrameWidth > 0.0) {
   11066              :                             // Reflected solar from outside horizontal and vertical reveal incident on frame
   11067            0 :                             s_surf->SurfWinOutsRevealDiffOntoFrame(SurfNum) +=
   11068            0 :                                 (0.5 - FracToGlassOuts) * BmSolRefldOutsReveal / s_surf->SurfWinFrameArea(SurfNum);
   11069              :                         }
   11070              : 
   11071              :                     } // End of check if A1ill > 0.0 (actually 10^-6)
   11072              : 
   11073              :                     // Quantities related to inside reveal; inside reveal reflection/absorption is assumed
   11074              :                     // to occur only if an interior shade or blind is not in place.
   11075              : 
   11076           12 :                     if (NOT_SHADED(ShadeFlag) || ShadeFlag == WinShadingType::SwitchableGlazing) {
   11077              : 
   11078           12 :                         if (A2ill > Constant::OneMillionth) {
   11079              : 
   11080           10 :                             DiffReflGlass = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   11081           10 :                             if (ShadeFlag == WinShadingType::SwitchableGlazing) {
   11082            0 :                                 auto const &thisConstructSh = state.dataConstruction->Construct(ConstrNumSh);
   11083              :                                 SolTransGlassSh =
   11084            0 :                                     Window::POLYF(state.dataHeatBal->SurfCosIncAng(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum),
   11085            0 :                                                   thisConstructSh.TransSolBeamCoef);
   11086            0 :                                 SolTransGlass = Window::InterpSw(s_surf->SurfWinSwitchingFactor(SurfNum), SolTransGlass, SolTransGlassSh);
   11087            0 :                                 DiffReflGlassSh = thisConstructSh.ReflectSolDiffBack;
   11088            0 :                                 DiffReflGlass = Window::InterpSw(s_surf->SurfWinSwitchingFactor(SurfNum), DiffReflGlass, DiffReflGlassSh);
   11089              :                             }
   11090              : 
   11091              :                             // Calc beam solar absorbed (m2)
   11092           10 :                             s_surf->SurfWinBmSolAbsdInsReveal(SurfNum) +=
   11093           10 :                                 A2ill * SolTransGlass * InsideRevealSolAbs * CosBeta * tmp_SunlitFracWithoutReveal;
   11094              : 
   11095              :                             // Added TH 5/26/2009 for reporting purpose - Beam solar absorbed by the inside reveal
   11096              :                             // (W)
   11097           10 :                             s_surf->SurfWinBmSolAbsdInsRevealReport(SurfNum) +=
   11098           10 :                                 state.dataEnvrn->BeamSolarRad * A2ill * SolTransGlass * InsideRevealSolAbs * CosBeta * tmp_SunlitFracWithoutReveal;
   11099              : 
   11100              :                             // in m2 = Area * solar transmitted fraction * inside reveal reflection fraction
   11101           10 :                             BmSolRefldInsReveal = A2ill * SolTransGlass * (1.0 - InsideRevealSolAbs) * CosBeta * tmp_SunlitFracWithoutReveal;
   11102              : 
   11103           10 :                             s_surf->SurfWinBmSolRefldInsReveal(SurfNum) += BmSolRefldInsReveal;
   11104              : 
   11105           10 :                             s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) +=
   11106           10 :                                 state.dataEnvrn->BeamSolarRad * BmSolRefldInsReveal; // W, BeamSolarRad in W/m2
   11107           10 :                             s_surf->SurfWinBmSolRefldInsRevealRepEnergy(SurfNum) =
   11108           10 :                                 s_surf->SurfWinBmSolRefldInsRevealReport(SurfNum) * state.dataGlobal->TimeStepZoneSec;
   11109              : 
   11110              :                             // Reflected solar from inside horizontal and vertical reveal incident on glazing
   11111           10 :                             s_surf->SurfWinInsRevealDiffOntoGlazing(SurfNum) += FracToGlassIns * BmSolRefldInsReveal / surf.Area;
   11112              : 
   11113              :                             // Added TH 5/26/2009 for reporting purpose - diffuse on window glass from inside
   11114              :                             // reveal (W)
   11115           10 :                             s_surf->SurfWinInsRevealDiffOntoGlazingReport(SurfNum) +=
   11116           10 :                                 state.dataEnvrn->BeamSolarRad * FracToGlassIns * BmSolRefldInsReveal;
   11117              : 
   11118              :                             // Reflected solar from inside horizontal and vertical reveal incident on frame
   11119           10 :                             if (FrameWidth > 0.0) {
   11120           10 :                                 s_surf->SurfWinInsRevealDiffOntoFrame(SurfNum) +=
   11121           10 :                                     (0.5 - FracToGlassIns) * BmSolRefldInsReveal / s_surf->SurfWinFrameArea(SurfNum);
   11122              : 
   11123              :                                 // Added TH 5/26/2009 for reporting purpose - diffuse on window frame from inside
   11124              :                                 // reveal (W)
   11125           10 :                                 s_surf->SurfWinInsRevealDiffOntoFrameReport(SurfNum) +=
   11126           10 :                                     state.dataEnvrn->BeamSolarRad * (0.5 - FracToGlassIns) * BmSolRefldInsReveal;
   11127              :                             }
   11128              : 
   11129              :                             // Reflected solar from inside reveal going directly into zone and reflected from
   11130              :                             // glass. Assumes half of solar reflected from inside reveal goes as diffuse radiation
   11131              :                             // into the zone and half goes as diffuse radiation towards window.
   11132           10 :                             s_surf->SurfWinInsRevealDiffIntoZone(SurfNum) += BmSolRefldInsReveal * (0.5 + DiffReflGlass * FracToGlassIns);
   11133              : 
   11134              :                             // Added TH 5/26/2009 for reporting purpose - diffuse into zone from inside reveal (W)
   11135           10 :                             s_surf->SurfWinInsRevealDiffIntoZoneReport(SurfNum) +=
   11136           10 :                                 state.dataEnvrn->BeamSolarRad * BmSolRefldInsReveal * (0.5 + DiffReflGlass * FracToGlassIns);
   11137              : 
   11138              :                         } // End of check if A2ill > 0.0 (actually 10^-6)
   11139              : 
   11140              :                     } // End of check if interior shade or blind is in place
   11141              : 
   11142              :                 } // End of loop over vertical and horizontal reveal
   11143              : 
   11144              :             } // End of surface loop
   11145              :         }
   11146              :     }
   11147            3 : }
   11148              : 
   11149       249964 : void ReportSurfaceShading(EnergyPlusData &state)
   11150              : {
   11151              : 
   11152              :     // SUBROUTINE INFORMATION:
   11153              :     //       AUTHOR         Linda Lawrie
   11154              :     //       DATE WRITTEN   April 2000
   11155              :     //       MODIFIED       na
   11156              :     //       RE-ENGINEERED  na
   11157              : 
   11158              :     // PURPOSE OF THIS SUBROUTINE:
   11159              :     // This subroutine uses the internal variables used in the Shading
   11160              :     // calculations and prepares them for reporting (at timestep level).
   11161              : 
   11162              :     // METHODOLOGY EMPLOYED:
   11163              :     // Because all of the calculations are done on a "daily" basis in this
   11164              :     // module, it is difficult to formulate the values that might be useful
   11165              :     // for reporting.  SunlitFrac was the first of these two arrays to be
   11166              :     // made into "two dimensions".  It is not clear that both have to be
   11167              :     // two dimensions.
   11168              : 
   11169              :     // REFERENCES:
   11170              :     // na
   11171              : 
   11172              :     // Using/Aliasing
   11173              :     using namespace OutputReportPredefined;
   11174              : 
   11175              :     // Locals
   11176              :     // SUBROUTINE ARGUMENT DEFINITIONS:
   11177              :     // na
   11178              : 
   11179              :     // SUBROUTINE PARAMETER DEFINITIONS:
   11180              :     // na
   11181              : 
   11182              :     // INTERFACE BLOCK SPECIFICATIONS
   11183              :     // na
   11184              : 
   11185              :     // DERIVED TYPE DEFINITIONS
   11186              :     // na
   11187              : 
   11188              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   11189              :     int SurfNum; // Loop Counter
   11190              :     int RepCol;  // the column of the predefined report
   11191              : 
   11192       249964 :     auto &s_surf = state.dataSurface;
   11193      2359397 :     for (SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
   11194      2109433 :         auto &surf = s_surf->Surface(SurfNum);
   11195              : 
   11196      2109433 :         s_surf->SurfSunlitFrac(SurfNum) = state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum);
   11197      2109433 :         s_surf->SurfSunlitArea(SurfNum) =
   11198      2109433 :             state.dataHeatBal->SurfSunlitFrac(state.dataGlobal->HourOfDay, state.dataGlobal->TimeStep, SurfNum) * surf.Area;
   11199              :     }
   11200              :     // added for predefined reporting
   11201       249964 :     RepCol = 0;
   11202       249964 :     if (state.dataEnvrn->Month == 3 && state.dataEnvrn->DayOfMonth == 21) {
   11203            0 :         if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
   11204            0 :             RepCol = state.dataOutRptPredefined->pdchSlfMar21_9;
   11205            0 :         } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
   11206            0 :             RepCol = state.dataOutRptPredefined->pdchSlfMar21_12;
   11207            0 :         } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
   11208            0 :             RepCol = state.dataOutRptPredefined->pdchSlfMar21_15;
   11209              :         }
   11210       249964 :     } else if (state.dataEnvrn->Month == 6 && state.dataEnvrn->DayOfMonth == 21) {
   11211            0 :         if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
   11212            0 :             RepCol = state.dataOutRptPredefined->pdchSlfJun21_9;
   11213            0 :         } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
   11214            0 :             RepCol = state.dataOutRptPredefined->pdchSlfJun21_12;
   11215            0 :         } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
   11216            0 :             RepCol = state.dataOutRptPredefined->pdchSlfJun21_15;
   11217              :         }
   11218       249964 :     } else if (state.dataEnvrn->Month == 12 && state.dataEnvrn->DayOfMonth == 21) {
   11219        73882 :         if ((state.dataGlobal->HourOfDay == 9) && (state.dataGlobal->TimeStep == 4)) {
   11220          472 :             RepCol = state.dataOutRptPredefined->pdchSlfDec21_9;
   11221        73410 :         } else if ((state.dataGlobal->HourOfDay == 12) && (state.dataGlobal->TimeStep == 4)) {
   11222          472 :             RepCol = state.dataOutRptPredefined->pdchSlfDec21_12;
   11223        72938 :         } else if ((state.dataGlobal->HourOfDay == 15) && (state.dataGlobal->TimeStep == 4)) {
   11224          472 :             RepCol = state.dataOutRptPredefined->pdchSlfDec21_15;
   11225              :         }
   11226              :     }
   11227       249964 :     if (RepCol != 0) {
   11228         9936 :         for (SurfNum = 1; SurfNum <= s_surf->TotSurfaces; ++SurfNum) {
   11229         8520 :             auto &surf = s_surf->Surface(SurfNum);
   11230         8520 :             if (surf.Class == SurfaceClass::Window) {
   11231           24 :                 PreDefTableEntry(state, RepCol, surf.Name, s_surf->SurfSunlitFrac(SurfNum));
   11232              :             }
   11233              :         }
   11234              :     }
   11235       249964 : }
   11236              : 
   11237           26 : void ReportSurfaceErrors(EnergyPlusData &state)
   11238              : {
   11239              : 
   11240              :     // SUBROUTINE INFORMATION:
   11241              :     //       AUTHOR         Linda Lawrie
   11242              :     //       DATE WRITTEN   November 2004
   11243              :     //       MODIFIED       na
   11244              :     //       RE-ENGINEERED  na
   11245              : 
   11246              :     // PURPOSE OF THIS SUBROUTINE:
   11247              :     // This subroutine reports some recurring type errors that can get mixed up with more important
   11248              :     // errors in the error file.
   11249              : 
   11250              :     using namespace DataErrorTracking; // for error tracking
   11251              : 
   11252           26 :     static Array1D_string const MSG(4, {"misses", "", "within", "overlaps"});
   11253              : 
   11254              :     int Loop1;
   11255              :     int Loop2;
   11256              :     int Count;
   11257              :     int TotCount;
   11258           26 :     Array1D_bool SurfErrorReported;
   11259           26 :     Array1D_bool SurfErrorReported2;
   11260              : 
   11261           26 :     auto &s_surf = state.dataSurface;
   11262              : 
   11263           26 :     if (state.dataSolarShading->NumTooManyFigures + state.dataSolarShading->NumTooManyVertices + state.dataSolarShading->NumBaseSubSurround > 0) {
   11264            0 :         ShowMessage(state, "");
   11265            0 :         ShowMessage(state, "===== Recurring Surface Error Summary =====");
   11266            0 :         ShowMessage(state, "The following surface error messages occurred.");
   11267            0 :         ShowMessage(state, "");
   11268              : 
   11269            0 :         if (state.dataSolarShading->NumBaseSubSurround > 0) {
   11270            0 :             ShowMessage(state, "Base Surface does not surround subsurface errors occurring...");
   11271            0 :             ShowMessage(state,
   11272              :                         "Check that the GlobalGeometryRules object is expressing the proper starting corner and "
   11273              :                         "direction [CounterClockwise/Clockwise]");
   11274            0 :             ShowMessage(state, "");
   11275              :         }
   11276              : 
   11277            0 :         SurfErrorReported.dimension(s_surf->TotSurfaces, false);
   11278            0 :         TotCount = 0;
   11279            0 :         for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumBaseSubSurround; ++Loop1) {
   11280            0 :             Count = 0;
   11281            0 :             if (SurfErrorReported(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1)) continue;
   11282            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumBaseSubSurround; ++Loop2) {
   11283            0 :                 if (state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1 ==
   11284            0 :                         state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex1 &&
   11285            0 :                     state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex == state.dataSolarShading->TrackBaseSubSurround(Loop2).MiscIndex) {
   11286            0 :                     ++Count;
   11287              :                 }
   11288              :             }
   11289            0 :             TotCount += Count;
   11290            0 :             state.dataErrTracking->TotalWarningErrors += Count - 1;
   11291            0 :             ShowWarningError(state,
   11292            0 :                              format("Base surface does not surround subsurface (CHKSBS), Overlap Status={}",
   11293            0 :                                     state.dataSolarShading->cOverLapStatus(state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex)));
   11294            0 :             ShowContinueError(state, format("  The base surround errors occurred {} times.", Count));
   11295            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumBaseSubSurround; ++Loop2) {
   11296            0 :                 if (state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1 ==
   11297            0 :                         state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex1 &&
   11298            0 :                     state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex == state.dataSolarShading->TrackBaseSubSurround(Loop2).MiscIndex) {
   11299            0 :                     ShowContinueError(state,
   11300            0 :                                       format("Surface \"{}\" {} SubSurface \"{}\"",
   11301            0 :                                              s_surf->Surface(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1).Name,
   11302            0 :                                              MSG(state.dataSolarShading->TrackBaseSubSurround(Loop1).MiscIndex),
   11303            0 :                                              s_surf->Surface(state.dataSolarShading->TrackBaseSubSurround(Loop2).SurfIndex2).Name));
   11304              :                 }
   11305              :             }
   11306            0 :             SurfErrorReported(state.dataSolarShading->TrackBaseSubSurround(Loop1).SurfIndex1) = true;
   11307              :         }
   11308            0 :         if (TotCount > 0) {
   11309            0 :             ShowMessage(state, "");
   11310            0 :             ShowContinueError(state, format("  The base surround errors occurred {} times (total).", TotCount));
   11311            0 :             ShowMessage(state, "");
   11312              :         }
   11313              : 
   11314            0 :         SurfErrorReported2.allocate(s_surf->TotSurfaces);
   11315            0 :         SurfErrorReported = false;
   11316            0 :         TotCount = 0;
   11317            0 :         if (state.dataSolarShading->NumTooManyVertices > 0) {
   11318            0 :             ShowMessage(state, format("Too many vertices [>={}] in shadow overlap errors occurring...", state.dataSolarShading->MaxHCV));
   11319            0 :             ShowMessage(state,
   11320              :                         "These occur throughout the year and may occur several times for the same surfaces. You "
   11321              :                         "may be able to reduce them by "
   11322              :                         "adding Output:Diagnostics,DoNotMirrorDetachedShading;");
   11323              :         }
   11324            0 :         for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumTooManyVertices; ++Loop1) {
   11325            0 :             Count = 0;
   11326            0 :             SurfErrorReported2 = false;
   11327            0 :             if (SurfErrorReported(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1)) continue;
   11328            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyVertices; ++Loop2) {
   11329            0 :                 if (state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1 ==
   11330            0 :                     state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex1) {
   11331            0 :                     ++Count;
   11332              :                 }
   11333              :             }
   11334            0 :             TotCount += Count;
   11335            0 :             state.dataErrTracking->TotalWarningErrors += Count - 1;
   11336            0 :             ShowMessage(state, "");
   11337            0 :             ShowWarningError(state, format("Too many vertices [>={}] in a shadow overlap", state.dataSolarShading->MaxHCV));
   11338            0 :             ShowContinueError(state,
   11339            0 :                               format("Overlapping figure={}, Surface Class=[{}]",
   11340            0 :                                      s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1).Name,
   11341            0 :                                      cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1).Class)));
   11342            0 :             ShowContinueError(state, format("  This error occurred {} times.", Count));
   11343            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyVertices; ++Loop2) {
   11344            0 :                 if (state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1 ==
   11345            0 :                     state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex1) {
   11346            0 :                     if (SurfErrorReported2(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2)) continue;
   11347            0 :                     ShowContinueError(state,
   11348            0 :                                       format("Figure being Overlapped={}, Surface Class=[{}]",
   11349            0 :                                              s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2).Name,
   11350            0 :                                              cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2).Class)));
   11351            0 :                     SurfErrorReported2(state.dataSolarShading->TrackTooManyVertices(Loop2).SurfIndex2) = true;
   11352              :                 }
   11353              :             }
   11354            0 :             SurfErrorReported(state.dataSolarShading->TrackTooManyVertices(Loop1).SurfIndex1) = true;
   11355              :         }
   11356            0 :         if (TotCount > 0) {
   11357            0 :             ShowMessage(state, "");
   11358            0 :             ShowContinueError(state, format("  The too many vertices errors occurred {} times (total).", TotCount));
   11359            0 :             ShowMessage(state, "");
   11360              :         }
   11361              : 
   11362            0 :         SurfErrorReported = false;
   11363            0 :         TotCount = 0;
   11364            0 :         if (state.dataSolarShading->NumTooManyFigures > 0) {
   11365            0 :             ShowMessage(state, format("Too many figures [>={}] in shadow overlap errors occurring...", state.dataSolarShading->MaxHCS));
   11366            0 :             ShowMessage(state,
   11367              :                         "These occur throughout the year and may occur several times for the same surfaces. You "
   11368              :                         "may be able to reduce them by "
   11369              :                         "adding OutputDiagnostics,DoNotMirrorDetachedShading;");
   11370              :         }
   11371            0 :         for (Loop1 = 1; Loop1 <= state.dataSolarShading->NumTooManyFigures; ++Loop1) {
   11372            0 :             Count = 0;
   11373            0 :             SurfErrorReported2 = false;
   11374            0 :             if (SurfErrorReported(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1)) continue;
   11375            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyFigures; ++Loop2) {
   11376            0 :                 if (state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1 == state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex1) {
   11377            0 :                     ++Count;
   11378              :                 }
   11379              :             }
   11380            0 :             TotCount += Count;
   11381            0 :             state.dataErrTracking->TotalWarningErrors += Count - 1;
   11382            0 :             ShowMessage(state, "");
   11383            0 :             ShowWarningError(state, format("Too many figures [>={}] in a shadow overlap", state.dataSolarShading->MaxHCS));
   11384            0 :             ShowContinueError(state,
   11385            0 :                               format("Overlapping figure={}, Surface Class=[{}]",
   11386            0 :                                      s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1).Name,
   11387            0 :                                      cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1).Class)));
   11388            0 :             ShowContinueError(state, format("  This error occurred {} times.", Count));
   11389            0 :             for (Loop2 = 1; Loop2 <= state.dataSolarShading->NumTooManyFigures; ++Loop2) {
   11390            0 :                 if (state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1 == state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex1) {
   11391            0 :                     if (SurfErrorReported2(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2)) continue;
   11392            0 :                     ShowContinueError(state,
   11393            0 :                                       format("Figure being Overlapped={}, Surface Class=[{}]",
   11394            0 :                                              s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2).Name,
   11395            0 :                                              cSurfaceClass(s_surf->Surface(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2).Class)));
   11396            0 :                     SurfErrorReported2(state.dataSolarShading->TrackTooManyFigures(Loop2).SurfIndex2) = true;
   11397              :                 }
   11398              :             }
   11399            0 :             SurfErrorReported(state.dataSolarShading->TrackTooManyFigures(Loop1).SurfIndex1) = true;
   11400              :         }
   11401            0 :         if (TotCount > 0) {
   11402            0 :             ShowMessage(state, "");
   11403            0 :             ShowContinueError(state, format("  The too many figures errors occurred {} times (total).", TotCount));
   11404            0 :             ShowMessage(state, "");
   11405              :         }
   11406            0 :         SurfErrorReported.deallocate();
   11407            0 :         SurfErrorReported2.deallocate();
   11408              :     }
   11409           26 : }
   11410              : 
   11411          114 : void ComputeWinShadeAbsorpFactors(EnergyPlusData &state)
   11412              : {
   11413              : 
   11414              :     // SUBROUTINE INFORMATION:
   11415              :     //       AUTHOR         Fred Winkelmann
   11416              :     //       DATE WRITTEN   Mar 2001
   11417              :     //       MODIFIED       Oct 2002,FCW: change ConstrNumSh =
   11418              :     //       WindowShadingControl(WinShadeCtrlNum)%ShadedConstruction
   11419              :     //                      to Surface(SurfNum)%ShadedConstruction
   11420              :     //       RE-ENGINEERED  na
   11421              : 
   11422              :     // PURPOSE OF THIS SUBROUTINE:
   11423              :     // Called by InitSolarCalculations. Finds fractions that apportion radiation absorbed by a
   11424              :     // window shade to the two faces of the shade. For radiation incident from the left,
   11425              :     // ShadeAbsFacFace(1) is the fraction of radiation absorbed in the left-hand half of the
   11426              :     // of the shade and ShadeAbsFacFace(2) is the fraction absorbed in the right-hand half.
   11427              :     // The shade is assumed to be homogeneous.
   11428              : 
   11429              :     // REFERENCES: See EnergyPlus engineering documentation
   11430              :     // USE STATEMENTS: na
   11431          114 :     auto &s_mat = state.dataMaterial;
   11432          114 :     auto &s_surf = state.dataSurface;
   11433              : 
   11434          247 :     for (int zoneNum = 1; zoneNum <= state.dataGlobal->NumOfZones; ++zoneNum) {
   11435          284 :         for (int spaceNum : state.dataHeatBal->Zone(zoneNum).spaceIndexes) {
   11436          151 :             auto &thisSpace = state.dataHeatBal->space(spaceNum);
   11437          151 :             int const firstSurfWin = thisSpace.WindowSurfaceFirst;
   11438          151 :             int const lastSurfWin = thisSpace.WindowSurfaceLast;
   11439          207 :             for (int SurfNum = firstSurfWin; SurfNum <= lastSurfWin; ++SurfNum) {
   11440           56 :                 auto &surf = s_surf->Surface(SurfNum);
   11441           56 :                 if (surf.Class == SurfaceClass::Window && surf.HasShadeControl) {
   11442            8 :                     int WinShadeCtrlNum = surf.activeWindowShadingControl; // Window shading control number
   11443              : 
   11444            8 :                     int MatNumSh = 0;       // Shade layer material number
   11445            8 :                     Real64 AbsorpEff = 0.0; // Effective absorptance of isolated shade layer (fraction of
   11446              :                     //  of incident radiation remaining after reflected portion is
   11447              :                     //  removed that is absorbed
   11448            8 :                     if (ANY_SHADE(s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType)) {
   11449            0 :                         int const ConstrNumSh = surf.activeShadedConstruction;                 // Window construction number with shade
   11450            0 :                         int TotLay = state.dataConstruction->Construct(ConstrNumSh).TotLayers; // Total layers in a construction
   11451              : 
   11452            0 :                         if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::IntShade) {
   11453            0 :                             MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(TotLay); // Interior shade
   11454            0 :                         } else if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::ExtShade) {
   11455            0 :                             MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(1); // Exterior shade
   11456            0 :                         } else if (s_surf->WindowShadingControl(WinShadeCtrlNum).ShadingType == WinShadingType::BGShade) {
   11457            0 :                             if (state.dataConstruction->Construct(ConstrNumSh).TotGlassLayers == 2) {
   11458              :                                 // Double pane with between-glass shade
   11459            0 :                                 MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(3);
   11460              :                             } else {
   11461              :                                 // Triple pane with between-glass shade
   11462            0 :                                 MatNumSh = state.dataConstruction->Construct(ConstrNumSh).LayerPoint(5);
   11463              :                             }
   11464              :                         }
   11465              : 
   11466            0 :                         auto const *matSh = s_mat->materials(MatNumSh);
   11467            0 :                         auto const *matFenSh = dynamic_cast<Material::MaterialFen const *>(matSh);
   11468            0 :                         assert(matFenSh != nullptr);
   11469            0 :                         AbsorpEff = matFenSh->AbsorpSolar / (matFenSh->AbsorpSolar + matFenSh->Trans + 0.0001);
   11470            0 :                         AbsorpEff = min(max(AbsorpEff, 0.0001),
   11471              :                                         0.999); // Constrain to avoid problems with following log eval
   11472            0 :                         s_surf->SurfWinShadeAbsFacFace1(SurfNum) = (1.0 - std::exp(0.5 * std::log(1.0 - AbsorpEff))) / AbsorpEff;
   11473            0 :                         s_surf->SurfWinShadeAbsFacFace2(SurfNum) = 1.0 - s_surf->SurfWinShadeAbsFacFace1(SurfNum);
   11474              :                     }
   11475              :                 }
   11476              :             }
   11477              :         }
   11478              :     }
   11479          114 : }
   11480              : 
   11481        71220 : void CalcWinTransDifSolInitialDistribution(EnergyPlusData &state)
   11482              : {
   11483              : 
   11484              :     // SUBROUTINE INFORMATION:
   11485              :     //       AUTHOR         Rob Hitchcock
   11486              :     //       DATE WRITTEN   July 2007
   11487              :     //       MODIFIED       N/A
   11488              :     //       RE-ENGINEERED  N/A
   11489              : 
   11490              :     // PURPOSE OF THIS SUBROUTINE:
   11491              :     // This subroutine calculates the initial distribution
   11492              :     // of diffuse solar transmitted through exterior windows
   11493              :     // to individual heat transfer surfaces in each zone(or enclosure).
   11494              : 
   11495              :     // METHODOLOGY EMPLOYED:
   11496              :     // Apportions diffuse solar transmitted through each exterior window
   11497              :     // that is then absorbed, reflected, and/or transmitted
   11498              :     // by other heat transfer surfaces in the zone.
   11499              :     // Calculations use:
   11500              :     // 1. WinDifSolar calculated in SUBROUTINE CalcInteriorSolarDistribution,
   11501              :     // 2. view factors between each exterior window and
   11502              :     // other heat transfer surfaces in a zone
   11503              :     // calculated in SUBROUTINE CalcApproximateViewFactors, and
   11504              :     // 3. surface absorptances, reflectances, and transmittances
   11505              :     // determined here using revised code from SUBROUTINE InitIntSolarDistribution
   11506              : 
   11507              :     // Using/Aliasing
   11508              :     using namespace DataViewFactorInformation;
   11509              :     using namespace DataWindowEquivalentLayer;
   11510              : 
   11511              :     Real64 AbsInt;               // Tmp var for Inside surface short-wave absorptance
   11512              :     Real64 InsideDifAbsorptance; // Inside diffuse solar absorptance of a surface
   11513              :     Real64 InsideDifReflectance; // Inside diffuse solar reflectance of a surface
   11514              :     int BlNum;                   // Blind number
   11515              :     Real64 BlAbsDiffBk;          // Glass layer back diffuse solar absorptance when blind in place
   11516              :     Real64 AbsDiffBkBl;          // Blind diffuse back solar absorptance as part of glazing system
   11517              : 
   11518              :     //  REAL(r64)    :: DividerSolAbs      ! Window divider solar absorptance
   11519              :     //  REAL(r64)    :: DividerSolRefl     ! Window divider solar reflectance
   11520              :     //  INTEGER :: MatNumGl           ! Glass layer material number
   11521              :     //  INTEGER :: MatNumSh           ! Shade layer material number
   11522              :     //  REAL(r64)    :: TransGl,ReflGl,AbsGl ! Glass layer solar transmittance, reflectance, absorptance
   11523              : 
   11524        71220 :     Real64 ViewFactor = 0.0;       // temp var for view factor
   11525              :                                    //        Real64 ViewFactorTotal;             // debug var for view factor total
   11526        71220 :     Real64 WinDifSolarTrans = 0.0; // debug var for WinDifSolar() [W]
   11527              :                                    //        Real64 WinDifSolarDistTotl;         // debug var for window total
   11528              :                                    //        distributed diffuse solar [W] Real64 WinDifSolarDistAbsorbedTotl; // debug
   11529              :                                    //        var for individual exterior window total distributed
   11530              :                                    //    diffuse solar absorbed [W]
   11531              :                                    //        Real64 WinDifSolarDistReflectedTotl; // debug var for individual exterior window total distributed
   11532              :                                    //    diffuse solar reflected [W]
   11533              :                                    //        Real64 WinDifSolarDistTransmittedTotl; // debug var for individual exterior window total distributed
   11534              :                                    //    diffuse solar transmitted [W]
   11535        71220 :     Real64 WinDifSolLayAbsW = 0.0; // temp var for diffuse solar absorbed by individual glass layer [W]
   11536              :                                    //        Real64 ZoneDifSolarTrans;               // debug var for WinDifSolar() [W]
   11537              :                                    //        Real64 ZoneDifSolarDistTotl;            // debug var for zone total
   11538              :                                    //        distributed diffuse solar [W] Real64 ZoneDifSolarDistAbsorbedTotl;    //
   11539              :                                    //        debug var for zone total distributed diffuse solar absorbed [W] Real64
   11540              :                                    //        ZoneDifSolarDistReflectedTotl;   // debug var for zone total distributed
   11541              :                                    //        diffuse solar reflected [W] Real64 ZoneDifSolarDistTransmittedTotl; //
   11542              :                                    //        debug var for zone total distributed diffuse solar transmitted [W]
   11543              : 
   11544        71220 :     Real64 DifSolarAbsW = 0.0;     // temp var for diffuse solar absorbed by surface [W]
   11545        71220 :     Real64 DifSolarAbs = 0.0;      // temp var for diffuse solar absorbed by surface [W/m2]
   11546        71220 :     Real64 DifSolarReflW = 0.0;    // temp var for diffuse solar reflected by surface [W]
   11547        71220 :     Real64 ShBlDifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by shade/blind [W]
   11548              : 
   11549        71220 :     Array2D<Real64> SurfWinAbsSolBeamEQL(2, CFSMAXNL + 1); // absorbed exterior beam radiation by layers fraction
   11550              :     Array2D<Real64> SurfWinAbsSolDiffEQL(2,
   11551        71220 :                                          CFSMAXNL + 1);        // absorbed exterior diffuse radiation by layers fraction
   11552        71220 :     Array2D<Real64> SurfWinAbsSolBeamBackEQL(2, CFSMAXNL + 1); // absorbed interior beam radiation by layers fraction from back
   11553        71220 :     Array2D<Real64> AbsSolDiffBackEQL(2, CFSMAXNL + 1);        // absorbed exterior diffuse radiation by layers fraction from back
   11554              :     int EQLNum;                                                // equivalent layer fenestration index
   11555              :     int Lay;                                                   // equivalent layer fenestration layer index
   11556              : 
   11557        71220 :     auto &s_surf = state.dataSurface;
   11558              : 
   11559              :     // Init accumulators for absorbed diffuse solar for all surfaces for later heat balance calcs
   11560        71220 :     state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs = 0.0;
   11561        71220 :     state.dataHeatBal->SurfWinInitialDifSolwinAbs = 0.0;
   11562              : 
   11563              :     // Init accumulator for total reflected diffuse solar within each zone for interreflection calcs
   11564        71220 :     state.dataHeatBal->EnclSolInitialDifSolReflW = 0.0;
   11565              : 
   11566              :     // Init accumulator for transmitted diffuse solar for all surfaces for reporting
   11567        71220 :     state.dataHeatBalSurf->SurfWinInitialDifSolInTrans = 0.0;
   11568              : 
   11569              :     // Loop over all zones doing initial distribution of diffuse solar to interior heat transfer surfaces
   11570       177270 :     for (int enclosureNum = 1; enclosureNum <= state.dataViewFactor->NumOfRadiantEnclosures; ++enclosureNum) {
   11571       106050 :         auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(enclosureNum);
   11572              :         // Init Zone accumulators for debugging
   11573              :         //            ZoneDifSolarTrans = 0.0;
   11574              :         //            ZoneDifSolarDistAbsorbedTotl = 0.0;
   11575              :         //            ZoneDifSolarDistReflectedTotl = 0.0;
   11576              :         //            ZoneDifSolarDistTransmittedTotl = 0.0;
   11577              :         // Loop over all diffuse solar transmitting surfaces (i.e., exterior windows and TDDs) in the current zone
   11578       719221 :         for (int const DifTransSurfNum : thisEnclosure.SurfacePtr) {
   11579              :             // Skip surfaces that are not exterior, except for TDD_Diffusers
   11580       613171 :             auto &difTransSurf = s_surf->Surface(DifTransSurfNum);
   11581       613171 :             if ((difTransSurf.ExtBoundCond != ExternalEnvironment) && (difTransSurf.ExtBoundCond != OtherSideCondModeledExt) &&
   11582       208431 :                 (difTransSurf.OriginalClass != SurfaceClass::TDD_Diffuser))
   11583       208431 :                 continue;
   11584              : 
   11585              :             // Do I need to do anything special for TDDs?
   11586              :             //                if ( SurfaceWindow( DifTransSurfNum ).OriginalClass == SurfaceClass::TDD_Diffuser )
   11587              :             //                {
   11588              :             //                }
   11589              : 
   11590              :             // Skip surfaces that are not exterior windows or TDD diffusers
   11591       404740 :             if (difTransSurf.Class != SurfaceClass::Window && difTransSurf.OriginalClass != SurfaceClass::TDD_Diffuser) continue;
   11592              : 
   11593              :             //----------------------------------------------------------------------------------------------------------
   11594              :             // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH EXTERIOR WINDOWS AND TDDS TO INTERIOR HEAT TRANSFER
   11595              :             // SURFACES
   11596              :             //----------------------------------------------------------------------------------------------------------
   11597              : 
   11598              :             // Init transmitted solar debug vars
   11599              :             //                ViewFactorTotal = 0.0;
   11600        31114 :             WinDifSolarTrans = s_surf->SurfWinDifSolar(DifTransSurfNum);
   11601              :             //                ZoneDifSolarTrans += WinDifSolarTrans;
   11602              : 
   11603              :             // Init Exterior Window accumulators for debugging
   11604              :             //                WinDifSolarDistAbsorbedTotl = 0.0;
   11605              :             //                WinDifSolarDistReflectedTotl = 0.0;
   11606              :             //                WinDifSolarDistTransmittedTotl = 0.0;
   11607              : 
   11608              :             // Loop over all heat transfer surfaces in the current zone that might receive diffuse solar
   11609       425000 :             for (int const HeatTransSurfNum : thisEnclosure.SurfacePtr) {
   11610              :                 // Skip surfaces that are not heat transfer surfaces
   11611              :                 // Skip tubular daylighting device domes
   11612       393886 :                 auto &surf = s_surf->Surface(HeatTransSurfNum);
   11613              : 
   11614       393886 :                 if (surf.Class == SurfaceClass::TDD_Dome) continue;
   11615              : 
   11616              :                 // View factor from current (sending) window DifTransSurfNum to current (receiving) surface
   11617              :                 // HeatTransSurfNum
   11618       393886 :                 int const HTenclosureSurfNum = surf.SolarEnclSurfIndex; // HT surface index for EnclSolInfo.SurfacePtr and F arrays
   11619       393886 :                 int const enclosureNum = surf.SolarEnclIndex;           // index for EnclSolInfo
   11620              :                 int const DTenclSurfNum =
   11621       393886 :                     s_surf->Surface(DifTransSurfNum).SolarEnclSurfIndex; // Window surface index for EnclSolInfo.SurfacePtr and F arrays
   11622              : 
   11623       393886 :                 ViewFactor = state.dataViewFactor->EnclSolInfo(enclosureNum).F(HTenclosureSurfNum, DTenclSurfNum);
   11624              :                 // debug ViewFactorTotal
   11625              :                 //                    ViewFactorTotal += ViewFactor; // debug
   11626              : 
   11627              :                 // Skip receiving surfaces with 0.0 view factor
   11628       393886 :                 if (ViewFactor <= 0.0) continue;
   11629              : 
   11630       297136 :                 Real64 const WinDifSolarTrans_Factor(WinDifSolarTrans * ViewFactor);
   11631       297136 :                 Real64 const win_SwitchingFactor(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum));
   11632       297136 :                 Real64 const per_HTSurfaceArea(1.0 / surf.Area);
   11633              : 
   11634              :                 // Calculate diffuse solar from current exterior window absorbed and reflected by current heat
   11635              :                 // transfer surface And calculate transmitted diffuse solar to adjacent zones through interior
   11636              :                 // windows
   11637       297136 :                 int const ConstrNum = s_surf->SurfActiveConstruction(HeatTransSurfNum);
   11638       297136 :                 if (state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) { // Interior Opaque Surface
   11639              : 
   11640              :                     // Determine the inside (back) diffuse solar absorptance
   11641              :                     // and reflectance of the current heat transfer surface
   11642       219812 :                     InsideDifAbsorptance = state.dataHeatBalSurf->SurfAbsSolarInt(HeatTransSurfNum);
   11643              :                     // Inside (back) diffuse solar reflectance is assumed to be 1 - absorptance
   11644       219812 :                     InsideDifReflectance = 1.0 - InsideDifAbsorptance;
   11645              : 
   11646              :                     // Absorbed diffuse solar [W] = current window transmitted diffuse solar [W]
   11647              :                     //    * view factor from current (sending) window DifTransSurfNum to current (receiving)
   11648              :                     //    surface HeatTransSurfNum
   11649              :                     //    * current surface inside solar absorptance
   11650       219812 :                     DifSolarAbsW = WinDifSolarTrans_Factor * InsideDifAbsorptance; // [W]
   11651              : 
   11652              :                     // Absorbed diffuse solar [W/m2] = Absorbed diffuse solar [W]
   11653              :                     //                                 / current surface net area
   11654       219812 :                     DifSolarAbs = DifSolarAbsW * per_HTSurfaceArea;
   11655              : 
   11656              :                     // Accumulate absorbed diffuse solar [W/m2] on this surface for heat balance calcs
   11657       219812 :                     state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs(HeatTransSurfNum) += DifSolarAbs;
   11658              : 
   11659              :                     // Reflected diffuse solar [W] = current window transmitted diffuse solar
   11660              :                     //    * view factor from current (sending) window DifTransSurfNum to current (receiving)
   11661              :                     //    surface HeatTransSurfNum
   11662              :                     //    * current window inside solar reflectance
   11663       219812 :                     DifSolarReflW = WinDifSolarTrans_Factor * InsideDifReflectance;
   11664              : 
   11665              :                     // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   11666              :                     // interreflection calcs
   11667       219812 :                     state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
   11668              : 
   11669              :                     // Accumulate Window and Zone total distributed diffuse solar to check for conservation of
   11670              :                     // energy For opaque surfaces all incident diffuse is either absorbed or reflected
   11671              : 
   11672              :                 } else { // Exterior or Interior Window
   11673        77324 :                     int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(HeatTransSurfNum);
   11674        77324 :                     int TotGlassLayers = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
   11675        77324 :                     WinShadingType ShadeFlag = s_surf->SurfWinShadingFlag(HeatTransSurfNum);
   11676              : 
   11677        77324 :                     if (s_surf->SurfWinWindowModelType(HeatTransSurfNum) != WindowModel::EQL) {
   11678        77322 :                         if (NOT_SHADED(ShadeFlag)) { // No window shading
   11679              :                             // Init accumulator for transmittance calc below
   11680        77322 :                             DifSolarAbsW = 0.0;
   11681              : 
   11682              :                             // Calc diffuse solar absorbed by all window glass layers
   11683              :                             // Note: I am assuming here that individual glass layer absorptances have been
   11684              :                             // corrected
   11685              :                             //       to account for layer by layer transmittance and reflection effects.
   11686       154686 :                             for (int IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
   11687              :                                 // Calc diffuse solar absorbed from the inside by each window glass layer [W]
   11688        77364 :                                 AbsInt = state.dataConstruction->Construct(ConstrNum).AbsDiffBack(IGlass);
   11689        77364 :                                 WinDifSolLayAbsW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).AbsDiffBack(IGlass);
   11690              : 
   11691              :                                 // Accumulate distributed diffuse solar absorbed [W] by overall window for
   11692              :                                 // transmittance calc below
   11693        77364 :                                 DifSolarAbsW += WinDifSolLayAbsW;
   11694              : 
   11695              :                                 // Accumulate diffuse solar absorbed from the inside by each window glass layer
   11696              :                                 // [W/m2] for heat balance calcs
   11697        77364 :                                 state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
   11698              :                             }
   11699              : 
   11700              :                             // Calc diffuse solar reflected back to zone
   11701              :                             // I don't really care if this is a window or opaque surface since I am just
   11702              :                             // accumulating all reflected diffuse solar in a zone bucket for "interreflected"
   11703              :                             // distribution Reflected diffuse solar [W] = current window transmitted diffuse solar
   11704              :                             //    * view factor from current (sending) window DifTransSurfNum to current
   11705              :                             //    (receiving) surface HeatTransSurfNum
   11706              :                             //    * current window inside solar reflectance
   11707        77322 :                             InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   11708        77322 :                             DifSolarReflW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   11709              : 
   11710              :                             // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   11711              :                             // interreflection calcs
   11712        77322 :                             state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
   11713              : 
   11714              :                             //------------------------------------------------------------------------------
   11715              :                             // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
   11716              :                             //------------------------------------------------------------------------------
   11717              : 
   11718              :                             // If this receiving window surface (HeatTransSurfNum) is an interior window,
   11719              :                             // calc distributed solar transmitted to adjacent zone [W]
   11720              :                             // NOTE: This calc is here because interior windows are currently assumed to have no
   11721              :                             // shading
   11722              : 
   11723              :                             // Get the adjacent surface number for this receiving window surface
   11724        77322 :                             int AdjSurfNum = surf.ExtBoundCond;
   11725              :                             // If the adjacent surface number is > 0, this is an interior window
   11726        77322 :                             if (AdjSurfNum > 0) { // this is an interior window surface
   11727              : 
   11728              :                                 // Calc diffuse solar from current exterior window
   11729              :                                 // transmitted through this interior window to adjacent zone [W]
   11730              :                                 // Transmitted diffuse solar [W] = current exterior window transmitted diffuse
   11731              :                                 // solar
   11732              :                                 //    * view factor from current (sending) window DifTransSurfNum to current
   11733              :                                 //    (receiving) surface HeatTransSurfNum
   11734              :                                 //    - diffuse absorbed by this interior window
   11735              :                                 //    - diffuse reflected by this interior window
   11736            0 :                                 Real64 DifSolarTransThroughW = WinDifSolarTrans_Factor - DifSolarAbsW - DifSolarReflW;
   11737              :                                 // HERE 8/15/07 Note Construct(AdjConstrNum)%TransDiff could be used here since
   11738              :                                 // the "front" transmittance for an interior window in the adjacent zone is the
   11739              :                                 // correct direction as long as I use the Construct() of the Surface in the
   11740              :                                 // adjacent zone. However, the above calculation better conserves energy, although
   11741              :                                 // possibly at the expense of less accurate transmittance calcs. Preliminary tests
   11742              :                                 // showed fairly good agreement between the two DifSolarTransW calculation
   11743              :                                 // methods, but for consistency I stuck with the above. int AdjConstrNum =
   11744              :                                 // Surface(AdjSurfNum).Construction;
   11745              :                                 //              DifSolarTransW = WinDifSolar(DifTransSurfNum) &
   11746              :                                 //                                * ViewFactor &
   11747              :                                 //                                * Construct(AdjConstrNum)%TransDiff
   11748              : 
   11749              :                                 // Get the adjacent zone index
   11750            0 :                                 int const adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
   11751              : 
   11752              :                                 // Call routine to distribute diffuse solar transmitted through this interior
   11753              :                                 // window into adjacent zone
   11754            0 :                                 CalcInteriorWinTransDifSolInitialDistribution(state, adjEnclosureNum, AdjSurfNum, DifSolarTransThroughW);
   11755              :                             }
   11756              : 
   11757              :                             // Calc transmitted Window and Zone total distributed diffuse solar to check for
   11758              :                             // conservation of energy This is not very effective since it assigns whatever
   11759              :                             // distributed diffuse solar has not been absorbed or reflected to transmitted.
   11760              :                             // Should be just total less reflected
   11761        77322 :                             Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
   11762              : 
   11763              :                             // Accumulate transmitted diffuse solar for reporting
   11764        77322 :                             state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
   11765              : 
   11766            0 :                         } else if (ShadeFlag == WinShadingType::SwitchableGlazing) { // Switchable glazing
   11767              :                             // Init accumulator for transmittance calc below
   11768            0 :                             DifSolarAbsW = 0.0;
   11769              : 
   11770            0 :                             auto const &construct = state.dataConstruction->Construct(ConstrNum);
   11771            0 :                             auto const &construct_AbsDiffBack = construct.AbsDiffBack;
   11772            0 :                             auto const &construct_sh = state.dataConstruction->Construct(ConstrNumSh);
   11773            0 :                             auto const &construct_sh_AbsDiffBack = construct_sh.AbsDiffBack;
   11774            0 :                             for (int IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
   11775              :                                 // Calc diffuse solar absorbed in each window glass layer
   11776            0 :                                 WinDifSolLayAbsW =
   11777              :                                     WinDifSolarTrans_Factor *
   11778            0 :                                     Window::InterpSw(win_SwitchingFactor, construct_AbsDiffBack(IGlass), construct_sh_AbsDiffBack(IGlass));
   11779              : 
   11780              :                                 // Accumulate distributed diffuse solar absorbed [W] by overall window for
   11781              :                                 // transmittance calc below
   11782            0 :                                 DifSolarAbsW += WinDifSolLayAbsW;
   11783              : 
   11784              :                                 // Accumulate diffuse solar absorbed from the inside by each window glass layer
   11785              :                                 // [W/m2] for heat balance calcs
   11786            0 :                                 state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
   11787              :                             }
   11788              : 
   11789              :                             // Calc diffuse solar reflected back to zone
   11790            0 :                             DifSolarReflW = WinDifSolarTrans_Factor *
   11791            0 :                                             Window::InterpSw(win_SwitchingFactor, construct.ReflectSolDiffBack, construct_sh.ReflectSolDiffBack);
   11792              : 
   11793              :                             // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   11794              :                             // interreflection calcs
   11795            0 :                             state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
   11796              : 
   11797              :                             // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
   11798              :                             // conservation of energy This is not very effective since it assigns whatever
   11799              :                             // distributed diffuse solar has not been absorbed or reflected to transmitted.
   11800              :                             // Should be just total less reflected
   11801            0 :                             Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
   11802              : 
   11803              :                             // Accumulate transmitted diffuse solar for reporting
   11804            0 :                             state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
   11805              : 
   11806            0 :                         } else if (ConstrNumSh != 0) {
   11807              :                             // Interior, exterior or between-glass shade, screen or blind in place
   11808              : 
   11809              :                             // Init accumulator for transmittance calc below
   11810            0 :                             DifSolarAbsW = 0.0;
   11811            0 :                             WinDifSolLayAbsW = 0.0;
   11812              : 
   11813              :                             // First calc diffuse solar absorbed by each glass layer in this window with
   11814              :                             // shade/blind in place
   11815            0 :                             auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
   11816            0 :                             auto const &surfShade = s_surf->surfShades(HeatTransSurfNum);
   11817            0 :                             Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   11818              : 
   11819            0 :                             for (int IGlass = 1; IGlass <= constrSh.TotGlassLayers; ++IGlass) {
   11820            0 :                                 if (ANY_SHADE_SCREEN(ShadeFlag)) {
   11821              :                                     // Calc diffuse solar absorbed in each window glass layer and shade
   11822            0 :                                     WinDifSolLayAbsW = WinDifSolarTrans_Factor * constrSh.AbsDiffBack(IGlass);
   11823            0 :                                 } else if (ANY_BLIND(ShadeFlag)) {
   11824            0 :                                     auto const &slatDfAbsLo = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxLo];
   11825            0 :                                     auto const &slatDfAbsHi = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxHi];
   11826            0 :                                     BlAbsDiffBk = Interp(slatDfAbsLo.Sol.Bk.Df.Abs, slatDfAbsHi.Sol.Bk.Df.Abs, slatInterpFac);
   11827              :                                     // Calc diffuse solar absorbed in each window glass layer and shade
   11828            0 :                                     WinDifSolLayAbsW = WinDifSolarTrans_Factor * BlAbsDiffBk;
   11829              :                                 }
   11830              : 
   11831              :                                 // Accumulate distributed diffuse solar absorbed [W] by overall window for
   11832              :                                 // transmittance calc below
   11833            0 :                                 DifSolarAbsW += WinDifSolLayAbsW;
   11834              : 
   11835              :                                 // Accumulate diffuse solar absorbed from the inside by each window glass layer
   11836              :                                 // [W/m2] for heat balance calcs
   11837            0 :                                 state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += WinDifSolLayAbsW * per_HTSurfaceArea;
   11838              :                             }
   11839              : 
   11840              :                             // Next calc diffuse solar reflected back to zone from window with shade or blind on
   11841              :                             // Diffuse back solar reflectance, bare glass or shade on
   11842            0 :                             InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   11843            0 :                             if ((ShadeFlag == WinShadingType::IntBlind) || (ShadeFlag == WinShadingType::ExtBlind)) {
   11844            0 :                                 auto const &constr = state.dataConstruction->Construct(ConstrNum);
   11845            0 :                                 auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
   11846            0 :                                 auto const &btarSlatLo = constr.blindTARs[surfShade.blind.slatAngIdxLo];
   11847            0 :                                 auto const &btarSlatHi = constr.blindTARs[surfShade.blind.slatAngIdxHi];
   11848            0 :                                 Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   11849              :                                 // Diffuse back solar reflectance, blind present, vs. slat angle
   11850            0 :                                 InsideDifReflectance = Interp(btarSlatLo.Sol.Bk.Df.Ref, btarSlatHi.Sol.Bk.Df.Ref, slatInterpFac);
   11851              :                             }
   11852            0 :                             DifSolarReflW = WinDifSolarTrans_Factor * InsideDifReflectance;
   11853              : 
   11854              :                             // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   11855              :                             // interreflection calcs
   11856            0 :                             state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
   11857              : 
   11858              :                             // Now calc diffuse solar absorbed by shade/blind itself
   11859            0 :                             BlNum = surfShade.blind.matNum;
   11860            0 :                             if (ANY_SHADE_SCREEN(ShadeFlag)) {
   11861              :                                 // Calc diffuse solar absorbed by shade or screen [W]
   11862            0 :                                 ShBlDifSolarAbsW = WinDifSolarTrans_Factor * constrSh.AbsDiffBackShade;
   11863            0 :                             } else if (ANY_BLIND(ShadeFlag)) {
   11864            0 :                                 auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
   11865            0 :                                 auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
   11866            0 :                                 auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
   11867            0 :                                 Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   11868            0 :                                 AbsDiffBkBl = Interp(btarSlatLo.Sol.Bk.Df.Abs, btarSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
   11869            0 :                                 ShBlDifSolarAbsW = WinDifSolarTrans_Factor * AbsDiffBkBl;
   11870              :                             }
   11871              :                             // Correct for divider shadowing
   11872            0 :                             if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
   11873            0 :                                 ShBlDifSolarAbsW *= s_surf->SurfaceWindow(HeatTransSurfNum).glazedFrac;
   11874              :                             }
   11875              : 
   11876              :                             // Accumulate diffuse solar absorbed  by shade or screen [W/m2] for heat balance calcs
   11877            0 :                             s_surf->SurfWinInitialDifSolAbsByShade(HeatTransSurfNum) += ShBlDifSolarAbsW * per_HTSurfaceArea;
   11878              : 
   11879              :                             // Accumulate distributed diffuse solar absorbed [W] by overall window for
   11880              :                             // transmittance calc below
   11881            0 :                             DifSolarAbsW += ShBlDifSolarAbsW;
   11882              : 
   11883              :                             // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
   11884              :                             // conservation of energy This is not very effective since it assigns whatever
   11885              :                             // distributed diffuse solar has not been absorbed or reflected to transmitted.
   11886              :                             // Should be just total less reflected
   11887            0 :                             Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
   11888              : 
   11889              :                             // Accumulate transmitted diffuse solar for reporting
   11890            0 :                             state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
   11891              :                         } // End of shading flag check
   11892              : 
   11893              :                     } else {
   11894              :                         // SurfaceWindow(HeatTransSurfNum)%WindowModelType == WindowModel:: EQL
   11895              :                         // ConstrNum=Surface(HeatTransSurfNum)%Construction
   11896              :                         // call the ASHWAT fenestration model for diffuse radiation here
   11897            2 :                         WindowEquivalentLayer::CalcEQLOpticalProperty(state, HeatTransSurfNum, SolarArrays::DIFF, AbsSolDiffBackEQL);
   11898              : 
   11899            2 :                         EQLNum = state.dataConstruction->Construct(ConstrNum).EQLConsPtr;
   11900            6 :                         for (Lay = 1; Lay <= state.dataWindowEquivLayer->CFS(EQLNum).NL; ++Lay) {
   11901              : 
   11902              :                             // Calc diffuse solar absorbed from the inside by each layer of EQL model [W]
   11903              :                             // WinDifSolLayAbsW = WinDifSolar(DifTransSurfNum)* ViewFactor *
   11904              :                             // Construct(ConstrNum)%AbsDiffBack(Lay)
   11905            4 :                             WinDifSolLayAbsW = WinDifSolarTrans_Factor * AbsSolDiffBackEQL(2, Lay);
   11906              : 
   11907              :                             // Accumulate distributed diffuse solar absorbed [W] by overall window for
   11908              :                             // transmittance calc below
   11909            4 :                             DifSolarAbsW += WinDifSolLayAbsW;
   11910              : 
   11911              :                             // Accumulate diffuse solar absorbed from the inside by each window layer [W/m2] for
   11912              :                             // heat balance calcs
   11913            4 :                             state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, Lay) += WinDifSolLayAbsW * per_HTSurfaceArea;
   11914              : 
   11915              :                             // ASHWAT equivalent layer model may require not the individual layer absorption but
   11916              :                             // the flux InitialDifSolwinEQL(HeatTransSurfNum) = WinDifSolar(DifTransSurfNum)*
   11917              :                             // ViewFactor
   11918              :                         }
   11919              : 
   11920              :                         // Calc diffuse solar reflected back to zone
   11921              :                         // I don't really care if this is a window or opaque surface since I am just
   11922              :                         // accumulating all reflected diffuse solar in a zone bucket for "interreflected"
   11923              :                         // distribution Reflected diffuse solar [W] = current window transmitted diffuse solar
   11924              :                         //    * view factor from current (sending) window DifTransSurfNum to current (receiving)
   11925              :                         //    surface HeatTransSurfNum
   11926              :                         //    * current window inside solar reflectance
   11927            2 :                         InsideDifReflectance = state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   11928            2 :                         DifSolarReflW = WinDifSolarTrans_Factor * state.dataConstruction->Construct(ConstrNum).ReflectSolDiffBack;
   11929              : 
   11930              :                         // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   11931              :                         // interreflection calcs
   11932            2 :                         state.dataHeatBal->EnclSolInitialDifSolReflW(enclosureNum) += DifSolarReflW; // [W]
   11933              : 
   11934              :                         //------------------------------------------------------------------------------
   11935              :                         // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
   11936              :                         //------------------------------------------------------------------------------
   11937              : 
   11938              :                         // If this receiving window surface (HeatTransSurfNum) is an interior window,
   11939              :                         // calc distributed solar transmitted to adjacent zone [W]
   11940              :                         // NOTE: This calc is here because interior windows are currently assumed to have no
   11941              :                         // shading
   11942              : 
   11943              :                         // Get the adjacent surface number for this receiving window surface
   11944            2 :                         int const AdjSurfNum = s_surf->Surface(HeatTransSurfNum).ExtBoundCond;
   11945              :                         // If the adjacent surface number is > 0, this is an interior window
   11946            2 :                         if (AdjSurfNum > 0) { // this is an interior window surface
   11947              : 
   11948              :                             // Calc diffuse solar from current exterior window
   11949              :                             // transmitted through this interior window to adjacent zone [W]
   11950              :                             // Transmitted diffuse solar [W] = current exterior window transmitted diffuse solar
   11951              :                             //    * view factor from current (sending) window DifTransSurfNum to current
   11952              :                             //    (receiving) surface HeatTransSurfNum
   11953            0 :                             Real64 DifSolarTransW = AbsSolDiffBackEQL(2, state.dataWindowEquivLayer->CFS(EQLNum).NL + 1) * ViewFactor;
   11954              :                             // int AdjConstrNum = Surface(AdjSurfNum).Construction;
   11955              :                             // Get the adjacent zone index
   11956            0 :                             int adjEnclosureNum = s_surf->Surface(AdjSurfNum).SolarEnclIndex;
   11957              :                             // Call routine to distribute diffuse solar transmitted through this interior window
   11958              :                             // into adjacent zone
   11959            0 :                             CalcInteriorWinTransDifSolInitialDistribution(state, adjEnclosureNum, AdjSurfNum, DifSolarTransW);
   11960              :                         }
   11961              : 
   11962              :                         // Calc transmitted Window and Zone total distributed diffuse solar to check for
   11963              :                         // conservation of energy This is not very effective since it assigns whatever
   11964              :                         // distributed diffuse solar has not been absorbed or reflected to transmitted.
   11965              :                         // Should be just total less reflected
   11966            2 :                         Real64 DifSolarTransIntoW = WinDifSolarTrans_Factor - DifSolarReflW;
   11967              : 
   11968              :                         // Accumulate transmitted diffuse solar for reporting
   11969            2 :                         state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += DifSolarTransIntoW * per_HTSurfaceArea;
   11970              : 
   11971              :                     } // IF (SurfaceWindow(HeatTransSurfNum)%WindowModelType /= WindowModel:: EQL) THEN
   11972              : 
   11973              :                     // HERE 8/14/07 Ignore absorptance and reflectance of Frames and Dividers for now.
   11974              :                     // I would need revised view factors that included these surface types.
   11975              :                     // By ignoring them here, the diffuse solar is accounted for on the other surfaces
   11976              : 
   11977              :                     //          IF(SurfaceWindow(HeatTransSurfNum)%FrameArea > 0.0) THEN  ! Window has a frame
   11978              :                     // Note that FrameQRadInAbs is initially calculated in InitSolarHeatGains
   11979              :                     //          END IF
   11980              : 
   11981              :                     //          IF(SurfaceWindow(HeatTransSurfNum)%DividerArea > 0.0) THEN  ! Window has dividers
   11982              :                     //            DividerSolAbs = SurfaceWindow(HeatTransSurfNum)%DividerSolAbsorp
   11983              :                     //            IF(SurfaceWindow(HeatTransSurfNum)%DividerType == Suspended) THEN ! Suspended
   11984              :                     //            divider; account for inside glass
   11985              :                     //              MatNumGl = Construct(ConstrNum)%LayerPoint(Construct(ConstrNum)%TotLayers)
   11986              :                     //              TransGl = dataMaterial.Material(MatNumGl)%Trans
   11987              :                     //              ReflGl = dataMaterial.Material(MatNumGl)%ReflectSolDiffBack
   11988              :                     //              AbsGl = 1.0d0-TransGl-ReflGl
   11989              :                     //              DividerSolRefl = 1.0d0-DividerSolAbs
   11990              :                     //              DividerSolAbs = AbsGl + TransGl*(DividerSolAbs +
   11991              :                     //              DividerSolRefl*AbsGl)/(1.0d0-DividerSolRefl*ReflGl)
   11992              :                     //            END IF
   11993              :                     // Correct for interior shade transmittance
   11994              :                     //            IF(ShadeFlag == IntShadeOn) THEN
   11995              :                     //              MatNumSh = Construct(ConstrNumSh)%LayerPoint(Construct(ConstrNumSh)%TotLayers)
   11996              :                     //              DividerSolAbs = DividerSolAbs * dataMaterial.Material(MatNumSh)%Trans
   11997              :                     //            ELSE IF(ShadeFlag == WinShadingType::IntBlind) THEN
   11998              :                     //              DividerSolAbs = DividerSolAbs *
   11999              :                     //              InterpSlatAng(SurfaceWindow(HeatTransSurfNum)%SlatAngThisTS, &
   12000              :                     //                  SurfaceWindow(HeatTransSurfNum)%MovableSlats,Blind(BlNum)%SolBackDiffDiffTrans)
   12001              :                     //            END IF
   12002              :                     // Note that DividerQRadInAbs is initially calculated in InitSolarHeatGains
   12003              : 
   12004              :                     //          END IF  ! Window has dividers
   12005              : 
   12006              :                 } // opaque or window heat transfer surface
   12007              : 
   12008              :             } // HeatTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
   12009              : 
   12010              :             // Check debug var for view factors here
   12011              :             // ViewFactorTotal
   12012              :             // Check debug vars for individual transmitting surfaces here
   12013              :             //                WinDifSolarDistTotl = WinDifSolarDistAbsorbedTotl + WinDifSolarDistReflectedTotl +
   12014              :             //                WinDifSolarDistTransmittedTotl;
   12015              :             // WinDifSolarTrans
   12016              : 
   12017              :         } // DifTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
   12018              : 
   12019              :         // Check debug vars for zone totals here
   12020              :         //            ZoneDifSolarDistTotl = ZoneDifSolarDistAbsorbedTotl + ZoneDifSolarDistReflectedTotl +
   12021              :         //            ZoneDifSolarDistTransmittedTotl;
   12022              :         // ZoneDifSolarTrans
   12023              :         // ZoneDifSolarDistAbsorbedTotl
   12024              :         // ZoneDifSolarDistReflectedTotl
   12025              :         // ZoneDifSolarDistTransmittedTotl
   12026              :         //    CALL DisplayString('Diffuse Solar Distribution Zone Totals')
   12027              : 
   12028              :     } // ZoneNum = 1, NumOfZones
   12029        71220 : }
   12030            0 : void CalcInteriorWinTransDifSolInitialDistribution(EnergyPlusData &state,
   12031              :                                                    int const IntWinEnclosureNum,     // Interior Window Enclosure index number
   12032              :                                                    int const IntWinSurfNum,          // Interior Window Surface number
   12033              :                                                    Real64 const IntWinDifSolarTransW // Diffuse Solar transmitted through Interior Window
   12034              :                                                                                      // IntWinSurfNum from adjacent enclosure [W]
   12035              : )
   12036              : {
   12037              : 
   12038              :     // SUBROUTINE INFORMATION:
   12039              :     //       AUTHOR         Rob Hitchcock
   12040              :     //       DATE WRITTEN   August 2007
   12041              :     //       MODIFIED       N/A
   12042              :     //       RE-ENGINEERED  N/A
   12043              : 
   12044              :     // PURPOSE OF THIS SUBROUTINE:
   12045              :     // This subroutine calculates the initial distribution
   12046              :     // of diffuse solar transmitted through the given interior window
   12047              :     // to individual heat transfer surfaces in the given enclosure.
   12048              :     // Diffuse solar transmitted through interior windows in this enclosure
   12049              :     // to adjacent enclosures, is added to the EnclSolInitialDifSolReflW
   12050              :     // of the adjacent enclosure for subsequent interreflection calcs
   12051              : 
   12052              :     // METHODOLOGY EMPLOYED:
   12053              :     // Similar to method used in CalcWinTransDifSolInitialDistribution.
   12054              :     // Apportions diffuse solar transmitted through an interior window
   12055              :     // that is then absorbed, reflected, and/or transmitted
   12056              :     // by other heat transfer surfaces in the given enclosure.
   12057              :     // Calculations use:
   12058              :     // 1. DifSolarTransW calculated in SUBROUTINE CalcWinTransDifSolInitialDistribution,
   12059              :     // 2. view factors between the interior window and
   12060              :     // other heat transfer surfaces in the given enclosure
   12061              :     // calculated in SUBROUTINE CalcApproximateViewFactors, and
   12062              :     // 3. surface absorptances, reflectances, and transmittances
   12063              :     // determined here using revised code from SUBROUTINE InitIntSolarDistribution
   12064              : 
   12065              :     // Using/Aliasing
   12066              :     using namespace DataViewFactorInformation;
   12067              : 
   12068              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
   12069              :     int IGlass;                  // Glass layer counter
   12070              :     int TotGlassLayers;          // Number of glass layers in a window construction
   12071              :     WinShadingType ShadeFlag;    // Shading flag
   12072              :     Real64 AbsInt;               // Tmp var for Inside surface short-wave absorptance
   12073              :     Real64 InsideDifAbsorptance; // Inside diffuse solar absorptance of a surface
   12074              :     Real64 InsideDifReflectance; // Inside diffuse solar reflectance of a surface
   12075              :     int BlNum;                   // Blind number
   12076              :     Real64 BlAbsDiffBk;          // Glass layer back diffuse solar absorptance when blind in place
   12077              :     Real64 AbsDiffBkBl;          // Blind diffuse back solar absorptance as part of glazing system
   12078              : 
   12079              :     //  REAL(r64)    :: DividerSolAbs      ! Window divider solar absorptance
   12080              :     //  REAL(r64)    :: DividerSolRefl     ! Window divider solar reflectance
   12081              :     //  INTEGER :: MatNumGl           ! Glass layer material number
   12082              :     //  INTEGER :: MatNumSh           ! Shade layer material number
   12083              :     //  REAL(r64)    :: TransGl,ReflGl,AbsGl ! Glass layer solar transmittance, reflectance, absorptance
   12084              : 
   12085              :     Real64 ViewFactor;       // temp var for view factor
   12086              :     Real64 ViewFactorTotal;  // debug var for view factor total
   12087              :     Real64 WinDifSolarTrans; // debug var for WinDifSolar() [W]
   12088              :                              //        Real64 WinDifSolarDistTotl; // debug var for window total distributed
   12089              :                              //        diffuse solar [W] Real64 WinDifSolarDistAbsorbedTotl( 0.0 ); // debug var
   12090              :                              //        for individual exterior window total
   12091              :                              // distributed
   12092              :     //           diffuse solar absorbed [W]
   12093              :     //        Real64 WinDifSolarDistReflectedTotl( 0.0 ); // debug var for individual exterior window total
   12094              :     //        distributed
   12095              :     //           diffuse solar reflected [W]
   12096              :     //        Real64 WinDifSolarDistTransmittedTotl( 0.0 ); // debug var for individual exterior window total
   12097              :     //        distributed
   12098              :     //           diffuse solar transmitted [W]
   12099              :     Real64 WinDifSolLayAbsW; // temp var for diffuse solar absorbed by individual glass layer [W]
   12100              :                              //        Real64 ZoneDifSolarTrans( 0.0 ); // debug var for WinDifSolar() [W]
   12101              :     //  REAL(r64)    :: ZoneDifSolarDistTotl    ! debug var for zone total distributed diffuse solar [W]
   12102              :     //        Real64 ZoneDifSolarDistAbsorbedTotl( 0.0 ); // debug var for zone total distributed diffuse solar
   12103              :     //        absorbed [W] Real64 ZoneDifSolarDistReflectedTotl( 0.0 ); // debug var for zone total distributed
   12104              :     //        diffuse solar reflected [W] Real64 ZoneDifSolarDistTransmittedTotl( 0.0 ); // debug var for zone
   12105              :     //        total distributed diffuse solar transmitted [W]
   12106              : 
   12107            0 :     Real64 DifSolarAbsW = 0.0;     // temp var for diffuse solar absorbed by surface [W]
   12108            0 :     Real64 DifSolarAbs = 0.0;      // temp var for diffuse solar absorbed by surface [W/m2]
   12109            0 :     Real64 DifSolarReflW = 0.0;    // temp var for diffuse solar reflected by surface [W]
   12110            0 :     Real64 DifSolarTransW = 0.0;   // temp var for diffuse solar transmitted through interior window surface [W]
   12111            0 :     Real64 ShBlDifSolarAbsW = 0.0; // temp var for diffuse solar absorbed by shade/blind [W]
   12112              : 
   12113              :     //-------------------------------------------------------------------------------------------------
   12114              :     // DISTRIBUTE TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO INTERIOR HEAT TRANSFER SURFACES
   12115              :     //-------------------------------------------------------------------------------------------------
   12116              : 
   12117            0 :     auto &s_surf = state.dataSurface;
   12118              : 
   12119              :     // Init debug vars
   12120            0 :     ViewFactorTotal = 0.0;
   12121            0 :     WinDifSolarTrans = IntWinDifSolarTransW;
   12122              : 
   12123            0 :     auto &thisEnclosure = state.dataViewFactor->EnclSolInfo(IntWinEnclosureNum);
   12124              :     // Loop over all heat transfer surfaces in the current zone that might receive diffuse solar
   12125            0 :     Real64 InitialZoneDifSolReflW_zone(0.0);
   12126            0 :     for (int const HeatTransSurfNum : thisEnclosure.SurfacePtr) {
   12127              : 
   12128            0 :         auto &surf = s_surf->Surface(HeatTransSurfNum);
   12129              : 
   12130              :         // Skip surfaces that are not heat transfer surfaces
   12131            0 :         if (!surf.HeatTransSurf) continue;
   12132              :         // Skip tubular daylighting device domes
   12133            0 :         if (surf.Class == SurfaceClass::TDD_Dome) continue;
   12134              : 
   12135              :         // View factor from current (sending) window IntWinSurfNum to current (receiving) surface HeatTransSurfNum
   12136            0 :         int HTenclosureSurfNum = surf.SolarEnclSurfIndex;                          // HT surface index for EnclSolInfo.SurfacePtr and F arrays
   12137            0 :         int enclosureNum = surf.SolarEnclIndex;                                    // index for EnclSolInfo
   12138            0 :         int IntWinEnclSurfNum = s_surf->Surface(IntWinSurfNum).SolarEnclSurfIndex; // Window surface index for EnclSolInfo.SurfacePtr and F arrays
   12139              : 
   12140            0 :         ViewFactor = state.dataViewFactor->EnclSolInfo(enclosureNum).F(HTenclosureSurfNum, IntWinEnclSurfNum);
   12141              :         // debug ViewFactorTotal
   12142            0 :         ViewFactorTotal += ViewFactor; // debug
   12143              : 
   12144              :         // Skip receiving surfaces with 0.0 view factor
   12145            0 :         if (ViewFactor <= 0.0) continue;
   12146            0 :         Real64 const SolarTrans_ViewFactor(IntWinDifSolarTransW * ViewFactor);
   12147              : 
   12148              :         // Calculate diffuse solar from current interior window absorbed and reflected by current heat transfer
   12149              :         // surface And calculate transmitted diffuse solar to adjacent zones through interior windows
   12150            0 :         int const ConstrNum = s_surf->SurfActiveConstruction(HeatTransSurfNum);
   12151            0 :         if (state.dataConstruction->Construct(ConstrNum).TransDiff <= 0.0) { // Interior Opaque Surface
   12152              : 
   12153              :             // Determine the inside (back) diffuse solar absorptance
   12154              :             // and reflectance of the current heat transfer surface
   12155            0 :             InsideDifAbsorptance = state.dataHeatBalSurf->SurfAbsSolarInt(HeatTransSurfNum);
   12156              :             // Inside (back) diffuse solar reflectance is assumed to be 1 - absorptance
   12157            0 :             InsideDifReflectance = 1.0 - InsideDifAbsorptance;
   12158              : 
   12159              :             // Absorbed diffuse solar [W] = current window transmitted diffuse solar [W]
   12160              :             //    * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
   12161              :             //    HeatTransSurfNum
   12162              :             //    * current surface inside solar absorptance
   12163            0 :             DifSolarAbsW = SolarTrans_ViewFactor * InsideDifAbsorptance; // [W]
   12164              : 
   12165              :             // Absorbed diffuse solar [W/m2] = Absorbed diffuse solar [W]
   12166              :             //                                 / current surface net area
   12167            0 :             DifSolarAbs = DifSolarAbsW / surf.Area;
   12168              : 
   12169              :             // Accumulate absorbed diffuse solar [W/m2] on this surface for heat balance calcs
   12170            0 :             state.dataHeatBalSurf->SurfOpaqInitialDifSolInAbs(HeatTransSurfNum) += DifSolarAbs;
   12171              : 
   12172              :             // Reflected diffuse solar [W] = current window transmitted diffuse solar
   12173              :             //    * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
   12174              :             //    HeatTransSurfNum
   12175              :             //    * current window inside solar reflectance
   12176            0 :             DifSolarReflW = SolarTrans_ViewFactor * InsideDifReflectance;
   12177              : 
   12178              :             // Accumulate total reflected distributed diffuse solar for each zone for subsequent interreflection
   12179              :             // calcs
   12180            0 :             InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
   12181              : 
   12182              :             // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12183              :             // For opaque surfaces all incident diffuse is either absorbed or reflected
   12184              :             //                WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug [W]
   12185              :             //                WinDifSolarDistReflectedTotl += DifSolarReflW; // debug [W]
   12186              :             //                ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug [W]
   12187              :             //                ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug [W]
   12188              : 
   12189              :         } else { // Exterior or Interior Window
   12190              : 
   12191            0 :             int const ConstrNumSh = s_surf->SurfWinActiveShadedConstruction(HeatTransSurfNum);
   12192            0 :             auto const &construction = state.dataConstruction->Construct(ConstrNum);
   12193              : 
   12194            0 :             TotGlassLayers = construction.TotGlassLayers;
   12195            0 :             ShadeFlag = s_surf->SurfWinShadingFlag(HeatTransSurfNum);
   12196              : 
   12197            0 :             if (NOT_SHADED(ShadeFlag)) { // No window shading
   12198              :                 // Init accumulator for transmittance calc below
   12199            0 :                 DifSolarAbsW = 0.0;
   12200              : 
   12201              :                 // Calc diffuse solar absorbed by all window glass layers
   12202              :                 // Note: I am assuming here that individual glass layer absorptances have been corrected
   12203              :                 //       to account for layer by layer transmittance and reflection effects.
   12204            0 :                 for (IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
   12205              :                     // Calc diffuse solar absorbed from the inside by each window glass layer [W]
   12206            0 :                     AbsInt = construction.AbsDiffBack(IGlass);
   12207            0 :                     WinDifSolLayAbsW = SolarTrans_ViewFactor * construction.AbsDiffBack(IGlass);
   12208              : 
   12209              :                     // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
   12210              :                     // below
   12211            0 :                     DifSolarAbsW += WinDifSolLayAbsW;
   12212              : 
   12213              :                     // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
   12214              :                     // heat balance calcs
   12215            0 :                     state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
   12216              :                 }
   12217              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12218              :                 //                    WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12219              :                 //                    ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12220              : 
   12221              :                 // Calc diffuse solar reflected back to zone
   12222              :                 // I don't really care if this is a window or opaque surface since I am just
   12223              :                 // accumulating all reflected diffuse solar in a zone bucket for "interreflected" distribution
   12224              :                 // Reflected diffuse solar [W] = current window transmitted diffuse solar
   12225              :                 //    * view factor from current (sending) window IntWinSurfNum to current (receiving) surface
   12226              :                 //    HeatTransSurfNum
   12227              :                 //    * current window inside solar reflectance
   12228            0 :                 DifSolarReflW = SolarTrans_ViewFactor * construction.ReflectSolDiffBack;
   12229              : 
   12230              :                 // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   12231              :                 // interreflection calcs
   12232            0 :                 InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
   12233              : 
   12234              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12235              : 
   12236              :                 //                    WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12237              :                 //                    ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12238              : 
   12239              :                 // Calc transmitted Window and Zone total distributed diffuse solar to check for conservation of
   12240              :                 // energy This is not very effective since it assigns whatever distributed diffuse solar has not
   12241              :                 // been absorbed or reflected to transmitted.
   12242            0 :                 DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
   12243              : 
   12244              :                 // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
   12245              :                 // conservation of energy
   12246              :                 //                    WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
   12247              :                 //                    ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
   12248              : 
   12249              :                 // Accumulate transmitted diffuse solar for reporting
   12250            0 :                 state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
   12251              : 
   12252              :                 //-----------------------------------------------------------------------------------
   12253              :                 // ADD TRANSMITTED DIFFUSE SOLAR THROUGH INTERIOR WINDOW TO ADJACENT ZONE
   12254              :                 // TOTAL REFLECTED DIFFUSE SOLAR FOR SUBSEQUENT INTERREFLECTION CALCS
   12255              :                 //-----------------------------------------------------------------------------------
   12256              : 
   12257              :                 // If this receiving window surface (HeatTransSurfNum) is an interior window,
   12258              :                 // add transmitted diffuse solar to adjacent zone total reflected distributed
   12259              :                 // diffuse solar for subsequent interreflection calcs
   12260              :                 // NOTE: This calc is here because interior windows are currently assumed to have no shading
   12261              : 
   12262              :                 // Get the adjacent surface number for this receiving window surface
   12263            0 :                 int const AdjSurfNum = surf.ExtBoundCond;
   12264              :                 // If the adjacent surface number is > 0, this is an interior window
   12265            0 :                 if (AdjSurfNum > 0) { // this is an interior window surface
   12266              : 
   12267              :                     // Get the adjacent zone/enclosure index
   12268              :                     // Add transmitted diffuse solar to total reflected distributed diffuse solar for each zone
   12269              :                     // for subsequent interreflection calcs
   12270            0 :                     state.dataHeatBal->EnclSolInitialDifSolReflW(s_surf->Surface(AdjSurfNum).SolarEnclIndex) += DifSolarTransW; // [W]
   12271              :                 }
   12272              : 
   12273            0 :             } else if (ShadeFlag == WinShadingType::SwitchableGlazing) { // Switchable glazing
   12274              :                 // Init accumulator for transmittance calc below
   12275            0 :                 auto const &constructionSh = state.dataConstruction->Construct(ConstrNumSh);
   12276            0 :                 DifSolarAbsW = 0.0;
   12277              : 
   12278            0 :                 for (IGlass = 1; IGlass <= TotGlassLayers; ++IGlass) {
   12279              :                     // Calc diffuse solar absorbed in each window glass layer
   12280            0 :                     WinDifSolLayAbsW = SolarTrans_ViewFactor * InterpSw(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum),
   12281            0 :                                                                         construction.AbsDiffBack(IGlass),
   12282            0 :                                                                         constructionSh.AbsDiffBack(IGlass));
   12283              : 
   12284              :                     // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
   12285              :                     // below
   12286            0 :                     DifSolarAbsW += WinDifSolLayAbsW;
   12287              : 
   12288              :                     // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
   12289              :                     // heat balance calcs
   12290            0 :                     state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
   12291              :                 }
   12292              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12293              :                 //                                      WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12294              :                 //                                      ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12295              : 
   12296              :                 // Calc diffuse solar reflected back to zone
   12297            0 :                 DifSolarReflW =
   12298              :                     SolarTrans_ViewFactor *
   12299            0 :                     InterpSw(s_surf->SurfWinSwitchingFactor(HeatTransSurfNum), construction.ReflectSolDiffBack, constructionSh.ReflectSolDiffBack);
   12300              : 
   12301              :                 // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   12302              :                 // interreflection calcs
   12303            0 :                 InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
   12304              : 
   12305              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12306              :                 //                                      WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12307              :                 //                                      ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12308              : 
   12309              :                 // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
   12310              :                 // conservation of energy This is not very effective since it assigns whatever distributed diffuse
   12311              :                 // solar has not been absorbed or reflected to transmitted.
   12312            0 :                 DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
   12313              :                 //                                      WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
   12314              :                 //                                      ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug
   12315              :                 //[W]
   12316              : 
   12317              :                 // Accumulate transmitted diffuse solar for reporting
   12318            0 :                 state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
   12319              : 
   12320              :             } else {
   12321            0 :                 auto const &surfShade = s_surf->surfShades(HeatTransSurfNum);
   12322              :                 // Interior, exterior or between-glass shade, screen or blind in place
   12323              : 
   12324              :                 // Init accumulator for transmittance calc below
   12325            0 :                 DifSolarAbsW = 0.0;
   12326            0 :                 WinDifSolLayAbsW = 0.0;
   12327              : 
   12328              :                 // First calc diffuse solar absorbed by each glass layer in this window with shade/blind in place
   12329            0 :                 auto const &constrSh = state.dataConstruction->Construct(ConstrNumSh);
   12330            0 :                 for (IGlass = 1; IGlass <= constrSh.TotGlassLayers; ++IGlass) {
   12331            0 :                     if (ANY_SHADE_SCREEN(ShadeFlag)) {
   12332              :                         // Calc diffuse solar absorbed in each window glass layer and shade
   12333            0 :                         WinDifSolLayAbsW = SolarTrans_ViewFactor * constrSh.AbsDiffBack(IGlass);
   12334            0 :                     } else if (ANY_BLIND(ShadeFlag)) {
   12335            0 :                         auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
   12336            0 :                         auto const &dfAbsSlatLo = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxLo];
   12337            0 :                         auto const &dfAbsSlatHi = constrSh.layerSlatBlindDfAbs(IGlass)[surfShade.blind.slatAngIdxHi];
   12338            0 :                         Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   12339            0 :                         BlAbsDiffBk = Interp(dfAbsSlatLo.Sol.Bk.Df.Abs, dfAbsSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
   12340              :                         // Calc diffuse solar absorbed in each window glass layer and shade
   12341            0 :                         WinDifSolLayAbsW = SolarTrans_ViewFactor * BlAbsDiffBk;
   12342              :                     }
   12343              : 
   12344              :                     // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
   12345              :                     // below
   12346            0 :                     DifSolarAbsW += WinDifSolLayAbsW;
   12347              : 
   12348              :                     // Accumulate diffuse solar absorbed from the inside by each window glass layer [W/m2] for
   12349              :                     // heat balance calcs
   12350            0 :                     state.dataHeatBal->SurfWinInitialDifSolwinAbs(HeatTransSurfNum, IGlass) += (WinDifSolLayAbsW / surf.Area);
   12351              :                 }
   12352              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12353              :                 //                    WinDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12354              :                 //                    ZoneDifSolarDistAbsorbedTotl += DifSolarAbsW; // debug
   12355              : 
   12356              :                 // Next calc diffuse solar reflected back to zone from window with shade or blind on
   12357              :                 // Diffuse back solar reflectance, bare glass or shade on
   12358            0 :                 InsideDifReflectance = construction.ReflectSolDiffBack;
   12359            0 :                 if ((ShadeFlag == WinShadingType::IntBlind) || (ShadeFlag == WinShadingType::ExtBlind)) {
   12360            0 :                     auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
   12361            0 :                     auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
   12362            0 :                     auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
   12363            0 :                     Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   12364              :                     // Diffuse back solar reflectance, blind present, vs. slat angle
   12365            0 :                     InsideDifReflectance = Interp(btarSlatLo.Sol.Bk.Df.Ref, btarSlatHi.Sol.Bk.Df.Ref, slatInterpFac);
   12366              :                 }
   12367            0 :                 DifSolarReflW = SolarTrans_ViewFactor * InsideDifReflectance;
   12368              : 
   12369              :                 // Accumulate total reflected distributed diffuse solar for each zone for subsequent
   12370              :                 // interreflection calcs
   12371            0 :                 InitialZoneDifSolReflW_zone += DifSolarReflW; // [W]
   12372              : 
   12373              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12374              :                 //                    WinDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12375              :                 //                    ZoneDifSolarDistReflectedTotl += DifSolarReflW; // debug
   12376              : 
   12377              :                 // Now calc diffuse solar absorbed by shade/blind itself
   12378            0 :                 BlNum = surfShade.blind.matNum;
   12379            0 :                 if (ANY_SHADE_SCREEN(ShadeFlag)) {
   12380              :                     // Calc diffuse solar absorbed by shade or screen [W]
   12381            0 :                     ShBlDifSolarAbsW = SolarTrans_ViewFactor * constrSh.AbsDiffBackShade;
   12382            0 :                 } else if (ANY_BLIND(ShadeFlag)) {
   12383            0 :                     auto const &surfShade = state.dataSurface->surfShades(HeatTransSurfNum);
   12384            0 :                     auto const &btarSlatLo = constrSh.blindTARs[surfShade.blind.slatAngIdxLo];
   12385            0 :                     auto const &btarSlatHi = constrSh.blindTARs[surfShade.blind.slatAngIdxHi];
   12386            0 :                     Real64 slatInterpFac = surfShade.blind.slatAngInterpFac;
   12387              :                     // Calc diffuse solar absorbed by blind [W]
   12388            0 :                     AbsDiffBkBl = Interp(btarSlatLo.Sol.Bk.Df.Abs, btarSlatHi.Sol.Bk.Df.Abs, slatInterpFac);
   12389            0 :                     ShBlDifSolarAbsW = SolarTrans_ViewFactor * AbsDiffBkBl;
   12390              :                 }
   12391              :                 // Correct for divider shadowing
   12392            0 :                 if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
   12393            0 :                     ShBlDifSolarAbsW *= s_surf->SurfaceWindow(HeatTransSurfNum).glazedFrac;
   12394              :                 }
   12395              : 
   12396              :                 // Accumulate diffuse solar absorbed  by shade or screen [W/m2] for heat balance calcs
   12397            0 :                 s_surf->SurfWinInitialDifSolAbsByShade(HeatTransSurfNum) += (ShBlDifSolarAbsW / surf.Area);
   12398              : 
   12399              :                 // Accumulate distributed diffuse solar absorbed [W] by overall window for transmittance calc
   12400              :                 // below
   12401            0 :                 DifSolarAbsW += ShBlDifSolarAbsW;
   12402              : 
   12403              :                 // Accumulate Window and Zone total distributed diffuse solar to check for conservation of energy
   12404              :                 //                    WinDifSolarDistAbsorbedTotl += ShBlDifSolarAbsW; // debug
   12405              :                 //                    ZoneDifSolarDistAbsorbedTotl += ShBlDifSolarAbsW; // debug
   12406              : 
   12407              :                 // Accumulate transmitted Window and Zone total distributed diffuse solar to check for
   12408              :                 // conservation of energy This is not very effective since it assigns whatever distributed diffuse
   12409              :                 // solar has not been absorbed or reflected to transmitted.
   12410            0 :                 DifSolarTransW = SolarTrans_ViewFactor - DifSolarAbsW - DifSolarReflW;
   12411              :                 //                    WinDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
   12412              :                 //                    ZoneDifSolarDistTransmittedTotl += DifSolarTransW; // debug [W]
   12413              : 
   12414              :                 // Accumulate transmitted diffuse solar for reporting
   12415            0 :                 state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(HeatTransSurfNum) += (SolarTrans_ViewFactor - DifSolarReflW) / surf.Area;
   12416              : 
   12417              :             } // End of shading flag check
   12418              : 
   12419              :             // HERE 8/14/07 Ignore absorptance and reflectance of Frames and Dividers for now.
   12420              :             // I would need revised view factors that included these surface types.
   12421              :             // By ignoring them here, the diffuse solar is accounted for on the other surfaces
   12422              : 
   12423              :             //          IF(SurfaceWindow(HeatTransSurfNum)%FrameArea > 0.0) THEN  ! Window has a frame
   12424              :             // Note that FrameQRadInAbs is initially calculated in InitSolarHeatGains
   12425              :             //          END IF
   12426              : 
   12427              :             //          IF(SurfaceWindow(HeatTransSurfNum)%DividerArea > 0.0) THEN  ! Window has dividers
   12428              :             //            DividerSolAbs = SurfaceWindow(HeatTransSurfNum)%DividerSolAbsorp
   12429              :             //            IF(SurfaceWindow(HeatTransSurfNum)%DividerType == Suspended) THEN ! Suspended divider;
   12430              :             //            account for inside glass
   12431              :             //              MatNumGl = Construct(ConstrNum)%LayerPoint(Construct(ConstrNum)%TotLayers)
   12432              :             //              TransGl = dataMaterial.Material(MatNumGl)%Trans
   12433              :             //              ReflGl = dataMaterial.Material(MatNumGl)%ReflectSolDiffBack
   12434              :             //              AbsGl = 1.0d0-TransGl-ReflGl
   12435              :             //              DividerSolRefl = 1.0d0-DividerSolAbs
   12436              :             //              DividerSolAbs = AbsGl + TransGl*(DividerSolAbs +
   12437              :             //              DividerSolRefl*AbsGl)/(1.0d0-DividerSolRefl*ReflGl)
   12438              :             //            END IF
   12439              :             // Correct for interior shade transmittance
   12440              :             //            IF(ShadeFlag == IntShadeOn) THEN
   12441              :             //              MatNumSh = Construct(ConstrNumSh)%LayerPoint(Construct(ConstrNumSh)%TotLayers)
   12442              :             //              DividerSolAbs = DividerSolAbs * dataMaterial.Material(MatNumSh)%Trans
   12443              :             //            ELSE IF(ShadeFlag == WinShadingType::IntBlind) THEN
   12444              :             //              DividerSolAbs = DividerSolAbs *
   12445              :             //              InterpSlatAng(SurfaceWindow(HeatTransSurfNum)%SlatAngThisTS, &
   12446              :             //                  SurfaceWindow(HeatTransSurfNum)%MovableSlats,Blind(BlNum)%SolBackDiffDiffTrans)
   12447              :             //            END IF
   12448              :             // Note that DividerQRadInAbs is initially calculated in InitSolarHeatGains
   12449              : 
   12450              :             //          END IF  ! Window has dividers
   12451              :         } // opaque or window heat transfer surface
   12452              : 
   12453              :     } // HeatTransSurfNum = Zone(ZoneNum)%SurfaceFirst, Zone(ZoneNum)%SurfaceLast
   12454            0 :     state.dataHeatBal->EnclSolInitialDifSolReflW(IntWinEnclosureNum) += InitialZoneDifSolReflW_zone;
   12455              : 
   12456              :     // Check debug var for view factors here
   12457              :     // ViewFactorTotal
   12458              :     // Check debug vars for individual transmitting surfaces here
   12459              :     //        WinDifSolarDistTotl = WinDifSolarDistAbsorbedTotl + WinDifSolarDistReflectedTotl +
   12460              :     //        WinDifSolarDistTransmittedTotl; //Debug
   12461              :     // WinDifSolarTrans
   12462            0 : }
   12463              : 
   12464            0 : void CalcComplexWindowOverlap(EnergyPlusData &state,
   12465              :                               BSDFGeomDescr &Geom,               // State Geometry
   12466              :                               BSDFWindowGeomDescr const &Window, // Window Geometry
   12467              :                               int const ISurf                    // Surface number of the complex fenestration
   12468              : )
   12469              : {
   12470              :     // SUBROUTINE INFORMATION:
   12471              :     //       AUTHOR         Simon Vidanovic
   12472              :     //       DATE WRITTEN   May 2012
   12473              :     //       MODIFIED       Simon Vidanovic (May 2013) - added overlaps calculations for daylighting
   12474              :     //       RE-ENGINEERED  na
   12475              : 
   12476              :     // PURPOSE OF THIS SUBROUTINE:
   12477              :     // For each of basis directions on back surface of the window calculates
   12478              :     // overlap areas. It also calculates overlap areas and reflectances for daylighting calculations
   12479              : 
   12480              :     using namespace Vectors;
   12481              : 
   12482              :     Real64 XShadowProjection; // temporary buffer
   12483              :     Real64 YShadowProjection; // temporary buffer
   12484              : 
   12485              :     Real64 XSp;            // for calc BSDF projection direction
   12486              :     Real64 YSp;            // for calc BSDF projection direction
   12487              :     Real64 ZSp;            // for calc BSDF projection direction
   12488              :     Real64 SdotX;          // temporary variable for manipulating .dot. product
   12489              :     Real64 SdotY;          // temporary variable for manipulating .dot. product
   12490              :     Real64 SdotZ;          // temporary variable for manipulating .dot. product
   12491              :     int BackSurfaceNumber; // current back surface number
   12492              :     int NVT;               // Number of vertices of back surface
   12493              :     int NS1;               // Number of the figure being overlapped
   12494              :     int NS2;               // Number of the figure doing overlapping
   12495              :     int NS3;               // Location to place results of overlap
   12496              :     int IRay;              // Current ray of BSDF direction
   12497              :     int KBkSurf;           // Current back surface
   12498              :     int N;
   12499              : 
   12500              :     // Daylighting
   12501              :     int IConst;                // Construction number of back surface
   12502              :     int InsideConLay;          // Construction's inside material layer number
   12503              :     Real64 VisibleReflectance; // Visible reflectance for inside surface material
   12504              :     Real64 TotAOverlap;        // Total overlap area for given outgoing direction
   12505              :     Real64 TotARhoVisOverlap;  // Total overlap area time reflectance for given outgoing direction
   12506              : 
   12507            0 :     auto &s_surf = state.dataSurface;
   12508              : 
   12509            0 :     state.dataSolarShading->XVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
   12510            0 :     state.dataSolarShading->YVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
   12511            0 :     state.dataSolarShading->ZVertex.dimension(s_surf->MaxVerticesPerSurface + 1, 0.0);
   12512              : 
   12513            0 :     Geom.AOverlap.dimension(Window.NBkSurf, Geom.Trn.NBasis, 0.0);
   12514            0 :     Geom.ARhoVisOverlap.dimension(Window.NBkSurf, Geom.Trn.NBasis, 0.0);
   12515            0 :     Geom.AveRhoVisOverlap.dimension(Geom.Trn.NBasis, 0.0);
   12516              : 
   12517              :     // First to calculate and store coordinates of the window surface
   12518            0 :     state.dataSolarShading->LOCHCA = 1;
   12519            0 :     int BaseSurf = s_surf->Surface(ISurf).BaseSurf; // Base surface number
   12520              : 
   12521              :     // Base surface contains current window surface (ISurf).
   12522              :     // Since that is case, below transformation should always return ZVT = 0.0
   12523              :     // for every possible transformation
   12524            0 :     CTRANS(state, ISurf, BaseSurf, NVT, state.dataSolarShading->XVertex, state.dataSolarShading->YVertex, state.dataSolarShading->ZVertex);
   12525              : 
   12526              :     // HTRANS routine is using coordinates stored in XVS and YVS in order to calculate
   12527              :     // surface area.  Since both projections are equal to zero, then simply
   12528              :     // copy these values into XVS and YVS arrays
   12529            0 :     for (N = 1; N <= NVT; ++N) {
   12530            0 :         state.dataSolarShading->XVS(N) = state.dataSolarShading->XVertex(N);
   12531            0 :         state.dataSolarShading->YVS(N) = state.dataSolarShading->YVertex(N);
   12532              :     }
   12533              : 
   12534              :     // This calculates the area stored in XVS and YVS
   12535            0 :     HTRANS1(state, state.dataSolarShading->LOCHCA, NVT);
   12536              : 
   12537              :     // Calculation of overlap areas for each outgoing basis direction
   12538            0 :     for (IRay = 1; IRay <= Geom.Trn.NBasis; ++IRay) { // basis directions loop (on back surface)
   12539              :         // For current basis direction calculate dot product between window surface
   12540              :         // and basis direction.  This will be used to calculate projection of each
   12541              :         // of the back surfaces to window surface for given basis direction
   12542            0 :         SdotX = dot(s_surf->Surface(ISurf).lcsx, Geom.sTrn(IRay));
   12543            0 :         SdotY = dot(s_surf->Surface(ISurf).lcsy, Geom.sTrn(IRay));
   12544            0 :         SdotZ = dot(s_surf->Surface(ISurf).lcsz, Geom.sTrn(IRay));
   12545            0 :         XSp = -SdotX;
   12546            0 :         YSp = -SdotY;
   12547            0 :         ZSp = -SdotZ;
   12548              : 
   12549              :         // Projection of shadows for current basis direction
   12550            0 :         if (std::abs(ZSp) > Constant::SmallDistance) {
   12551            0 :             XShadowProjection = XSp / ZSp;
   12552            0 :             YShadowProjection = YSp / ZSp;
   12553            0 :             if (std::abs(XShadowProjection) < 1.e-8) XShadowProjection = 0.0;
   12554            0 :             if (std::abs(YShadowProjection) < 1.e-8) YShadowProjection = 0.0;
   12555              :         } else {
   12556            0 :             XShadowProjection = 0.0;
   12557            0 :             YShadowProjection = 0.0;
   12558              :         }
   12559              : 
   12560            0 :         for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
   12561              :             // BaseSurf = Surface(ISurf).BaseSurf
   12562            0 :             BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
   12563              : 
   12564              :             // Transform coordinates of back surface from general system to the
   12565              :             // plane of the receiving surface
   12566            0 :             CTRANS(state,
   12567              :                    BackSurfaceNumber,
   12568              :                    BaseSurf,
   12569              :                    NVT,
   12570            0 :                    state.dataSolarShading->XVertex,
   12571            0 :                    state.dataSolarShading->YVertex,
   12572            0 :                    state.dataSolarShading->ZVertex);
   12573              : 
   12574              :             // Project "shadow" from back surface along sun's rays to receiving surface.  Back surface vertices
   12575              :             // become clockwise sequential.
   12576              : 
   12577            0 :             for (N = 1; N <= NVT; ++N) {
   12578            0 :                 state.dataSolarShading->YVS(N) = state.dataSolarShading->YVertex(N) - YShadowProjection * state.dataSolarShading->ZVertex(N);
   12579            0 :                 state.dataSolarShading->XVS(N) = state.dataSolarShading->XVertex(N) - XShadowProjection * state.dataSolarShading->ZVertex(N);
   12580              :             }
   12581              : 
   12582              :             // Transform to the homogeneous coordinate system.
   12583              : 
   12584            0 :             NS3 = state.dataSolarShading->LOCHCA + 1;
   12585            0 :             state.dataSolarShading->HCT(NS3) = 0.0;
   12586            0 :             HTRANS1(state, NS3, NVT);
   12587              : 
   12588              :             // Determine area of overlap of projected back surface and receiving surface.
   12589              : 
   12590            0 :             NS1 = 1;
   12591            0 :             NS2 = NS3;
   12592            0 :             state.dataSolarShading->HCT(NS3) = 1.0;
   12593            0 :             DeterminePolygonOverlap(state, NS1, NS2, NS3);
   12594              : 
   12595            0 :             if (state.dataSolarShading->OverlapStatus == NoOverlap) continue; // to next back surface
   12596            0 :             if ((state.dataSolarShading->OverlapStatus == TooManyVertices) || (state.dataSolarShading->OverlapStatus == TooManyFigures))
   12597            0 :                 break; // back surfaces DO loop
   12598              : 
   12599            0 :             state.dataSolarShading->LOCHCA = NS3;
   12600            0 :             state.dataSolarShading->HCNS(state.dataSolarShading->LOCHCA) = BackSurfaceNumber;
   12601            0 :             state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA) = -state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
   12602              : 
   12603            0 :             Geom.AOverlap(KBkSurf, IRay) = state.dataSolarShading->HCAREA(state.dataSolarShading->LOCHCA);
   12604              :         } // DO KBkSurf  = 1 , NBkSurf
   12605              : 
   12606              :         // If some of back surfaces is contained in base surface, then need to subtract shadow of subsurface
   12607              :         // from shadow on base surface.  Reason is that above shadowing algorithm is calculating shadow without
   12608              :         // influence of subsurfaces
   12609            0 :         for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
   12610            0 :             BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
   12611              :             // CurBaseSurf is Current base surface number for shadow overlap calculations
   12612            0 :             int CurBaseSurf = s_surf->Surface(BackSurfaceNumber).BaseSurf;
   12613            0 :             if (CurBaseSurf != BackSurfaceNumber) {
   12614              :                 // Search if that base surface in list of back surfaces for current window
   12615              :                 // CurBackSurface is Current back surface number for base surface
   12616            0 :                 int CurBackSurface = 0;
   12617            0 :                 for (N = 1; N <= Window.NBkSurf; ++N) {
   12618            0 :                     if (state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(N) == CurBaseSurf) {
   12619            0 :                         CurBackSurface = N;
   12620            0 :                         break;
   12621              :                     }
   12622              :                 }
   12623            0 :                 if (CurBackSurface != 0) {
   12624            0 :                     Geom.AOverlap(CurBackSurface, IRay) -= Geom.AOverlap(KBkSurf, IRay);
   12625              :                 }
   12626              :             }
   12627              :         }
   12628              : 
   12629            0 :         auto &s_mat = state.dataMaterial;
   12630              : 
   12631              :         // Calculate overlap area times reflectance.  This is necessary for complex fenestration daylighting
   12632              :         // calculations
   12633            0 :         TotAOverlap = 0.0;
   12634            0 :         TotARhoVisOverlap = 0.0;
   12635            0 :         for (KBkSurf = 1; KBkSurf <= Window.NBkSurf; ++KBkSurf) { // back surf loop
   12636            0 :             BackSurfaceNumber = state.dataShadowComb->ShadowComb(BaseSurf).BackSurf(KBkSurf);
   12637            0 :             IConst = s_surf->Surface(BackSurfaceNumber).Construction;
   12638            0 :             InsideConLay = state.dataConstruction->Construct(IConst).TotLayers;
   12639            0 :             if (s_surf->SurfWinWindowModelType(BackSurfaceNumber) == WindowModel::BSDF) {
   12640            0 :                 VisibleReflectance = state.dataConstruction->Construct(IConst).ReflectVisDiffBack;
   12641              :             } else {
   12642            0 :                 VisibleReflectance = (1.0 - s_mat->materials(InsideConLay)->AbsorpVisible);
   12643              :             }
   12644            0 :             Geom.ARhoVisOverlap(KBkSurf, IRay) = Geom.AOverlap(KBkSurf, IRay) * VisibleReflectance;
   12645            0 :             TotAOverlap += Geom.AOverlap(KBkSurf, IRay);
   12646            0 :             TotARhoVisOverlap += Geom.ARhoVisOverlap(KBkSurf, IRay);
   12647              :         }
   12648              : 
   12649            0 :         if (TotAOverlap != 0.0) {
   12650            0 :             Geom.AveRhoVisOverlap(IRay) = TotARhoVisOverlap / TotAOverlap;
   12651              :         }
   12652              : 
   12653              :     } // DO IRay = 1, Geom%Trn%NBasis
   12654              : 
   12655              :     // Reset back shadowing counter since complex windows do not need it anymore
   12656            0 :     state.dataSolarShading->LOCHCA = 1;
   12657            0 : }
   12658              : 
   12659       249956 : void TimestepInitComplexFenestration(EnergyPlusData &state)
   12660              : {
   12661              :     // SUBROUTINE INFORMATION:
   12662              :     //       AUTHOR         Simon Vidanovic
   12663              :     //       DATE WRITTEN   May 2012
   12664              :     //       MODIFIED       May 2012 (Initialize complex fenestration in case of EMS)
   12665              :     //       RE-ENGINEERED  na
   12666              : 
   12667              :     // PURPOSE OF THIS SUBROUTINE:
   12668              :     // Performs initialization of complex fenestration. It also performs check if current surface containing
   12669              :     // complex fenestration have construction changed (by EMS) in which case performs addition of current states
   12670              :     // into complex fenestration array
   12671              : 
   12672              :     using WindowComplexManager::CheckCFSStates;
   12673              : 
   12674              :     // Locals
   12675              :     int iSurf;       // Current surface number
   12676              :     int iState;      // current state number
   12677              :     int NumOfStates; // number of states for current window
   12678              : 
   12679       249956 :     auto &s_surf = state.dataSurface;
   12680              : 
   12681      2359340 :     for (iSurf = 1; iSurf <= s_surf->TotSurfaces; ++iSurf) {
   12682      2109384 :         if (s_surf->SurfWinWindowModelType(iSurf) == WindowModel::BSDF) {
   12683              :             // This will check complex fenestrations state and add new one if necessary (EMS case)
   12684            0 :             CheckCFSStates(state, iSurf);
   12685              : 
   12686            0 :             NumOfStates = state.dataBSDFWindow->ComplexWind(iSurf).NumStates;
   12687              : 
   12688              :             // Check for overlap areas and initialize if necessary
   12689            0 :             for (iState = 1; iState <= NumOfStates; ++iState) {
   12690              :                 // do initialization only once
   12691            0 :                 if (state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState).InitState) {
   12692            0 :                     CalcComplexWindowOverlap(
   12693            0 :                         state, state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState), state.dataBSDFWindow->ComplexWind(iSurf), iSurf);
   12694            0 :                     state.dataBSDFWindow->ComplexWind(iSurf).Geom(iState).InitState = false;
   12695              :                 }
   12696              :             }
   12697              :         }
   12698              :     }
   12699       249956 : }
   12700              : 
   12701              : } // namespace EnergyPlus::SolarShading
        

Generated by: LCOV version 2.0-1